Split Refusal into Refusal1 + Refusal2, fix endgame bug, remove castling
authorBenjamin Auder <benjamin.auder@somewhere>
Sat, 13 Mar 2021 13:57:48 +0000 (14:57 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Sat, 13 Mar 2021 13:57:48 +0000 (14:57 +0100)
15 files changed:
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Refusal1/en.pug [moved from client/src/translations/rules/Refusal/en.pug with 64% similarity]
client/src/translations/rules/Refusal1/es.pug [moved from client/src/translations/rules/Refusal/es.pug with 70% similarity]
client/src/translations/rules/Refusal1/fr.pug [moved from client/src/translations/rules/Refusal/fr.pug with 69% similarity]
client/src/translations/rules/Refusal2/en.pug [new file with mode: 0644]
client/src/translations/rules/Refusal2/es.pug [new file with mode: 0644]
client/src/translations/rules/Refusal2/fr.pug [new file with mode: 0644]
client/src/translations/variants/en.pug
client/src/translations/variants/es.pug
client/src/translations/variants/fr.pug
client/src/variants/Refusal1.js [moved from client/src/variants/Refusal.js with 79% similarity]
client/src/variants/Refusal2.js [new file with mode: 0644]
server/db/populate.sql

index 502b8bb..50f648a 100644 (file)
@@ -205,7 +205,8 @@ export const translations = {
   "Dance with the King": "Dance with the King",
   "Dangerous captures": "Dangerous captures",
   "Dangerous collisions": "Dangerous collisions",
-  "Do not play that!": "Do not play that!",
+  "Do not play that! (v1)": "Do not play that! (v1)",
+  "Do not play that! (v2)": "Do not play that! (v2)",
   "Double moves (v1)": "Double moves (v1)",
   "Double moves (v2)": "Double moves (v2)",
   "Dynasty versus Kingdom": "Dynasty versus Kingdom",
index 7e39759..74414b9 100644 (file)
@@ -205,7 +205,8 @@ export const translations = {
   "Dance with the King": "Baila con el Rey",
   "Dangerous captures": "Capturas peligrosas",
   "Dangerous collisions": "Colisiones peligrosas",
-  "Do not play that!": "¡No juegues eso!",
+  "Do not play that! (v1)": "¡No juegues eso! (v1)",
+  "Do not play that! (v2)": "¡No juegues eso! (v2)",
   "Double moves (v1)": "Jugadas doble (v1)",
   "Double moves (v2)": "Jugadas doble (v2)",
   "Dynasty versus Kingdom": "Dinastía contra Reino",
index 6d04f40..521df05 100644 (file)
@@ -205,7 +205,8 @@ export const translations = {
   "Dance with the King": "Dansez avec le Roi",
   "Dangerous captures": "Captures dangeureuses",
   "Dangerous collisions": "Collisions dangeureuses",
-  "Do not play that!": "Ne joue pas ça !",
+  "Do not play that! (v1)": "Ne joue pas ça ! (v1)",
+  "Do not play that! (v2)": "Ne joue pas ça ! (v2)",
   "Double moves (v1)": "Coups doubles (v1)",
   "Double moves (v2)": "Coups doubles (v2)",
   "Dynasty versus Kingdom": "Dynastie contre Royaume",
similarity index 64%
rename from client/src/translations/rules/Refusal/en.pug
rename to client/src/translations/rules/Refusal1/en.pug
index c5ad81a..2be7b7f 100644 (file)
@@ -1,16 +1,20 @@
 p.boxed
-  | You can forbid the opponent to play the move he wanted.
+  | You can forbid the opponent to play the move he wanted,
+  | even if only one move is available.
 
 p.
   All rules are as in normal chess, except for the following: each turn,
   a player has the right to refuse at most one move of the opponent.
   To refuse a move, re-play it from end to starting square.
+  To avoid unnecessary complications, castle is not allowed.
 
 p.
   Two moves promoting the same pawn on the same square, but to a
   different type of piece, count as two different moves.
 
-p If a player has only one legal move, this move must be accepted.
+p.
+  If a player has only one legal move, refusing it will end the game,
+  either by checkmate or stalemate (draw).
 
 h3 More information
 
similarity index 70%
rename from client/src/translations/rules/Refusal/es.pug
rename to client/src/translations/rules/Refusal1/es.pug
index c2f75fc..796200d 100644 (file)
@@ -1,16 +1,20 @@
 p.boxed
-  | Puedes evitar que el oponente haga cualquier movimiento que quiera.
+  | Puedes evitar que el oponente haga cualquier movimiento que quiera,
+  | incluso si solo tiene un movimiento legal.
 
 p.
   Todo va como en el ajedrez ortodoxo, excepto por un detalle:
   en cada turno, un jugador tiene derecho a rechazar como máximo una jugada
   del oponente. Para rechazar un movimiento, vuelva a reproducirlo al revés.
+  Para evitar complicaciones innecesarias, no se permite el enroque.
 
 p.
   Dos movimientos, cada uno promoviendo un peón en la misma casilla,
   pero en dos piezas diferentes, se ven como jugadas diferentes.
 
-p Si un jugador tiene solo un movimiento legal, debe ser aceptado.
+p.
+  Si un jugador tiene solo un movimiento legal, su rechazo conduce al final
+  del juego, con jaque mate o empate (dibujar).
 
 h3 Más información
 
similarity index 69%
rename from client/src/translations/rules/Refusal/fr.pug
rename to client/src/translations/rules/Refusal1/fr.pug
index e1b1750..7aa534b 100644 (file)
@@ -1,16 +1,20 @@
 p.boxed
-  | Vous pouvez empêcher l'adversaire de jouer le coup qu'il souhaite.
+  | Vous pouvez empêcher l'adversaire de jouer le coup qu'il souhaite,
+  | même s'il ne dispose que d'un seul coup légal.
 
 p.
   Tout se déroule comme aux échecs orthodoxes, à l'exception d'un détail :
   à chaque tour, un joueur a le droit de refuser au plus un coup adverse.
   Pour refuser un coup, re-jouez le à l'envers.
+  Afin d'éviter les complications inutiles, le roque n'est pas autorisé.
 
 p.
   Deux coups promouvant chacun un pion sur la même case, mais en deux pièces
   différentes, sont vus comme des coups différents.
 
-p Si un joueur n'a qu'un seul coup légal, celui-ci doit être accepté.
+p.
+  Si un joueur n'a qu'un seul coup légal, son refus entraîne la fin de la
+  partie, par échec et mat ou pat (match nul).
 
 h3 Plus d'information
 
diff --git a/client/src/translations/rules/Refusal2/en.pug b/client/src/translations/rules/Refusal2/en.pug
new file mode 100644 (file)
index 0000000..29f741b
--- /dev/null
@@ -0,0 +1,7 @@
+p.boxed
+  | You can forbid the opponent to play the move he wanted,
+  | unless it is the only move available.
+
+p
+  a(href="/#/variants/Refusal1") Refusal1
+  | , but if a player has only one legal move, this move must be accepted.
diff --git a/client/src/translations/rules/Refusal2/es.pug b/client/src/translations/rules/Refusal2/es.pug
new file mode 100644 (file)
index 0000000..00ba425
--- /dev/null
@@ -0,0 +1,7 @@
+p.boxed
+  | Puedes evitar que el oponente haga cualquier movimiento que quiera,
+  | a menos que sea el único movimiento posible.
+
+p
+  a(href="/#/variants/Refusal1") Refusal1
+  | , pero si un jugador tiene solo un movimiento legal, debe ser aceptado.
diff --git a/client/src/translations/rules/Refusal2/fr.pug b/client/src/translations/rules/Refusal2/fr.pug
new file mode 100644 (file)
index 0000000..b1fddd9
--- /dev/null
@@ -0,0 +1,7 @@
+p.boxed
+  | Vous pouvez empêcher l'adversaire de jouer le coup qu'il souhaite,
+  | sauf si c'est le seul coup possible.
+
+p
+  a(href="/#/variants/Refusal1") Refusal1
+  | , mais si un joueur n'a qu'un seul coup légal, celui-ci doit être accepté.
index c380c42..c384bab 100644 (file)
@@ -474,7 +474,8 @@ p.
     "Kingsmaker",
     "Magnetic",
     "Pandemonium",
-    "Refusal",
+    "Refusal1",
+    "Refusal2",
     "Relayup",
     "Rollerball",
     "Selfabsorb",
index 6658c9b..d8151ef 100644 (file)
@@ -484,7 +484,8 @@ p.
     "Kingsmaker",
     "Magnetic",
     "Pandemonium",
-    "Refusal",
+    "Refusal1",
+    "Refusal2",
     "Relayup",
     "Rollerball",
     "Selfabsorb",
index 7d7ab45..19a799d 100644 (file)
@@ -482,7 +482,8 @@ p.
     "Kingsmaker",
     "Magnetic",
     "Pandemonium",
-    "Refusal",
+    "Refusal1",
+    "Refusal2",
     "Relayup",
     "Rollerball",
     "Selfabsorb",
similarity index 79%
rename from client/src/variants/Refusal.js
rename to client/src/variants/Refusal1.js
index 76d737d..4f50d75 100644 (file)
@@ -1,7 +1,11 @@
 import { ChessRules } from "@/base_rules";
 import { randInt } from "@/utils/alea";
 
-export class RefusalRules extends ChessRules {
+export class Refusal1Rules extends ChessRules {
+
+  static get HasFlags() {
+    return false;
+  }
 
   static IsGoodFen(fen) {
     if (!ChessRules.IsGoodFen(fen)) return false;
@@ -11,7 +15,7 @@ export class RefusalRules extends ChessRules {
 
   static ParseFen(fen) {
     return Object.assign(
-      { lastMove: fen.split(" ")[5] },
+      { lastMove: fen.split(" ")[4] },
       ChessRules.ParseFen(fen)
     );
   }
@@ -26,7 +30,7 @@ export class RefusalRules extends ChessRules {
   // some extra repetitions could be detected... TODO (...)
 
   static GenRandInitFen(randomness) {
-    return ChessRules.GenRandInitFen(randomness) + " null";
+    return ChessRules.GenRandInitFen(randomness).slice(0, -6)  + "- null";
   }
 
   setOtherVariables(fen) {
@@ -66,26 +70,6 @@ export class RefusalRules extends ChessRules {
     return super.getPotentialMovesFrom([x, y]);
   }
 
-  // NOTE: do not take refusal move into account here (two own moves)
-  atLeastTwoMoves() {
-    let movesCounter = 0;
-    const color = this.turn;
-    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) == color) {
-          const moves = this.getPotentialMovesFrom([i, j]);
-          for (let m of moves) {
-            if (m.vanish[0].c == color && this.filterValid([m]).length > 0) {
-              movesCounter++;
-              if (movesCounter >= 2) return true;
-            }
-          }
-        }
-      }
-    }
-    return false;
-  }
-
   filterValid(moves) {
     if (moves.length == 0) return [];
     const color = this.turn;
@@ -115,16 +99,13 @@ export class RefusalRules extends ChessRules {
   prePlay(move) {
     const L = this.lastMove.length;
     const lm = this.lastMove[L-1];
-    if (
-      // My previous move was already refused?
-      (!!lm && this.getColor(lm.end.x, lm.end.y) == this.turn) ||
-      // I've only one move available?
-      !this.atLeastTwoMoves()
-    ) {
-      move.noRef = true;
-    }
     // NOTE: refusal could be recomputed, but, it's easier like this
     if (move.vanish[0].c != this.turn) move.refusal = true;
+    move.noRef = (
+      !!move.refusal ||
+      // My previous move was already refused?
+      !!lm && this.getColor(lm.end.x, lm.end.y) == this.turn
+    );
   }
 
   getEpSquare(move) {
@@ -137,7 +118,8 @@ export class RefusalRules extends ChessRules {
     else {
       const L = this.lastMove.length;
       const lm = this.lastMove[L-1];
-      this.disaggregateFlags(JSON.parse(lm.flags));
+      if (move.appear[0].p == V.KING)
+        this.kingPos[move.appear[0].c] = [move.end.x, move.end.y];
     }
     // NOTE: explicitely give fields, because some are assigned in BaseGame
     let mvInLm = {
@@ -145,7 +127,6 @@ export class RefusalRules extends ChessRules {
       end: move.end,
       appear: move.appear,
       vanish: move.vanish,
-      flags: move.flags
     };
     if (!!move.noRef) mvInLm.noRef = true;
     if (!!move.refusal) mvInLm.refusal = true;
@@ -154,6 +135,10 @@ export class RefusalRules extends ChessRules {
 
   postUndo(move) {
     if (!move.refusal) super.postUndo(move);
+    else {
+      if (move.appear[0].p == V.KING)
+        this.kingPos[move.appear[0].c] = [move.start.x, move.start.y];
+    }
     this.lastMove.pop();
   }
 
@@ -162,16 +147,12 @@ export class RefusalRules extends ChessRules {
     const L = this.lastMove.length;
     const lm = this.lastMove[L-1];
     let potentialMoves = [];
+    if (!!lm && !lm.noRef)
+      // Add refusal move:
+      potentialMoves = this.getPotentialMovesFrom([lm.end.x, lm.end.y]);
     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) == color ||
-            // Add move refusal:
-            (!!lm && lm.end.x == i && lm.end.y == j)
-          )
-        ) {
+        if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == color) {
           Array.prototype.push.apply(
             potentialMoves,
             this.getPotentialMovesFrom([i, j])
@@ -182,13 +163,20 @@ export class RefusalRules extends ChessRules {
     return potentialMoves;
   }
 
+  atLeastOneMove() {
+    const L = this.lastMove.length;
+    const lm = this.lastMove[L-1];
+    if (!!lm && !lm.noRef) return true;
+    return super.atLeastOneMove();
+  }
+
   getComputerMove() {
     // Just play at random for now... (TODO?)
     // Refuse last move with odds 1/3.
     const moves = this.getAllValidMoves();
     const refusal = moves.find(m => m.vanish[0].c != this.turn);
     if (!!refusal) {
-      if (Math.random() <= 0.33) return refusal;
+      if (moves.length == 1 || Math.random() <= 0.33) return refusal;
       const others = moves.filter(m => m.vanish[0].c == this.turn);
       return others[randInt(others.length)];
     }
diff --git a/client/src/variants/Refusal2.js b/client/src/variants/Refusal2.js
new file mode 100644 (file)
index 0000000..05eca7a
--- /dev/null
@@ -0,0 +1,40 @@
+import { Refusal1Rules } from "@/variants/Refusal1";
+
+export class Refusal2Rules extends Refusal1Rules {
+
+  // NOTE: do not take refusal move into account here (two own moves)
+  atLeastTwoMoves() {
+    let movesCounter = 0;
+    const color = this.turn;
+    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) == color) {
+          const moves = this.getPotentialMovesFrom([i, j]);
+          for (let m of moves) {
+            if (m.vanish[0].c == color && this.filterValid([m]).length > 0) {
+              movesCounter++;
+              if (movesCounter >= 2) return true;
+            }
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  prePlay(move) {
+    const L = this.lastMove.length;
+    const lm = this.lastMove[L-1];
+    if (
+      // My previous move was already refused?
+      (!!lm && this.getColor(lm.end.x, lm.end.y) == this.turn) ||
+      // I've only one move available?
+      !this.atLeastTwoMoves()
+    ) {
+      move.noRef = true;
+    }
+    // NOTE: refusal could be recomputed, but, it's easier like this
+    if (move.vanish[0].c != this.turn) move.refusal = true;
+  }
+
+};
index 3726f97..aa0dace 100644 (file)
@@ -133,7 +133,8 @@ insert or ignore into Variants (name, description) values
   ('Relayup', 'Upgrade pieces'),
   ('Rifle', 'Shoot pieces'),
   ('Recycle', 'Reuse pieces'),
-  ('Refusal', 'Do not play that!'),
+  ('Refusal1', 'Do not play that! (v1)'),
+  ('Refusal2', 'Do not play that! (v2)'),
   ('Rollerball', 'As in the movie'),
   ('Rococo', 'Capture on the edge'),
   ('Rookpawns', 'Rook versus pawns'),