From 31e9e40ad45faba38612982cfb1d6bdfd98ae20f Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Sun, 23 Feb 2020 17:17:36 +0100 Subject: [PATCH] Draft Suction Chess --- client/src/translations/en.js | 1 + client/src/translations/es.js | 1 + client/src/translations/fr.js | 1 + client/src/translations/rules/Suction/en.pug | 37 ++++ client/src/translations/rules/Suction/es.pug | 39 +++++ client/src/translations/rules/Suction/fr.pug | 39 +++++ client/src/variants/Magnetic.js | 7 +- client/src/variants/Suction.js | 169 +++++++++++++++++++ server/db/populate.sql | 1 + 9 files changed, 292 insertions(+), 3 deletions(-) create mode 100644 client/src/translations/rules/Suction/en.pug create mode 100644 client/src/translations/rules/Suction/es.pug create mode 100644 client/src/translations/rules/Suction/fr.pug create mode 100644 client/src/variants/Suction.js diff --git a/client/src/translations/en.js b/client/src/translations/en.js index f2495d8f..d1759ebc 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -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", diff --git a/client/src/translations/es.js b/client/src/translations/es.js index d45f870f..3698845f 100644 --- a/client/src/translations/es.js +++ b/client/src/translations/es.js @@ -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", diff --git a/client/src/translations/fr.js b/client/src/translations/fr.js index 016a2cd8..647c35e7 100644 --- a/client/src/translations/fr.js +++ b/client/src/translations/fr.js @@ -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 index 00000000..60ccf6ae --- /dev/null +++ b/client/src/translations/rules/Suction/en.pug @@ -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 + |  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 index 00000000..685b7552 --- /dev/null +++ b/client/src/translations/rules/Suction/es.pug @@ -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 + |  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 index 00000000..2097062b --- /dev/null +++ b/client/src/translations/rules/Suction/fr.pug @@ -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 + |  sur chessvariants.com. diff --git a/client/src/variants/Magnetic.js b/client/src/variants/Magnetic.js index c2201d60..fedd2492 100644 --- a/client/src/variants/Magnetic.js +++ b/client/src/variants/Magnetic.js @@ -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 index 00000000..bfb9fa00 --- /dev/null +++ b/client/src/variants/Suction.js @@ -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]; + } +}; diff --git a/server/db/populate.sql b/server/db/populate.sql index 80f2e0b3..2876ba78 100644 --- a/server/db/populate.sql +++ b/server/db/populate.sql @@ -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'); -- 2.44.0