Fix parseInt() usage, rename Doubleorda --> Ordamirror, implement Clorange variant
[vchess.git] / client / src / variants / Baroque.js
index a19d09e..4ff23a0 100644 (file)
@@ -1,16 +1,12 @@
 import { ChessRules, PiPo, Move } from "@/base_rules";
 import { ArrayFun } from "@/utils/array";
-import { randInt } from "@/utils/alea";
+import { shuffle } from "@/utils/alea";
 
-export const VariantRules = class BaroqueRules extends ChessRules {
+export class BaroqueRules extends ChessRules {
   static get HasFlags() {
     return false;
   }
 
-  static get HasCastle() {
-    return false;
-  }
-
   static get HasEnpassant() {
     return false;
   }
@@ -42,7 +38,7 @@ export const VariantRules = class BaroqueRules extends ChessRules {
             this.kingPos["w"] = [i, k];
             break;
           default: {
-            const num = parseInt(position[i].charAt(j));
+            const num = parseInt(position[i].charAt(j), 10);
             if (!isNaN(num)) k += num - 1;
           }
         }
@@ -91,7 +87,8 @@ export const VariantRules = class BaroqueRules extends ChessRules {
           }
           return true; //immobilizer isn't neutralized
         }
-        // Chameleons can't be immobilized twice, because there is only one immobilizer
+        // Chameleons can't be immobilized twice,
+        // because there is only one immobilizer
         if (oppPiece == V.BISHOP && piece == V.IMMOBILIZER) return true;
       }
     }
@@ -134,7 +131,9 @@ export const VariantRules = class BaroqueRules extends ChessRules {
     const color = this.turn;
     const oppCol = V.GetOppCol(color);
     moves.forEach(m => {
-      if (!!byChameleon && m.start.x != m.end.x && m.start.y != m.end.y) return; //chameleon not moving as pawn
+      if (!!byChameleon && m.start.x != m.end.x && m.start.y != m.end.y)
+        // Chameleon not moving as pawn
+        return;
       // Try capturing in every direction
       for (let step of steps) {
         const sq2 = [m.end.x + 2 * step[0], m.end.y + 2 * step[1]];
@@ -228,10 +227,11 @@ export const VariantRules = class BaroqueRules extends ChessRules {
       ) {
         continue;
       }
-      // last(thing), cur(thing) : stop if "cur" is our color, or beyond board limits,
-      // or if "last" isn't empty and cur neither. Otherwise, if cur is empty then
-      // add move until cur square; if cur is occupied then stop if !!byChameleon and
-      // the square not occupied by a leaper.
+      // last(thing), cur(thing) : stop if "cur" is our color,
+      // or beyond board limits, or if "last" isn't empty and cur neither.
+      // Otherwise, if cur is empty then add move until cur square;
+      // if cur is occupied then stop if !!byChameleon and the square not
+      // occupied by a leaper.
       let last = [i, j];
       let cur = [i + step[0], j + step[1]];
       let vanished = [new PiPo({ x: x, y: y, c: color, p: piece })];
@@ -293,12 +293,7 @@ export const VariantRules = class BaroqueRules extends ChessRules {
           mergedMoves[key].vanish.push(m.vanish[i]);
       }
     });
-    // Finally return an array
-    moves = [];
-    Object.keys(mergedMoves).forEach(k => {
-      moves.push(mergedMoves[k]);
-    });
-    return moves;
+    return Object.values(mergedMoves);
   }
 
   addQueenCaptures(moves, byChameleon) {
@@ -420,16 +415,19 @@ export const VariantRules = class BaroqueRules extends ChessRules {
             this.getColor(i, j) == color &&
             this.getPiece(i, j) == V.ROOK
           ) {
-            if (this.isImmobilized([i, j])) return false; //because only one rook
-            // Can it reach a capturing square?
-            // Easy but quite suboptimal way (TODO): generate all moves (turn is OK)
+            if (this.isImmobilized([i, j]))
+              // Because only one rook:
+              return false;
+            // Can it reach a capturing square? Easy but quite suboptimal way
+            // (TODO: generate all moves (turn is OK))
             const moves = this.getPotentialMovesFrom([i, j]);
             for (let move of moves) {
               if (
                 (sameRow && move.end.y == y) ||
                 (sameColumn && move.end.x == x)
-              )
+              ) {
                 return true;
+              }
             }
           }
         }
