Add Tencubed and Omega variants + some fixes (updateCastleFlags()) + cleaner FEN...
[vchess.git] / client / src / base_rules.js
index d35a918..1a4a32d 100644 (file)
@@ -47,7 +47,9 @@ export const ChessRules = class ChessRules {
   static get PawnSpecs() {
     return {
       directions: { 'w': -1, 'b': 1 },
+      initShift: { w: 1, b: 1 },
       twoSquares: true,
+      threeSquares: false,
       promotions: [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN],
       canCapture: true,
       captureBackward: false,
@@ -164,6 +166,7 @@ export const ChessRules = class ChessRules {
     return !!flags.match(/^[a-z]{4,4}$/);
   }
 
+  // NOTE: not with regexp to adapt to different board sizes. (TODO?)
   static IsGoodEnpassant(enpassant) {
     if (enpassant != "-") {
       const ep = V.SquareToCoords(enpassant);
@@ -721,7 +724,6 @@ export const ChessRules = class ChessRules {
     const [sizeX, sizeY] = [V.size.x, V.size.y];
     const pawnShiftX = V.PawnSpecs.directions[color];
     const firstRank = (color == "w" ? sizeX - 1 : 0);
-    const startRank = (color == "w" ? sizeX - 2 : 1);
 
     // Pawn movements in shiftX direction:
     const getPawnMoves = (shiftX) => {
@@ -734,11 +736,23 @@ export const ChessRules = class ChessRules {
           // Next condition because pawns on 1st rank can generally jump
           if (
             V.PawnSpecs.twoSquares &&
-            [startRank, firstRank].includes(x) &&
-            this.board[x + 2 * shiftX][y] == V.EMPTY
+            (
+              (color == 'w' && x >= V.size.x - 1 - V.PawnSpecs.initShift['w'])
+              ||
+              (color == 'b' && x <= V.PawnSpecs.initShift['b'])
+            )
           ) {
-            // Two squares jump
-            moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
+            if (this.board[x + 2 * shiftX][y] == V.EMPTY) {
+              // Two squares jump
+              moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
+              if (
+                V.PawnSpecs.threeSquares &&
+                this.board[x + 3 * shiftX][y] == V.EMPTY
+              ) {
+                // Three squares jump
+                moves.push(this.getBasicMove([x, y], [x + 3 * shiftX, y]));
+              }
+            }
           }
         }
         // Captures
@@ -862,7 +876,9 @@ export const ChessRules = class ChessRules {
       i = y;
       do {
         if (
-          (!castleInCheck && this.isAttacked([x, i], oppCol)) ||
+          // NOTE: "castling" arg is used by some variants (Monster),
+          // where "isAttacked" is overloaded in an infinite-recursive way.
+          (!castleInCheck && this.isAttacked([x, i], oppCol, "castling")) ||
           (this.board[x][i] != V.EMPTY &&
             // NOTE: next check is enough, because of chessboard constraints
             (this.getColor(x, i) != c ||
@@ -882,9 +898,12 @@ export const ChessRules = class ChessRules {
       // Nothing on final squares, except maybe king and castling rook?
       for (i = 0; i < 2; i++) {
         if (
+          finalSquares[castleSide][i] != rookPos &&
           this.board[x][finalSquares[castleSide][i]] != V.EMPTY &&
-          this.getPiece(x, finalSquares[castleSide][i]) != V.KING &&
-          finalSquares[castleSide][i] != rookPos
+          (
+            this.getPiece(x, finalSquares[castleSide][i]) != V.KING ||
+            this.getColor(x, finalSquares[castleSide][i]) != c
+          )
         ) {
           continue castlingCheck;
         }
@@ -942,9 +961,7 @@ export const ChessRules = class ChessRules {
     });
   }
 
-  // Search for all valid moves considering current turn
-  // (for engine and game end)
-  getAllValidMoves() {
+  getAllPotentialMoves() {
     const color = this.turn;
     let potentialMoves = [];
     for (let i = 0; i < V.size.x; i++) {
@@ -957,7 +974,13 @@ export const ChessRules = class ChessRules {
         }
       }
     }
-    return this.filterValid(potentialMoves);
+    return potentialMoves;
+  }
+
+  // Search for all valid moves considering current turn
+  // (for engine and game end)
+  getAllValidMoves() {
+    return this.filterValid(this.getAllPotentialMoves());
   }
 
   // Stop at the first move found
@@ -1149,7 +1172,6 @@ export const ChessRules = class ChessRules {
     if (piece == V.KING && move.appear.length > 0) {
       this.kingPos[c][0] = move.appear[0].x;
       this.kingPos[c][1] = move.appear[0].y;
-      return;
     }
     if (V.HasCastle) this.updateCastleFlags(move, piece);
   }