Fix Convert, start Chaining
[xogo.git] / variants / Chaining / class.js
diff --git a/variants/Chaining/class.js b/variants/Chaining/class.js
new file mode 100644 (file)
index 0000000..5cd4c1d
--- /dev/null
@@ -0,0 +1,117 @@
+import ChessRules from "/base_rules.js";
+import PiPo from "/utils/PiPo.js";
+import Move from "/utils/Move.js";
+
+export default class ChainingRules extends ChessRules {
+
+  static get Options() {
+    return {
+      select: C.Options.select,
+      input: C.Options.input,
+      styles: ["atomic", "capture", "crazyhouse", "cylinder", "dark", "zen"]
+    };
+  }
+
+  get hasSelfCaptures() {
+    return true;
+  }
+
+  canSelfTake() {
+    return true; //self captures induce chaining
+  }
+
+  setOtherVariables(fenParsed, pieceArray) {
+    super.setOtherVariables(fenParsed, pieceArray);
+    // Stack of "last move" only for intermediate chaining
+    this.lastMoveEnd = [];
+  }
+
+  getBasicMove([sx, sy], [ex, ey], tr) {
+    const L = this.lastMoveEnd.length;
+    const piece = (L >= 1 ? this.lastMoveEnd[L-1].p : null);
+    if (
+      this.board[ex][ey] == "" ||
+      this.getColor(ex, ey) == C.GetOppTurn(this.turn)
+    ) {
+      if (piece && !tr)
+        tr = {c: this.turn, p: piece};
+      let mv = super.getBasicMove([sx, sy], [ex, ey], tr);
+      if (piece)
+        mv.vanish.pop(); //end of a chain: initial piece remains
+      return mv;
+    }
+    // (Self)Capture: initial, or inside a chain
+    const initPiece = (piece || this.getPiece(sx, sy)),
+          destPiece = this.getPiece(ex, ey);
+    let mv = new Move({
+      start: {x: sx, y: sy},
+      end: {x: ex, y: ey},
+      appear: [
+        new PiPo({
+          x: ex,
+          y: ey,
+          c: this.turn,
+          p: (!!tr ? tr.p : initPiece)
+        })
+      ],
+      vanish: [
+        new PiPo({
+          x: ex,
+          y: ey,
+          c: this.turn,
+          p: destPiece
+        })
+      ]
+    });
+    if (!piece) {
+      // Initial capture
+      mv.vanish.unshift(
+        new PiPo({
+          x: sx,
+          y: sy,
+          c: this.turn,
+          p: initPiece
+        })
+      );
+    }
+    mv.chained = destPiece; //easier (no need to detect it)
+    return mv;
+  }
+
+  getPiece(x, y) {
+    const L = this.lastMoveEnd.length;
+    if (L >= 1 && this.lastMoveEnd[L-1].x == x && this.lastMoveEnd[L-1].y == y)
+      return this.lastMoveEnd[L-1].p;
+    return super.getPiece(x, y);
+  }
+
+  getPotentialMovesFrom([x, y], color) {
+    const L = this.lastMoveEnd.length;
+    if (
+      L >= 1 &&
+      (x != this.lastMoveEnd[L-1].x || y != this.lastMoveEnd[L-1].y)
+    ) {
+      // A self-capture was played: wrong square
+      return [];
+    }
+    return super.getPotentialMovesFrom([x, y], color);
+  }
+
+  isLastMove(move) {
+    return !move.chained;
+  }
+
+  postPlay(move) {
+    super.postPlay(move);
+    if (!!move.converted) {
+      this.lastMoveEnd.push({
+        x: move.end.x,
+        y: move.end.y,
+        p: move.chained
+      });
+    }
+    else
+      this.lastMoveEnd = [];
+  }
+
+};