Attempt to clarify installation instructions a little
[vchess.git] / client / src / variants / Switching.js
index 04bb110..8cb3141 100644 (file)
@@ -1,41 +1,35 @@
-class SwitchingRules extends ChessRules
-{
-       // Build switch move between squares x1,y1 and x2,y2
-       getSwitchMove_s([x1,y1],[x2,y2])
-       {
-               const c = this.getColor(x1,y1); //same as color at square 2
-               const p1 = this.getPiece(x1,y1);
-               const p2 = this.getPiece(x2,y2);
-               if (p1 == V.KING && p2 == V.ROOK)
-                       return []; //avoid duplicate moves (potential conflict with castle)
+import { ChessRules, Move, PiPo } from "@/base_rules";
+
+export class SwitchingRules extends ChessRules {
+
+  // Build switch move between squares x1,y1 and x2,y2
+       getSwitchMove_s([x1, y1], [x2, y2]) {
+               const c = this.getColor(x1, y1); //same as color at square 2
+               const p1 = this.getPiece(x1, y1);
+               const p2 = this.getPiece(x2, y2);
                let move = new Move({
                        appear: [
-                               new PiPo({x:x2,y:y2,c:c,p:p1}),
-                               new PiPo({x:x1,y:y1,c:c,p:p2})
+                               new PiPo({ x: x2, y: y2, c: c, p: p1 }),
+                               new PiPo({ x: x1, y: y1, c: c, p: p2 })
                        ],
                        vanish: [
-                               new PiPo({x:x1,y:y1,c:c,p:p1}),
-                               new PiPo({x:x2,y:y2,c:c,p:p2})
-                       ],
-                       start: {x:x1,y:y1},
-                       end: {x:x2,y:y2}
+                               new PiPo({ x: x1, y: y1, c: c, p: p1 }),
+                               new PiPo({ x: x2, y: y2, c: c, p: p2 })
+                       ]
                });
                // Move completion: promote switched pawns (as in Magnetic)
-               const lastRank = (c == "w" ? 0 : V.size.x-1);
+               const lastRank = (c == "w" ? 0 : V.size.x - 1);
                let moves = [];
-               if ((p1==V.PAWN && x2==lastRank) || (p2==V.PAWN && x1==lastRank))
-               {
-                       const idx = (p1==V.PAWN ? 0 : 1);
+               if ((p1 == V.PAWN && x2 == lastRank) || (p2 == V.PAWN && x1 == lastRank)) {
+                       const idx = (p1 == V.PAWN ? 0 : 1);
                        move.appear[idx].p = V.ROOK;
                        moves.push(move);
-                       for (let piece of [V.KNIGHT, V.BISHOP, V.QUEEN])
-                       {
+                       for (let piece of [V.KNIGHT, V.BISHOP, V.QUEEN]) {
                                let cmove = JSON.parse(JSON.stringify(move));
                                cmove.appear[idx].p = piece;
                                moves.push(cmove);
                        }
-                       if (idx == 1)
-                       {
+                       if (idx == 1) {
                                // Swap moves[i].appear[0] and [1] for moves presentation [TODO...]
                                moves.forEach(m => {
                                        let tmp = m.appear[0];
@@ -44,92 +38,91 @@ class SwitchingRules extends ChessRules
                                });
                        }
                }
-               else //other cases
+               else
+      // Other cases
                        moves.push(move);
                return moves;
        }
 
-       getPotentialMovesFrom([x,y], computer)
-       {
+       getPotentialMovesFrom([x,y]) {
                let moves = super.getPotentialMovesFrom([x,y]);
-               // Add switches: respecting chessboard ordering if "computer" is on
-               const color = this.turn;
                const piece = this.getPiece(x,y);
-               const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
-               const kp = this.kingPos[color];
-               const oppCol = V.GetOppCol(color);
-               for (let step of steps)
-               {
-                       let [i,j] = [x+step[0],y+step[1]];
-                       if (!!computer && (i<x || (i==x && j<y)))
-                               continue; //only switch with superior indices
-                       if (V.OnBoard(i,j) && this.board[i][j]!=V.EMPTY
-                               && this.getColor(i,j)==color && this.getPiece(i,j)!=piece
-                               // No switching under check (theoretically non-king pieces could, but not)
-                               && !this.isAttacked(kp, [oppCol]))
-                       {
-                               let switchMove_s = this.getSwitchMove_s([x,y],[i,j]);
-                               if (switchMove_s.length == 1)
-                                       moves.push(switchMove_s[0]);
-                               else //promotion
-                                       moves = moves.concat(switchMove_s);
-                       }
-               }
+    const color = this.turn;
+    const oppCol = V.GetOppCol(color);
+    const kp = this.kingPos[color];
+               // Add switches (if not under check, from anything but the king)
+               if (piece != V.KING && !this.isAttacked(kp, oppCol)) {
+      const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
+      for (let step of steps) {
+        const [i, j] = [x+step[0], y+step[1]];
+        if (
+          V.OnBoard(i, j) &&
+          this.board[i][j] != V.EMPTY &&
+          this.getColor(i,j) == color &&
+          this.getPiece(i,j) != piece
+        ) {
+          const switchMove_s = this.getSwitchMove_s([x,y], [i,j]);
+          Array.prototype.push.apply(moves, switchMove_s);
+        }
+      }
+    }
                return moves;
        }
 
-       getAllValidMoves(computer)
-       {
-               const color = this.turn;
-               const oppCol = V.GetOppCol(color);
-               let potentialMoves = [];
-               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 && this.getColor(i,j) == color)
-                               {
-                                       Array.prototype.push.apply(potentialMoves,
-                                               this.getPotentialMovesFrom([i,j], computer));
-                               }
-                       }
-               }
-               return this.filterValid(potentialMoves);
+       postPlay(move) {
+    // Did some king move?
+    move.appear.forEach(a => {
+      if (a.p == V.KING) {
+        this.kingPos[a.c] = [a.x, a.y];
+        this.castleFlags[a.c] = [V.size.y, V.size.y];
+      }
+    });
+    const firstRank = (move.vanish[0].c == 'w' ? 7 : 0);
+    for (let coords of [move.start, move.end]) {
+      if (
+        Object.keys(firstRank).includes(coords.x) &&
+        this.castleFlags[firstRank[coords.x]].includes(coords.y)
+      ) {
+        const c = firstRank[coords.x];
+        const flagIdx = (coords.y == this.castleFlags[c][0] ? 0 : 1);
+        this.castleFlags[c][flagIdx] = V.size.y;
+      }
+    }
        }
 
-       updateVariables(move)
-       {
-               super.updateVariables(move);
-               if (move.appear.length == 2 && move.vanish.length == 2
-                       && move.appear[1].p == V.KING)
-               {
-                       // Switch with the king; not castle, and not handled by main class
-                       const color = move.vanish[0].c;
-                       this.kingPos[color] = [move.appear[1].x, move.appear[1].y];
-               }
+       postUndo(move) {
+    // Did some king move?
+    move.vanish.forEach(v => {
+      if (v.p == V.KING) this.kingPos[v.c] = [v.x, v.y];
+    });
        }
 
-       unupdateVariables(move)
-       {
-               super.unupdateVariables(move);
-               if (move.appear.length == 2 && move.vanish.length == 2
-                       && move.appear[1].p == V.KING)
-               {
-                       const color = move.vanish[0].c;
-                       this.kingPos[color] = [move.appear[0].x, move.appear[0].y];
-               }
-       }
+       static get SEARCH_DEPTH() {
+    // Branching factor is quite high
+    return 2;
+  }
 
-       static get SEARCH_DEPTH() { return 2; } //high branching factor
+  getAllPotentialMoves() {
+    // Since this function is used only for computer play,
+    // remove duplicate switches:
+    return super.getAllPotentialMoves().filter(m => {
+      return (
+        m.appear.length == 1 ||
+        (m.appear[0].p == V.KING && m.appear[1].p == V.ROOK) ||
+        (m.appear[1].x <= m.vanish[1].x && m.appear[1].y <= m.vanish[1].y)
+      );
+    });
+  }
 
-       getNotation(move)
-       {
-               if (move.appear.length == 1)
-                       return super.getNotation(move); //no switch
-               // Switch or castle
-               if (move.appear[0].p == V.KING && move.appear[1].p == V.ROOK)
-                       return (move.end.y < move.start.y ? "0-0-0" : "0-0");
-               // Switch:
-               return "S" + V.CoordsToSquare(move.start) + V.CoordsToSquare(move.end);
-       }
-}
+  getNotation(move) {
+    if (move.appear.length == 1)
+      // Normal move
+      return super.getNotation(move);
+    if (move.appear[0].p == V.KING && move.appear[1].p == V.ROOK)
+      // Castle
+      return (move.end.y < move.start.y ? "0-0-0" : "0-0");
+    // Switch
+    return "S" + V.CoordsToSquare(move.start) + V.CoordsToSquare(move.end);
+  }
+
+};