Pandemonium 1 & 2, Stealthbomb 1 & 2
authorBenjamin Auder <benjamin.auder@somewhere>
Thu, 25 Mar 2021 11:18:43 +0000 (12:18 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Thu, 25 Mar 2021 11:18:43 +0000 (12:18 +0100)
27 files changed:
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Pandemonium1/en.pug [moved from client/src/translations/rules/Pandemonium/en.pug with 100% similarity]
client/src/translations/rules/Pandemonium1/es.pug [moved from client/src/translations/rules/Pandemonium/es.pug with 100% similarity]
client/src/translations/rules/Pandemonium1/fr.pug [moved from client/src/translations/rules/Pandemonium/fr.pug with 100% similarity]
client/src/translations/rules/Pandemonium2/en.pug [new file with mode: 0644]
client/src/translations/rules/Pandemonium2/es.pug [new file with mode: 0644]
client/src/translations/rules/Pandemonium2/fr.pug [new file with mode: 0644]
client/src/translations/rules/Stealthbomb1/en.pug [moved from client/src/translations/rules/Stealthbomb/en.pug with 96% similarity]
client/src/translations/rules/Stealthbomb1/es.pug [moved from client/src/translations/rules/Stealthbomb/es.pug with 96% similarity]
client/src/translations/rules/Stealthbomb1/fr.pug [moved from client/src/translations/rules/Stealthbomb/fr.pug with 96% similarity]
client/src/translations/rules/Stealthbomb2/en.pug [new file with mode: 0644]
client/src/translations/rules/Stealthbomb2/es.pug [new file with mode: 0644]
client/src/translations/rules/Stealthbomb2/fr.pug [new file with mode: 0644]
client/src/translations/rules/Wildebeest/en.pug
client/src/translations/rules/Wildebeest/es.pug
client/src/translations/rules/Wildebeest/fr.pug
client/src/translations/variants/en.pug
client/src/translations/variants/es.pug
client/src/translations/variants/fr.pug
client/src/variants/Pandemonium1.js [new file with mode: 0644]
client/src/variants/Pandemonium2.js [moved from client/src/variants/Pandemonium.js with 78% similarity]
client/src/variants/Stealthbomb1.js [moved from client/src/variants/Stealthbomb.js with 97% similarity]
client/src/variants/Stealthbomb2.js [new file with mode: 0644]
client/src/variants/Wildebeest.js
server/db/populate.sql

index a86b6e1..38155cf 100644 (file)
@@ -181,7 +181,8 @@ export const translations = {
   "Augmented Queens": "Augmented Queens",
   "Balanced sliders & leapers": "Balanced sliders & leapers",
   "Baroque Music": "Baroque Music",
-  "Beware the bomb": "Beware the bomb",
+  "Beware the bomb (v1)": "Beware the bomb (v1)",
+  "Beware the bomb (v2)": "Beware the bomb (v2)",
   "Big board": "Big board",
   "Bishop versus pawns": "Bishop versus pawns",
   "Board upside down": "Board upside down",
@@ -277,7 +278,8 @@ export const translations = {
   "New fairy pieces": "New fairy pieces",
   "No paralyzed pieces": "No paralyzed pieces",
   "No-check mode": "No-check mode",
-  "Noise and confusion": "Noise and confusion",
+  "Noise and confusion (v1)": "Noise and confusion (v1)",
+  "Noise and confusion (v2)": "Noise and confusion (v2)",
   "Non-conformism and utopia": "Non-conformism and utopia",
   "Occupy the enemy palace": "Occupy the enemy palace",
   "Paralyzed pieces": "Paralyzed pieces",
index a5cd67b..9e8088b 100644 (file)
@@ -181,7 +181,8 @@ export const translations = {
   "Augmented Queens": "Damas aumentadas",
   "Balanced sliders & leapers": "Modos de desplazamiento equilibrados",
   "Baroque Music": "Música Barroca",
-  "Beware the bomb": "Cuidado con la bomba",
+  "Beware the bomb (v1)": "Cuidado con la bomba (v1)",
+  "Beware the bomb (v2)": "Cuidado con la bomba (v2)",
   "Big board": "Gran tablero",
   "Bishop versus pawns": "Alfil contra peones",
   "Board upside down": "Tablero al revés",
@@ -277,7 +278,8 @@ export const translations = {
   "New fairy pieces": "Nuevas piezas magicas",
   "No paralyzed pieces": "No piezas paralizadas",
   "No-check mode": "Modo sin jaque",
-  "Noise and confusion": "Ruido y confusión",
+  "Noise and confusion (v1)": "Ruido y confusión (v1)",
+  "Noise and confusion (v2)": "Ruido y confusión (v2)",
   "Non-conformism and utopia": "No-conformismo y utopía",
   "Occupy the enemy palace": "Ocupar el palacio enemigo",
   "Paralyzed pieces": "Piezas paralizadas",
index 9ca4717..c095bb0 100644 (file)
@@ -181,7 +181,8 @@ export const translations = {
   "Augmented Queens": "Dames augmentées",
   "Balanced sliders & leapers": "Modes de déplacement équilibrés",
   "Baroque Music": "Musique Baroque",
-  "Beware the bomb": "Attention à la bombe",
+  "Beware the bomb (v1)": "Attention à la bombe (v1)",
+  "Beware the bomb (v2)": "Attention à la bombe (v2)",
   "Big board": "Grand échiquier",
   "Bishop versus pawns": "Fou contre pions",
   "Board upside down": "Échiquier à l'envers",
@@ -277,7 +278,8 @@ export const translations = {
   "New fairy pieces": "Nouvelles pièces féériques",
   "No paralyzed pieces": "Pas de pièces paralysées",
   "No-check mode": "Mode sans échec",
-  "Noise and confusion": "Bruit et confusion",
+  "Noise and confusion (v1)": "Bruit et confusion (v1)",
+  "Noise and confusion (v2)": "Bruit et confusion (v2)",
   "Non-conformism and utopia": "Non-conformisme et utopie",
   "Occupy the enemy palace": "Occuper le palais ennemi",
   "Paralyzed pieces": "Pièces paralysées",
diff --git a/client/src/translations/rules/Pandemonium2/en.pug b/client/src/translations/rules/Pandemonium2/en.pug
new file mode 100644 (file)
index 0000000..8f1570f
--- /dev/null
@@ -0,0 +1,14 @@
+p.boxed
+  | All pieces can promote. Captured units can be dropped later.
+  | 10x8 board. Some new pieces.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkmcbnr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR:
+  figcaption Initial deterministic position.
+
+p
+  a(href="/#/variants/Pandemonium1") Pandemonium1
+  | &nbsp;on a 10x8 board.
+  | Pawns move as in orthodox chess, and promotions
+  | occur only on the final rank.
diff --git a/client/src/translations/rules/Pandemonium2/es.pug b/client/src/translations/rules/Pandemonium2/es.pug
new file mode 100644 (file)
index 0000000..863d3e4
--- /dev/null
@@ -0,0 +1,14 @@
+p.boxed
+  | Todas las piezas pueden promocionarse. Las unidades capturadas son
+  | en paracaídas más tarde. Tablero de ajedrez 10x8. Algunas piezas nuevas.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkmcbnr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR:
+  figcaption Posición inicial determinista.
+
+p
+  a(href="/#/variants/Pandemonium1") Pandemonium1
+  | &nbsp;en un tablero 10x8.
+  | Los peones se mueven como en el ajedrez ortodoxo,
+  | y las promociones solo ocurren en la última fila.
diff --git a/client/src/translations/rules/Pandemonium2/fr.pug b/client/src/translations/rules/Pandemonium2/fr.pug
new file mode 100644 (file)
index 0000000..c70bd96
--- /dev/null
@@ -0,0 +1,14 @@
+p.boxed
+  | Toutes les pièces peuvent être promues. Les unités capturées sont
+  | parachutées plus tard. Échiquier 10x8. Quelques nouvelles pièces.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkmcbnr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR:
+  figcaption Position initiale déterministe.
+
+p
+  a(href="/#/variants/Pandemonium1") Pandemonium1
+  | &nbsp;sur un échiquier 10x8.
+  | Les pions se déplacent comme aux échecs orthodoxes,
+  | et les promotions ne surviennent que sur la dernière rangée.
@@ -29,3 +29,5 @@ p
   | . This variant is Stealthbomber on 
   a(href="fishrandom.io") fishrandom.io
   | , and "Stealthbomb" here... why not :-)
+
+p Inventor: Jim Winslow (1992)
@@ -29,3 +29,5 @@ p
   | . Esta variante es Stealthbomber en 
   a(href="fishrandom.io") fishrandom.io
   | , y "Stealthbomb" aquí... ¿Por qué no? :-)
+
+p Inventor: Jim Winslow (1992)
@@ -29,3 +29,5 @@ p
   | . Cette variante est Stealthbomber sur 
   a(href="fishrandom.io") fishrandom.io
   | , et "Stealthbomb" ici... pourquoi pas :-)
+
+p Inventeur : Jim Winslow (1992)
diff --git a/client/src/translations/rules/Stealthbomb2/en.pug b/client/src/translations/rules/Stealthbomb2/en.pug
new file mode 100644 (file)
index 0000000..6ee7beb
--- /dev/null
@@ -0,0 +1,7 @@
+p.boxed.
+  One pawn of each side hides a bomb,
+  which can be triggered instead of playing a move.
+
+p
+  a(href="/#/variants/Stealthbomb1") Stealthbomb1
+  | , where only pawns can hold a bomb.
diff --git a/client/src/translations/rules/Stealthbomb2/es.pug b/client/src/translations/rules/Stealthbomb2/es.pug
new file mode 100644 (file)
index 0000000..b41a979
--- /dev/null
@@ -0,0 +1,7 @@
+p.boxed.
+  Un peon de cada campamento esconde una bomba,
+  que se puede activar en lugar de ejecutar un movimiento.
+
+p
+  a(href="/#/variants/Stealthbomb1") Stealthbomb1
+  | , donde solo los peones pueden llevar una bomba.
diff --git a/client/src/translations/rules/Stealthbomb2/fr.pug b/client/src/translations/rules/Stealthbomb2/fr.pug
new file mode 100644 (file)
index 0000000..14a90b8
--- /dev/null
@@ -0,0 +1,7 @@
+p.boxed.
+  Un pion de chaque camp cache une bombe,
+  qui peut être déclenchée au lieu de jouer un coup.
+
+p
+  a(href="/#/variants/Stealthbomb1") Stealthbomb1
+  | , où seuls les pions peuvent porter une bombe.
index 5f0b631..16323ee 100644 (file)
@@ -24,8 +24,9 @@ p.
   which will end next to him on the other side.
 
 p.
-  When a pawn reaches last rank, it can promote
-  into a queen or a wildebeest (only).
+  When a pawn reaches the last rank, it promotes into a queen or a
+  wildebeest (only). Promotion is also possible (optionally) on 9th rank.
+  This is an experimental addition to the official rules.
 
 h3 Source
 
index a407e33..e5e6d7d 100644 (file)
@@ -24,7 +24,10 @@ p.
   el rey puede saltar cualquier número de casillas (libres) a la torre,
   que terminará junto a él en el otro lado.
 
-p Un peón en la última fila es promovido a dama o ñu solamente.
+p.
+  Un peón que llega a la última fila es promovido a dama o ñu solamente.
+  La promoción también es posible (opcionalmente) en la novena fila.
+  Es una adición experimental a las reglas oficiales.
 
 h3 Fuente
 
index fb04759..52dfc3d 100644 (file)
@@ -26,7 +26,8 @@ p.
 
 p.
   Un pion arrivé sur la dernière rangée se promeut en une dame ou un gnou
-  seulement.
+  seulement. La promotion est également possible (optionnellement)
+  sur la 9eme rangée. C'est un ajout expérimental aux règles officielles.
 
 h3 Source
 
index c933d9c..0da0179 100644 (file)
@@ -222,7 +222,8 @@ p.
     "Dark",
     "Hidden",
     "Hiddenqueen",
-    "Stealthbomb",
+    "Stealthbomb1",
+    "Stealthbomb2",
     "Synchrone1",
     "Synchrone2"
   ]
@@ -480,7 +481,8 @@ p.
     "Iceage",
     "Kingsmaker",
     "Magnetic",
-    "Pandemonium",
+    "Pandemonium1",
+    "Pandemonium2",
     "Refusal1",
     "Refusal2",
     "Relayup",
index 81fad93..cc246bd 100644 (file)
@@ -229,7 +229,8 @@ p.
     "Dark",
     "Hidden",
     "Hiddenqueen",
-    "Stealthbomb",
+    "Stealthbomb1",
+    "Stealthbomb2",
     "Synchrone1",
     "Synchrone2"
   ]
@@ -490,7 +491,8 @@ p.
     "Iceage",
     "Kingsmaker",
     "Magnetic",
-    "Pandemonium",
+    "Pandemonium1",
+    "Pandemonium2",
     "Refusal1",
     "Refusal2",
     "Relayup",
index 6743ce2..ae68c66 100644 (file)
@@ -228,7 +228,8 @@ p.
     "Dark",
     "Hidden",
     "Hiddenqueen",
-    "Stealthbomb",
+    "Stealthbomb1",
+    "Stealthbomb2",
     "Synchrone1",
     "Synchrone2"
   ]
@@ -488,7 +489,8 @@ p.
     "Iceage",
     "Kingsmaker",
     "Magnetic",
-    "Pandemonium",
+    "Pandemonium1",
+    "Pandemonium2",
     "Refusal1",
     "Refusal2",
     "Relayup",
diff --git a/client/src/variants/Pandemonium1.js b/client/src/variants/Pandemonium1.js
new file mode 100644 (file)
index 0000000..579ee9c
--- /dev/null
@@ -0,0 +1,128 @@
+import { Pandemonium2Rules } from "@/variants/Pandemonium2";
+
+export class Pandemonium1Rules extends Pandemonium2Rules {
+
+  static get PawnSpecs() {
+    return Object.assign(
+      { },
+      Pandemonium2Rules.PawnSpecs,
+      { threeSquares: true }
+    );
+  }
+
+  static get size() {
+    return { x: 10, y: 10};
+  }
+
+  static IsGoodEnpassant(enpassant) {
+    if (enpassant != "-") {
+      const squares = enpassant.split(",");
+      if (squares.length > 2) return false;
+      for (let sq of squares) {
+        if (!sq.match(/[a-j0-9]/)) return false;
+      }
+    }
+    return true;
+  }
+
+  static GenRandInitFen(randomness) {
+    const baseFen = Pandemonium2Rules.GenRandInitFen(randomness)
+    return baseFen.substr(0, 22) + "91/91/" + baseFen.substr(22);
+  }
+
+  getEnpassantFen() {
+    const L = this.epSquares.length;
+    if (!this.epSquares[L - 1]) return "-"; //no en-passant
+    let res = "";
+    this.epSquares[L - 1].forEach(sq => {
+      res += V.CoordsToSquare(sq) + ",";
+    });
+    return res.slice(0, -1); //remove last comma
+  }
+
+  getEpSquare(moveOrSquare) {
+    if (!moveOrSquare) return undefined;
+    if (typeof moveOrSquare === "string") {
+      const square = moveOrSquare;
+      if (square == "-") return undefined;
+      let res = [];
+      square.split(",").forEach(sq => {
+        res.push(V.SquareToCoords(sq));
+      });
+      return res;
+    }
+    // Argument is a move:
+    const move = moveOrSquare;
+    const [sx, sy, ex] = [move.start.x, move.start.y, move.end.x];
+    if (this.getPiece(sx, sy) == V.PAWN && Math.abs(sx - ex) >= 2) {
+      const step = (ex - sx) / Math.abs(ex - sx);
+      let res = [{
+        x: sx + step,
+        y: sy
+      }];
+      if (sx + 2 * step != ex) {
+        // 3-squares jump
+        res.push({
+          x: sx + 2 * step,
+          y: sy
+        });
+      }
+      return res;
+    }
+    return undefined; //default
+  }
+
+  applyPromotions(moves, promoted) {
+    const lastRanks = (this.turn == 'w' ? [0, 1] : [V.size.x - 1, V.size.x]);
+    let promotions = [];
+    moves.forEach(m => {
+      if (lastRanks.includes(m.start.x) || lastRanks.includes(m.end.x)) {
+        let pMove = JSON.parse(JSON.stringify(m));
+        pMove.appear[0].p = promoted;
+        promotions.push(pMove);
+      }
+    });
+    Array.prototype.push.apply(moves, promotions);
+  }
+
+  addPawnMoves([x1, y1], [x2, y2], moves) {
+    const color = this.turn;
+    const lastRanks = (color == "w" ? [0, 1] : [V.size.x - 1, V.size.x - 2]);
+    if (!lastRanks.includes(x2)) {
+      moves.push(this.getBasicMove([x1, y1], [x2, y2]));
+      return;
+    }
+    let finalPieces = [V.GILDING];
+    if (x2 == lastRanks[1]) finalPieces.push(V.PAWN);
+    for (let piece of finalPieces) {
+      const tr = (piece != V.PAWN ? { c: color, p: piece } : null);
+      moves.push(this.getBasicMove([x1, y1], [x2, y2], tr));
+    }
+  }
+
+  getEnpassantCaptures([x, y], shiftX) {
+    const Lep = this.epSquares.length;
+    const epSquare = this.epSquares[Lep - 1];
+    let moves = [];
+    if (!!epSquare) {
+      for (let epsq of epSquare) {
+        // TODO: some redundant checks
+        if (epsq.x == x + shiftX && Math.abs(epsq.y - y) == 1) {
+          let enpassantMove = this.getBasicMove([x, y], [epsq.x, epsq.y]);
+          // WARNING: the captured pawn may be diagonally behind us,
+          // if it's a 3-squares jump and we take on 1st passing square
+          const px = this.board[x][epsq.y] != V.EMPTY ? x : x - shiftX;
+          enpassantMove.vanish.push({
+            x: px,
+            y: epsq.y,
+            p: "p",
+            c: this.getColor(px, epsq.y)
+          });
+          moves.push(enpassantMove);
+        }
+      }
+    }
+    return moves;
+  }
+
+};
similarity index 78%
rename from client/src/variants/Pandemonium.js
rename to client/src/variants/Pandemonium2.js
index 4894ec1..7951608 100644 (file)
@@ -2,7 +2,15 @@ import { ChessRules, Move, PiPo } from "@/base_rules";
 import { randInt } from "@/utils/alea";
 import { ArrayFun } from "@/utils/array";
 
-export class PandemoniumRules extends ChessRules {
+export class Pandemonium2Rules extends ChessRules {
+
+  static get PawnSpecs() {
+    return Object.assign(
+      { },
+      ChessRules.PawnSpecs,
+      { promotions: [V.GILDING] }
+    );
+  }
 
   loseOnRepetition() {
     // If current side is under check: lost
@@ -55,7 +63,7 @@ export class PandemoniumRules extends ChessRules {
   }
 
   static get size() {
-    return { x: 10, y: 10};
+    return { x: 8, y: 10};
   }
 
   getColor(i, j) {
@@ -97,17 +105,6 @@ export class PandemoniumRules extends ChessRules {
     };
   }
 
-  static IsGoodEnpassant(enpassant) {
-    if (enpassant != "-") {
-      const squares = enpassant.split(",");
-      if (squares.length > 2) return false;
-      for (let sq of squares) {
-        if (!sq.match(/[a-j0-9]/)) return false;
-      }
-    }
-    return true;
-  }
-
   static IsGoodFen(fen) {
     if (!ChessRules.IsGoodFen(fen)) return false;
     const fenParsed = V.ParseFen(fen);
@@ -145,7 +142,7 @@ export class PandemoniumRules extends ChessRules {
   static GenRandInitFen(randomness) {
     if (randomness == 0) {
       return (
-        "rnbqkmcbnr/pppppppppp/91/91/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR " +
+        "rnbqkmcbnr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR " +
         "w 0 ajaj - 00000000000000"
       );
     }
@@ -212,48 +209,6 @@ export class PandemoniumRules extends ChessRules {
     );
   }
 
-  getEnpassantFen() {
-    const L = this.epSquares.length;
-    if (!this.epSquares[L - 1]) return "-"; //no en-passant
-    let res = "";
-    this.epSquares[L - 1].forEach(sq => {
-      res += V.CoordsToSquare(sq) + ",";
-    });
-    return res.slice(0, -1); //remove last comma
-  }
-
-  getEpSquare(moveOrSquare) {
-    if (!moveOrSquare) return undefined;
-    if (typeof moveOrSquare === "string") {
-      const square = moveOrSquare;
-      if (square == "-") return undefined;
-      let res = [];
-      square.split(",").forEach(sq => {
-        res.push(V.SquareToCoords(sq));
-      });
-      return res;
-    }
-    // Argument is a move:
-    const move = moveOrSquare;
-    const [sx, sy, ex] = [move.start.x, move.start.y, move.end.x];
-    if (this.getPiece(sx, sy) == V.PAWN && Math.abs(sx - ex) >= 2) {
-      const step = (ex - sx) / Math.abs(ex - sx);
-      let res = [{
-        x: sx + step,
-        y: sy
-      }];
-      if (sx + 2 * step != ex) {
-        // 3-squares jump
-        res.push({
-          x: sx + 2 * step,
-          y: sy
-        });
-      }
-      return res;
-    }
-    return undefined; //default
-  }
-
   getReservePpath(index, color) {
     const p = V.RESERVE_PIECES[index];
     const prefix = (ChessRules.PIECES.includes(p) ? "" : "Pandemonium/");
@@ -316,6 +271,19 @@ export class PandemoniumRules extends ChessRules {
     };
   }
 
+  applyPromotions(moves, promoted) {
+    const lastRank = (this.turn == 'w' ? 0 : V.size.x - 1);
+    let promotions = [];
+    moves.forEach(m => {
+      if ([m.start.x, m.end.x].includes(lastRank)) {
+        let pMove = JSON.parse(JSON.stringify(m));
+        pMove.appear[0].p = promoted;
+        promotions.push(pMove);
+      }
+    });
+    Array.prototype.push.apply(moves, promotions);
+  }
+
   getPotentialMovesFrom([x, y]) {
     const c = this.getColor(x, y);
     const oppCol = V.GetOppCol(c);
@@ -331,12 +299,12 @@ export class PandemoniumRules extends ChessRules {
           })
         ];
       }
-      const firstRank = (this.movesCount == 0 ? 9 : 0);
+      const firstRank = (this.movesCount == 0 ? V.size.x - 1 : 0);
       if (x != firstRank || this.getPiece(x, y) != V.KNIGHT) return [];
       // Swap with who? search for matching bishop:
       let knights = [],
           bishops = [];
-      for (let i = 0; i < 10; i++) {
+      for (let i = 0; i < V.size.y; i++) {
         const elt = this.board[x][i][1];
         if (elt == 'n') knights.push(i);
         else if (elt == 'b') bishops.push(i);
@@ -404,73 +372,8 @@ export class PandemoniumRules extends ChessRules {
         break;
     }
     // Maybe apply promotions:
-    if (Object.keys(V.PromoteMap).includes(p)) {
-      const promoted = V.PromoteMap[p];
-      const lastRanks = (c == 'w' ? [0, 1] : [9, 8]);
-      let promotions = [];
-      moves.forEach(m => {
-        if (lastRanks.includes(m.start.x) || lastRanks.includes(m.end.x)) {
-          let pMove = JSON.parse(JSON.stringify(m));
-          pMove.appear[0].p = promoted;
-          promotions.push(pMove);
-        }
-      });
-      Array.prototype.push.apply(moves, promotions);
-    }
-    return moves;
-  }
-
-  addPawnMoves([x1, y1], [x2, y2], moves) {
-    const color = this.turn;
-    const lastRanks = (color == "w" ? [0, 1] : [9, 8]);
-    if (!lastRanks.includes(x2)) {
-      moves.push(this.getBasicMove([x1, y1], [x2, y2]));
-      return;
-    }
-    let finalPieces = [V.GILDING];
-    if (x2 == lastRanks[1]) finalPieces.push(V.PAWN);
-    for (let piece of finalPieces) {
-      const tr = (piece != V.PAWN ? { c: color, p: piece } : null);
-      moves.push(this.getBasicMove([x1, y1], [x2, y2], tr));
-    }
-  }
-
-  getPotentialPawnMoves([x, y]) {
-    const color = this.turn;
-    const shiftX = (color == 'w' ? -1 : 1);
-    let moves = [];
-    if (this.board[x + shiftX][y] == V.EMPTY) {
-      this.addPawnMoves([x, y], [x + shiftX, y], moves);
-      if ((color == 'w' && x >= V.size.x - 3) || (color == 'b' && x <= 2)) {
-        if (this.board[x + 2 * shiftX][y] == V.EMPTY) {
-          moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
-          if (
-            (
-              (color == 'w' && x == V.size.x - 2) ||
-              (color == 'b' && x == 1)
-            )
-            &&
-            this.board[x + 3 * shiftX][y] == V.EMPTY
-          ) {
-            moves.push(this.getBasicMove([x, y], [x + 3 * shiftX, y]));
-          }
-        }
-      }
-    }
-    for (let shiftY of [-1, 1]) {
-      if (y + shiftY >= 0 && y + shiftY < V.size.y) {
-        if (
-          this.board[x + shiftX][y + shiftY] != V.EMPTY &&
-          this.canTake([x, y], [x + shiftX, y + shiftY])
-        ) {
-          this.addPawnMoves([x, y], [x + shiftX, y + shiftY], moves);
-        }
-      }
-    }
-    Array.prototype.push.apply(
-      moves,
-      this.getEnpassantCaptures([x, y], shiftX)
-    );
+    if (Object.keys(V.PromoteMap).includes(p))
+      this.applyPromotions(moves, V.PromoteMap[p]);
     return moves;
   }
 
@@ -502,31 +405,6 @@ export class PandemoniumRules extends ChessRules {
       this.getSlideNJumpMoves(sq, V.steps[V.BISHOP], "oneStep"));
   }
 
-  getEnpassantCaptures([x, y], shiftX) {
-    const Lep = this.epSquares.length;
-    const epSquare = this.epSquares[Lep - 1];
-    let moves = [];
-    if (!!epSquare) {
-      for (let epsq of epSquare) {
-        // TODO: some redundant checks
-        if (epsq.x == x + shiftX && Math.abs(epsq.y - y) == 1) {
-          let enpassantMove = this.getBasicMove([x, y], [epsq.x, epsq.y]);
-          // WARNING: the captured pawn may be diagonally behind us,
-          // if it's a 3-squares jump and we take on 1st passing square
-          const px = this.board[x][epsq.y] != V.EMPTY ? x : x - shiftX;
-          enpassantMove.vanish.push({
-            x: px,
-            y: epsq.y,
-            p: "p",
-            c: this.getColor(px, epsq.y)
-          });
-          moves.push(enpassantMove);
-        }
-      }
-    }
-    return moves;
-  }
-
   getPotentialKingMoves(sq) {
     // Initialize with normal moves
     let moves = this.getSlideNJumpMoves(
similarity index 97%
rename from client/src/variants/Stealthbomb.js
rename to client/src/variants/Stealthbomb1.js
index ee73ef5..dce7f5a 100644 (file)
@@ -1,6 +1,6 @@
 import { ChessRules, Move, PiPo } from "@/base_rules";
 
-export class StealthbombRules extends ChessRules {
+export class Stealthbomb1Rules extends ChessRules {
 
   static get CanAnalyze() {
     return false;
@@ -84,7 +84,7 @@ export class StealthbombRules extends ChessRules {
       this.movesCount >= 2 ||
       (
         (c == 'w' && square[0] < 6) ||
-        (c == 'b' && square[0] > 2)
+        (c == 'b' && square[0] > 1)
       )
     ) {
       return null;
@@ -94,7 +94,8 @@ export class StealthbombRules extends ChessRules {
     return new Move({
       appear: [ new PiPo({ x: x, y: y, c: c, p: V.BOMB_CODE[piece] }) ],
       vanish: [ new PiPo({ x: x, y: y, c: c, p: piece }) ],
-      start: { x: -1, y: -1 }
+      start: { x: -1, y: -1 },
+      end: { x: x, y: y, noHighlight: true }
     });
   }
 
diff --git a/client/src/variants/Stealthbomb2.js b/client/src/variants/Stealthbomb2.js
new file mode 100644 (file)
index 0000000..613a5c2
--- /dev/null
@@ -0,0 +1,27 @@
+import { Move, PiPo } from "@/base_rules";
+import { Stealthbomb1Rules } from "@/variants/Stealthbomb1";
+
+export class Stealthbomb2Rules extends Stealthbomb1Rules {
+
+  // Initiate the game by choosing a square for the bomb:
+  doClick(square) {
+    const c = this.turn;
+    if (
+      this.movesCount >= 2 ||
+      (
+        (c == 'w' && square[0] != 6) ||
+        (c == 'b' && square[0] != 1)
+      )
+    ) {
+      return null;
+    }
+    const [x, y] = square;
+    return new Move({
+      appear: [ new PiPo({ x: x, y: y, c: c, p: 's' }) ],
+      vanish: [ new PiPo({ x: x, y: y, c: c, p: 'p' }) ],
+      start: { x: -1, y: -1 },
+      end: { x: x, y: y, noHighlight: true }
+    });
+  }
+
+};
index a49da9b..93353f9 100644 (file)
@@ -112,10 +112,12 @@ export class WildebeestRules extends ChessRules {
     const [sizeX, sizeY] = [V.size.x, V.size.y];
     const shiftX = color == "w" ? -1 : 1;
     const startRanks = color == "w" ? [sizeX - 2, sizeX - 3] : [1, 2];
-    const lastRank = color == "w" ? 0 : sizeX - 1;
-    const finalPieces = x + shiftX == lastRank
-      ? [V.WILDEBEEST, V.QUEEN]
-      : [V.PAWN];
+    const lastRanks = color == "w" ? [0, 1] : [sizeX - 1, sizeX  -2];
+    let finalPieces = [V.PAWN];
+    if (x + shiftX == lastRanks[1])
+      Array.prototype.push.apply(finalPieces, [V.WILDEBEEST, V.QUEEN]);
+    else if (x + shiftX == lastRanks[0])
+      finalPieces = [V.WILDEBEEST, V.QUEEN];
 
     if (this.board[x + shiftX][y] == V.EMPTY) {
       // One square forward
index 13a4fb8..e7e7b70 100644 (file)
@@ -122,7 +122,8 @@ insert or ignore into Variants (name, description) values
   ('Pacifist1', 'Convert & support (v1)'),
   ('Pacifist2', 'Convert & support (v2)'),
   ('Pacosako', 'Dance with the King'),
-  ('Pandemonium', 'Noise and confusion'),
+  ('Pandemonium1', 'Noise and confusion (v1)'),
+  ('Pandemonium2', 'Noise and confusion (v2)'),
   ('Parachute', 'Landing on the board'),
   ('Pawnmassacre', 'Pieces upside down'),
   ('Pawns', 'Reach the last rank (v1)'),
@@ -156,7 +157,8 @@ insert or ignore into Variants (name, description) values
   ('Spartan', 'Spartan versus Persians'),
   ('Squatter1', 'Squat last rank (v1)'),
   ('Squatter2', 'Squat last rank (v2)'),
-  ('Stealthbomb', 'Beware the bomb'),
+  ('Stealthbomb1', 'Beware the bomb (v1)'),
+  ('Stealthbomb2', 'Beware the bomb (v2)'),
   ('Suicide', 'Lose all pieces'),
   ('Suction', 'Attract opposite king'),
   ('Swap', 'Dangerous captures'),