Several small improvements + integrate options + first working draft of Cwda
[vchess.git] / client / src / variants / Zen.js
index f5bff8f..bfbc7e2 100644 (file)
@@ -1,34 +1,37 @@
 import { ChessRules } from "@/base_rules";
 
-export const VariantRules = class ZenRules extends ChessRules {
-  // NOTE: enPassant, if enabled, would need to redefine carefully getEpSquare
-  static get HasEnpassant() {
-    return false;
-  }
-
-  // TODO(?): some duplicated code in 2 next functions
-  getSlideNJumpMoves([x, y], steps, oneStep) {
-    let moves = [];
-    outerLoop: for (let loop = 0; loop < steps.length; loop++) {
-      const step = steps[loop];
-      let i = x + step[0];
-      let j = y + step[1];
-      while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
-        moves.push(this.getBasicMove([x, y], [i, j]));
-        if (oneStep) continue outerLoop;
-        i += step[0];
-        j += step[1];
-      }
-      // No capture check: handled elsewhere (next method)
+export class ZenRules extends ChessRules {
+
+  getEpSquare(moveOrSquare) {
+    if (!moveOrSquare) return undefined;
+    if (typeof moveOrSquare === "string") {
+      const square = moveOrSquare;
+      if (square == "-") return undefined;
+      return V.SquareToCoords(square);
     }
-    return moves;
+    const move = moveOrSquare;
+    const s = move.start,
+          e = move.end;
+    if (
+      // Exclude captures (of rooks for example)
+      move.vanish.length == 1 &&
+      s.y == e.y &&
+      Math.abs(s.x - e.x) == 2 &&
+      move.appear[0].p == V.PAWN
+    ) {
+      return {
+        x: (s.x + e.x) / 2,
+        y: s.y
+      };
+    }
+    return undefined;
   }
 
   // follow steps from x,y until something is met.
   // if met piece is opponent and same movement (asA): eat it!
   findCaptures_aux([x, y], asA) {
     const color = this.getColor(x, y);
-    var moves = [];
+    let moves = [];
     const steps =
       asA != V.PAWN
         ? asA == V.QUEEN
@@ -43,9 +46,10 @@ export const VariantRules = class ZenRules extends ChessRules {
             [1, -1],
             [1, 1]
           ];
-    const oneStep = asA == V.KNIGHT || asA == V.PAWN; //we don't capture king
+    const oneStep = [V.KNIGHT,V.PAWN].includes(asA); //we don't capture king
     const lastRank = color == "w" ? 0 : V.size.x - 1;
     const promotionPieces = [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN];
+    const oppCol = V.GetOppCol(color);
     outerLoop: for (let loop = 0; loop < steps.length; loop++) {
       const step = steps[loop];
       let i = x + step[0];
@@ -57,7 +61,8 @@ export const VariantRules = class ZenRules extends ChessRules {
       }
       if (
         V.OnBoard(i, j) &&
-        this.getColor(i, j) == V.GetOppCol(color) &&
+        this.board[i][j] != V.EMPTY &&
+        this.getColor(i, j) == oppCol &&
         this.getPiece(i, j) == asA
       ) {
         // eat!
@@ -66,7 +71,8 @@ export const VariantRules = class ZenRules extends ChessRules {
           promotionPieces.forEach(p => {
             moves.push(this.getBasicMove([x, y], [i, j], { c: color, p: p }));
           });
-        } else {
+        }
+        else {
           // All other cases
           moves.push(this.getBasicMove([x, y], [i, j]));
         }
@@ -78,93 +84,20 @@ export const VariantRules = class ZenRules extends ChessRules {
   // Find possible captures from a square: look in every direction!
   findCaptures(sq) {
     let moves = [];
-
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.PAWN));
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.ROOK));
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.KNIGHT));
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.BISHOP));
     Array.prototype.push.apply(moves, this.findCaptures_aux(sq, V.QUEEN));
