Some fixes + draft newmove pingback logic (unfinished, not working)
[vchess.git] / client / src / base_rules.js
index 8b49436..b39fe9c 100644 (file)
@@ -197,12 +197,13 @@ export const ChessRules = class ChessRules {
     const move = moveOrSquare;
     const s = move.start,
           e = move.end;
-    // NOTE: next conditions are first for Atomic, and last for Checkered
+    // NOTE: next conditions are first for Crazyhouse, and last for Checkered
+    // TODO: Checkered exceptions are too weird and should move in its own file.
     if (
-      move.appear.length > 0 &&
+      move.vanish.length > 0 &&
       Math.abs(s.x - e.x) == 2 &&
       s.y == e.y &&
-      move.appear[0].p == V.PAWN &&
+      move.vanish[0].p == V.PAWN &&
       ["w", "b"].includes(move.appear[0].c)
     ) {
       return {
@@ -238,11 +239,20 @@ export const ChessRules = class ChessRules {
   /////////////
   // FEN UTILS
 
-  // Setup the initial random (assymetric) position
-  static GenRandInitFen() {
+  // Setup the initial random (asymmetric) position
+  static GenRandInitFen(randomness) {
+    if (randomness == 0)
+      // Deterministic:
+      return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0 1111 -";
+
     let pieces = { w: new Array(8), b: new Array(8) };
-    // Shuffle pieces on first and last rank
+    // Shuffle pieces on first (and last rank if randomness == 2)
     for (let c of ["w", "b"]) {
+      if (c == 'b' && randomness == 1) {
+        pieces['b'] = pieces['w'];
+        break;
+      }
+
       let positions = ArrayFun.range(8);
 
       // Get random squares for bishops
@@ -310,16 +320,24 @@ export const ChessRules = class ChessRules {
   // Return current fen (game state)
   getFen() {
     return (
-      this.getBaseFen() +
-      " " +
-      this.getTurnFen() +
-      " " +
+      this.getBaseFen() + " " +
+      this.getTurnFen() + " " +
       this.movesCount +
       (V.HasFlags ? " " + this.getFlagsFen() : "") +
       (V.HasEnpassant ? " " + this.getEnpassantFen() : "")
     );
   }
 
+  getFenForRepeat() {
+    // Omit movesCount, only variable allowed to differ
+    return (
+      this.getBaseFen() + "_" +
+      this.getTurnFen() +
+      (V.HasFlags ? "_" + this.getFlagsFen() : "") +
+      (V.HasEnpassant ? "_" + this.getEnpassantFen() : "")
+    );
+  }
+
   // Position part of the FEN string
   getBaseFen() {
     let position = "";
@@ -395,14 +413,12 @@ export const ChessRules = class ChessRules {
   //////////////////
   // INITIALIZATION
 
-  constructor(fen) {
-    // In printDiagram() fen isn't supply because only getPpath() is used
-    if (fen)
-      this.re_init(fen);
-  }
-
   // Fen string fully describes the game state
-  re_init(fen) {
+  constructor(fen) {
+    if (!fen)
+      // In printDiagram() fen isn't supply because only getPpath() is used
+      // TODO: find a better solution!
+      return;
     const fenParsed = V.ParseFen(fen);
     this.board = V.GetBoard(fenParsed.position);
     this.turn = fenParsed.turn[0]; //[0] to work with MarseilleRules
@@ -1114,30 +1130,17 @@ export const ChessRules = class ChessRules {
     return 3;
   }
 
-  // NOTE: works also for extinction chess because depth is 3...
   getComputerMove() {
     const maxeval = V.INFINITY;
     const color = this.turn;
     // Some variants may show a bigger moves list to the human (Switching),
     // thus the argument "computer" below (which is generally ignored)
-    let moves1 = this.getAllValidMoves("computer");
+    let moves1 = this.getAllValidMoves();
 
     if (moves1.length == 0)
       // TODO: this situation should not happen
       return null;
 
-    // Can I mate in 1 ? (for Magnetic & Extinction)
-    for (let i of shuffle(ArrayFun.range(moves1.length))) {
-      this.play(moves1[i]);
-      let finish = Math.abs(this.evalPosition()) >= V.THRESHOLD_MATE;
-      if (!finish) {
-        const score = this.getCurrentScore();
-        if (["1-0", "0-1"].includes(score)) finish = true;
-      }
-      this.undo(moves1[i]);
-      if (finish) return moves1[i];
-    }
-
     // Rank moves using a min-max at depth 2
     for (let i = 0; i < moves1.length; i++) {
       // Initial self evaluation is very low: "I'm checkmated"
@@ -1149,7 +1152,7 @@ export const ChessRules = class ChessRules {
         // Initial enemy evaluation is very low too, for him
         eval2 = (color == "w" ? 1 : -1) * maxeval;
         // Second half-move:
-        let moves2 = this.getAllValidMoves("computer");
+        let moves2 = this.getAllValidMoves();
         for (let j = 0; j < moves2.length; j++) {
           this.play(moves2[j]);
           const score2 = this.getCurrentScore();
@@ -1185,6 +1188,7 @@ export const ChessRules = class ChessRules {
     moves1.sort((a, b) => {
       return (color == "w" ? 1 : -1) * (b.eval - a.eval);
     });
+//    console.log(moves1.map(m => { return [this.getNotation(m), m.eval]; }));
 
     let candidates = [0]; //indices of candidates moves
     for (let j = 1; j < moves1.length && moves1[j].eval == moves1[0].eval; j++)
@@ -1225,7 +1229,7 @@ export const ChessRules = class ChessRules {
     if (score != "*")
       return score == "1/2" ? 0 : (score == "1-0" ? 1 : -1) * maxeval;
     if (depth == 0) return this.evalPosition();
-    const moves = this.getAllValidMoves("computer");
+    const moves = this.getAllValidMoves();
     let v = color == "w" ? -maxeval : maxeval;
     if (color == "w") {
       for (let i = 0; i < moves.length; i++) {