From: Benjamin Auder Date: Wed, 18 Mar 2020 07:56:59 +0000 (+0100) Subject: Add Cannibal variant X-Git-Url: https://git.auder.net/%7B%7B%20asset%28%27mixstore/images/assets/current/doc/%7B%7B?a=commitdiff_plain;h=dfc782637eeb231c82515461ec167f0375ed1e1e;p=vchess.git Add Cannibal variant --- diff --git a/client/src/translations/en.js b/client/src/translations/en.js index 4267fa41..c0c95a29 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -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", diff --git a/client/src/translations/es.js b/client/src/translations/es.js index fe6509e9..c9f30e93 100644 --- a/client/src/translations/es.js +++ b/client/src/translations/es.js @@ -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", diff --git a/client/src/translations/fr.js b/client/src/translations/fr.js index b29ccb7a..b02969f8 100644 --- a/client/src/translations/fr.js +++ b/client/src/translations/fr.js @@ -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 index 00000000..5335038a --- /dev/null +++ b/client/src/translations/rules/Cannibal/en.pug @@ -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 + |  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 index 00000000..60b75a5b --- /dev/null +++ b/client/src/translations/rules/Cannibal/es.pug @@ -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 + |  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 index 00000000..344a7f8e --- /dev/null +++ b/client/src/translations/rules/Cannibal/fr.pug @@ -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 + |  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 index 00000000..fc0ef0b5 --- /dev/null +++ b/client/src/variants/Cannibal.js @@ -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; + } +}; diff --git a/server/db/populate.sql b/server/db/populate.sql index c37709b7..a1921062 100644 --- a/server/db/populate.sql +++ b/server/db/populate.sql @@ -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'),