From 0e0010227e46acb7774d134c9aa345eaa0c4404d Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Thu, 9 Apr 2020 12:26:53 +0200
Subject: [PATCH] Fix Sittuyin variant + basic computer play

---
 client/src/variants/Crazyhouse.js |   5 +-
 client/src/variants/Recycle.js    |   5 +-
 client/src/variants/Sittuyin.js   | 109 +++++++++++++++++++-----------
 3 files changed, 75 insertions(+), 44 deletions(-)

diff --git a/client/src/variants/Crazyhouse.js b/client/src/variants/Crazyhouse.js
index a133b275..8e619743 100644
--- a/client/src/variants/Crazyhouse.js
+++ b/client/src/variants/Crazyhouse.js
@@ -173,12 +173,13 @@ export class CrazyhouseRules extends ChessRules {
   }
 
   getAllValidMoves() {
-    let moves = super.getAllValidMoves();
+    let moves = super.getAllPotentialMoves();
     const color = this.turn;
-    for (let i = 0; i < V.RESERVE_PIECES.length; i++)
+    for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
       moves = moves.concat(
         this.getReserveMoves([V.size.x + (color == "w" ? 0 : 1), i])
       );
+    }
     return this.filterValid(moves);
   }
 
diff --git a/client/src/variants/Recycle.js b/client/src/variants/Recycle.js
index 0579de7a..bf252632 100644
--- a/client/src/variants/Recycle.js
+++ b/client/src/variants/Recycle.js
@@ -144,12 +144,13 @@ export class RecycleRules extends ChessRules {
   }
 
   getAllValidMoves() {
-    let moves = super.getAllValidMoves();
+    let moves = super.getAllPotentialMoves();
     const color = this.turn;
-    for (let i = 0; i < V.RESERVE_PIECES.length; i++)
+    for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
       moves = moves.concat(
         this.getReserveMoves([V.size.x + (color == "w" ? 0 : 1), i])
       );
+    }
     return this.filterValid(moves);
   }
 
diff --git a/client/src/variants/Sittuyin.js b/client/src/variants/Sittuyin.js
index 0912e701..f37eabf3 100644
--- a/client/src/variants/Sittuyin.js
+++ b/client/src/variants/Sittuyin.js
@@ -1,4 +1,5 @@
 import { ChessRules, Move, PiPo } from "@/base_rules";
+import { randInt } from "@/utils/alea";
 
 export class SittuyinRules extends ChessRules {
   static get HasFlags() {
@@ -76,44 +77,44 @@ 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]) {
@@ -183,7 +184,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 +200,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 +268,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 +369,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 "";
-- 
2.44.0