Several small improvements + integrate options + first working draft of Cwda
[vchess.git] / client / src / variants / Suicide.js
index 4bb5d36..3b3c03c 100644 (file)
@@ -1,53 +1,49 @@
 import { ChessRules } from "@/base_rules";
 import { ArrayFun } from "@/utils/array";
-import { randInt } from "@/utils/alea";
+import { shuffle } from "@/utils/alea";
+
+export class SuicideRules extends ChessRules {
 
-export const VariantRules = class SuicideRules extends ChessRules {
   static get HasFlags() {
     return false;
   }
 
-  static get HasCastle() {
-    return false;
+  static get PawnSpecs() {
+    return Object.assign(
+      {},
+      ChessRules.PawnSpecs,
+      { promotions: ChessRules.PawnSpecs.promotions.concat([V.KING]) }
+    );
   }
 
-  getPotentialPawnMoves([x, y]) {
-    let moves = super.getPotentialPawnMoves([x, y]);
-
-    // Complete with promotion(s) into king, if possible
-    const color = this.turn;
-    const shift = color == "w" ? -1 : 1;
-    const lastRank = color == "w" ? 0 : V.size.x - 1;
-    if (x + shift == lastRank) {
-      // Normal move
-      if (this.board[x + shift][y] == V.EMPTY)
-        moves.push(
-          this.getBasicMove([x, y], [x + shift, y], { c: color, p: V.KING })
-        );
-      // Captures
-      if (
-        y > 0 &&
-        this.canTake([x, y], [x + shift, y - 1]) &&
-        this.board[x + shift][y - 1] != V.EMPTY
-      ) {
-        moves.push(
-          this.getBasicMove([x, y], [x + shift, y - 1], { c: color, p: V.KING })
-        );
-      }
-      if (
-        y < V.size.y - 1 &&
-        this.canTake([x, y], [x + shift, y + 1]) &&
-        this.board[x + shift][y + 1] != V.EMPTY
-      ) {
-        moves.push(
-          this.getBasicMove([x, y], [x + shift, y + 1], { c: color, p: V.KING })
-        );
+  static IsGoodPosition(position) {
+    if (position.length == 0) return false;
+    const rows = position.split("/");
+    if (rows.length != V.size.x) return false;
+    // Just check that at least one piece of each color is there:
+    let pieces = { "w": 0, "b": 0 };
+    for (let row of rows) {
+      let sumElts = 0;
+      for (let i = 0; i < row.length; i++) {
+        const lowerRi = row[i].toLowerCase();
+        if (V.PIECES.includes(lowerRi)) {
+          pieces[row[i] == lowerRi ? "b" : "w"]++;
+          sumElts++;
+        }
+        else {
+          const num = parseInt(row[i], 10);
+          if (isNaN(num)) return false;
+          sumElts += num;
+        }
       }
+      if (sumElts != V.size.y) return false;
     }
-
-    return moves;
+    if (Object.values(pieces).some(v => v == 0)) return false;
+    return true;
   }
 
+  scanKings() {}
+
   // Trim all non-capturing moves (not the most efficient, but easy)
   static KeepCaptures(moves) {
     return moves.filter(m => m.vanish.length == 2);
@@ -56,12 +52,11 @@ export const VariantRules = class SuicideRules extends ChessRules {
   // Stop at the first capture found (if any)
   atLeastOneCapture() {
     const color = this.turn;
-    const oppCol = V.GetOppCol(color);
     for (let i = 0; i < V.size.x; i++) {
       for (let j = 0; j < V.size.y; j++) {
         if (
           this.board[i][j] != V.EMPTY &&
-          this.getColor(i, j) != oppCol &&
+          this.getColor(i, j) == color &&
           this.getPotentialMovesFrom([i, j]).some(m => m.vanish.length == 2)
         ) {
           return true;
@@ -140,61 +135,31 @@ export const VariantRules = class SuicideRules extends ChessRules {
     return -super.evalPosition();
   }
 
-  static GenRandInitFen(randomness) {
-    if (randomness == 0)
+  static GenRandInitFen(options) {
+    if (options.randomness == 0)
       return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0 -";
 
     let pieces = { w: new Array(8), b: new Array(8) };
-    // Shuffle pieces on first and last rank
     for (let c of ["w", "b"]) {
-      if (c == 'b' && randomness == 1) {
+      if (c == 'b' && options.randomness == 1) {
         pieces['b'] = pieces['w'];
         break;
       }
 
-      let positions = ArrayFun.range(8);
-
-      // Get random squares for bishops
-      let randIndex = 2 * randInt(4);
-      let bishop1Pos = positions[randIndex];
-      // The second bishop must be on a square of different color
-      let randIndex_tmp = 2 * randInt(4) + 1;
-      let bishop2Pos = positions[randIndex_tmp];
-      // Remove chosen squares
-      positions.splice(Math.max(randIndex, randIndex_tmp), 1);
-      positions.splice(Math.min(randIndex, randIndex_tmp), 1);
-
-      // Get random squares for knights
-      randIndex = randInt(6);
-      let knight1Pos = positions[randIndex];
-      positions.splice(randIndex, 1);
-      randIndex = randInt(5);
-      let knight2Pos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      // Get random square for queen
-      randIndex = randInt(4);
-      let queenPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      // Random square for king (no castle)
-      randIndex = randInt(3);
-      let kingPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      // Rooks positions are now fixed
-      let rook1Pos = positions[0];
-      let rook2Pos = positions[1];
-
-      // Finally put the shuffled pieces in the board array
-      pieces[c][rook1Pos] = "r";
-      pieces[c][knight1Pos] = "n";
-      pieces[c][bishop1Pos] = "b";
-      pieces[c][queenPos] = "q";
-      pieces[c][kingPos] = "k";
-      pieces[c][bishop2Pos] = "b";
-      pieces[c][knight2Pos] = "n";
-      pieces[c][rook2Pos] = "r";
+      // Get random squares for every piece, totally freely
+      let positions = shuffle(ArrayFun.range(8));
+      const composition = ['b', 'b', 'r', 'r', 'n', 'n', 'k', 'q'];
+      const rem2 = positions[0] % 2;
+      if (rem2 == positions[1] % 2) {
+        // Fix bishops (on different colors)
+        for (let i=2; i<8; i++) {
+          if (positions[i] % 2 != rem2) {
+            [positions[1], positions[i]] = [positions[i], positions[1]];
+            break;
+          }
+        }
+      }
+      for (let i = 0; i < 8; i++) pieces[c][positions[i]] = composition[i];
     }
     return (
       pieces["b"].join("") +
@@ -204,4 +169,5 @@ export const VariantRules = class SuicideRules extends ChessRules {
       " w 0 -"
     );
   }
+
 };