fix: can make moves after undo

This commit is contained in:
Cozma Rares
2023-08-17 22:30:47 +03:00
parent e51bbcd36c
commit 9d87a344c3
7 changed files with 71 additions and 30 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
NODE_ENV=development
PORT=5000
ID_LENGTH=10
ID_LENGTH=8
+3 -2
View File
@@ -13,15 +13,16 @@ const ChessUI: React.FC<InferProps<[typeof ChessBoard, typeof History]>> = (
const [showModal, setShowModal] = useState(true);
const navigate = useNavigate();
const chess = props.chess;
const currentChess = chess.getCurrentBoardPosition();
return (
<>
<div className="w-screen h-screen flex items-center justify-center">
<div className="m-4 flex flex-row gap-4">
<ChessBoard
key={`${props.blackPerspective}` + chess.getFEN()}
key={`${props.blackPerspective}` + currentChess.getFEN()}
{...props}
chess={chess.getCurrentBoardPosition()}
chess={currentChess}
disabled={(props.disabled ?? false) || chess.isGameOver()}
/>
<History {...props} />
+19 -10
View File
@@ -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 = <HalfStar />;
tileProps[kings[COLOR.WHITE]].EndGameIcon = <HalfStar />;
tileProps[kings[COLOR.BLACK]].endGameIcon = <HalfStar />;
tileProps[kings[COLOR.WHITE]].endGameIcon = <HalfStar />;
} else {
const loser = chess.getTurn(),
winner = swapColor(loser);
tileProps[kings[winner]].EndGameIcon = <Crown />;
tileProps[kings[loser]].EndGameIcon = <Hashtag />;
tileProps[kings[winner]].endGameIcon = <Crown />;
tileProps[kings[loser]].endGameIcon = <Hashtag />;
}
}
@@ -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"
/>
)}
<Show when={EndGameIcon != undefined}>
<Show when={endGameIcon != undefined}>
<div className="absolute top-0 left-full -translate-x-1/2 -translate-y-1/2 bg-white z-10 rounded-full p-1 shadow-lg shadow-black aspect-square flex justify-center items-center">
{EndGameIcon}
{endGameIcon}
</div>
</Show>
<Show when={isAttacked}>
+1 -1
View File
@@ -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();
+1 -2
View File
@@ -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}
/>
</Show>
+45 -13
View File
@@ -509,7 +509,9 @@ export default class Chess {
private _moves: Array<InternalMove> = [];
private _attacks: Array<number> = [];
private _history: Array<Readonly<{ fen: string; san: string }>> = [];
private _history: Array<
Readonly<{ fen: string; san: string; move: InternalMove }>
> = [];
private _boardPositionCounter = new Map<string, number>();
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<string, number>();
this._history.forEach(({ fen }) => this._incrementPositionCounter(fen));
this._processBoardState();
}
getTurn() {
return this._turn;
}
+1 -1
View File
@@ -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);