Draft Suction Chess
authorBenjamin Auder <benjamin.auder@somewhere>
Sun, 23 Feb 2020 16:17:36 +0000 (17:17 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Sun, 23 Feb 2020 16:17:36 +0000 (17:17 +0100)
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Suction/en.pug [new file with mode: 0644]
client/src/translations/rules/Suction/es.pug [new file with mode: 0644]
client/src/translations/rules/Suction/fr.pug [new file with mode: 0644]
client/src/variants/Magnetic.js
client/src/variants/Suction.js [new file with mode: 0644]
server/db/populate.sql

index f2495d8..d1759eb 100644 (file)
@@ -125,6 +125,7 @@ export const translations = {
   "Your message": "Your message",
 
   // Variants boxes:
+  "Attract opposite king": "Attract opposite king",
   "Balanced sliders & leapers": "Balanced sliders & leapers",
   "Big board": "Big board",
   "Board upside down": "Board upside down",
index d45f870..3698845 100644 (file)
@@ -125,6 +125,7 @@ export const translations = {
   "Your message": "Tu mensaje",
 
   // Variants boxes:
+  "Attract opposite king": "Atraer al rey contrario",
   "Balanced sliders & leapers": "Modos de desplazamiento equilibrados",
   "Big board": "Gran tablero",
   "Board upside down": "Tablero al revés",
index 016a2cd..647c35e 100644 (file)
@@ -125,6 +125,7 @@ export const translations = {
   "Your message": "Votre message",
 
   // Variants boxes:
+  "Attract opposite king": "Attirer le roi adverse",
   "Balanced sliders & leapers": "Modes de déplacement équilibrés",
   "Big board": "Grand échiquier",
   "Board upside down": "Échiquier à l'envers",
diff --git a/client/src/translations/rules/Suction/en.pug b/client/src/translations/rules/Suction/en.pug
new file mode 100644 (file)
index 0000000..60ccf6a
--- /dev/null
@@ -0,0 +1,37 @@
+p.boxed
+  | Captures swap pieces. Goal is to bring enemy king to your first row.
+
+p.
+  When a piece is taken it is not removed from the board, but moved instead
+  to the square that was initially occupied by the capturing piece.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkb1r/ppp1pppp/5B2/3p4/8/1P6/PnPPPPPP/RN1QKBNR:
+  figcaption After 1.b3 d5 2.Bb2 Nf6 3.Bxf6
+
+ul
+  li.
+    The king cannot move at all, except by being captured by one of the
+    opponent's pieces. There is no castling.
+  li Taking a king has no effect besides moving it.
+
+p.
+  Pawns don't promote, but instead just stay on the back rank where they
+  can't move. A pawn can still re-enter play after this happens,
+  by being captured.
+
+h3 End of the game
+
+p The goal is to "suck" the opponent's king to your own first rank.
+
+figure.diagram-container
+  .diagram
+    | fen:2Pb3r/1rP3nq/1p2p2p/p1p2NpP/1P2R2k/P3p2P/pN1PP1B1/R1BnQ1Kb:
+  figcaption White can win with 1.Qxh4
+
+h3 Source
+
+p
+  a(href="https://www.chessvariants.com/rules/suction-chess") Suction chess
+  | &nbsp;on chessvariants.com.
diff --git a/client/src/translations/rules/Suction/es.pug b/client/src/translations/rules/Suction/es.pug
new file mode 100644 (file)
index 0000000..685b755
--- /dev/null
@@ -0,0 +1,39 @@
+p.boxed
+  | Las capturas intercambian las piezas.
+  | El objetivo es llevar al rey contrario a tu primera fila.
+
+p.
+  Cuando se captura una pieza, no se retira del tablero, sino
+  solo se movió a la casilla originalmente ocupada por la pieza que capturó.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkb1r/ppp1pppp/5B2/3p4/8/1P6/PnPPPPPP/RN1QKBNR:
+  figcaption Después de 1.b3 d5 2.Bb2 Nf6 3.Bxf6
+
+ul
+  li.
+    El rey no puede moverse excepto ser capturado por uno de los
+    piezas opuestas. No hay enroque.
+  li Tomar al rey no tiene otro efecto que moverlo.
+
+p.
+  Los peones no son promovidos: permanecen en la última fila desde donde
+  ya no puede moverse. Sin embargo, dicho peón puede volver al juego
+  siendo capturado.
+
+h3 Fin de la partida
+
+p El objetivo es "absorber" al rey contrario a tu primera fila.
+
+figure.diagram-container
+  .diagram
+    | fen:2Pb3r/1rP3nq/1p2p2p/p1p2NpP/1P2R2k/P3p2P/pN1PP1B1/R1BnQ1Kb:
+  figcaption White puede ganar con 1.Dxh4
+
+h3 Fuente
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/rules/suction-chess") variante Succión
+  | &nbsp;en chessvariants.com.
diff --git a/client/src/translations/rules/Suction/fr.pug b/client/src/translations/rules/Suction/fr.pug
new file mode 100644 (file)
index 0000000..2097062
--- /dev/null
@@ -0,0 +1,39 @@
+p.boxed
+  | Les captures échangent les pièces.
+  | L'objectif est d'amener le roi adverse sur votre première rangée.
+
+p.
+  Quand une pièce est capturée elle n'est pas retirée de l'échiquier, mais
+  seulement déplacée sur la case initialement occupée par la pièce capturante.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkb1r/ppp1pppp/5B2/3p4/8/1P6/PnPPPPPP/RN1QKBNR:
+  figcaption Après 1.b3 d5 2.Bb2 Nf6 3.Bxf6
+
+ul
+  li.
+    Le roi ne peut pas se déplacer, sauf en en étant capturé par l'une des
+    pièces adverses. Il n'y a pas de roque.
+  li Prendre le roi n'a aucun autre effet que de le déplacer.
+
+p.
+  Les pions ne sont pas promus : ils restent sur la dernière rangée d'où ils
+  ne peuvent plus bouger. Un tel pion peut cependant revenir dans le jeu
+  en étant capturé.
+
+h3 Fin de la partie
+
+p Le but est d'"aspirer" le roi adverse jusqu'à votre première rangée.
+
+figure.diagram-container
+  .diagram
+    | fen:2Pb3r/1rP3nq/1p2p2p/p1p2NpP/1P2R2k/P3p2P/pN1PP1B1/R1BnQ1Kb:
+  figcaption White can win with 1.Qxh4
+
+h3 Source
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/rules/suction-chess") variante Suction
+  | &nbsp;sur chessvariants.com.
index c2201d6..fedd249 100644 (file)
@@ -136,8 +136,9 @@ export const VariantRules = class MagneticRules extends ChessRules {
     return true; //TODO: is it right?
   }
 
-  underCheck() {
-    return false; //there is no check
+  filterValid(moves) {
+    // There are no checks
+    return moves;
   }
 
   getCheckSquares() {
@@ -189,7 +190,7 @@ export const VariantRules = class MagneticRules extends ChessRules {
     const color = this.turn;
     const kp = this.kingPos[color];
     if (kp[0] < 0)
-      //king disappeared
+      // King disappeared
       return color == "w" ? "0-1" : "1-0";
     if (this.atLeastOneMove())
       // game not over
diff --git a/client/src/variants/Suction.js b/client/src/variants/Suction.js
new file mode 100644 (file)
index 0000000..bfb9fa0
--- /dev/null
@@ -0,0 +1,169 @@
+import { ChessRules, PiPo, Move } from "@/base_rules";
+
+export const VariantRules = class AntimatterRules extends ChessRules {
+  getBasicMove([sx, sy], [ex, ey]) {
+    const startColor = this.getColor(sx, sy);
+    const startPiece = this.getPiece(sx, sy);
+    let mv = new Move({
+      appear: [
+        new PiPo({
+          x: ex,
+          y: ey,
+          c: startColor,
+          p: startPiece
+        })
+      ],
+      vanish: [
+        new PiPo({
+          x: sx,
+          y: sy,
+          c: startColor,
+          p: startPiece
+        })
+      ]
+    });
+
+    if (this.board[ex][ey] != V.EMPTY) {
+      const endColor = this.getColor(ex, ey);
+      const endPiece = this.getPiece(ex, ey);
+      mv.vanish.push(
+        new PiPo({
+          x: ex,
+          y: ey,
+          c: endColor,
+          p: endPiece
+        })
+      );
+      mv.appear.push(
+        new PiPo({
+          x: sx,
+          y: sy,
+          c: endColor,
+          p: endPiece
+        })
+      );
+    }
+    return mv;
+  }
+
+  getPotentialPawnMoves([x, y]) {
+    const color = this.turn;
+    let moves = [];
+    const [sizeX, sizeY] = [V.size.x, V.size.y];
+    const shiftX = color == "w" ? -1 : 1;
+    const startRank = color == "w" ? sizeX - 2 : 1;
+    const firstRank = color == "w" ? sizeX - 1 : 0;
+
+    if (x + shiftX >= 0 && x + shiftX < sizeX) {
+      // One square forward
+      if (this.board[x + shiftX][y] == V.EMPTY) {
+        moves.push(
+          this.getBasicMove([x, y], [x + shiftX, y], {
+            c: color,
+            p: "p"
+          })
+        );
+        if (
+          [startRank,firstRank].includes(x) &&
+          this.board[x + 2 * shiftX][y] == V.EMPTY
+        ) {
+          // Two squares jump
+          moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
+        }
+      }
+      // Swaps
+      for (let shiftY of [-1, 1]) {
+        if (
+          y + shiftY >= 0 &&
+          y + shiftY < sizeY &&
+          this.board[x + shiftX][y + shiftY] != V.EMPTY &&
+          this.canTake([x, y], [x + shiftX, y + shiftY])
+        ) {
+          moves.push(
+            this.getBasicMove([x, y], [x + shiftX, y + shiftY], {
+              c: color,
+              p: "p"
+            })
+          );
+        }
+      }
+    }
+
+    // En passant
+    const Lep = this.epSquares.length;
+    const epSquare = this.epSquares[Lep - 1]; //always at least one element
+    if (
+      !!epSquare &&
+      epSquare.x == x + shiftX &&
+      Math.abs(epSquare.y - y) == 1
+    ) {
+      let enpassantMove = this.getBasicMove([x, y], [epSquare.x, epSquare.y]);
+      const oppCol = V.GetOppCol(color);
+      enpassantMove.vanish.push({
+        x: x,
+        y: epSquare.y,
+        p: "p",
+        c: oppCol
+      });
+      enpassantMove.appear.push({
+        x: x,
+        y: y,
+        p: "p",
+        c: oppCol
+      });
+      moves.push(enpassantMove);
+    }
+
+    return moves;
+  }
+
+  getPotentialKingMoves() {
+    return [];
+  }
+
+  updateVariables(move) {
+    super.updateVariables(move);
+    if (move.vanish.length == 2) {
+      // Was opponent king swapped?
+      if (move.vanish[1].p == V.KING)
+        this.kingPos[this.turn] = [move.appear[1].x, move.appear[1].y];
+    }
+  }
+
+  unupdateVariables(move) {
+    super.unupdateVariables(move);
+    if (move.appear.length == 2) {
+      // Was opponent king swapped?
+      if (move.appear[1].p == V.KING)
+        this.kingPos[move.vanish[1].c] = [move.vanish[1].x,move.vanish[1].y];
+    }
+  }
+
+  atLeastOneMove() {
+    return true;
+  }
+
+  filterValid(moves) {
+    return moves;
+  }
+
+  getCheckSquares() {
+    return [];
+  }
+
+  getCurrentScore() {
+    const color = this.turn;
+    const kp = this.kingPos[color];
+    if (color == "w" && kp[0] == 0)
+      return "0-1";
+    if (color == "b" && kp[0] == V.size.x - 1)
+      return "1-0";
+    // King is not on the opposite edge: game not over
+    return "*";
+  }
+
+  evalPosition() {
+    // Very simple criterion for now: kings position
+    return this.kingPos["w"][0] + this.kingPos["b"][0];
+  }
+};
index 80f2e0b..2876ba7 100644 (file)
@@ -20,6 +20,7 @@ insert or ignore into Variants (name,description) values
   ('Magnetic', 'Laws of attraction'),
   ('Marseille', 'Move twice'),
   ('Recycle', 'Reuse pieces'),
+  ('Suction', 'Attract opposite king'),
   ('Upsidedown', 'Board upside down'),
   ('Wildebeest', 'Balanced sliders & leapers'),
   ('Zen', 'Reverse captures');