From 35ff9d1b79c050a7b8304bd725221aaee57f7209 Mon Sep 17 00:00:00 2001 From: Benjamin Auder Date: Sat, 2 May 2020 14:27:48 +0200 Subject: [PATCH] Add Rampage Chess --- client/src/translations/en.js | 1 + client/src/translations/es.js | 1 + client/src/translations/fr.js | 1 + client/src/translations/rules/Rampage/en.pug | 29 +++++++ client/src/translations/rules/Rampage/es.pug | 30 +++++++ client/src/translations/rules/Rampage/fr.pug | 30 +++++++ client/src/variants/Rampage.js | 83 ++++++++++++++++++-- server/db/populate.sql | 1 + 8 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 client/src/translations/rules/Rampage/en.pug create mode 100644 client/src/translations/rules/Rampage/es.pug create mode 100644 client/src/translations/rules/Rampage/fr.pug diff --git a/client/src/translations/en.js b/client/src/translations/en.js index a72cf612..8b7daa72 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -210,6 +210,7 @@ export const translations = { "Mongolian Horde": "Mongolian Horde", "Move like a knight (v1)": "Move like a knight (v1)", "Move like a knight (v2)": "Move like a knight (v2)", + "Move under cover": "Move under cover", "Neverending rows": "Neverending rows", "No-check mode": "No-check mode", "Non-conformism and utopia": "Non-conformism and utopia", diff --git a/client/src/translations/es.js b/client/src/translations/es.js index 10e5422b..4b5c2759 100644 --- a/client/src/translations/es.js +++ b/client/src/translations/es.js @@ -210,6 +210,7 @@ export const translations = { "Mongolian Horde": "Horda mongol", "Move like a knight (v1)": "Moverse como un caballo (v1)", "Move like a knight (v2)": "Moverse como un caballo (v2)", + "Move under cover": "Ir bajo cubierta", "Neverending rows": "Filas interminables", "No-check mode": "Modo sin jaque", "Non-conformism and utopia": "No-conformismo y utopía", diff --git a/client/src/translations/fr.js b/client/src/translations/fr.js index c4de1448..8684b286 100644 --- a/client/src/translations/fr.js +++ b/client/src/translations/fr.js @@ -210,6 +210,7 @@ export const translations = { "Mongolian Horde": "Horde mongole", "Move like a knight (v1)": "Bouger comme un cavalier (v1)", "Move like a knight (v2)": "Bouger comme un cavalier (v2)", + "Move under cover": "Avancez à couvert", "Neverending rows": "Rangées sans fin", "No-check mode": "Mode sans échec", "Non-conformism and utopia": "Non-conformisme et utopie", diff --git a/client/src/translations/rules/Rampage/en.pug b/client/src/translations/rules/Rampage/en.pug new file mode 100644 index 00000000..a7ddca75 --- /dev/null +++ b/client/src/translations/rules/Rampage/en.pug @@ -0,0 +1,29 @@ +p.boxed + | Units may move to any square that is guarded by more friendly units + | than enemy units. + +p. + In addition to their usual abilities, pieces may jump to controlled squares, + that is to say squares attacked by more friendly pieces than enemy pieces. + The king in check may only move as in orthodox chess, but "rampage" moves + of other pieces are allowed to cover the check. + +p. + Attacks on the same row, file or diagonal are cumulative. So, + on the next diagram the marked square (e5) is guarded twice by each side: + "rampage" moves to that square are impossible. + +figure.diagram-container + .diagram + | fen:k7/p7/2n1r3/8/8/8/4R2P/4Q2K e5: + figcaption No repositioning moves to e5. + +h3 Source + +p + | This variant is + a(href="https://www.chessvariants.com/play/erf/RampageC.html") + | mentioned here + | . + +p Inventor: Bruce R. Trose (1976) diff --git a/client/src/translations/rules/Rampage/es.pug b/client/src/translations/rules/Rampage/es.pug new file mode 100644 index 00000000..4fedc77f --- /dev/null +++ b/client/src/translations/rules/Rampage/es.pug @@ -0,0 +1,30 @@ +p.boxed + | Las piezas pueden moverse en cualquier espacio defendido por más de + | piezas amigas que piezas enemigas. + +p. + Además de sus capacidades habituales, las piezas pueden saltar a + espacios controlados, es decir, espacios atacados por más piezas del + mismo lado que las piezas opuestas. + El rey en jaque solo puede hacer movimientos normales, pero las jugadas + "rampage" de las otras piezas pueden contrarrestar el jaque. + +p. + Los ataques a la misma columna, fila o diagonal son acumulativos. Entonces + en el siguiente diagrama, la casilla marcada (e5) es defendida dos veces por + cada lado: los movimientos "rampage" hacia esta casilla son imposibles. + +figure.diagram-container + .diagram + | fen:k7/p7/2n1r3/8/8/8/4R2P/4Q2K e5: + figcaption No movimientos de reposicionamiento a e5. + +h3 Fuente + +p + | Esta variante es + a(href="https://www.chessvariants.com/play/erf/RampageC.html") + | mencionada aquí + | . + +p Inventor: Bruce R. Trose (1976) diff --git a/client/src/translations/rules/Rampage/fr.pug b/client/src/translations/rules/Rampage/fr.pug new file mode 100644 index 00000000..d0a57f5f --- /dev/null +++ b/client/src/translations/rules/Rampage/fr.pug @@ -0,0 +1,30 @@ +p.boxed + | Les pièces peuvent se déplacer sur toute case défendue par plus de + | pièces amies que de pièces ennemies. + +p. + En plus de leurs capacités habituelles, les pièces peuvent sauter vers des + cases controlées, c'est-à-dire des cases attaquées par plus de pièces du + même camp que de pièces adverses. + Le roi en échec ne peut effectuer que des coups normaux, mais les coups + "rampage" des autres pièces sont autorisés pour parer l'échec. + +p. + Les attaques sur la même colonne, rangée ou diagonale se cumulent. Ainsi, + sur le diagramme suivant la case marquée (e5) est défendue deux fois par + chaque camp : les coups "rampage" vers cette case sont impossibles. + +figure.diagram-container + .diagram + | fen:k7/p7/2n1r3/8/8/8/4R2P/4Q2K e5: + figcaption Pas de coups de repositionnement vers e5. + +h3 Source + +p + | Cette variante est + a(href="https://www.chessvariants.com/play/erf/RampageC.html") + | mentionnée ici + | . + +p Inventeur : Bruce R. Trose (1976) diff --git a/client/src/variants/Rampage.js b/client/src/variants/Rampage.js index 31d4f359..2fe96db6 100644 --- a/client/src/variants/Rampage.js +++ b/client/src/variants/Rampage.js @@ -1,10 +1,81 @@ import { ChessRules } from "@/base_rules"; -// Plan : garder intact isAttacked, -// ajouter "guarded" qui somme les attaques blanches et soustrait les attaques noires sur une case -// (regarder toutes directions, OK) -// --> boulot à faire sur chaque case vide, après chaque getPotentialMoves() -// --> sauf si le roi est en échec (avant de jouer). - export class RampageRules extends ChessRules { + // Sum white pieces attacking a square, and remove black pieces count. + sumAttacks([x, y]) { + const getSign = (color) => { + return (color == 'w' ? 1 : -1); + }; + let res = 0; + // Knights: + V.steps[V.KNIGHT].forEach(s => { + const [i, j] = [x + s[0], y + s[1]]; + if (V.OnBoard(i, j) && this.getPiece(i, j) == V.KNIGHT) + res += getSign(this.getColor(i, j)); + }); + // Kings: + V.steps[V.ROOK].concat(V.steps[V.BISHOP]).forEach(s => { + const [i, j] = [x + s[0], y + s[1]]; + if (V.OnBoard(i, j) && this.getPiece(i, j) == V.KING) + res += getSign(this.getColor(i, j)); + }); + // Pawns: + for (let c of ['w', 'b']) { + for (let shift of [-1, 1]) { + const sign = getSign(c); + const [i, j] = [x + sign, y + shift]; + if ( + V.OnBoard(i, j) && + this.getPiece(i, j) == V.PAWN && + this.getColor(i, j) == c + ) { + res += sign; + } + } + } + // Other pieces (sliders): + V.steps[V.ROOK].concat(V.steps[V.BISHOP]).forEach(s => { + let [i, j] = [x + s[0], y + s[1]]; + let compatible = [V.QUEEN]; + compatible.push(s[0] == 0 || s[1] == 0 ? V.ROOK : V.BISHOP); + let firstCol = undefined; + while (V.OnBoard(i, j)) { + if (this.board[i][j] != V.EMPTY) { + if (!(compatible.includes(this.getPiece(i, j)))) break; + const colIJ = this.getColor(i, j); + if (!firstCol) firstCol = colIJ; + if (colIJ == firstCol) res += getSign(colIJ); + else break; + } + i += s[0]; + j += s[1]; + } + }); + return res; + } + + getPotentialMovesFrom([x, y]) { + let moves = super.getPotentialMovesFrom([x, y]); + const color = this.turn; + if (this.getPiece(x, y) == V.KING && this.underCheck(color)) + // The king under check can only move as usual + return moves; + // Remember current final squares to not add moves twice: + const destinations = {}; + moves.forEach(m => destinations[m.end.x + "_" + m.end.y] = true); + for (let i=0; i<8; i++) { + for (let j=0; j<8; j++) { + if (this.board[i][j] == V.EMPTY && !destinations[i + "_" + j]) { + const sa = this.sumAttacks([i, j]); + if ((color == 'w' && sa > 0) || (color == 'b' && sa < 0)) + moves.push(this.getBasicMove([x, y], [i, j])); + } + } + } + return moves; + } + + static get SEARCH_DEPTH() { + return 1; + } }; diff --git a/server/db/populate.sql b/server/db/populate.sql index 49419674..97f78bc4 100644 --- a/server/db/populate.sql +++ b/server/db/populate.sql @@ -70,6 +70,7 @@ insert or ignore into Variants (name, description) values ('Parachute', 'Landing on the board'), ('Perfect', 'Powerful pieces'), ('Racingkings', 'Kings cross the 8x8 board'), + ('Rampage', 'Move under cover'), ('Rifle', 'Shoot pieces'), ('Recycle', 'Reuse pieces'), ('Rococo', 'Capture on the edge'), -- 2.44.0