Fix Convert, start Chaining
[xogo.git] / variants / Convert / class.js
index 1a006e2..37c2c3d 100644 (file)
@@ -4,15 +4,10 @@ import Move from "/utils/Move.js";
 
 export default class ConvertRules extends ChessRules {
 
-  // TODO
   static get Options() {
     return {
       select: C.Options.select,
-      input: C.Options.input,
-      styles: [
-        "atomic", "cannibal", "capture", "cylinder",
-        "dark", "madrasi", "rifle", "teleport"
-      ]
+      styles: ["cylinder", "dark", "recycle", "teleport"]
     };
   }
 
@@ -23,7 +18,7 @@ export default class ConvertRules extends ChessRules {
   setOtherVariables(fenParsed, pieceArray) {
     super.setOtherVariables(fenParsed, pieceArray);
     // Stack of "last move" only for intermediate chaining
-    this.lastMoveEnd = [null];
+    this.lastMoveEnd = [];
   }
 
   genRandInitBaseFen() {
@@ -37,21 +32,18 @@ export default class ConvertRules extends ChessRules {
 
   getBasicMove([sx, sy], [ex, ey], tr) {
     const L = this.lastMoveEnd.length;
-    const lm = this.lastMoveEnd[L-1];
-    const piece = (!!lm ? lm.p : null);
-    const c = this.turn;
+    const piece = (L >= 1 ? this.lastMoveEnd[L-1].p : null);
     if (this.board[ex][ey] == "") {
       if (piece && !tr)
-        tr = {c: c, p: piece};
+        tr = {c: this.turn, p: piece};
       let mv = super.getBasicMove([sx, sy], [ex, ey], tr);
       if (piece)
-        mv.vanish.pop();
+        mv.vanish.pop(); //end of a chain: initial piece remains
       return mv;
     }
     // Capture: initial, or inside a chain
-    const initPiece = (piece || this.getPiece(sx, sy));
-    const oppCol = C.GetOppTurn(c);
-    const oppPiece = this.getPiece(ex, ey);
+    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},
@@ -59,7 +51,7 @@ export default class ConvertRules extends ChessRules {
         new PiPo({
           x: ex,
           y: ey,
-          c: c,
+          c: this.turn,
           p: (!!tr ? tr.p : initPiece)
         })
       ],
@@ -67,8 +59,8 @@ export default class ConvertRules extends ChessRules {
         new PiPo({
           x: ex,
           y: ey,
-          c: oppCol,
-          p: oppPiece
+          c: C.GetOppTurn(this.turn),
+          p: destPiece
         })
       ]
     });
@@ -78,58 +70,43 @@ export default class ConvertRules extends ChessRules {
         new PiPo({
           x: sx,
           y: sy,
-          c: c,
+          c: this.turn,
           p: initPiece
         })
       );
     }
+    mv.converted = destPiece; //easier (no need to detect it)
     return mv;
   }
 
-// TODO from here
-
-  getPotentialMovesFrom([x, y], asA) {
+  getPiece(x, y) {
     const L = this.lastMoveEnd.length;
-    if (!!this.lastMoveEnd[L-1]) {
-      if (x != this.lastMoveEnd[L-1].x || y != this.lastMoveEnd[L-1].y)
-        // A capture was played: wrong square
-        return [];
-      asA = this.lastMoveEnd[L-1].p;
-    }
-    switch (asA || this.getPiece(x, y)) {
-      case V.PAWN: return super.getPotentialPawnMoves([x, y]);
-      case V.ROOK: return super.getPotentialRookMoves([x, y]);
-      case V.KNIGHT: return super.getPotentialKnightMoves([x, y]);
-      case V.BISHOP: return super.getPotentialBishopMoves([x, y]);
-      case V.QUEEN: return super.getPotentialQueenMoves([x, y]);
-      case V.KING: return super.getPotentialKingMoves([x, y]);
-    }
-    return [];
+    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);
   }
 
