Fix computer moves randomness, rename random() into randInt()
[vchess.git] / client / src / base_rules.js
index 087b4f5..5fb0027 100644 (file)
@@ -2,7 +2,7 @@
 // Variants generally inherit from it, and modify some parts.
 
 import { ArrayFun } from "@/utils/array";
-import { random, sample, shuffle } from "@/utils/alea";
+import { randInt, sample, shuffle } from "@/utils/alea";
 
 export const PiPo = class PiPo //Piece+Position
 {
@@ -50,13 +50,13 @@ export const ChessRules = class ChessRules
   // Turn "wb" into "B" (for FEN)
   static board2fen(b)
   {
-    return b[0]=='w' ? b[1].toUpperCase() : b[1];
+    return (b[0]=='w' ? b[1].toUpperCase() : b[1]);
   }
 
   // Turn "p" into "bp" (for board)
   static fen2board(f)
   {
-    return f.charCodeAt()<=90 ? "w"+f.toLowerCase() : "b"+f;
+    return (f.charCodeAt()<=90 ? "w"+f.toLowerCase() : "b"+f);
   }
 
   // Check if FEN describe a position
@@ -243,25 +243,25 @@ export const ChessRules = class ChessRules
       let positions = ArrayFun.range(8);
 
       // Get random squares for bishops
-      let randIndex = 2 * random(4);
+      let randIndex = 2 * randInt(4);
       const bishop1Pos = positions[randIndex];
       // The second bishop must be on a square of different color
-      let randIndex_tmp = 2 * random(4) + 1;
+      let randIndex_tmp = 2 * randInt(4) + 1;
       const 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 = random(6);
+      randIndex = randInt(6);
       const knight1Pos = positions[randIndex];
       positions.splice(randIndex, 1);
-      randIndex = random(5);
+      randIndex = randInt(5);
       const knight2Pos = positions[randIndex];
       positions.splice(randIndex, 1);
 
       // Get random square for queen
-      randIndex = random(4);
+      randIndex = randInt(4);
       const queenPos = positions[randIndex];
       positions.splice(randIndex, 1);
 
@@ -409,8 +409,13 @@ export const ChessRules = class ChessRules
   //////////////////
   // INITIALIZATION
 
-  // Fen string fully describes the game state
   constructor(fen)
+  {
+    this.re_init(fen);
+  }
+
+  // Fen string fully describes the game state
+  re_init(fen)
   {
     const fenParsed = V.ParseFen(fen);
     this.board = V.GetBoard(fenParsed.position);
@@ -1057,8 +1062,6 @@ export const ChessRules = class ChessRules
       move.flags = JSON.stringify(this.aggregateFlags()); //save flags (for undo)
     if (V.HasEnpassant)
       this.epSquares.push( this.getEpSquare(move) );
-    if (!move.color)
-      move.color = this.turn; //for interface
     V.PlayOnBoard(this.board, move);
     this.turn = V.GetOppCol(this.turn);
     this.movesCount++;
@@ -1196,12 +1199,11 @@ export const ChessRules = class ChessRules
       candidates.push(j);
     let currentBest = moves1[sample(candidates)];
 
-    // From here, depth >= 3: may take a while, so we control time
-    const timeStart = Date.now();
-
     // Skip depth 3+ if we found a checkmate (or if we are checkmated in 1...)
     if (V.SEARCH_DEPTH >= 3 && Math.abs(moves1[0].eval) < V.THRESHOLD_MATE)
     {
+      // From here, depth >= 3: may take a while, so we control time
+      const timeStart = Date.now();
       for (let i=0; i<moves1.length; i++)
       {
         if (Date.now()-timeStart >= 5000) //more than 5 seconds
@@ -1222,7 +1224,7 @@ export const ChessRules = class ChessRules
     candidates = [0];
     for (let j=1; j<moves1.length && moves1[j].eval == moves1[0].eval; j++)
       candidates.push(j);
-    return moves1[sample(candidates)];
+    return moves1[candidates[randInt(candidates.length)]];
   }
 
   alphabeta(depth, alpha, beta)