@@ -457,11 +455,13 @@ export const VariantRules = class BaroqueRules extends ChessRules {
               if (
                 this.getPiece(i, j) == V.KNIGHT &&
                 !this.isImmobilized([i, j])
-              )
+              ) {
                 return true;
+              }
               continue outerLoop;
             }
-            // [else] Our color, could be captured *if there was an empty space*
+            // [else] Our color,
+            // could be captured *if there was an empty space*
             if (this.board[i + step[0]][j + step[1]] != V.EMPTY)
               continue outerLoop;
             i -= step[0];
@@ -483,9 +483,10 @@ export const VariantRules = class BaroqueRules extends ChessRules {
         V.OnBoard(i, j) &&
         this.board[i][j] != V.EMPTY &&
         this.getColor(i, j) == color &&
-        this.getPiece(i, j) == V.BISHOP
+        this.getPiece(i, j) == V.BISHOP &&
+        !this.isImmobilized([i, j])
       ) {
-        return true; //bishops are never immobilized
+        return true;
       }
     }
     return false;
@@ -529,26 +530,10 @@ export const VariantRules = class BaroqueRules extends ChessRules {
     return false;
   }
 
-  static get VALUES() {
-    return {
-      p: 1,
-      r: 2,
-      n: 5,
-      b: 3,
-      q: 3,
-      m: 5,
-      k: 1000
-    };
-  }
-
-  static get SEARCH_DEPTH() {
-    return 2;
-  }
-
   static GenRandInitFen(randomness) {
     if (randomness == 0)
       // Deterministic:
-      return "rnbqkbnrm/pppppppp/8/8/8/8/PPPPPPPP/MNBKQBNR w 0";
+      return "rnbkqbnm/pppppppp/8/8/8/8/PPPPPPPP/MNBQKBNR w 0";
 
     let pieces = { w: new Array(8), b: new Array(8) };
     // Shuffle pieces on first and last rank
@@ -558,46 +543,10 @@ export const VariantRules = class BaroqueRules extends ChessRules {
         break;
       }
 
-      let positions = ArrayFun.range(8);
       // Get random squares for every piece, totally freely
-
-      let randIndex = randInt(8);
-      const bishop1Pos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(7);
-      const bishop2Pos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(6);
-      const knight1Pos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(5);
-      const knight2Pos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(4);
-      const queenPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(3);
-      const kingPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-
-      randIndex = randInt(2);
-      const rookPos = positions[randIndex];
-      positions.splice(randIndex, 1);
-      const immobilizerPos = positions[0];
-
-      pieces[c][bishop1Pos] = "b";
-      pieces[c][bishop2Pos] = "b";
-      pieces[c][knight1Pos] = "n";
-      pieces[c][knight2Pos] = "n";
-      pieces[c][queenPos] = "q";
-      pieces[c][kingPos] = "k";
-      pieces[c][rookPos] = "r";
-      pieces[c][immobilizerPos] = "m";
+      let positions = shuffle(ArrayFun.range(8));
+      const composition = ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'm'];
+      for (let i = 0; i < 8; i++) pieces[c][positions[i]] = composition[i];
     }
     return (
       pieces["b"].join("") +
@@ -607,6 +556,22 @@ export const VariantRules = class BaroqueRules extends ChessRules {
     );
   }
 
+  static get VALUES() {
+    return {
+      p: 1,
+      r: 2,
+      n: 5,
+      b: 3,
+      q: 3,
+      m: 5,
+      k: 1000
+    };
+  }
+
+  static get SEARCH_DEPTH() {
+    return 2;
+  }
+
   getNotation(move) {
     const initialSquare = V.CoordsToSquare(move.start);
     const finalSquare = V.CoordsToSquare(move.end);