Some fixes, draw lines on board, add 7 variants
[vchess.git] / client / src / variants / Sittuyin.js
index 0912e70..61bab56 100644 (file)
@@ -1,4 +1,5 @@
 import { ChessRules, Move, PiPo } from "@/base_rules";
+import { randInt } from "@/utils/alea";
 
 export class SittuyinRules extends ChessRules {
   static get HasFlags() {
@@ -9,12 +10,22 @@ export class SittuyinRules extends ChessRules {
     return false;
   }
 
+  static get Monochrome() {
+    return true;
+  }
+
+  static get Lines() {
+    return ChessRules.Lines.concat([
+      [[0, 0], [8, 8]],
+      [[0, 8], [8, 0]]
+    ]);
+  }
+
   static get PawnSpecs() {
     return Object.assign(
       {},
       ChessRules.PawnSpecs,
       {
-        twoSquares: false,
         // Promotions are handled differently here
         promotions: [V.QUEEN]
       }
@@ -76,71 +87,62 @@ export class SittuyinRules extends ChessRules {
   }
 
   getPotentialMovesFrom([x, y]) {
-    if (this.movesCount <= 1) {
-      const color = this.turn;
-      const p = V.RESERVE_PIECES[y];
-      if (this.reserve[color][p] == 0) return [];
-      const iBound =
-        p != V.ROOK
-          ? (color == 'w' ? [4, 7] : [0, 3])
-          : (color == 'w' ? [7, 7] : [0, 0]);
-      const jBound = (i) => {
-        if (color == 'w' && i == 4) return [4, 7];
-        if (color == 'b' && i == 3) return [0, 3];
-        return [0, 7];
-      };
-      let moves = [];
-      for (let i = iBound[0]; i <= iBound[1]; i++) {
-        const jb = jBound(i);
-        for (let j = jb[0]; j <= jb[1]; j++) {
-          if (this.board[i][j] == V.EMPTY) {
-            let mv = new Move({
-              appear: [
-                new PiPo({
-                  x: i,
-                  y: j,
-                  c: color,
-                  p: p
-                })
-              ],
-              vanish: [],
-              start: { x: x, y: y },
-              end: { x: i, y: j }
-            });
-            moves.push(mv);
-          }
+    if (this.movesCount >= 2) return super.getPotentialMovesFrom([x, y]);
+    // Only reserve moves are allowed for now:
+    if (V.OnBoard(x, y)) return [];
+    const color = this.turn;
+    const p = V.RESERVE_PIECES[y];
+    if (this.reserve[color][p] == 0) return [];
+    const iBound =
+      p != V.ROOK
+        ? (color == 'w' ? [4, 7] : [0, 3])
+        : (color == 'w' ? [7, 7] : [0, 0]);
+    const jBound = (i) => {
+      if (color == 'w' && i == 4) return [4, 7];
+      if (color == 'b' && i == 3) return [0, 3];
+      return [0, 7];
+    };
+    let moves = [];
+    for (let i = iBound[0]; i <= iBound[1]; i++) {
+      const jb = jBound(i);
+      for (let j = jb[0]; j <= jb[1]; j++) {
+        if (this.board[i][j] == V.EMPTY) {
+          let mv = new Move({
+            appear: [
+              new PiPo({
+                x: i,
+                y: j,
+                c: color,
+                p: p
+              })
+            ],
+            vanish: [],
+            start: { x: x, y: y },
+            end: { x: i, y: j }
+          });
+          moves.push(mv);
         }
       }
-      return moves;
     }
-    return super.getPotentialMovesFrom([x, y]);
+    return moves;
   }
 
   getPotentialPawnMoves([x, y]) {
     const color = this.turn;
-    const [sizeX, sizeY] = [V.size.x, V.size.y];
     const shiftX = V.PawnSpecs.directions[color];
     let moves = [];
-    // NOTE: next condition is generally true (no pawn on last rank)
-    if (x + shiftX >= 0 && x + shiftX < sizeX) {
-      if (this.board[x + shiftX][y] == V.EMPTY) {
+    if (x + shiftX >= 0 && x + shiftX < 8) {
+      if (this.board[x + shiftX][y] == V.EMPTY)
         // One square forward
         moves.push(this.getBasicMove([x, y], [x + shiftX, y]));
-      }
       // Captures
-      if (V.PawnSpecs.canCapture) {
-        for (let shiftY of [-1, 1]) {
-          if (
-            y + shiftY >= 0 &&
-            y + shiftY < sizeY
-          ) {
-            if (
-              this.board[x + shiftX][y + shiftY] != V.EMPTY &&
-              this.canTake([x, y], [x + shiftX, y + shiftY])
-            ) {
-              moves.push(this.getBasicMove([x, y], [x + shiftX, y + shiftY]));
-            }
-          }
+      for (let shiftY of [-1, 1]) {
+        if (
+          y + shiftY >= 0 && y + shiftY < 8 &&
+          this.board[x + shiftX][y + shiftY] != V.EMPTY &&
+          this.canTake([x, y], [x + shiftX, y + shiftY])
+        ) {
+          moves.push(this.getBasicMove([x, y], [x + shiftX, y + shiftY]));
         }
       }
     }
@@ -183,7 +185,7 @@ export class SittuyinRules extends ChessRules {
           }
         }
         if (validP && !!moveTo) {
-          // Also check discovered attacks { n, e, w, s : enemy / my rook --> if both, then it's a discovered attack }
+          // Also check rook discovered attacks on the enemy king
           let found = {
             "0,-1": 0,
             "0,1": 0,
@@ -199,10 +201,12 @@ export class SittuyinRules extends ChessRules {
               j += step[1];
             }
             if (V.OnBoard(i, j)) {
-              if (this.getColor(i, j) != color)
-                found[step[0] + "," + step[1]] = -1; //enemy
-              else if (this.getPiece(i, j) == V.ROOK)
-                found[step[0] + "," + step[1]] = 1; //my rook
+              const colIJ = this.getColor(i, j);
+              const pieceIJ = this.getPiece(i, j);
+              if (colIJ != color && pieceIJ == V.KING)
+                found[step[0] + "," + step[1]] = -1;
+              else if (colIJ == color && pieceIJ == V.ROOK)
+                found[step[0] + "," + step[1]] = 1;
             }
           }
           if (
@@ -265,6 +269,18 @@ export class SittuyinRules extends ChessRules {
     );
   }
 
+  getAllValidMoves() {
+    if (this.movesCount >= 2) return super.getAllValidMoves();
+    const color = this.turn;
+    let moves = [];
+    for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
+      moves = moves.concat(
+        this.getPotentialMovesFrom([V.size.x + (color == "w" ? 0 : 1), i])
+      );
+    }
+    return this.filterValid(moves);
+  }
+
   isAttackedByBishop(sq, color) {
     const forward = (this.turn == 'w' ? 1 : -1);
     return this.isAttackedBySlideNJump(
@@ -354,6 +370,20 @@ export class SittuyinRules extends ChessRules {
     };
   }
 
+  getComputerMove() {
+    if (this.movesCount >= 2) return super.getComputerMove();
+    // Play a random "initialization move"
+    let res = [];
+    for (let i=0; i<8; i++) {
+      const moves = this.getAllValidMoves();
+      const moveIdx = randInt(moves.length);
+      this.play(moves[moveIdx]);
+      res.push(moves[moveIdx]);
+    }
+    for (let i=7; i>=0; i--) this.undo(res[i]);
+    return res;
+  }
+
   getNotation(move) {
     // Do not note placement moves (complete move would be too long)
     if (move.vanish.length == 0) return "";