Prevent infinite loops for moves input in Pacosako + Otage
authorBenjamin Auder <benjamin.auder@somewhere>
Sun, 17 Jan 2021 01:33:21 +0000 (02:33 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Sun, 17 Jan 2021 01:33:21 +0000 (02:33 +0100)
client/src/variants/Otage.js
client/src/variants/Pacosako.js

index 938ef0e..3e35767 100644 (file)
@@ -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);
   }
 
index 218980c..efc8fd3 100644 (file)
@@ -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);
   }