From 9d87a344c34e8e9d3430477ca784efdafc2ae511 Mon Sep 17 00:00:00 2001 From: Cozma Rares Date: Thu, 17 Aug 2023 22:30:47 +0300 Subject: [PATCH] fix: can make moves after undo --- .env.example | 2 +- client/src/components/ChessUI.tsx | 5 ++- client/src/components/Chessboard.tsx | 29 +++++++++----- client/src/routes/LocalGame.tsx | 2 +- client/src/routes/OnlineGame.tsx | 3 +- server/src/engine.ts | 58 +++++++++++++++++++++------- server/src/server.ts | 2 +- 7 files changed, 71 insertions(+), 30 deletions(-) diff --git a/.env.example b/.env.example index 2eda92f..8c69e7e 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,3 @@ NODE_ENV=development PORT=5000 -ID_LENGTH=10 +ID_LENGTH=8 diff --git a/client/src/components/ChessUI.tsx b/client/src/components/ChessUI.tsx index eb62cb9..82c27f7 100644 --- a/client/src/components/ChessUI.tsx +++ b/client/src/components/ChessUI.tsx @@ -13,15 +13,16 @@ const ChessUI: React.FC> = ( const [showModal, setShowModal] = useState(true); const navigate = useNavigate(); const chess = props.chess; + const currentChess = chess.getCurrentBoardPosition(); return ( <>
diff --git a/client/src/components/Chessboard.tsx b/client/src/components/Chessboard.tsx index cdd0854..bddeefa 100644 --- a/client/src/components/Chessboard.tsx +++ b/client/src/components/Chessboard.tsx @@ -57,9 +57,18 @@ const ChessBoard: React.FC<{ isAttacked: false, isPromotion: false, isActive: false, - EndGameIcon: undefined, + endGameIcon: undefined, })); + const lastMove = chess.getHistory().history.at(-1)?.move; + console.log(chess.getHistory().history.at(-1)); + + if (lastMove) { + console.log(lastMove); + tileProps[squareIndex(lastMove.from)].isActive = true; + tileProps[squareIndex(lastMove.to)].isActive = true; + } + if (activeTile != -1) { tileProps[activeTile].isActive = true; chess.getMovesForSquare(activeTile).forEach(({ to, flags }) => { @@ -72,13 +81,13 @@ const ChessBoard: React.FC<{ if (chess.isGameOver()) { const kings = chess.getKings(); if (chess.isDraw()) { - tileProps[kings[COLOR.BLACK]].EndGameIcon = ; - tileProps[kings[COLOR.WHITE]].EndGameIcon = ; + tileProps[kings[COLOR.BLACK]].endGameIcon = ; + tileProps[kings[COLOR.WHITE]].endGameIcon = ; } else { const loser = chess.getTurn(), winner = swapColor(loser); - tileProps[kings[winner]].EndGameIcon = ; - tileProps[kings[loser]].EndGameIcon = ; + tileProps[kings[winner]].endGameIcon = ; + tileProps[kings[loser]].endGameIcon = ; } } @@ -93,7 +102,7 @@ const ChessBoard: React.FC<{ if (isNaN(tile)) return; - if (!chess.didUndo() && activeTile != -1 && tileProps[tile].isAttacked) { + if (activeTile != -1 && tileProps[tile].isAttacked) { const moveObj = { from: algebraic(activeTile), to: algebraic(tile), @@ -180,14 +189,14 @@ const Tile: React.FC<{ isActive: boolean; isAttacked: boolean; blackPerspective?: boolean; - EndGameIcon?: ReactNode; + endGameIcon?: ReactNode; }> = ({ tileNumber, piece, isActive, isAttacked, blackPerspective, - EndGameIcon, + endGameIcon, }) => { const color = squareColor(tileNumber); @@ -216,9 +225,9 @@ const Tile: React.FC<{ className="max-w-full max-h-full aspect-square" /> )} - +
- {EndGameIcon} + {endGameIcon}
diff --git a/client/src/routes/LocalGame.tsx b/client/src/routes/LocalGame.tsx index cc004b3..13a692c 100644 --- a/client/src/routes/LocalGame.tsx +++ b/client/src/routes/LocalGame.tsx @@ -20,7 +20,7 @@ const LocalGame = () => { const rerender = () => aux((prev) => !prev); const makeMove = (move: Move) => { - if (chess.didUndo()) return; + if (chess.didUndo()) chess.undoMoves(); chess.makeMove(move); rerender(); diff --git a/client/src/routes/OnlineGame.tsx b/client/src/routes/OnlineGame.tsx index 99f7f57..42605ee 100644 --- a/client/src/routes/OnlineGame.tsx +++ b/client/src/routes/OnlineGame.tsx @@ -7,7 +7,6 @@ import { socket } from "../utils/socket"; import { CaretLeft, CaretRight, CopyIcon } from "../components/icons"; import Show from "../utils/Show"; import ErrorNorification from "../components/ErrorNotification"; -import Modal, { ModalButton } from "../components/Modal"; import ChessUI from "../components/ChessUI"; import { removeLocationState } from "../utils/utils"; import InferProps from "../utils/InferProps"; @@ -106,7 +105,7 @@ const Game = () => { chess={chess} makeMove={makeMove} blackPerspective={color === COLOR.BLACK} - disabled={color !== chess.getTurn()} + disabled={color !== chess.getTurn() || chess.didUndo()} buttons={buttons} /> diff --git a/server/src/engine.ts b/server/src/engine.ts index 810478d..1a052f8 100644 --- a/server/src/engine.ts +++ b/server/src/engine.ts @@ -509,7 +509,9 @@ export default class Chess { private _moves: Array = []; private _attacks: Array = []; - private _history: Array> = []; + private _history: Array< + Readonly<{ fen: string; san: string; move: InternalMove }> + > = []; private _boardPositionCounter = new Map(); private _undoCount = 0; @@ -600,19 +602,26 @@ export default class Chess { } } - private _getPositionCounter() { - const trimFEN = this.getFEN(true); + private _trimFEN(fen: string) { + const split = fen.split(" "); + return split.splice(0, 4).join(" "); + } + + private _getPositionCounter(fen: string) { + const trimFEN = this._trimFEN(fen); return this._boardPositionCounter.get(trimFEN) ?? 0; } + private _incrementPositionCounter(fen: string) { + const trimFEN = this._trimFEN(fen); + const counter = this._boardPositionCounter.get(trimFEN) ?? 0; + this._boardPositionCounter.set(trimFEN, counter + 1); + } + private _processBoardState() { this._computeMoves(); - if (this._enableHistory) { - const trimFEN = this.getFEN(true); - const counter = this._boardPositionCounter.get(trimFEN) ?? 0; - this._boardPositionCounter.set(trimFEN, counter + 1); - } + if (this._enableHistory) this._incrementPositionCounter(this.getFEN()); } private static _load( @@ -660,7 +669,7 @@ export default class Chess { return this._load(fen, { enableProcessMoves: true, enableHistory: true }); } - getFEN(trim = false) { + getFEN() { let position = ""; let emptySquares = 0; @@ -702,10 +711,10 @@ export default class Chess { this._turn, castling, this._enPassant, + this._halfMoves, + this._fullMoves, ]; - if (!trim) arr.push(this._halfMoves, this._fullMoves); - return arr.join(" "); } @@ -752,6 +761,7 @@ export default class Chess { this._history.push({ fen: this.getFEN(), san: this._generateSan(move), + move, }); this._board[squareIndex(move.to)] = @@ -998,7 +1008,7 @@ export default class Chess { } isThreefoldRepetition() { - return this._getPositionCounter() >= 3; + return this._getPositionCounter(this.getFEN()) >= 3; } is50Rule() { @@ -1041,11 +1051,33 @@ export default class Chess { enableHistory: false, enableProcessMoves: true, }); - chess._undoCount = this._undoCount; + chess._undoCount = 0; + chess._history = this._history.slice( + 0, + this._history.length - this._undoCount + ); return chess; } + undoMoves() { + const chess = this.getCurrentBoardPosition(); + + this._board = chess._board; + this._turn = chess._turn; + this._castling = chess._castling; + this._enPassant = chess._enPassant; + this._halfMoves = chess._halfMoves; + this._fullMoves = chess._fullMoves; + this._kings = chess._kings; + this._history = chess._history; + this._undoCount = 0; + this._boardPositionCounter = new Map(); + this._history.forEach(({ fen }) => this._incrementPositionCounter(fen)); + + this._processBoardState(); + } + getTurn() { return this._turn; } diff --git a/server/src/server.ts b/server/src/server.ts index b5d3d1c..7b9eedb 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -9,7 +9,7 @@ import { nanoid as nanoidOriginal } from "nanoid"; dotenv.config(); const ID_LENGTH = isNaN(parseInt(process.env.ID_LENGTH!)) - ? 10 + ? 8 : parseInt(process.env.ID_LENGTH!); const nanoid = () => nanoidOriginal(ID_LENGTH);