Fix Bario
[xogo.git] / variants / Bario / class.js
index 80a3cce..871a537 100644 (file)
@@ -133,8 +133,10 @@ export default class BarioRules extends ChessRules {
   filterValid(moves) {
     if (this.movesCount <= 1 || this.subTurn == 0)
       return moves;
+    let filterLater = [];
     if (this.subTurn == 1) {
-      // Remove defining moves with un-movable def piece
+      // Remove defining moves with un-movable def piece,
+      // and separate compatible definitions.
       moves = moves.filter(m => {
         if (m.vanish.length >= 2 || m.vanish[0].p != 'u')
           return true;
@@ -142,10 +144,12 @@ export default class BarioRules extends ChessRules {
         const canMove = super.filterValid(
           super.getPotentialMovesFrom([m.end.x, m.end.y])).length >= 1;
         this.undoOnBoard(m);
-        return canMove;
+        if (canMove)
+          filterLater.push(m);
+        return false;
       });
     }
-    return super.filterValid(moves);
+    return super.filterValid(moves).concat(filterLater);
   }
 
   atLeastOneMove(color) {
@@ -154,14 +158,13 @@ export default class BarioRules extends ChessRules {
     return super.atLeastOneMove(color);
   }
 
-  // TODO: this method fails to detect undefined checks
   underCheck(square_s, oppCol) {
     if (super.underCheck(square_s, oppCol))
       return true;
     // Check potential specializations of undefined using reserve:
     const allAttacks = Array.prototype.concat.apply(
       ['r', 'n', 'b', 'q'].map(p => this.pieces()[p].moves[0]));
-    const [x, y] = [square_s[0], square_s[1]];
+    const [x, y] = square_s[0];
     for (let i=0; i<this.size.x; i++) {
       for (let j=0; j<this.size.y; j++) {
         if (
@@ -195,19 +198,16 @@ export default class BarioRules extends ChessRules {
     return false;
   }
 
-  // TODO: missing "undefined reset" check (is everything defined? If yes, reset if enough variety)
   postPlay(move) {
     const color = this.turn;
-    const toNextPlayer = () => {
-      this.turn = C.GetOppCol(color);
-      this.movesCount++;
-    };
-    if (this.movesCount <= 1) {
-      toNextPlayer();
+    if (this.movesCount <= 1 || move.reset || move.next) {
+      this.tryChangeTurn();
       return;
     }
+    if (this.subTurn == 0)
+      this.captureUndef = null; //already used
     const captureUndef = (
-      move.vanish.length == 2 &&
+      move.vanish.length == 2 && //exclude subTurn == 0
       move.vanish[1].c != color &&
       move.vanish[1].p == 'u'
     );
@@ -215,7 +215,8 @@ export default class BarioRules extends ChessRules {
       // Normal move (including Teleport)
       super.postPlay(move);
     else if (typeof move.start.x == "string") {
-      this.reserve[color][move.appear[0].p]--;
+      super.updateReserve(
+        color, move.appear[0].p, this.reserve[color][move.appear[0].p] - 1);
       if (move.vanish.length == 1 && move.vanish[0].p == 'u')
         this.definition = move.end;
       this.subTurn++;
@@ -223,7 +224,68 @@ export default class BarioRules extends ChessRules {
     else {
       this.subTurn = 0;
       this.captureUndef = move.end;
-      toNextPlayer();
+      this.tryChangeTurn(move, captureUndef);
+    }
+  }
+
+  tryChangeTurn(move, captureUndef) {
+    if (!move.next) {
+      this.definition = null;
+      this.subTurn = captureUndef ? 0 : 1;
+      this.turn = C.GetOppCol(this.turn);
+      this.movesCount++;
+    }
+  }
+
+  computeNextMove(move) {
+    if (
+      !this.definition || this.playerColor != this.turn ||
+      this.board.some(row => row.some(cell =>
+        cell.charAt(0) == this.turn && cell.charAt(1) == 'u'))
+    ) {
+      return;
+    }
+    const variety = (c) => {
+      return (
+        [...new Set(
+          Array.prototype.concat.apply([],
+            this.board.map(row =>
+              row.filter(cell =>
+                cell.charAt(0) == c && !['p', 'k'].includes(cell.charAt(1))
+              ).map(cell => cell.charAt(1))
+            )
+          )
+        )].length >= 2
+      );
+    };
+    let next = {start: move.end, end: move.end, vanish: [], appear: []};
+    this.playOnBoard(move);
+    const twoOrMorePieces = {w: variety('w'), b: variety('b')};
+    const resetCols =
+      Object.keys(twoOrMorePieces).filter(k => twoOrMorePieces[k]);
+    if (resetCols.length >= 1) {
+      for (let i=0; i<this.size.x; i++) {
+        for (let j=0; j<this.size.y; j++) {
+          const colIJ = this.getColor(i, j);
+          const pieceIJ = this.getPiece(i, j);
+          if (
+            resetCols.includes(colIJ) &&
+            this.board[i][j] != "" &&
+            !['p', 'k', 'u'].includes(pieceIJ)
+          ) {
+            // NOTE: could also use a "flip" strategy similar to Benedict
+            next.vanish.push(new PiPo({c: colIJ, p: pieceIJ, x: i, y: j}));
+            next.appear.push(new PiPo({c: colIJ, p: 'u', x: i, y: j}));
+            this.reserve[colIJ][pieceIJ]++;
+          }
+        }
+      }
+      super.re_drawReserve(resetCols);
+    }
+    this.undoOnBoard(move);
+    if (next.vanish.length >= 1) {
+      next.reset = true;
+      move.next = next;
     }
   }