-
     return moves;
   }
 
-  getPotentialPawnMoves([x, y]) {
-    const color = this.getColor(x, y);
-    let moves = [];
-    const sizeY = V.size.y;
-    const shift = color == "w" ? -1 : 1;
-    const startRank = color == "w" ? sizeY - 2 : 1;
-    const firstRank = color == "w" ? sizeY - 1 : 0;
-    const lastRank = color == "w" ? 0 : sizeY - 1;
-
-    if (x + shift != lastRank) {
-      // Normal moves
-      if (this.board[x + shift][y] == V.EMPTY) {
-        moves.push(this.getBasicMove([x, y], [x + shift, y]));
-        if (
-          [startRank, firstRank].includes(x) &&
-          this.board[x + 2 * shift][y] == V.EMPTY
-        ) {
-          //two squares jump
-          moves.push(this.getBasicMove([x, y], [x + 2 * shift, y]));
-        }
-      }
-    } //promotion
-    else {
-      let promotionPieces = [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN];
-      promotionPieces.forEach(p => {
-        // Normal move
-        if (this.board[x + shift][y] == V.EMPTY)
-          moves.push(
-            this.getBasicMove([x, y], [x + shift, y], { c: color, p: p })
-          );
-      });
-    }
-
-    // No en passant here
-
-    // Add "zen" captures
-    Array.prototype.push.apply(moves, this.findCaptures([x, y]));
-
-    return moves;
-  }
-
-  getPotentialRookMoves(sq) {
-    let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.ROOK]);
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures);
+  canTake() {
+    return false; //captures handled separately
   }
 
-  getPotentialKnightMoves(sq) {
-    let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.KNIGHT], "oneStep");
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures);
-  }
-
-  getPotentialBishopMoves(sq) {
-    let noCaptures = this.getSlideNJumpMoves(sq, V.steps[V.BISHOP]);
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures);
-  }
-
-  getPotentialQueenMoves(sq) {
-    let noCaptures = this.getSlideNJumpMoves(
-      sq,
-      V.steps[V.ROOK].concat(V.steps[V.BISHOP])
-    );
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures);
-  }
-
-  getPotentialKingMoves(sq) {
-    // Initialize with normal moves
-    let noCaptures = this.getSlideNJumpMoves(
-      sq,
-      V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
-      "oneStep"
-    );
-    let captures = this.findCaptures(sq);
-    return noCaptures.concat(captures).concat(this.getCastleMoves(sq));
+  getPotentialMovesFrom(sq) {
+    return super.getPotentialMovesFrom(sq).concat(this.findCaptures(sq));
   }
 
   getNotation(move) {
@@ -175,7 +108,7 @@ export const VariantRules = class ZenRules extends ChessRules {
       return "0-0";
     }
 
-    // Translate initial square (because pieces may fly unusually in this variant!)
+    // Translate initial square (because pieces may fly unusually!)
     const initialSquare = V.CoordsToSquare(move.start);
 
     // Translate final square
@@ -185,15 +118,16 @@ export const VariantRules = class ZenRules extends ChessRules {
     const piece = this.getPiece(move.start.x, move.start.y);
     if (piece == V.PAWN) {
       // pawn move (TODO: enPassant indication)
-      if (move.vanish.length > 1) {
+      if (move.vanish.length == 2) {
         // capture
         notation = initialSquare + "x" + finalSquare;
-      } //no capture
+      }
       else notation = finalSquare;
       if (piece != move.appear[0].p)
         //promotion
         notation += "=" + move.appear[0].p.toUpperCase();
-    } else {
+    }
+    else {
       // Piece movement
       notation = piece.toUpperCase();
       if (move.vanish.length > 1) notation += initialSquare + "x";
@@ -212,4 +146,5 @@ export const VariantRules = class ZenRules extends ChessRules {
       k: 1000
     };
   }
+
 };