From: Benjamin Auder Date: Tue, 12 Jan 2021 08:58:32 +0000 (+0100) Subject: Add Joker Chess X-Git-Url: https://git.auder.net/doc/html/index.html?a=commitdiff_plain;h=459edd581fa23f511e224f07554944bbe53a2d70;p=vchess.git Add Joker Chess --- diff --git a/TODO b/TODO index 734ab154..0bd4ab0d 100644 --- a/TODO +++ b/TODO @@ -3,10 +3,6 @@ Embedded rules language not updated when language is set (in Analyse, Game and P If new live game starts in background, "new game" notify OK but not first move. NEW VARIANTS: -https://www.reddit.com/r/TotemChess/comments/imi3v7/totem_rules/ ---> replaced by "Joker" chess --> start on bishop of our color (instead), - moves like a Bishop + Dabbabah, can swap with a piece *on same color* (as a move) at anytime. hmm - or rather: start as in Antiking + Mesmer, in front of. moves like an amazon. swap with any color. better! http://history.chess.free.fr/rollerball.htm https://www.chessvariants.com/40.dir/rollerball/index.html diff --git a/client/public/images/pieces/Joker/bj.svg b/client/public/images/pieces/Joker/bj.svg new file mode 120000 index 00000000..000f539e --- /dev/null +++ b/client/public/images/pieces/Joker/bj.svg @@ -0,0 +1 @@ +../Maxima/bg.svg \ No newline at end of file diff --git a/client/public/images/pieces/Joker/wj.svg b/client/public/images/pieces/Joker/wj.svg new file mode 120000 index 00000000..436f84d6 --- /dev/null +++ b/client/public/images/pieces/Joker/wj.svg @@ -0,0 +1 @@ +../Maxima/wg.svg \ No newline at end of file diff --git a/client/src/translations/en.js b/client/src/translations/en.js index 1839c669..bfd3f2ea 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -275,6 +275,7 @@ export const translations = { "Queen versus pawns": "Queen versus pawns", "Reach the last rank (v1)": "Reach the last rank (v1)", "Reach the last rank (v2)": "Reach the last rank (v2)", + "Replace pieces": "Replace pieces", "Reposition pieces": "Reposition pieces", "Reuse pieces": "Reuse pieces", "Reverse captures": "Reverse captures", diff --git a/client/src/translations/es.js b/client/src/translations/es.js index 322661c8..03be9bbf 100644 --- a/client/src/translations/es.js +++ b/client/src/translations/es.js @@ -275,6 +275,7 @@ export const translations = { "Queen versus pawns": "Dama contra peones", "Reach the last rank (v1)": "Llegar a la última fila (v1)", "Reach the last rank (v2)": "Llegar a la última fila (v2)", + "Replace pieces": "Reemplazar piezas", "Reposition pieces": "Reposicionar las piezas", "Reuse pieces": "Reutilizar piezas", "Reverse captures": "Capturas invertidas", diff --git a/client/src/translations/fr.js b/client/src/translations/fr.js index 94a36189..22f333af 100644 --- a/client/src/translations/fr.js +++ b/client/src/translations/fr.js @@ -275,6 +275,7 @@ export const translations = { "Queen versus pawns": "Dame contre pions", "Reach the last rank (v1)": "Atteignez la dernière rangée (v1)", "Reach the last rank (v2)": "Atteignez la dernière rangée (v2)", + "Replace pieces": "Remplacer les pièces", "Reposition pieces": "Replacer les pièces", "Reuse pieces": "Réutiliser les pièces", "Reverse captures": "Captures inversées", diff --git a/client/src/translations/rules/Joker/en.pug b/client/src/translations/rules/Joker/en.pug index 21203baa..1f102384 100644 --- a/client/src/translations/rules/Joker/en.pug +++ b/client/src/translations/rules/Joker/en.pug @@ -1 +1,22 @@ -p.boxed TODO +p.boxed + | A new piece can swap with any of your other pieces. + +p. + A new piece appears, starting in front of the pawns. + It moves like an Amazon: Queen + Knight, but doesn't capture. + Instead, it can swap its position with any piece. + +figure.diagram-container + .diagram + | fen:rnbqkbnr/pppppppp/3j4/8/8/3J4/PPPPPPPP/RNBQKBNR: + figcaption Deterministic initial position. + +p Pawns can promote into a Joker if you have none on the board. + +h3 Source + +p + | This variant is inspired by + a(href="https://www.reddit.com/r/TotemChess/comments/imi3v7/totem_rules/") + | Totem Chess + | , which seemed a bit too complicated. diff --git a/client/src/translations/rules/Joker/es.pug b/client/src/translations/rules/Joker/es.pug index 21203baa..7aaaf9fb 100644 --- a/client/src/translations/rules/Joker/es.pug +++ b/client/src/translations/rules/Joker/es.pug @@ -1 +1,23 @@ -p.boxed TODO +p.boxed + | Se puede cambiar una nueva pieza con cualquiera de sus otras piezas. + +p. + Aparece una nueva pieza, comenzando por delante de los peones. + Se mueve como una Amazona: Dama + Caballo, pero no captura. + En cambio, puede cambiar su posición con cualquier pieza. + +figure.diagram-container + .diagram + | fen:rnbqkbnr/pppppppp/3j4/8/8/3J4/PPPPPPPP/RNBQKBNR: + figcaption Posición inicial determinista. + +p. + Los peones pueden promocionarse a Joker si no le queda nada en el tablero. + +h3 Fuente + +p + | Esta variante está inspirada en + a(href="https://www.reddit.com/r/TotemChess/comments/imi3v7/totem_rules/") + | Totem Chess + | , que me pareció un poco complicado. diff --git a/client/src/translations/rules/Joker/fr.pug b/client/src/translations/rules/Joker/fr.pug index 21203baa..853d7040 100644 --- a/client/src/translations/rules/Joker/fr.pug +++ b/client/src/translations/rules/Joker/fr.pug @@ -1 +1,25 @@ -p.boxed TODO +p.boxed + | Une nouvelle pièce peut s'échanger avec + | n'importe laquelle de vos autres pièces. + +p. + Une nouvelle pièce fait son apparition, démarrant devant les pions. + Elle se déplace comme une Amazone : Dame + Cavalier, mais ne capture pas. + Au lieu de ça, elle peut échanger sa position avec n'importe quelle pièce. + +figure.diagram-container + .diagram + | fen:rnbqkbnr/pppppppp/3j4/8/8/3J4/PPPPPPPP/RNBQKBNR: + figcaption Position initiale déterministe. + +p. + Les pions peuvent se promouvoir en Joker + s'il ne vous en reste plus sur l'échiquier. + +h3 Source + +p + | Cette variante est inspirée de + a(href="https://www.reddit.com/r/TotemChess/comments/imi3v7/totem_rules/") + | Totem Chess + | , qui m'a paru un peu trop compliquée. diff --git a/client/src/translations/variants/en.pug b/client/src/translations/variants/en.pug index 7d788bdf..6e7d42ad 100644 --- a/client/src/translations/variants/en.pug +++ b/client/src/translations/variants/en.pug @@ -408,6 +408,7 @@ p. "Hamilton", "Hypnotic", "Isardam", + "Joker", "Kingsmaker", "Magnetic", "Maharajah", diff --git a/client/src/translations/variants/es.pug b/client/src/translations/variants/es.pug index 9ba6c2d9..2b767403 100644 --- a/client/src/translations/variants/es.pug +++ b/client/src/translations/variants/es.pug @@ -419,6 +419,7 @@ p. "Hamilton", "Hypnotic", "Isardam", + "Joker", "Kingsmaker", "Magnetic", "Maharajah", diff --git a/client/src/translations/variants/fr.pug b/client/src/translations/variants/fr.pug index 82a38424..431a725b 100644 --- a/client/src/translations/variants/fr.pug +++ b/client/src/translations/variants/fr.pug @@ -418,6 +418,7 @@ p. "Hamilton", "Hypnotic", "Isardam", + "Joker", "Kingsmaker", "Magnetic", "Maharajah", diff --git a/client/src/variants/Joker.js b/client/src/variants/Joker.js new file mode 100644 index 00000000..137249c4 --- /dev/null +++ b/client/src/variants/Joker.js @@ -0,0 +1,87 @@ +import { ChessRules, Move, PiPo } from "@/base_rules"; +import { Antiking2Rules } from "@/variants/Antiking2"; + +export class JokerRules extends ChessRules { + + static get PawnSpecs() { + return Object.assign( + {}, + ChessRules.PawnSpecs, + { promotions: ChessRules.PawnSpecs.promotions.concat([V.JOKER]) } + ); + } + + static GenRandInitFen(randomness) { + const antikingFen = Antiking2Rules.GenRandInitFen(randomness); + return antikingFen.replace('a', 'J').replace('A', 'j'); + } + + static get JOKER() { + return 'j'; + } + + static get PIECES() { + return ChessRules.PIECES.concat([V.JOKER]); + } + + getPpath(b) { + return (b.charAt(1) == 'j' ? "Joker/" : "") + b; + } + + getPotentialMovesFrom([x, y]) { + const piece = this.getPiece(x, y); + if (piece == V.JOKER) return this.getPotentialJokerMoves([x, y]); + let moves = super.getPotentialMovesFrom([x, y]); + if (piece == V.PAWN) { + const c = this.turn; + const alreadyOneJoker = this.board.some(row => + row.some(cell => cell == c + 'j')); + if (alreadyOneJoker) moves = moves.filter(m => m.appear[0].p != V.JOKER) + } + return moves; + } + + canTake([x1, y1], [x2, y2]) { + if (this.getPiece(x1, y1) == V.JOKER) return false; + return super.canTake([x1, y1], [x2, y2]); + } + + getPotentialJokerMoves([x, y]) { + const moving = + super.getSlideNJumpMoves([x, y], V.steps[V.KNIGHT], "oneStep") + .concat(super.getSlideNJumpMoves([x, y], + V.steps[V.ROOK].concat(V.steps[V.BISHOP]))); + let swapping = []; + const c = this.turn; + for (let i=0; i<8; i++) { + for (let j=0; j<8; j++) { + // Following test is OK because only one Joker on board at a time + if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == c) { + const p = this.getPiece(i, j); + swapping.push( + new Move({ + vanish: [ + new PiPo({ x: x, y: y, c: c, p: V.JOKER }), + new PiPo({ x: i, y: j, c: c, p: p }) + ], + appear: [ + new PiPo({ x: i, y: j, c: c, p: V.JOKER }), + new PiPo({ x: x, y: y, c: c, p: p }) + ] + }) + ); + } + } + } + return moving.concat(swapping); + } + + static get VALUES() { + return Object.assign({ j: 2 }, ChessRules.VALUES); + } + + static get SEARCH_DEPTH() { + return 2; + } + +}; diff --git a/server/db/populate.sql b/server/db/populate.sql index b6d0bf78..043c8a8f 100644 --- a/server/db/populate.sql +++ b/server/db/populate.sql @@ -74,6 +74,7 @@ insert or ignore into Variants (name, description) values ('Interweave', 'Interweaved colorbound teams'), ('Isardam', 'No paralyzed pieces'), ('Janggi', 'Korean Chess'), + ('Joker', 'Replace pieces'), ('Kinglet', 'Protect your pawns'), ('Kingsmaker', 'Promote into kings'), ('Knightmate', 'Mate the knight'),