Add Cannibal variant
authorBenjamin Auder <benjamin.auder@somewhere>
Wed, 18 Mar 2020 07:56:59 +0000 (08:56 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Wed, 18 Mar 2020 07:56:59 +0000 (08:56 +0100)
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Cannibal/en.pug [new file with mode: 0644]
client/src/translations/rules/Cannibal/es.pug [new file with mode: 0644]
client/src/translations/rules/Cannibal/fr.pug [new file with mode: 0644]
client/src/variants/Cannibal.js [new file with mode: 0644]
server/db/populate.sql

index 4267fa4..c0c95a2 100644 (file)
@@ -160,6 +160,7 @@ export const translations = {
   "Both sides of the mirror": "Both sides of the mirror",
   "Capture all of a kind": "Capture all of a kind",
   "Capture en passant": "Capture en passant",
+  "Capture powers": "Capture powers",
   "Captures reborn": "Captures reborn",
   "Change colors": "Change colors",
   "Dangerous collisions": "Dangerous collisions",
index fe6509e..c9f30e9 100644 (file)
@@ -160,6 +160,7 @@ export const translations = {
   "Both sides of the mirror": "Ambos lados del espejo",
   "Capture all of a kind": "Capturar todo del mismo tipo",
   "Capture en passant": "Capturar en passant",
+  "Capture powers": "Capturar los poderes",
   "Captures reborn": "Las capturas renacen",
   "Change colors": "Cambiar colores",
   "Dangerous collisions": "Colisiones peligrosas",
index b29ccb7..b02969f 100644 (file)
@@ -160,6 +160,7 @@ export const translations = {
   "Both sides of the mirror": "Les deux côté du miroir",
   "Capture all of a kind": "Capturez tout d'un même type",
   "Capture en passant": "Capturer en passant",
+  "Capture powers": "Capturer les pouvoirs",
   "Captures reborn": "Les captures renaissent",
   "Change colors": "Changer les couleurs",
   "Dangerous collisions": "Collisions dangeureuses",
diff --git a/client/src/translations/rules/Cannibal/en.pug b/client/src/translations/rules/Cannibal/en.pug
new file mode 100644 (file)
index 0000000..5335038
--- /dev/null
@@ -0,0 +1,24 @@
+p.boxed
+  | Captures are mandatory, with transformation into the captured piece.
+
+p.
+  Everything is the same as in orthodox rules, except that when possible,
+  captures are forced.
+  The goal is still to checkmate, and stalemate is a draw.
+
+p.
+  After each capture the capturer takes the nature of the captured piece.
+  For example after 1.e4 a6 2.Bxa6 is forced and a6 is now a white pawn.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/1ppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR a6:
+  figcaption After 1.e4 a6, 2.Bxa6 turns the bishop into a pawn.
+
+p If the king captures, it transforms as well but stays royal.
+
+h3 More information
+
+p
+  a(href="https://www.chessvariants.com/difftaking.dir/cannibal.html") Cannibal Chess
+  | &nbsp;on chessvariants.com. I added the forced captures for more fun.
diff --git a/client/src/translations/rules/Cannibal/es.pug b/client/src/translations/rules/Cannibal/es.pug
new file mode 100644 (file)
index 0000000..60b75a5
--- /dev/null
@@ -0,0 +1,26 @@
+p.boxed
+  | Las capturas son obligatorias, con transformación en la pieza capturada.
+
+p.
+  Todo va como el ajedrez ortodoxo, pero cuando es posible
+  las capturas son forzadas.
+  El objetivo aún es de matar, y el empate es tablas.
+
+p.
+  Después de cada captura, el atacante toma la naturaleza de la pieza capturada.
+  Por ejemplo, después de 1.e4 a6 2.Bxa6 es forzado y a6 ahora es un peón blanco.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/pppp1pp1/7p/4P3/8/8/PPP1PPPP/RNBQKBNR:
+  figcaption Después de 1.e4 a6, 2.Bxa6 transforma el alfil en un peón.
+
+p Si el rey captura, también se transforma pero permanece real.
+
+h3 Más información
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/difftaking.dir/cannibal.html") variante Cannibal
+  | &nbsp;en chessvariants.com.
+  | Esta regla me parece más divertida con las capturas obligatorias.
diff --git a/client/src/translations/rules/Cannibal/fr.pug b/client/src/translations/rules/Cannibal/fr.pug
new file mode 100644 (file)
index 0000000..344a7f8
--- /dev/null
@@ -0,0 +1,26 @@
+p.boxed
+  | Les captures sont obligatoires, avec transformation en la pièce capturée.
+
+p.
+  Tout se déroule comme aux échecs orthodoxes, mais quand elles sont possibles
+  les captures sont forcées.
+  L'objectif est toujours de mater, et le pat fait nulle.
+
+p.
+  Après chaque capture, l'attaquant prend la nature de la pièce capturée.
+  Par exemple après 1.e4 a6 2.Bxa6 est forcé et a6 est maintenant un pion blanc.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/1ppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR a6:
+  figcaption Après 1.e4 a6, 2.Bxa6 transforme le fou en un pion.
+
+p Si le roi capture, il se transforme aussi mais reste royal.
+
+h3 Plus d'information
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/difftaking.dir/cannibal.html") variante Cannibal
+  | &nbsp;sur chessvariants.com.
+  | Cett règle me paraît plus amusante avec des captures obligatoires.
diff --git a/client/src/variants/Cannibal.js b/client/src/variants/Cannibal.js
new file mode 100644 (file)
index 0000000..fc0ef0b
--- /dev/null
@@ -0,0 +1,62 @@
+import { ChessRules } from "@/base_rules";
+
+export class CannibalRules extends ChessRules {
+  // Trim all non-capturing moves
+  static KeepCaptures(moves) {
+    return moves.filter(m => m.vanish.length == 2 && m.appear.length == 1);
+  }
+
+       // 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.filterValid(this.getPotentialMovesFrom([i, j])).some(m =>
+            // Warning: discard castle moves
+            m.vanish.length == 2 && m.appear.length == 1)
+        ) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  getPotentialMovesFrom([x, y]) {
+    let moves = super.getPotentialMovesFrom([x, y]);
+    // Transform capturers, except for the king
+    moves.forEach(m => {
+      if (
+        m.appear[0].p != V.KING &&
+        m.vanish.length == 2 &&
+        m.appear.length == 1 &&
+        m.vanish[0].p != m.vanish[1].p
+      ) {
+        m.appear[0].p = m.vanish[1].p;
+      }
+    });
+    return moves;
+  }
+
+  getPossibleMovesFrom(sq) {
+    let moves = this.filterValid(this.getPotentialMovesFrom(sq));
+    const captureMoves = V.KeepCaptures(moves);
+    if (captureMoves.length > 0) return captureMoves;
+    if (this.atLeastOneCapture()) return [];
+    return moves;
+  }
+
+  getAllValidMoves() {
+    const moves = super.getAllValidMoves();
+    if (moves.some(m => m.vanish.length == 2)) return V.KeepCaptures(moves);
+    return moves;
+  }
+
+  static get SEARCH_DEPTH() {
+    return 4;
+  }
+};
index c37709b..a192106 100644 (file)
@@ -12,6 +12,7 @@ insert or ignore into Variants (name,description) values
   ('Baroque', 'Exotic captures'),
   ('Benedict', 'Change colors'),
   ('Berolina', 'Pawns move diagonally'),
+  ('Cannibal', 'Capture powers'),
   ('Capture', 'Mandatory captures'),
   ('Checkered', 'Shared pieces'),
   ('Chess960', 'Standard rules'),