base_rules.js refactoring. draft state (untested)
[xogo.git] / variants / Benedict / class.js
index e08a79c..bf15ee6 100644 (file)
@@ -6,15 +6,22 @@ export default class BenedictRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: [],
-      styles: (
-        C.Options.styles.filter(s => {
-          return (
-            ["balance", "cylinder", "dark", "doublemove", "progressive", "zen"]
-            .includes(s)
-          );
-        })
-      )
+      input: [
+        {
+          label: "Cleopatra",
+          variable: "cleopatra",
+          type: "checkbox",
+          defaut: false
+        }
+      ],
+      styles: [
+        "balance",
+        "cylinder",
+        "dark",
+        "doublemove",
+        "progressive",
+        "zen"
+      ]
     };
   }
 
@@ -22,77 +29,77 @@ export default class BenedictRules extends ChessRules {
     return false;
   }
 
-  get pawnSpecs() {
-    return Object.assign(
-      {},
-      super.pawnSpecs,
-      { canCapture: false }
-    );
-  }
-
   canTake() {
     return false;
   }
 
-  // Find potential captures from a square
-  // follow steps from x,y until something is met.
-  findAttacks([x, y]) {
-    const [color, piece] = [this.getColor(x, y), this.getPiece(x, y)];
-    const oppCol = C.GetOppCol(color);
-    let squares = {};
-    const specs = this.pieces(color)[piece];
-    const steps = specs.attack || specs.steps;
-    outerLoop: for (let step of steps) {
-      let [i, j] = [x + step[0], this.computeY(y + step[1])];
-      let nbSteps = 1;
-      while (this.onBoard(i, j) && this.board[i][j] == "") {
-        if (specs.range <= nbSteps++) continue outerLoop;
-        i += step[0];
-        j = this.computeY(j + step[1]);
-      }
-      if (this.onBoard(i, j) && this.getColor(i, j) == oppCol)
-        squares[C.CoordsToSquare({x: i, y: j})] = true;
-    }
-    return Object.keys(squares);
+  pieces(color, x, y) {
+    if (!this.options["cleopatra"])
+      return super.pieces(color, x, y);
+    const allSpecs = super.pieces(color, x, y);
+    return Object.assign({},
+      allSpecs,
+      {'q': Object.assign({}, allSpecs['q'], {"class": "cleopatra"})}
+    );
   }
 
   postProcessPotentialMoves(moves) {
-    if (moves.length == 0) return moves;
-    const [x, y] = [moves[0].end.x, moves[0].end.y];
-    const color = this.getColor(moves[0].start.x, moves[0].start.y);
-    const oppCol = C.GetOppCol(color);
-    moves = super.postProcessPotentialMoves(moves);
     moves.forEach(m => {
-      this.playOnBoard(m);
-      let attacks;
-      if (this.options["zen"]) {
-        let endSquares = {};
-        super.getZenCaptures(x, y).forEach(c => {
-          endSquares[C.CoordsToSquare(c.end)] = true;
-        });
-        attacks = Object.keys(endSquares);
+      m.flips = [];
+      if (!this.options["cleopatra"] || m.vanish[0].p == 'q') {
+        super.playOnBoard(m);
+        let attacks = super.findDestSquares(
+          [m.end.x, m.end.y],
+          {attackOnly: true, segments: false},
+          ([x, y] => this.canTake([m.end.x, m.end.y], [x, y]))
+        );
+        if (this.options["zen"]) {
+          const zenAttacks = super.findCapturesOn(
+            [m.end.x, m.end.y],
+            {segments: false},
+            ([x, y] => this.canTake([m.end.x, m.end.y], [x, y]))
+          );
+          Array.prototype.push.apply(attacks, zenAttacks);
+        }
+        super.undoOnBoard(m);
+        attacks.forEach(a => m.flips.push({x: a.sq[0], y: a.sq[1]}));
       }
-      else attacks = this.findAttacks([m.end.x, m.end.y])
-      this.undoOnBoard(m);
-      attacks.map(C.SquareToCoords).forEach(a => {
-        const p = this.getPiece(a.x, a.y);
-        m.appear.push(new PiPo({x: a.x, y: a.y, c: color, p: p}));
-        m.vanish.push(new PiPo({x: a.x, y: a.y, c: oppCol, p: p}));
-      });
     });
     return moves;
   }
 
-  // Moves cannot flip our king's color, so (almost) all are valid
+  playOnBoard(move) {
+    super.playOnBoard(move);
+    this.flipColorOf(move.flips);
+  }
+  undoOnBoard(move) {
+    super.undoOnBoard(move);
+    this.flipColorOf(move.flips);
+  }
+
+  flipColorOf(flips) {
+    for (let xy of flips) {
+      const newColor = C.GetOppCol(this.getColor(xy.x, xy.y));
+      this.board[xy.x][xy.y] = newColor + this.board[xy.x][xy.y][1];
+    }
+  }
+
+  // Moves cannot flip our king's color, so all are valid
   filterValid(moves) {
-    if (this.options["balance"] && [1, 3].includes(this.movesCount))
-      return moves.filter(m => m.vanish.every(v => v.p != C.KING));
     return moves;
   }
 
-  // Since it's used just for the king, and there are no captures:
-  underCheck(square, color) {
+  // A king under (regular) check flips color, and the game is over.
+  underCheck() {
     return false;
   }
 
+  playVisual(move, r) {
+    super.playVisual(move, r);
+    move.flips.forEach(f => {
+      this.g_pieces[f.x][f.y].classList.toggle("white");
+      this.g_pieces[f.x][f.y].classList.toggle("black");
+    });
+  }
+
 };