Bug fixes
[vchess.git] / client / src / variants / Checkered.js
index e930fb8..1e42d99 100644 (file)
@@ -37,7 +37,7 @@ export const VariantRules = class CheckeredRules extends ChessRules {
   }
 
   getPpath(b) {
-    return b[0] == "c" ? "Checkered/" + b : b;
+    return (b[0] == "c" ? "Checkered/" : "") + b;
   }
 
   setOtherVariables(fen) {
@@ -90,6 +90,13 @@ export const VariantRules = class CheckeredRules extends ChessRules {
     this.pawnFlags = flags[1];
   }
 
+  getEpSquare(moveOrSquare) {
+    if (typeof moveOrSquare !== "object" || moveOrSquare.appear[0].c != 'c')
+      return super.getEpSquare(moveOrSquare);
+    // Checkered move: no en-passant
+    return undefined;
+  }
+
   getCmove(move) {
     if (move.appear[0].c == "c" && move.vanish.length == 1)
       return { start: move.start, end: move.end };
@@ -149,6 +156,77 @@ export const VariantRules = class CheckeredRules extends ChessRules {
     return moves;
   }
 
+  getPotentialPawnMoves([x, y]) {
+    const color = this.turn;
+    let moves = [];
+    const [sizeX, sizeY] = [V.size.x, V.size.y];
+    const shiftX = color == "w" ? -1 : 1;
+    const startRank = color == "w" ? sizeX - 2 : 1;
+    const lastRank = color == "w" ? 0 : sizeX - 1;
+    const pawnColor = this.getColor(x, y); //can be  checkered
+
+    const finalPieces =
+      x + shiftX == lastRank
+        ? [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]
+        : [V.PAWN];
+    if (this.board[x + shiftX][y] == V.EMPTY) {
+      // One square forward
+      for (let piece of finalPieces) {
+        moves.push(
+          this.getBasicMove([x, y], [x + shiftX, y], {
+            c: pawnColor,
+            p: piece
+          })
+        );
+      }
+      if (
+        x == startRank &&
+        this.board[x + 2 * shiftX][y] == V.EMPTY
+      ) {
+        // Two squares jump
+        moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
+      }
+    }
+    // Captures
+    for (let shiftY of [-1, 1]) {
+      if (
+        y + shiftY >= 0 &&
+        y + shiftY < sizeY &&
+        this.board[x + shiftX][y + shiftY] != V.EMPTY &&
+        this.canTake([x, y], [x + shiftX, y + shiftY])
+      ) {
+        for (let piece of finalPieces) {
+          moves.push(
+            this.getBasicMove([x, y], [x + shiftX, y + shiftY], {
+              c: pawnColor,
+              p: piece
+            })
+          );
+        }
+      }
+    }
+
+    // En passant
+    const Lep = this.epSquares.length;
+    const epSquare = this.epSquares[Lep - 1]; //always at least one element
+    if (
+      !!epSquare &&
+      epSquare.x == x + shiftX &&
+      Math.abs(epSquare.y - y) == 1
+    ) {
+      let enpassantMove = this.getBasicMove([x, y], [epSquare.x, epSquare.y]);
+      enpassantMove.vanish.push({
+        x: x,
+        y: epSquare.y,
+        p: "p",
+        c: this.getColor(x, epSquare.y)
+      });
+      moves.push(enpassantMove);
+    }
+
+    return moves;
+  }
+
   canIplay(side, [x, y]) {
     return side == this.turn && [side, "c"].includes(this.getColor(x, y));
   }
@@ -180,6 +258,41 @@ export const VariantRules = class CheckeredRules extends ChessRules {
     });
   }
 
+  getAllValidMoves() {
+    const oppCol = V.GetOppCol(this.turn);
+    let potentialMoves = [];
+    for (let i = 0; i < V.size.x; i++) {
+      for (let j = 0; j < V.size.y; j++) {
+        // NOTE: just testing == color isn't enough because of checkred pieces
+        if (this.board[i][j] != V.EMPTY && this.getColor(i, j) != oppCol) {
+          Array.prototype.push.apply(
+            potentialMoves,
+            this.getPotentialMovesFrom([i, j])
+          );
+        }
+      }
+    }
+    return this.filterValid(potentialMoves);
+  }
+
+  atLeastOneMove() {
+    const oppCol = V.GetOppCol(this.turn);
+    for (let i = 0; i < V.size.x; i++) {
+      for (let j = 0; j < V.size.y; j++) {
+        // NOTE: just testing == color isn't enough because of checkered pieces
+        if (this.board[i][j] != V.EMPTY && this.getColor(i, j) != oppCol) {
+          const moves = this.getPotentialMovesFrom([i, j]);
+          if (moves.length > 0) {
+            for (let k = 0; k < moves.length; k++) {
+              if (this.filterValid([moves[k]]).length > 0) return true;
+            }
+          }
+        }
+      }
+    }
+    return false;
+  }
+
   isAttackedByPawn([x, y], colors) {
     for (let c of colors) {
       const color = c == "c" ? this.turn : c;
@@ -245,23 +358,25 @@ export const VariantRules = class CheckeredRules extends ChessRules {
 
   evalPosition() {
     let evaluation = 0;
-    //Just count material for now, considering checkered neutral (...)
+    // Just count material for now, considering checkered neutral (...)
     for (let i = 0; i < V.size.x; i++) {
       for (let j = 0; j < V.size.y; j++) {
         if (this.board[i][j] != V.EMPTY) {
           const sqColor = this.getColor(i, j);
-          const sign = sqColor == "w" ? 1 : sqColor == "b" ? -1 : 0;
-          evaluation += sign * V.VALUES[this.getPiece(i, j)];
+          if (["w","b"].includes(sqColor)) {
+            const sign = sqColor == "w" ? 1 : -1;
+            evaluation += sign * V.VALUES[this.getPiece(i, j)];
+          }
         }
       }
     }
     return evaluation;
   }
 
-  static GenRandInitFen() {
-    const randFen = ChessRules.GenRandInitFen();
-    // Add 16 pawns flags + empty cmove:
-    return randFen.replace(" w 0 1111", " w 0 11111111111111111111 -");
+  static GenRandInitFen(randomness) {
+    return ChessRules.GenRandInitFen(randomness)
+      // Add 16 pawns flags + empty cmove:
+      .replace(" w 0 1111", " w 0 11111111111111111111 -");
   }
 
   static ParseFen(fen) {
@@ -299,6 +414,10 @@ export const VariantRules = class CheckeredRules extends ChessRules {
     super.undo(move);
   }
 
+  static get SEARCH_DEPTH() {
+    return 2;
+  }
+
   getNotation(move) {
     if (move.appear.length == 2) {
       // Castle