-  getPossibleMovesFrom(sq) {
+  getPotentialMovesFrom([x, y], color) {
     const L = this.lastMoveEnd.length;
-    let asA = undefined;
-    if (!!this.lastMoveEnd[L-1]) {
-      if (
-        sq[0] != this.lastMoveEnd[L-1].x ||
-        sq[1] != this.lastMoveEnd[L-1].y
-      ) {
-        return [];
-      }
-      asA = this.lastMoveEnd[L-1].p;
+    if (
+      L >= 1 &&
+      (x != this.lastMoveEnd[L-1].x || y != this.lastMoveEnd[L-1].y)
+    ) {
+      // A capture was played: wrong square
+      return [];
     }
-    return this.filterValid(this.getPotentialMovesFrom(sq, asA));
+    return super.getPotentialMovesFrom([x, y], color);
   }
 
-  isAttacked_aux([x, y], color, explored) {
+  underAttack_aux([x, y], color, explored) {
     if (explored.some(sq => sq[0] == x && sq[1] == y))
       // Start of an infinite loop: exit
       return false;
     explored.push([x, y]);
-    if (super.isAttacked([x, y], color)) return true;
+    if (super.underAttack([x, y], [color]))
+      return true;
     // Maybe indirect "chaining" attack:
-    const myColor = this.turn
+    const myColor = this.turn;
     let res = false;
     let toCheck = []; //check all but king (no need)
     // Pawns:
@@ -137,51 +114,53 @@ export default class ConvertRules extends ChessRules {
     for (let yShift of [-1, 1]) {
       const [i, j] = [x + shiftToPawn, y + yShift];
       if (
-        V.OnBoard(i, j) &&
-        this.board[i][j] != V.EMPTY &&
+        this.onBoard(i, j) &&
+        this.board[i][j] != "" &&
         // NOTE: no need to check color (no enemy pawn can take directly)
-        this.getPiece(i, j) == V.PAWN
+        this.getPiece(i, j) == 'p'
       ) {
         toCheck.push([i, j]);
       }
     }
     // Knights:
-    V.steps[V.KNIGHT].forEach(s => {
+    this.pieces()['n'].both[0].steps.forEach(s => {
       const [i, j] = [x + s[0], y + s[1]];
       if (
-        V.OnBoard(i, j) &&
-        this.board[i][j] != V.EMPTY &&
-        this.getPiece(i, j) == V.KNIGHT
+        this.onBoard(i, j) &&
+        this.board[i][j] != "" &&
+        this.getPiece(i, j) == 'n'
       ) {
         toCheck.push([i, j]);
       }
     });
     // Sliders:
-    V.steps[V.ROOK].concat(V.steps[V.BISHOP]).forEach(s => {
+    this.pieces()['q'].both[0].steps.forEach(s => {
       let [i, j] = [x + s[0], y + s[1]];
-      while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+      while (this.onBoard(i, j) && this.board[i][j] == "") {
         i += s[0];
         j += s[1];
       }
-      if (!V.OnBoard(i, j)) return;
+      if (!this.onBoard(i, j))
+        return;
       const piece = this.getPiece(i, j);
       if (
-        piece == V.QUEEN ||
-        (piece == V.ROOK && (s[0] == 0 || s[1] == 0)) ||
-        (piece == V.BISHOP && (s[0] != 0 && s[1] != 0))
+        piece == 'q' ||
+        (piece == 'r' && (s[0] == 0 || s[1] == 0)) ||
+        (piece == 'b' && (s[0] != 0 && s[1] != 0))
       ) {
         toCheck.push([i, j]);
       }
     });
     for (let ij of toCheck) {
-      if (this.isAttacked_aux(ij, color, explored)) return true;
+      if (this.underAttack_aux(ij, color, explored))
+        return true;
     }
     return false;
   }
 
-  isAttacked([x, y], color) {
+  underAttack([x, y], [color]) {
     let explored = [];
-    return this.isAttacked_aux([x, y], color, explored);
+    return this.underAttack_aux([x, y], color, explored);
   }
 
   filterValid(moves) {
@@ -189,36 +168,21 @@ export default class ConvertRules extends ChessRules {
     return moves;
   }
 
-  prePlay(move) {
-    const c = this.turn;
-    // Extra conditions to avoid tracking converted kings:
-    if (
-      move.appear[0].p == V.KING &&
-      move.vanish.length >= 1 &&
-      move.vanish[0].p == V.KING
-    ) {
-      this.kingPos[c][0] = move.appear[0].x;
-      this.kingPos[c][1] = move.appear[0].y;
-    }
+  isLastMove(move) {
+    return !move.converted;
   }
 
-  play(move) {
-    this.prePlay(move);
-    const c = this.turn;
-    move.flags = JSON.stringify(this.aggregateFlags());
-    V.PlayOnBoard(this.board, move);
-    if (!move.end.converted) {
-      // Not a capture: change turn
-      this.turn = V.GetOppCol(this.turn);
-      this.movesCount++;
-      this.lastMoveEnd.push(null);
-    }
-    else {
-      this.lastMoveEnd.push(
-        Object.assign({}, move.end, { p: move.end.converted })
-      );
+  postPlay(move) {
+    super.postPlay(move);
+    if (!!move.converted) {
+      this.lastMoveEnd.push({
+        x: move.end.x,
+        y: move.end.y,
+        p: move.converted
+      });
     }
-    super.updateCastleFlags(move, move.appear[0].p, c);
+    else
+      this.lastMoveEnd = [];
   }
 
 };