From f3f8470750e91ac7b5bf57a4e01c5791c54b65fb Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Sun, 17 Jan 2021 02:33:21 +0100 Subject: [PATCH] Prevent infinite loops for moves input in Pacosako + Otage --- client/src/variants/Otage.js | 29 ++++++++++++++++++++++++++++- client/src/variants/Pacosako.js | 30 +++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/client/src/variants/Otage.js b/client/src/variants/Otage.js index 938ef0ee..3e35767a 100644 --- a/client/src/variants/Otage.js +++ b/client/src/variants/Otage.js @@ -167,6 +167,7 @@ export class OtageRules extends ChessRules { super.setOtherVariables(fen); // Stack of "last move" only for intermediate chaining this.lastMoveEnd = [null]; + this.repetitions = []; } static IsGoodFlags(flags) { @@ -638,8 +639,24 @@ export class OtageRules extends ChessRules { getCheckSquares() { return []; } + filterValid(moves) { - return moves; + if (moves.length == 0) return []; + return moves.filter(m => { + if (!m.end.released) return true; + // Check for repetitions: + V.PlayOnBoard(this.board, m); + const newState = { piece: m.end.released, position: this.getBaseFen() }; + const repet = + this.repetitions.some(r => { + return ( + r.piece == newState.piece && + r.position == newState.position + ); + }); + V.UndoOnBoard(this.board, m); + return !repet; + }); } updateCastleFlags(move, piece) { @@ -702,6 +719,15 @@ export class OtageRules extends ChessRules { else this.lastMoveEnd.push(Object.assign({ p: move.end.released }, move.end)); V.PlayOnBoard(this.board, move); + if (!move.end.released) this.repetitions = []; + else { + this.repetitions.push( + { + piece: move.end.released, + position: this.getBaseFen() + } + ); + } } undo(move) { @@ -713,6 +739,7 @@ export class OtageRules extends ChessRules { this.turn = V.GetOppCol(this.turn); this.movesCount--; } + if (!!move.end.releasd) this.repetitions.pop(); this.postUndo(move); } diff --git a/client/src/variants/Pacosako.js b/client/src/variants/Pacosako.js index 218980c4..efc8fd38 100644 --- a/client/src/variants/Pacosako.js +++ b/client/src/variants/Pacosako.js @@ -139,6 +139,8 @@ export class PacosakoRules extends ChessRules { end: ChessRules.SquareToCoords(umove.substr(2)) }); } + // Local stack of positions to avoid redundant moves: + this.repetitions = []; } static IsGoodFen(fen) { @@ -705,10 +707,26 @@ export class PacosakoRules extends ChessRules { getCheckSquares() { return []; } + filterValid(moves) { if (moves.length == 0) return []; const L = this.umoves.length; //at least 1: init from FEN - return moves.filter(m => !this.oppositeMoves(this.umoves[L - 1], m)); + return moves.filter(m => { + if (this.oppositeMoves(this.umoves[L - 1], m)) return false; + if (!m.end.released) return true; + // Check for repetitions: + V.PlayOnBoard(this.board, m); + const newState = { piece: m.end.released, position: this.getBaseFen() }; + const repet = + this.repetitions.some(r => { + return ( + r.piece == newState.piece && + r.position == newState.position + ); + }); + V.UndoOnBoard(this.board, m); + return !repet; + }); } updateCastleFlags(move, piece) { @@ -778,6 +796,15 @@ export class PacosakoRules extends ChessRules { } V.PlayOnBoard(this.board, move); this.umoves.push(this.getUmove(move)); + if (!move.end.released) this.repetitions = []; + else { + this.repetitions.push( + { + piece: move.end.released, + position: this.getBaseFen() + } + ); + } } undo(move) { @@ -790,6 +817,7 @@ export class PacosakoRules extends ChessRules { this.movesCount--; } this.umoves.pop(); + if (!!move.end.releasd) this.repetitions.pop(); this.postUndo(move); } -- 2.44.0