New variant idea
[xogo.git] / variants / Bario / class.js
index 80a3cce..2dd64d6 100644 (file)
@@ -6,7 +6,8 @@ export default class BarioRules extends ChessRules {
 
   static get Options() {
     return {
-      // TODO: Zen too?
+      select: C.Options.select,
+      input: C.Options.input,
       styles: [
         "atomic", "cannibal", "capture", "cylinder",
         "dark", "madrasi", "rifle", "teleport"
@@ -25,12 +26,7 @@ export default class BarioRules extends ChessRules {
 
   pieces(color, x, y) {
     return Object.assign(
-      {
-        'u': {
-          "class": "undefined",
-          moves: []
-        }
-      },
+      { 'u': {"class": "undefined"} },
       super.pieces(color, x, y)
     );
   }
@@ -113,6 +109,8 @@ export default class BarioRules extends ChessRules {
       case 0:
         if (typeof x == "string")
           moves = this.getDropMovesFrom([x, y]);
+        // Empty move: just start + end
+        moves.forEach(m => {m.vanish.pop(); m.appear.pop();});
         break;
       case 1:
         // Both normal move (from defined piece) and definition allowed
@@ -133,8 +131,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 +142,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 +156,15 @@ 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 inReserve = Object.keys(this.reserve[oppCol])
+                        .filter(k => this.reserve[oppCol][k] >= 1);
     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]];
+      inReserve.map(p => this.pieces()[p].both[0]));
+    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,17 @@ 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) {
+      if (!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 +216,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.start.y, this.reserve[color][move.start.y] - 1);
       if (move.vanish.length == 1 && move.vanish[0].p == 'u')
         this.definition = move.end;
       this.subTurn++;
@@ -223,7 +225,67 @@ export default class BarioRules extends ChessRules {
     else {
       this.subTurn = 0;
       this.captureUndef = move.end;
-      toNextPlayer();
+      this.tryChangeTurn(null, captureUndef);
+    }
+  }
+
+  // NOTE: not "trying", the turn always change here (TODO?)
+  tryChangeTurn(move, captureUndef) {
+    this.definition = null;
+    this.subTurn = captureUndef ? 0 : 1;
+    this.turn = C.GetOppTurn(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;
     }
   }