socket connection established and chess logic imported from old codebase
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"exception": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"ostream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"system_error": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ const cors = require("cors");
|
||||
const authRoutes = require("./routes/auth");
|
||||
const userRoutes = require("./routes/user");
|
||||
const mongoose = require("mongoose");
|
||||
require("dotenv").config();
|
||||
|
||||
mongoose
|
||||
.connect("mongodb://127.0.0.1:27017/test")
|
||||
@@ -14,27 +15,65 @@ const app = express();
|
||||
const http = require("http");
|
||||
const server = http.createServer(app);
|
||||
const { Server } = require("socket.io");
|
||||
const { sendEmail } = require("./mail");
|
||||
const { User } = require("./models/user");
|
||||
const io = new Server(server, { cors: { origin: "*" } });
|
||||
|
||||
io.on("connection", (socket) => {
|
||||
// console.log("Connected: ", socket.data);
|
||||
socket.broadcast.emit("game", "emitting...");
|
||||
socket.emit("game", "Welcome");
|
||||
const activeRooms = new Map();
|
||||
const pendingChallenges = new Map();
|
||||
|
||||
socket.on("join-room", async (data) => {
|
||||
if (data?.roomid) await socket.join(roomid);
|
||||
else socket.emit("error", "Room id not received");
|
||||
io.on("connection", (socket) => {
|
||||
console.log("Client connected:", socket.id);
|
||||
|
||||
// Handle join event
|
||||
socket.on("join-room", async (roomID, playerUsername, challengedPlayerUsername) => {
|
||||
// room exists
|
||||
if (activeRooms.has(roomID)) {
|
||||
socket.emit("room-full");
|
||||
return;
|
||||
} else if (pendingChallenges.has(roomID)) {
|
||||
const challenge = pendingChallenges.get(roomID);
|
||||
pendingChallenges.delete(roomID);
|
||||
let newRoom = {
|
||||
id: roomID,
|
||||
players: {
|
||||
challenger: {
|
||||
id: challenge.challengerID,
|
||||
name: challenge.challengerUsername,
|
||||
},
|
||||
challenged: {
|
||||
id: socket.id,
|
||||
name: playerUsername,
|
||||
},
|
||||
},
|
||||
};
|
||||
activeRooms.set(roomID, newRoom);
|
||||
io.to(roomID).emit("room-created");
|
||||
} else {
|
||||
// no room on pending challenges found
|
||||
const challenge = {
|
||||
roomID,
|
||||
challengerID: socket.id,
|
||||
challengerUsername: playerUsername,
|
||||
challengedUsername: challengedPlayerUsername,
|
||||
};
|
||||
pendingChallenges.set(roomID, challenge);
|
||||
|
||||
console.log(challengedPlayerUsername);
|
||||
// notify the challenged player
|
||||
const email = (await User.findOne({ username: challengedPlayerUsername })).email;
|
||||
sendEmail(
|
||||
email,
|
||||
`Challenge from ${playerUsername}`,
|
||||
`To accept the challenge follow the link: http://localhost:5173/game/friend/${roomID}`
|
||||
);
|
||||
|
||||
socket.emit("challenge-pending");
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("play", (data) => {
|
||||
console.log(data);
|
||||
let { fromRow, fromCol, toRow, toCol, room } = data;
|
||||
fromRow = 7 - fromRow;
|
||||
fromCol = 7 - fromCol;
|
||||
toRow = 7 - toRow;
|
||||
toCol = 7 - toCol;
|
||||
socket.to(room).emit("play", { fromCol, fromRow, toCol, toRow });
|
||||
socket.broadcast.emit("play", { fromCol, fromRow, toCol, toRow });
|
||||
socket.on("move", (roomID, moveData) => {
|
||||
socket.to(roomID).emit("opponent-move", moveData);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{"events":[{"title":"new event","image":"https://images.squarespace-cdn.com/content/v1/56d082a760b5e95c074d11a0/8ce30633-23f2-4dc9-b301-c251cbf26d02/Mercedes+Benz+Oscar+Party?format=2500w","date":"2023-05-03","description":"hello","id":"1f24eb47-5019-4a07-9c3c-1ba18b591800"},{"title":"concert","image":"https://business.twitter.com/content/dam/business-twitter/insights/may-2018/event-targeting.png.twimg.1920.png","date":"2023-05-04","description":"lorem","id":"2035d991-0e72-456c-b6df-1aa9774caaaa"}],"users":[{"email":"m@g.com","password":"$2a$12$.GW99UfbOfISG6mQHN.8MOXtYXePsWH592XudNWU9Df9tYEV.K.QG","id":"2a744c6d-da1a-4938-ab45-144b567d5187"},{"email":"moon@gmails.com","password":"$2a$12$o7p.OS1vA66yBlkOsh.xV.ifDsItbSeBOTaN5VgjYHIUVtDvP3nbu","id":"8f394056-592e-45fc-9808-e923e1a1d60a"},{"email":"moon@gmail.com","password":"$2a$12$3t8sENEvXNvC1XeKhMsJFOsaU0vVh27wnY4hHIPlXzzOIAwMiSSJC","id":"421e3728-ac58-4fc1-86d5-70b618d01f9b"},{"email":"moonpatel2003@gmail.com","password":"$2a$12$QxG6hh0vFudhlsX3MJvXLuVfnFKBAPd15Bei42MNB2v69BwwGT3oq","id":"d77a0a0b-2b82-489e-9782-ccac490db36d"}]}
|
||||
@@ -0,0 +1,29 @@
|
||||
const nodemailer = require("nodemailer");
|
||||
const transporter = nodemailer.createTransport({
|
||||
service: "gmail",
|
||||
auth: {
|
||||
user: "chessroyalemail@gmail.com",
|
||||
pass: process.env.MAIL_SERVER_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
const sendEmail = (receiverEmail, subject, data) => {
|
||||
console.log(process.env.MAIL_SERVER_PASSWORD);
|
||||
let mailDetails = {
|
||||
from: "chessroyalemail@gmail.com",
|
||||
to: receiverEmail,
|
||||
subject: subject,
|
||||
text: data,
|
||||
};
|
||||
transporter.sendMail(mailDetails, function (err, data) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
} else {
|
||||
console.log("Email sent successfully");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
sendEmail,
|
||||
};
|
||||
@@ -39,7 +39,7 @@ const userSchema = new Schema(
|
||||
methods: {
|
||||
async getFriends() {
|
||||
await this.populate("friends", "username");
|
||||
console.log(this.friends);
|
||||
// console.log(this.friends);
|
||||
return this.friends.map(friend => friend.username);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongoose": "^7.2.1",
|
||||
"nodemailer": "^6.9.3",
|
||||
"socket.io": "^4.6.1",
|
||||
"uuid": "^9.0.0"
|
||||
}
|
||||
@@ -211,6 +213,17 @@
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
|
||||
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/motdotla/dotenv?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
@@ -774,6 +787,14 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/nodemailer": {
|
||||
"version": "6.9.3",
|
||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.3.tgz",
|
||||
"integrity": "sha512-fy9v3NgTzBngrMFkDsKEj0r02U7jm6XfC3b52eoNV+GCrGj+s8pt5OqhiJdWKuw51zCTdiNR/IUD1z33LIIGpg==",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"mongoose": "^7.2.1",
|
||||
"nodemailer": "^6.9.3",
|
||||
"socket.io": "^4.6.1",
|
||||
"uuid": "^9.0.0"
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
"@tabler/icons-react": "^2.23.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.14.0"
|
||||
"react-router-dom": "^6.14.0",
|
||||
"socket.io-client": "^4.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.37",
|
||||
@@ -1273,6 +1274,11 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@socket.io/component-emitter": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"node_modules/@tabler/icons": {
|
||||
"version": "2.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-2.23.0.tgz",
|
||||
@@ -1704,7 +1710,6 @@
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
@@ -1762,6 +1767,26 @@
|
||||
"integrity": "sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/engine.io-client": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.1.tgz",
|
||||
"integrity": "sha512-hE5wKXH8Ru4L19MbM1GgYV/2Qo54JSMh1rlJbfpa40bEWkCKNo3ol2eOtGmowcr+ysgbI7+SGL+by42Q3pt/Ng==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1",
|
||||
"engine.io-parser": "~5.1.0",
|
||||
"ws": "~8.11.0",
|
||||
"xmlhttprequest-ssl": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/engine.io-parser": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz",
|
||||
"integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
@@ -3016,8 +3041,7 @@
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
@@ -3687,6 +3711,32 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-client": {
|
||||
"version": "4.7.1",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.1.tgz",
|
||||
"integrity": "sha512-Qk3Xj8ekbnzKu3faejo4wk2MzXA029XppiXtTF/PkbTg+fcwaTw1PlDrTrrrU4mKoYC4dvlApOnSeyLCKwek2w==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.2",
|
||||
"engine.io-client": "~6.5.1",
|
||||
"socket.io-parser": "~4.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/socket.io-parser": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
|
||||
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
|
||||
"dependencies": {
|
||||
"@socket.io/component-emitter": "~3.1.0",
|
||||
"debug": "~4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
@@ -4127,6 +4177,34 @@
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xmlhttprequest-ssl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
|
||||
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
"@tabler/icons-react": "^2.23.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.14.0"
|
||||
"react-router-dom": "^6.14.0",
|
||||
"socket.io-client": "^4.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.37",
|
||||
|
||||
@@ -17,8 +17,8 @@ import Play from './pages/Play/Play'
|
||||
import AuthenticationPage, { loginAction, signupAction } from './pages/Authentication/Authentication'
|
||||
import { getAuthToken } from '../utils/auth'
|
||||
import { logoutAction } from './components/Logout'
|
||||
|
||||
|
||||
import ChallengeFriend, { playFriendAction } from './pages/Play/ChallengeFriend'
|
||||
import ChessGame from './pages/Chess/ChessGame'
|
||||
|
||||
const router = createBrowserRouter([{
|
||||
path: '/',
|
||||
@@ -30,11 +30,13 @@ const router = createBrowserRouter([{
|
||||
{
|
||||
path: 'play', element: <PlayLayout />, children: [
|
||||
{ index: true, element: <Play /> },
|
||||
{ path: 'friend/:friend_username', element: <ChallengeFriend />, action: playFriendAction },
|
||||
{ path: 'friend', element: <PlayFriend /> },
|
||||
{ path: 'computer', element: <div>Computer</div> },
|
||||
{ path: 'online', element: <div>Online</div> }
|
||||
]
|
||||
},
|
||||
{ path: "game/friend/:roomID", element: <ChessGame /> },
|
||||
{
|
||||
path: 'settings', element: <Settings />, children: [
|
||||
{ index: true, element: <Profile /> },
|
||||
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,44 @@
|
||||
import React from 'react'
|
||||
import Piece from './Piece';
|
||||
import { socket } from '../socket';
|
||||
import { Box, Flex } from '@mantine/core';
|
||||
|
||||
const Cell = ({ cellProps, selectedPiece, dispatch, myColor }) => {
|
||||
const { row, col, piece, marked } = cellProps;
|
||||
let bgColor = (selectedPiece?.row === row && selectedPiece?.col === col) ? 'bg-gray-100' : ((row + col) % 2 ? 'bg-stone-800' : 'bg-neutral-200');
|
||||
bgColor = marked && piece ? `bg-red-300` : bgColor;
|
||||
|
||||
const handleClick = () => {
|
||||
// if (!myTurn) return;
|
||||
if (piece && piece.color === myColor) {
|
||||
dispatch({ type: 'SELECT_PIECE', val: { row, col, color: piece.color } }) // select piece
|
||||
}
|
||||
else if (!piece && selectedPiece && marked) {
|
||||
let payload = { fromRow: selectedPiece.row, fromCol: selectedPiece.col, toRow: row, toCol: col };
|
||||
socket.emit('move', payload);
|
||||
dispatch({ type: 'MOVE_PIECE', val: payload, }); // move piece
|
||||
}
|
||||
else if (piece && marked && piece.color !== myColor) {
|
||||
let payload = { fromRow: selectedPiece.row, fromCol: selectedPiece.col, toRow: row, toCol: col, color: piece.color };
|
||||
socket.emit('move', payload);
|
||||
dispatch({ type: 'CAPTURE_PIECE', val: payload }) // capture piece
|
||||
}
|
||||
}
|
||||
|
||||
const content = marked ? <Mark /> : <Piece piece={piece} />;
|
||||
|
||||
return (
|
||||
<Flex onClick={handleClick} w="75px" h="75px" bg={(row + col) % 2 ? 'gray' : 'white'} className={`w-12 h-12 md:w-20 md:h-20 ${bgColor} flex justify-center items-center relative`}>
|
||||
{content}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export const Mark = () => {
|
||||
return (
|
||||
<Box w="33%" h="33%" sx={{ backgroundColor: 'gray', borderRadius: '100%' }} m="auto"></Box>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default Cell
|
||||
@@ -0,0 +1,53 @@
|
||||
import { Avatar, Flex, Image, Loader, NavLink, Text, Title } from '@mantine/core';
|
||||
import { Link } from 'react-router-dom';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
const FriendsList = () => {
|
||||
const [friends, setFriends] = useState(null);
|
||||
useEffect(() => {
|
||||
const abortController = new AbortController();
|
||||
let response = null;
|
||||
|
||||
const fetchData = async () => {
|
||||
let url = `${import.meta.env.VITE_BACKEND_HOST}/api/user/user1/friends`;
|
||||
try {
|
||||
response = await fetch(url, { signal: abortController.signal });
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
setFriends(data.friends);
|
||||
} else {
|
||||
throw data;
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.message === 'The user aborted a request.');
|
||||
else {
|
||||
console.log('Error fetching data');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fetchData();
|
||||
|
||||
return () => {
|
||||
if (!response) {
|
||||
abortController.abort();
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Flex sx={{ flexGrow: '1' }} height="100%" justify="start" my="md" align="start" direction="column">
|
||||
<Title px="sm" pt="md" order={3}>Friends</Title>
|
||||
|
||||
{
|
||||
friends ?
|
||||
friends.map((friend, index) => <NavLink key={index} component={Link} to="/play/friend/moonpatel" p='5px' icon={<Avatar size='sm' color='blue' children="M" />} label={<Text fw={700}>{friend}</Text>} />)
|
||||
:
|
||||
<Loader m="20px" variant='dots' color='lime' />
|
||||
}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default FriendsList
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Image } from '@mantine/core';
|
||||
import React from 'react';
|
||||
|
||||
const Piece = ({ piece }) => {
|
||||
if (piece === null) return null;
|
||||
const { type, color } = piece;
|
||||
let logo;
|
||||
switch (type) {
|
||||
case 'P':
|
||||
logo = color === 'W' ? 'pawn_white' : 'pawn_black';
|
||||
break;
|
||||
case 'R':
|
||||
logo = color === 'W' ? 'rook_white' : 'rook_black';
|
||||
break;
|
||||
case 'N':
|
||||
logo = color === 'W' ? 'knight_white' : 'knight_black';
|
||||
break;
|
||||
case 'B':
|
||||
logo = color === 'W' ? 'bishop_white' : 'bishop_black';
|
||||
break;
|
||||
case 'Q':
|
||||
logo = color === 'W' ? 'queen_white' : 'queen_black';
|
||||
break;
|
||||
case 'K':
|
||||
logo = color === 'W' ? 'king_white' : 'king_black';
|
||||
break;
|
||||
}
|
||||
return (
|
||||
<Image src={`/src/assets/${logo}.png`} />
|
||||
)
|
||||
}
|
||||
|
||||
export default Piece
|
||||
@@ -8,7 +8,7 @@ const AuthenticationPage = (props) => {
|
||||
const { isLogin } = props;
|
||||
|
||||
return (
|
||||
<Container maw="100%" bg="gray" style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
|
||||
<Container maw="100%" sx={(theme) => ({ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', backgroundImage: theme.fn.gradient({ from: 'blue', to: 'teal' }) })}>
|
||||
<Card shadow="md" p="lg" style={{ maxWidth: 400, width: '100%' }}>
|
||||
<Text align="center" variant="h4" style={{ marginBottom: 20 }}>
|
||||
{isLogin ? 'Login' : 'Sign Up'}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Avatar, Flex, Image, NavLink, Text, Title } from '@mantine/core'
|
||||
import React from 'react'
|
||||
import ChessBoard from '../Play/ChessBoard'
|
||||
|
||||
const ChessGame = () => {
|
||||
return (
|
||||
<Flex gap="xl" justify='center' align='center' wrap='nowrap' direction='row'>
|
||||
<Flex gap="xs" justify='center' align='start' wrap='nowrap' direction='column' >
|
||||
<NavLink
|
||||
p="2px"
|
||||
label={"username"}
|
||||
icon={<Avatar radius="3px" />}
|
||||
description={"description"}
|
||||
/>
|
||||
<ChessBoard />
|
||||
<NavLink
|
||||
p="2px"
|
||||
label={"username"}
|
||||
icon={<Avatar radius="3px" />}
|
||||
description={"description"}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex w="450px" bg='gray' h="600px" sx={{ borderRadius: '10px' }}>
|
||||
<Title>Game Data</Title>
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChessGame
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Avatar, Button, Card, Flex, Image, Select, Text, TextInput, Title } from '@mantine/core'
|
||||
import React from 'react'
|
||||
import FriendsList from '../../components/FriendsList'
|
||||
import { IconSearch } from '@tabler/icons-react'
|
||||
import { Form, Link, redirect, useParams, useSearchParams } from 'react-router-dom'
|
||||
import { socket } from '../../socket'
|
||||
|
||||
const ChallengeFriend = () => {
|
||||
const params = useParams();
|
||||
let friend_username = params["friend_username"];
|
||||
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
width: '450px',
|
||||
height: '600px',
|
||||
textAlign: 'center'
|
||||
}}
|
||||
>
|
||||
<Flex align="center" direction="column" justify="center" gap="xs" my="lg">
|
||||
<Title order={2}>Play vs {friend_username}</Title>
|
||||
<Avatar mt="lg" color='lime' size="100px">{friend_username[0].toUpperCase()}</Avatar>
|
||||
<Text>{friend_username}</Text>
|
||||
</Flex>
|
||||
<Select label="Time limit" placeholder='Time limit' value='10' data={['5', '10', '15', '30']} />
|
||||
<Select value='W' onChange={(evt) => setColor(evt.target.value)} my="20px" label={<Text mx="auto" order={3}>I play as</Text>} placeholder='choose your color' data={[
|
||||
{ value: 'W', label: 'White' },
|
||||
{ value: 'B', label: 'Black' },
|
||||
{ value: 'RANDOM', label: 'Random' }
|
||||
]} />
|
||||
<Form action={`/play/friend/${friend_username}`} method='POST'>
|
||||
<Button color='lime' type='submit' >Challenge</Button>
|
||||
</Form>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export const playFriendAction = ({ request, params }) => {
|
||||
let roomID = Math.floor(Math.random() * 1_000_000_000).toString();
|
||||
// const req = new URL(request);
|
||||
socket.connect();
|
||||
socket.emit('join-room', roomID, 'user1', params.friend_username);
|
||||
|
||||
// socket.on('pending-challenge', () => {
|
||||
// })
|
||||
return redirect(`/game/friend/${roomID}`);
|
||||
}
|
||||
|
||||
export default ChallengeFriend;
|
||||
@@ -0,0 +1,104 @@
|
||||
import React, { useEffect, useReducer, useRef } from 'react';
|
||||
import { blackColor, chessBoardInit, getPieceHint, pieces, whiteColor } from '../../../utils/chess';
|
||||
import Cell from '../../components/Cell';
|
||||
import { socket } from '../../socket';
|
||||
import { Flex } from '@mantine/core';
|
||||
|
||||
let myColor = 'W';
|
||||
|
||||
const reducer = (state, action) => {
|
||||
if (state.capturedPieces.length && state.capturedPieces.at(-1).type === pieces.king) return state;
|
||||
switch (action.type) {
|
||||
case 'SELECT_PIECE':
|
||||
{
|
||||
let { row, col, color } = action.val;
|
||||
let selectedPiece = { row, col, color };
|
||||
let possibleMoves = getPieceHint(state.chessBoard, { row, col, color, type: state.chessBoard[row][col].type }, color).movePos;
|
||||
return { ...state, selectedPiece, possibleMoves };
|
||||
}
|
||||
break;
|
||||
case 'MOVE_PIECE':
|
||||
{
|
||||
let { fromRow, fromCol, toRow, toCol } = action.val;
|
||||
let newChessBoard = state.chessBoard.map(row => row.slice());
|
||||
let piece = state.chessBoard[fromRow][fromCol];
|
||||
newChessBoard[toRow][toCol] = piece;
|
||||
newChessBoard[fromRow][fromCol] = null;
|
||||
return { ...state, chessBoard: newChessBoard, possibleMoves: [], selectedPiece: null, myTurn: !state.myTurn };
|
||||
}
|
||||
break;
|
||||
case 'CAPTURE_PIECE':
|
||||
{
|
||||
let { fromRow, fromCol, toRow, toCol } = action.val;
|
||||
let newChessBoard = state.chessBoard.map(row => row.slice());
|
||||
let capturedPieces = [...state.capturedPieces, state.chessBoard[toRow][toCol]];
|
||||
newChessBoard[toRow][toCol] = state.chessBoard[fromRow][fromCol];
|
||||
newChessBoard[fromRow][fromCol] = null;
|
||||
return { ...state, chessBoard: newChessBoard, capturedPieces, possibleMoves: [], selectedPiece: null, myTurn: !state.myTurn };
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
const ChessBoard = () => {
|
||||
const [gameState, dispatch] = useReducer(reducer, {
|
||||
chessBoard: chessBoardInit(myColor), selectedPiece: null, possibleMoves: [], capturedPieces: [], myTurn: myColor === whiteColor
|
||||
});
|
||||
|
||||
const chessBoardRef = useRef(gameState.chessBoard);
|
||||
chessBoardRef.current = gameState.chessBoard;
|
||||
|
||||
useEffect(() => {
|
||||
function handleOpponentMove(data) {
|
||||
let { fromCol, fromRow, toCol, toRow } = data;
|
||||
if (chessBoardRef.current[toRow][toCol] === null) {
|
||||
console.log('Moving piece: ', data)
|
||||
dispatch({ type: 'MOVE_PIECE', val: { fromRow, fromCol, toRow, toCol } });
|
||||
} else if (myColor === chessBoardRef.current[toRow][toCol].color) {
|
||||
dispatch({ type: 'CAPTURE_PIECE', val: { fromRow, fromCol, toRow, toCol } });
|
||||
}
|
||||
}
|
||||
socket.on('move', handleOpponentMove)
|
||||
|
||||
return () => {
|
||||
socket.off('move', handleOpponentMove);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Flex w="600px">
|
||||
<div>
|
||||
{gameState.chessBoard.map((line, row) => {
|
||||
return (
|
||||
<Flex className='flex' key={row * 2}>
|
||||
{line.map((cell, col) => {
|
||||
let marked = null;
|
||||
for (let k = 0; k < gameState.possibleMoves.length; k++) {
|
||||
if (gameState.possibleMoves[k].row === row && gameState.possibleMoves[k].col === col) {
|
||||
marked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let piece = cell ? { type: cell.type, color: cell.color } : null;
|
||||
return <Cell
|
||||
key={col * 3 + 1}
|
||||
selectedPiece={gameState.selectedPiece}
|
||||
cellProps={{ row, col, piece, marked }}
|
||||
dispatch={dispatch}
|
||||
myColor={myColor}
|
||||
myTurn={gameState.myTurn}
|
||||
/>
|
||||
})}
|
||||
</Flex>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Flex>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChessBoard
|
||||
@@ -6,7 +6,7 @@ const Play = () => {
|
||||
return (
|
||||
<Card sx={{
|
||||
width: '450px',
|
||||
height: '100%',
|
||||
height: '600px',
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
<Flex gap="5px" px="20px" justify='center' align='center' wrap='nowrap' direction='column'>
|
||||
@@ -28,7 +28,7 @@ const CardItem = ({ label, description, src, to }) => {
|
||||
label={label}
|
||||
icon={<Image src={src} width={50} />}
|
||||
description={description}
|
||||
sx={{ backgroundColor: 'gray', borderRadius: '5px' }}
|
||||
sx={{ backgroundColor: 'black', borderRadius: '5px' }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Button, Card, CopyButton, Flex, Group, Image, Modal, NativeSelect, NavLink, Select, Text, TextInput, Title } from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { IconSearch } from '@tabler/icons-react'
|
||||
import { PersonIcon } from '@radix-ui/react-icons'
|
||||
import { IconSearch, IconUserCircle } from '@tabler/icons-react'
|
||||
import FriendsList from '../../components/FriendsList'
|
||||
|
||||
const createChallengeLink = (color) => {
|
||||
let challengeLink = Math.floor(Math.random() * 100_000_000).toString();
|
||||
@@ -46,10 +46,7 @@ const PlayFriend = () => {
|
||||
<Title order={2}>Play a Friend</Title>
|
||||
</Flex>
|
||||
<TextInput my="5px" placeholder="Search by email or username" icon={<IconSearch />} />
|
||||
<Flex sx={{ flexGrow: '1' }} height="100%" justify="start" align="start" direction="column">
|
||||
<Title px="md" pt="md" order={3}>Friends</Title>
|
||||
{friends.map((friend, index) => <NavLink key={index} icon={friend.avatar} label={<Text fw={700}>{friend.username}</Text>} />)}
|
||||
</Flex>
|
||||
<FriendsList />
|
||||
<Flex direction='column' gap='10px'>
|
||||
<Button color='lime' onClick={open}>Create Challenge Link</Button>
|
||||
<Button color='lime'>Join using Challenge Link</Button>
|
||||
@@ -60,10 +57,10 @@ const PlayFriend = () => {
|
||||
}
|
||||
|
||||
const friends = [
|
||||
{ avatar: <PersonIcon />, username: "friend", rating: 100 },
|
||||
{ avatar: <PersonIcon />, username: "friend", rating: 100 },
|
||||
{ avatar: <PersonIcon />, username: "friend", rating: 100 },
|
||||
{ avatar: <PersonIcon />, username: "friend", rating: 100 },
|
||||
{ avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
||||
{ avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
||||
{ avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
||||
{ avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
||||
]
|
||||
|
||||
export default PlayFriend
|
||||
@@ -0,0 +1,3 @@
|
||||
import { io } from "socket.io-client";
|
||||
const url = import.meta.env.VITE_BACKEND_HOST
|
||||
export const socket = io(url, { autoConnect: false });
|
||||
@@ -0,0 +1,305 @@
|
||||
const pawn = "P",
|
||||
rook = "R",
|
||||
knight = "N",
|
||||
bishop = "B",
|
||||
queen = "Q",
|
||||
king = "K";
|
||||
|
||||
export const pieces = {
|
||||
pawn,
|
||||
rook,
|
||||
knight,
|
||||
bishop,
|
||||
queen,
|
||||
king,
|
||||
};
|
||||
|
||||
export const whiteColor = "W",
|
||||
blackColor = "B";
|
||||
|
||||
export function chessBoardInit(myColor) {
|
||||
let opColor = myColor === whiteColor ? blackColor : whiteColor;
|
||||
const chessBoardMatrix = [
|
||||
[
|
||||
{ color: opColor, type: rook },
|
||||
{ color: opColor, type: knight },
|
||||
{ color: opColor, type: bishop },
|
||||
{ color: opColor, type: myColor === whiteColor ? queen : king },
|
||||
{ color: opColor, type: myColor === whiteColor ? king : queen },
|
||||
{ color: opColor, type: bishop },
|
||||
{ color: opColor, type: knight },
|
||||
{ color: opColor, type: rook },
|
||||
],
|
||||
Array(8).fill({ color: opColor, type: pawn }),
|
||||
[null, null, null, null, null, null, null, null],
|
||||
[null, null, null, null, null, null, null, null],
|
||||
[null, null, null, null, null, null, null, null],
|
||||
[null, null, null, null, null, null, null, null],
|
||||
Array(8).fill({ color: myColor, type: pawn }),
|
||||
[
|
||||
{ color: myColor, type: rook },
|
||||
{ color: myColor, type: knight },
|
||||
{ color: myColor, type: bishop },
|
||||
{ color: myColor, type: myColor === whiteColor ? queen : king },
|
||||
{ color: myColor, type: myColor === whiteColor ? king : queen },
|
||||
{ color: myColor, type: bishop },
|
||||
{ color: myColor, type: knight },
|
||||
{ color: myColor, type: rook },
|
||||
],
|
||||
];
|
||||
return chessBoardMatrix;
|
||||
}
|
||||
|
||||
function inBoard(i, j) {
|
||||
if (i >= 0 && i < 8 && j >= 0 && j < 8) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
function isBlocked(chessBoard, chessPiece, i, j) {
|
||||
if (chessBoard[i][j] === null) return false;
|
||||
else if (chessBoard[i][j].color === chessPiece.color) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
function isAttacking(chessBoard, chessPiece, i, j) {
|
||||
if (chessBoard[i][j] === null) return false;
|
||||
else if (chessBoard[i][j].color !== chessPiece.color) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
function getPawnHint(chessBoard, chessPiece, myColor) {
|
||||
const { row, col } = chessPiece;
|
||||
let movePos = [];
|
||||
if (chessPiece.color === myColor) {
|
||||
// for moving forward
|
||||
if (inBoard(row - 1, col) && chessBoard[row - 1][col] === null && movePos.push({ row: row - 1, col })) {
|
||||
chessPiece.row === 6 &&
|
||||
chessBoard[row - 2][col] === null &&
|
||||
inBoard(row - 2, col) &&
|
||||
!isBlocked(chessBoard, chessPiece, row - 1, col) &&
|
||||
movePos.push({ row: row - 2, col });
|
||||
}
|
||||
// for killing opponent piece
|
||||
if (
|
||||
inBoard(row - 1, col + 1) &&
|
||||
chessBoard[row - 1][col + 1]?.type &&
|
||||
chessBoard[row - 1][col + 1]?.color !== myColor
|
||||
)
|
||||
inBoard(row - 1, col + 1) && movePos.push({ row: row - 1, col: col + 1 });
|
||||
if (
|
||||
inBoard(row - 1, col - 1) &&
|
||||
chessBoard[row - 1][col - 1]?.type &&
|
||||
chessBoard[row - 1][col - 1]?.color !== myColor
|
||||
)
|
||||
inBoard(row - 1, col - 1) && movePos.push({ row: row - 1, col: col - 1 });
|
||||
} else {
|
||||
// for moving forward
|
||||
if (inBoard(row + 1, col) && chessBoard[row + 1][col] === null && movePos.push({ row: row + 1, col })) {
|
||||
chessPiece.row === 1 &&
|
||||
chessBoard[row + 2][col] === null &&
|
||||
inBoard(row + 2, col) &&
|
||||
movePos.push({ row: row + 2, col });
|
||||
}
|
||||
// for killing opponent piece
|
||||
if (
|
||||
inBoard(row + 1, col + 1) &&
|
||||
chessBoard[row + 1][col + 1]?.type &&
|
||||
chessBoard[row + 1][col + 1]?.color === myColor
|
||||
)
|
||||
inBoard(row + 1, col + 1) && movePos.push({ row: row + 1, col: col + 1 });
|
||||
if (
|
||||
inBoard(row + 1, col - 1) &&
|
||||
chessBoard[row + 1][col - 1]?.type &&
|
||||
chessBoard[row + 1][col - 1]?.color === myColor
|
||||
)
|
||||
inBoard(row + 1, col - 1) && movePos.push({ row: row + 1, col: col - 1 });
|
||||
}
|
||||
|
||||
return { movePos };
|
||||
}
|
||||
|
||||
function getRookHint(chessBoard, chessPiece, myColor) {
|
||||
const { row, col, color } = chessPiece;
|
||||
let movePos = [];
|
||||
let i = row,
|
||||
j = col;
|
||||
while (inBoard(++i, j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(--i, j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(i, ++j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(i, --j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
console.log(movePos);
|
||||
|
||||
return { movePos };
|
||||
}
|
||||
|
||||
function getKnightHint(chessBoard, chessPiece, myColor) {
|
||||
const { row, col, color } = chessPiece;
|
||||
let movePos = [];
|
||||
|
||||
if (inBoard(row + 2, col + 1) && !isBlocked(chessBoard, chessPiece, row + 2, col + 1))
|
||||
movePos.push({ row: row + 2, col: col + 1 });
|
||||
if (inBoard(row + 2, col - 1) && !isBlocked(chessBoard, chessPiece, row + 2, col - 1))
|
||||
movePos.push({ row: row + 2, col: col - 1 });
|
||||
if (inBoard(row - 2, col + 1) && !isBlocked(chessBoard, chessPiece, row - 2, col + 1))
|
||||
movePos.push({ row: row - 2, col: col + 1 });
|
||||
if (inBoard(row - 2, col - 1) && !isBlocked(chessBoard, chessPiece, row - 2, col - 1))
|
||||
movePos.push({ row: row - 2, col: col - 1 });
|
||||
if (inBoard(row + 1, col + 2) && !isBlocked(chessBoard, chessPiece, row + 1, col + 2))
|
||||
movePos.push({ row: row + 1, col: col + 2 });
|
||||
if (inBoard(row - 1, col + 2) && !isBlocked(chessBoard, chessPiece, row - 1, col + 2))
|
||||
movePos.push({ row: row - 1, col: col + 2 });
|
||||
if (inBoard(row + 1, col - 2) && !isBlocked(chessBoard, chessPiece, row + 1, col - 2))
|
||||
movePos.push({ row: row + 1, col: col - 2 });
|
||||
if (inBoard(row - 1, col - 2) && !isBlocked(chessBoard, chessPiece, row - 1, col - 2))
|
||||
movePos.push({ row: row - 1, col: col - 2 });
|
||||
|
||||
return { movePos };
|
||||
}
|
||||
|
||||
function getBishopHint(chessBoard, chessPiece, myColor) {
|
||||
const { row, col, color } = chessPiece;
|
||||
let movePos = [];
|
||||
|
||||
let i = row,
|
||||
j = col;
|
||||
while (inBoard(++i, ++j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(++i, --j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(--i, ++j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(--i, --j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
|
||||
return { movePos };
|
||||
}
|
||||
|
||||
function getQueenHint(chessBoard, chessPiece, myColor) {
|
||||
const { row, col, color } = chessPiece;
|
||||
let movePos = [];
|
||||
let i = row,
|
||||
j = col;
|
||||
while (inBoard(++i, j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(--i, j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(i, ++j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(i, --j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(++i, ++j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(++i, --j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(--i, ++j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
i = row;
|
||||
j = col;
|
||||
while (inBoard(--i, --j) && !isBlocked(chessBoard, chessPiece, i, j)) {
|
||||
movePos.push({ row: i, col: j });
|
||||
if (isAttacking(chessBoard, chessPiece, i, j)) break;
|
||||
}
|
||||
|
||||
return { movePos };
|
||||
}
|
||||
|
||||
function getKingHint(chessBoard, chessPiece, myColor) {
|
||||
const { row, col } = chessPiece;
|
||||
let movePos = [];
|
||||
|
||||
if (inBoard(row, col + 1) && !isBlocked(chessBoard, chessPiece, row, col + 1))
|
||||
movePos.push({ row: row, col: col + 1 });
|
||||
if (inBoard(row, col - 1) && !isBlocked(chessBoard, chessPiece, row, col - 1))
|
||||
movePos.push({ row: row, col: col - 1 });
|
||||
if (inBoard(row + 1, col + 1) && !isBlocked(chessBoard, chessPiece, row + 1, col + 1))
|
||||
movePos.push({ row: row + 1, col: col + 1 });
|
||||
if (inBoard(row + 1, col) && !isBlocked(chessBoard, chessPiece, row + 1, col))
|
||||
movePos.push({ row: row + 1, col: col });
|
||||
if (inBoard(row + 1, col - 1) && !isBlocked(chessBoard, chessPiece, row + 1, col - 1))
|
||||
movePos.push({ row: row + 1, col: col - 1 });
|
||||
if (inBoard(row - 1, col + 1) && !isBlocked(chessBoard, chessPiece, row - 1, col + 1))
|
||||
movePos.push({ row: row - 1, col: col + 1 });
|
||||
if (inBoard(row - 1, col) && !isBlocked(chessBoard, chessPiece, row - 1, col))
|
||||
movePos.push({ row: row - 1, col: col });
|
||||
if (inBoard(row - 1, col - 1) && !isBlocked(chessBoard, chessPiece, row - 1, col - 1))
|
||||
movePos.push({ row: row - 1, col: col - 1 });
|
||||
|
||||
return { movePos };
|
||||
}
|
||||
|
||||
export function getPieceHint(chessBoard, chessPiece, myColor) {
|
||||
switch (chessPiece.type) {
|
||||
case pawn:
|
||||
return getPawnHint(chessBoard, chessPiece, myColor);
|
||||
case rook:
|
||||
return getRookHint(chessBoard, chessPiece, myColor);
|
||||
case knight:
|
||||
return getKnightHint(chessBoard, chessPiece, myColor);
|
||||
case bishop:
|
||||
return getBishopHint(chessBoard, chessPiece, myColor);
|
||||
case queen:
|
||||
return getQueenHint(chessBoard, chessPiece, myColor);
|
||||
case king:
|
||||
return getKingHint(chessBoard, chessPiece, myColor);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||