From 737a5dafb39740ebe304b8d0a82df85070def571 Mon Sep 17 00:00:00 2001 From: Benjamin Auder <benjamin.auder@somewhere> Date: Thu, 28 May 2020 14:54:37 +0200 Subject: [PATCH] Fix Eightpieces, add some simple variants, add a basic variants classification instead of the list --- client/src/components/MoveList.vue | 6 +- client/src/router.js | 5 + client/src/translations/en.js | 10 +- client/src/translations/es.js | 10 +- client/src/translations/fr.js | 10 +- .../src/translations/rules/Bishopawns/en.pug | 19 + .../src/translations/rules/Bishopawns/es.pug | 19 + .../src/translations/rules/Bishopawns/fr.pug | 19 + client/src/translations/rules/Capture/en.pug | 11 +- client/src/translations/rules/Capture/es.pug | 12 +- client/src/translations/rules/Capture/fr.pug | 12 +- .../src/translations/rules/Discoduel/en.pug | 22 + .../src/translations/rules/Discoduel/es.pug | 23 + .../src/translations/rules/Discoduel/fr.pug | 23 + .../src/translations/rules/Doublemove1/en.pug | 2 +- .../src/translations/rules/Knightpawns/en.pug | 20 + .../src/translations/rules/Knightpawns/es.pug | 20 + .../src/translations/rules/Knightpawns/fr.pug | 20 + .../translations/rules/Pawnmassacre/en.pug | 21 + .../translations/rules/Pawnmassacre/es.pug | 23 + .../translations/rules/Pawnmassacre/fr.pug | 23 + .../src/translations/rules/Pawnsking/en.pug | 21 + .../src/translations/rules/Pawnsking/es.pug | 22 + .../src/translations/rules/Pawnsking/fr.pug | 22 + .../src/translations/rules/Progressive/en.pug | 35 ++ .../src/translations/rules/Progressive/es.pug | 35 ++ .../src/translations/rules/Progressive/fr.pug | 35 ++ .../src/translations/rules/Rookpawns/en.pug | 19 + .../src/translations/rules/Rookpawns/es.pug | 19 + .../src/translations/rules/Rookpawns/fr.pug | 19 + client/src/translations/variants/en.pug | 395 +++++++++++++++++ client/src/translations/variants/es.pug | 406 ++++++++++++++++++ client/src/translations/variants/fr.pug | 405 +++++++++++++++++ client/src/utils/notation.js | 14 +- client/src/variants/Bishopawns.js | 51 +++ client/src/variants/Dark.js | 8 +- client/src/variants/Discoduel.js | 50 +++ client/src/variants/Doublemove1.js | 58 +-- client/src/variants/Doublemove2.js | 36 +- client/src/variants/Eightpieces.js | 19 +- client/src/variants/Knightpawns.js | 47 ++ client/src/variants/Pawnmassacre.js | 18 + client/src/variants/Pawns.js | 9 + client/src/variants/Pawnsking.js | 56 +++ client/src/variants/Progressive.js | 111 +++++ client/src/variants/Rookpawns.js | 51 +++ client/src/views/VariantList.vue | 96 +++++ client/src/views/Variants.vue | 70 +-- server/db/populate.sql | 9 +- 49 files changed, 2330 insertions(+), 136 deletions(-) create mode 100644 client/src/translations/rules/Bishopawns/en.pug create mode 100644 client/src/translations/rules/Bishopawns/es.pug create mode 100644 client/src/translations/rules/Bishopawns/fr.pug create mode 100644 client/src/translations/rules/Discoduel/en.pug create mode 100644 client/src/translations/rules/Discoduel/es.pug create mode 100644 client/src/translations/rules/Discoduel/fr.pug create mode 100644 client/src/translations/rules/Knightpawns/en.pug create mode 100644 client/src/translations/rules/Knightpawns/es.pug create mode 100644 client/src/translations/rules/Knightpawns/fr.pug create mode 100644 client/src/translations/rules/Pawnmassacre/en.pug create mode 100644 client/src/translations/rules/Pawnmassacre/es.pug create mode 100644 client/src/translations/rules/Pawnmassacre/fr.pug create mode 100644 client/src/translations/rules/Pawnsking/en.pug create mode 100644 client/src/translations/rules/Pawnsking/es.pug create mode 100644 client/src/translations/rules/Pawnsking/fr.pug create mode 100644 client/src/translations/rules/Progressive/en.pug create mode 100644 client/src/translations/rules/Progressive/es.pug create mode 100644 client/src/translations/rules/Progressive/fr.pug create mode 100644 client/src/translations/rules/Rookpawns/en.pug create mode 100644 client/src/translations/rules/Rookpawns/es.pug create mode 100644 client/src/translations/rules/Rookpawns/fr.pug create mode 100644 client/src/translations/variants/en.pug create mode 100644 client/src/translations/variants/es.pug create mode 100644 client/src/translations/variants/fr.pug create mode 100644 client/src/variants/Bishopawns.js create mode 100644 client/src/variants/Discoduel.js create mode 100644 client/src/variants/Knightpawns.js create mode 100644 client/src/variants/Pawnmassacre.js create mode 100644 client/src/variants/Pawnsking.js create mode 100644 client/src/variants/Progressive.js create mode 100644 client/src/variants/Rookpawns.js create mode 100644 client/src/views/VariantList.vue diff --git a/client/src/components/MoveList.vue b/client/src/components/MoveList.vue index 2e011b49..e36c058c 100644 --- a/client/src/components/MoveList.vue +++ b/client/src/components/MoveList.vue @@ -53,14 +53,12 @@ div .td( :class="{'highlight-lm': cursor == moveIdx}" @click="() => gotoMove(moveIdx)" - ) - | {{ notation(moveIdx) }} + v-html="notation(moveIdx)") .td( v-if="moveIdx < moves.length-1" :class="{'highlight-lm': cursor == moveIdx+1}" @click="() => gotoMove(moveIdx+1)" - ) - | {{ notation(moveIdx + 1) }} + v-html="notation(moveIdx + 1)") </template> <script> diff --git a/client/src/router.js b/client/src/router.js index 04c8f06c..8590c334 100644 --- a/client/src/router.js +++ b/client/src/router.js @@ -20,6 +20,11 @@ const router = new Router({ name: "variants", component: loadView("Variants") }, + { + path: "/variants/list", + name: "variantlist", + component: loadView("VariantList") + }, { path: "/variants/:vname([a-zA-Z0-9]+)", name: "rules", diff --git a/client/src/translations/en.js b/client/src/translations/en.js index 13869e9f..41c007af 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -149,6 +149,7 @@ export const translations = { Variant: "Variant", Variants: "Variants", Versus: "Versus", + "View alphabetical variants list": "View alphabetical variants list", White: "White", "White to move": "White to move", "White surrender": "White surrender", @@ -172,6 +173,7 @@ export const translations = { "Attract opposite king": "Attract opposite king", "Balanced sliders & leapers": "Balanced sliders & leapers", "Big board": "Big board", + "Bishop versus pawns": "Bishop versus pawns", "Board upside down": "Board upside down", "Both sides of the mirror": "Both sides of the mirror", "Burmese chess": "Burmese chess", @@ -190,6 +192,7 @@ export const translations = { "Double moves (v1)": "Double moves (v1)", "Double moves (v2)": "Double moves (v2)", "Each piece is unique": "Each piece is unique", + "Enter the disco": "Enter the disco", "Exchange pieces' positions": "Exchange pieces' positions", "Exotic captures": "Exotic captures", "Explosive captures": "Explosive captures", @@ -207,6 +210,7 @@ export const translations = { "Kings cross the 8x8 board": "Kings cross the 8x8 board", "Kings cross the 11x11 board": "Kings cross the 11x11 board", "Knight in pocket": "Knight in pocket", + "Knight versus pawns": "Knight versus pawns", "Landing on the board": "Landing on the board", "Laws of attraction": "Laws of attraction", "Long jumps over pieces": "Long jumps over pieces", @@ -231,18 +235,22 @@ export const translations = { "Occupy the enemy palace": "Occupy the enemy palace", "Paralyzed pieces": "Paralyzed pieces", "Pawns move diagonally": "Pawns move diagonally", + "Pieces upside down": "Pieces upside down", "Play at the same time": "Play at the same time", + "Play more and more moves": "Play more and more moves", "Play opponent's pieces": "Play opponent's pieces", "Powerful pieces": "Powerful pieces", "Prolongated captures": "Prolongated captures", "Protect your pawns": "Protect your pawns", "Push and pull": "Push and pull", "Queen disguised as a pawn": "Queen disguised as a pawn", - "Reach the last rank": "Reach the last rank", + "Reach the last rank (v1)": "Reach the last rank (v1)", + "Reach the last rank (v2)": "Reach the last rank (v2)", "Reposition pieces": "Reposition pieces", "Reuse pieces": "Reuse pieces", "Reverse captures": "Reverse captures", "Roll the dice": "Roll the dice", + "Rook versus pawns": "Rook versus pawns", "Rotating board": "Rotating board", "Run forward": "Run forward", "Score a goal": "Score a goal", diff --git a/client/src/translations/es.js b/client/src/translations/es.js index 2036ad53..bc25339d 100644 --- a/client/src/translations/es.js +++ b/client/src/translations/es.js @@ -149,6 +149,7 @@ export const translations = { Variant: "Variante", Variants: "Variantes", Versus: "Contra", + "View alphabetical variants list": "Ver la lista alfabética de variantes", White: "Blancas", "White to move": "Juegan las blancas", "White surrender": "Las blancas abandonan", @@ -172,6 +173,7 @@ export const translations = { "Attract opposite king": "Atraer al rey contrario", "Balanced sliders & leapers": "Modos de desplazamiento equilibrados", "Big board": "Gran tablero", + "Bishop versus pawns": "Alfil contra peones", "Board upside down": "Tablero al revés", "Both sides of the mirror": "Ambos lados del espejo", "Burmese chess": "Ajedrez birmano", @@ -190,6 +192,7 @@ export const translations = { "Double moves (v1)": "Jugadas doble (v1)", "Double moves (v2)": "Jugadas doble (v2)", "Each piece is unique": "Cada pieza es única", + "Enter the disco": "Entrar en la discoteca", "Exchange pieces' positions": "Intercambiar posiciones de piezas", "Exotic captures": "Capturas exóticas", "Explosive captures": "Capturas explosivas", @@ -207,6 +210,7 @@ export const translations = { "Kings cross the 8x8 board": "Los reyes cruzan el 8x8 tablero", "Kings cross the 11x11 board": "Los reyes cruzan el 11x11 tablero", "Knight in pocket": "Caballo en bolsillo", + "Knight versus pawns": "Caballo contra peones", "Landing on the board": "Aterrizando en el tablero", "Laws of attraction": "Las leyes de las atracciones", "Long jumps over pieces": "Saltos largos sobre las piezas", @@ -231,18 +235,22 @@ export const translations = { "Occupy the enemy palace": "Ocupar el palacio enemigo", "Paralyzed pieces": "Piezas paralizadas", "Pawns move diagonally": "Peones se mueven en diagonal", + "Pieces upside down": "Piezas al revés", "Play at the same time": "Jugar al mismo tiempo", + "Play more and more moves": "Jugar más y más movimientos", "Play opponent's pieces": "Jugar piezas opuestas", "Powerful pieces": "Piezas poderosas", "Prolongated captures": "Capturas extendidas", "Protect your pawns": "Protege tus peones", "Push and pull": "Empujar y tirar", "Queen disguised as a pawn": "Reina disfrazada de peón", - "Reach the last rank": "Llegar a la última fila", + "Reach the last rank (v1)": "Llegar a la última fila (v1)", + "Reach the last rank (v2)": "Llegar a la última fila (v2)", "Reposition pieces": "Reposicionar las piezas", "Reuse pieces": "Reutilizar piezas", "Reverse captures": "Capturas invertidas", "Roll the dice": "Tirar los dados", + "Rook versus pawns": "Torre contra peones", "Rotating board": "Tablero giratorio", "Run forward": "Correr hacia adelante", "Score a goal": "Marcar una meta", diff --git a/client/src/translations/fr.js b/client/src/translations/fr.js index 2e34016a..869a68d3 100644 --- a/client/src/translations/fr.js +++ b/client/src/translations/fr.js @@ -149,6 +149,7 @@ export const translations = { Variant: "Variante", Variants: "Variantes", Versus: "Contre", + "View alphabetical variants list": "Voir la liste alphabétique des variantes", White: "Blancs", "White to move": "Trait aux blancs", "White surrender": "Les blancs abandonnent", @@ -172,6 +173,7 @@ export const translations = { "Attract opposite king": "Attirer le roi adverse", "Balanced sliders & leapers": "Modes de déplacement équilibrés", "Big board": "Grand échiquier", + "Bishop versus pawns": "Fou contre pions", "Board upside down": "Ãchiquier à l'envers", "Both sides of the mirror": "Les deux côté du miroir", "Burmese chess": "Ãchecs birmans", @@ -190,6 +192,7 @@ export const translations = { "Double moves (v1)": "Coups doubles (v1)", "Double moves (v2)": "Coups doubles (v2)", "Each piece is unique": "Chaque pièce est unique", + "Enter the disco": "Entrez dans la boîte", "Exchange pieces' positions": "Ãchangez les positions des pièces", "Exotic captures": "Captures exotiques", "Explosive captures": "Captures explosives", @@ -207,6 +210,7 @@ export const translations = { "Kings cross the 8x8 board": "Les rois traversent l'échiquier 8x8", "Kings cross the 11x11 board": "Les rois traversent l'échiquier 11x11", "Knight in pocket": "Cavalier en poche", + "Knight versus pawns": "Cavalier contre pions", "Landing on the board": "Débarquement sur l'échiquier", "Laws of attraction": "Les lois de l'attraction", "Long jumps over pieces": "Sauts longs par dessus les pièces", @@ -231,18 +235,22 @@ export const translations = { "Occupy the enemy palace": "Occuper le palais ennemi", "Paralyzed pieces": "Pièces paralysées", "Pawns move diagonally": "Les pions vont en diagonale", + "Pieces upside down": "Pièces à l'envers", "Play at the same time": "Jouer en même temps", + "Play more and more moves": "Jouez de plus en plus de coups", "Play opponent's pieces": "Jouez les pièces adverses", "Powerful pieces": "Pièces puissantes", "Prolongated captures": "Captures prolongées", "Protect your pawns": "Protégez vos pions", "Push and pull": "Pousser et tirer", "Queen disguised as a pawn": "Reine déguisée en pion", - "Reach the last rank": "Atteignez la dernière rangée", + "Reach the last rank (v1)": "Atteignez la dernière rangée (v1)", + "Reach the last rank (v2)": "Atteignez la dernière rangée (v2)", "Reposition pieces": "Replacer les pièces", "Reuse pieces": "Réutiliser les pièces", "Reverse captures": "Captures inversées", "Roll the dice": "Lancez le dé", + "Rook versus pawns": "Tour contre pions", "Rotating board": "Ãchiquier tournant", "Run forward": "Courir vers l'avant", "Score a goal": "Marquer un but", diff --git a/client/src/translations/rules/Bishopawns/en.pug b/client/src/translations/rules/Bishopawns/en.pug new file mode 100644 index 00000000..e08e8f5b --- /dev/null +++ b/client/src/translations/rules/Bishopawns/en.pug @@ -0,0 +1,19 @@ +p.boxed + | A bishop versus three pawns. + +figure.diagram-container + .diagram + | fen:8/ppp5/8/8/8/8/8/5B2: + figcaption Initial position + +p. + The pawns win if one reaches the other end + without being immediately captured. + The bishop wins if it captures all the pawns. + +h3 Source + +p + a(href="https://chessplus.net/interactive-games/") + | Bishop vs 3 Pawns + | on chessplus.net. diff --git a/client/src/translations/rules/Bishopawns/es.pug b/client/src/translations/rules/Bishopawns/es.pug new file mode 100644 index 00000000..8c46e065 --- /dev/null +++ b/client/src/translations/rules/Bishopawns/es.pug @@ -0,0 +1,19 @@ +p.boxed + | Un alfil contra tres peones. + +figure.diagram-container + .diagram + | fen:8/ppp5/8/8/8/8/8/5B2: + figcaption Posición inicial + +p. + Los peones ganan si uno de ellos llega al otro lado sin ser + inmediatamente capturado. + El alfil gana si se come todos los peones. + +h3 Fuente + +p + a(href="https://chessplus.net/interactive-games/") + | Bishop vs 3 Pawns + | en chessplus.net. diff --git a/client/src/translations/rules/Bishopawns/fr.pug b/client/src/translations/rules/Bishopawns/fr.pug new file mode 100644 index 00000000..8d06d2fb --- /dev/null +++ b/client/src/translations/rules/Bishopawns/fr.pug @@ -0,0 +1,19 @@ +p.boxed + | Un fou contre trois pions. + +figure.diagram-container + .diagram + | fen:8/ppp5/8/8/8/8/8/5B2: + figcaption Position initiale + +p. + Les pions gagnent si l'un d'eux arrive de l'autre côté sans être + immédiatement capturé. + Le fou gagne s'il mange tous les pions. + +h3 Source + +p + a(href="https://chessplus.net/interactive-games/") + | Bishop vs 3 Pawns + | sur chessplus.net. diff --git a/client/src/translations/rules/Capture/en.pug b/client/src/translations/rules/Capture/en.pug index 5ed55414..0007569b 100644 --- a/client/src/translations/rules/Capture/en.pug +++ b/client/src/translations/rules/Capture/en.pug @@ -17,6 +17,11 @@ figure.diagram-container h3 More information -p. - This idea was suggested recently (2020) by Vincent Rothuis. - It's simple so probably not new, but I never saw it before. +p + | The variant idea was suggested recently (2020) by Vincent Rothuis. + | It is mentioned on + a(href="https://www.chessvariants.com/other.dir/modest-various.html") + | this page + | . + +p Inventor: Roger Cooper (2000) diff --git a/client/src/translations/rules/Capture/es.pug b/client/src/translations/rules/Capture/es.pug index 505a04e7..7cd18827 100644 --- a/client/src/translations/rules/Capture/es.pug +++ b/client/src/translations/rules/Capture/es.pug @@ -17,7 +17,11 @@ figure.diagram-container h3 Más información -p. - Esta idea fue sugerida recientemente (2020) por Vincent Rothuis. - Es simple, asà que probablemente no sea nuevo, pero nunca - previamente encontrado. +p + | Esta idea fue sugerida recientemente (2020) por Vincent Rothuis. + | La variante es mencionada en + a(href="https://www.chessvariants.com/other.dir/modest-various.html") + | esta página + | . + +p Inventor: Roger Cooper (2000) diff --git a/client/src/translations/rules/Capture/fr.pug b/client/src/translations/rules/Capture/fr.pug index 21a03538..e956d8ab 100644 --- a/client/src/translations/rules/Capture/fr.pug +++ b/client/src/translations/rules/Capture/fr.pug @@ -17,7 +17,11 @@ figure.diagram-container h3 Plus d'information -p. - Cette idée a été suggérée récemment (2020) par Vincent Rothuis. - Elle est simple donc probablement pas nouvelle, mais je ne l'ai jamais - rencontrée auparavant. +p + | Cette idée a été suggérée récemment (2020) par Vincent Rothuis. + | La variante est mentionnée sur + a(href="https://www.chessvariants.com/other.dir/modest-various.html") + | cette page + | . + +p Inventeur : Roger Cooper (2000) diff --git a/client/src/translations/rules/Discoduel/en.pug b/client/src/translations/rules/Discoduel/en.pug new file mode 100644 index 00000000..130e1763 --- /dev/null +++ b/client/src/translations/rules/Discoduel/en.pug @@ -0,0 +1,22 @@ +p.boxed + | Cross the board with as many pawns as possible. + +figure.diagram-container + .diagram + | fen:1n4n1/8/8/8/8/8/PPPPPPPP/8: + figcaption Initial position + +p. + The story is that 8 teenagers (pawns) want to go to a disco but they have to + pass 2 security guards (knights). The objective is to get as many pawns to + the other side as possible. + Once a pawn has reached the end it cannot be captured. + +p No winning condition: play two games and sum pawns on eighth rank. + +h3 Source + +p + a(href="https://chessplus.net/interactive-games/") + | Disco Duel + | on chessplus.net. diff --git a/client/src/translations/rules/Discoduel/es.pug b/client/src/translations/rules/Discoduel/es.pug new file mode 100644 index 00000000..0aafec5b --- /dev/null +++ b/client/src/translations/rules/Discoduel/es.pug @@ -0,0 +1,23 @@ +p.boxed + | Cruza el tablero con tantos peones como sea posible. + +figure.diagram-container + .diagram + | fen:1n4n1/8/8/8/8/8/PPPPPPPP/8: + figcaption Posición inicial + +p. + Según la historia, 8 adolescentes (peones) quieren ir al fiesta, pero ellos + debe evitar a los dos guardias (caballos). El objetivo es traer un + número máximo de peones en la última fila. + +p. + Sin condiciones de victoria: + juega dos partidas y agrega los peones en la octava fila. + +h3 Fuente + +p + a(href="https://chessplus.net/interactive-games/") + | Disco Duel + | en chessplus.net. diff --git a/client/src/translations/rules/Discoduel/fr.pug b/client/src/translations/rules/Discoduel/fr.pug new file mode 100644 index 00000000..dc45913e --- /dev/null +++ b/client/src/translations/rules/Discoduel/fr.pug @@ -0,0 +1,23 @@ +p.boxed + | Traversez l'échiquier avec autant de pions que possible. + +figure.diagram-container + .diagram + | fen:1n4n1/8/8/8/8/8/PPPPPPPP/8: + figcaption Position initiale + +p. + Selon l'histoire, 8 adolescents (les pions) veulent aller en boîte, mais ils + doivent éviter les deux vigiles (cavaliers). L'objectif est d'amener un + maximum de pions sur la dernière rangée. + +p. + Pas de conditions de victoire : + jouez deux parties et sommez les pions sur la huitième rangée. + +h3 Source + +p + a(href="https://chessplus.net/interactive-games/") + | Disco Duel + | sur chessplus.net. diff --git a/client/src/translations/rules/Doublemove1/en.pug b/client/src/translations/rules/Doublemove1/en.pug index 6d1982e4..9b7595bc 100644 --- a/client/src/translations/rules/Doublemove1/en.pug +++ b/client/src/translations/rules/Doublemove1/en.pug @@ -50,7 +50,7 @@ h3 More information p | See for example the a(href="https://www.chessvariants.com/multimove.dir/marseill.html") - | Marseillais Chess + | Marseillais Chess | page on chessvariants.com. p diff --git a/client/src/translations/rules/Knightpawns/en.pug b/client/src/translations/rules/Knightpawns/en.pug new file mode 100644 index 00000000..5a783907 --- /dev/null +++ b/client/src/translations/rules/Knightpawns/en.pug @@ -0,0 +1,20 @@ +p.boxed + | A knight versus three pawns. + +figure.diagram-container + .diagram + | fen:8/ppp5/8/8/8/8/8/6N2: + figcaption Initial position + +p. + The pawns win if one reaches the other end + without being immediately captured. + The knight wins if it captures all the pawns. + +h3 Source + +p + | Inspired by + a(href="https://chessplus.net/interactive-games/") + | Bishop vs 3 Pawns + | on chessplus.net. diff --git a/client/src/translations/rules/Knightpawns/es.pug b/client/src/translations/rules/Knightpawns/es.pug new file mode 100644 index 00000000..e295638e --- /dev/null +++ b/client/src/translations/rules/Knightpawns/es.pug @@ -0,0 +1,20 @@ +p.boxed + | Un caballo contra tres peones. + +figure.diagram-container + .diagram + | fen:8/ppp5/8/8/8/8/8/6N1: + figcaption Posición inicial + +p. + Los peones ganan si uno de ellos llega al otro lado sin ser + inmediatamente capturado. + El caballo gana si se come todos los peones. + +h3 Fuente + +p + | Inspirado por + a(href="https://chessplus.net/interactive-games/") + | Bishop vs 3 Pawns + | en chessplus.net. diff --git a/client/src/translations/rules/Knightpawns/fr.pug b/client/src/translations/rules/Knightpawns/fr.pug new file mode 100644 index 00000000..2c53b225 --- /dev/null +++ b/client/src/translations/rules/Knightpawns/fr.pug @@ -0,0 +1,20 @@ +p.boxed + | Un cavalier contre trois pions. + +figure.diagram-container + .diagram + | fen:8/ppp5/8/8/8/8/8/6N1: + figcaption Position initiale + +p. + Les pions gagnent si l'un d'eux arrive de l'autre côté sans être + immédiatement capturé. + Le cavalier gagne s'il mange tous les pions. + +h3 Source + +p + | Inspiré par + a(href="https://chessplus.net/interactive-games/") + | Bishop vs 3 Pawns + | sur chessplus.net. diff --git a/client/src/translations/rules/Pawnmassacre/en.pug b/client/src/translations/rules/Pawnmassacre/en.pug new file mode 100644 index 00000000..90559143 --- /dev/null +++ b/client/src/translations/rules/Pawnmassacre/en.pug @@ -0,0 +1,21 @@ +p.boxed + | White pieces start on the eigth rank, black pieces start on the first rank. + +figure.diagram-container + .diagram + | fen:RNBQKBNR/pppppppp/8/8/8/8/PPPPPPPP/rnbqkbnr: + figcaption Initial deterministic position + +p. + All orthodox rules apply, except for castling. + Pawns are very vulnerable, their role seems mostly to limit pieces movements. + +h3 Source + +p + | The variant is mentioned on + a(href="https://www.chessvariants.com/other.dir/modest-various.html") + | this page + | . + +p Inventor: Jeff "Cavebear" Stroud (1998) diff --git a/client/src/translations/rules/Pawnmassacre/es.pug b/client/src/translations/rules/Pawnmassacre/es.pug new file mode 100644 index 00000000..66950624 --- /dev/null +++ b/client/src/translations/rules/Pawnmassacre/es.pug @@ -0,0 +1,23 @@ +p.boxed + | Las piezas blancas comienzan en la octava fila, + | las piezas negras comienzan en la primera fila. + +figure.diagram-container + .diagram + | fen:RNBQKBNR/pppppppp/8/8/8/8/PPPPPPPP/rnbqkbnr: + figcaption Posición inicial determinista + +p. + Se aplican todas las reglas ortodoxos, excepto el enroque. + Los peones son muy vulnerables, su papel parece esencialmente + limite el movimiento de las piezas. + +h3 Fuente + +p + | La variante está mencionada en + a(href="https://www.chessvariants.com/other.dir/modest-various.html") + | esta página + | . + +p Inventor: Jeff "Cavebear" Stroud (1998) diff --git a/client/src/translations/rules/Pawnmassacre/fr.pug b/client/src/translations/rules/Pawnmassacre/fr.pug new file mode 100644 index 00000000..adfb203a --- /dev/null +++ b/client/src/translations/rules/Pawnmassacre/fr.pug @@ -0,0 +1,23 @@ +p.boxed + | Les pièces blanches démarrent sur la huitième rangée, + | les pièces noires démarrent sur la première rangée. + +figure.diagram-container + .diagram + | fen:RNBQKBNR/pppppppp/8/8/8/8/PPPPPPPP/rnbqkbnr: + figcaption Position initiale déterministe + +p. + Toutes les règles orthodoxes s'appliquent, sauf le roque. + Les pions sont très vulnérables, leur rôle semble essentiellement de + limiter les mouvements des pièces. + +h3 Source + +p + | La variante est mentionnée sur + a(href="https://www.chessvariants.com/other.dir/modest-various.html") + | cette page + | . + +p Inventeur : Jeff "Cavebear" Stroud (1998) diff --git a/client/src/translations/rules/Pawnsking/en.pug b/client/src/translations/rules/Pawnsking/en.pug new file mode 100644 index 00000000..1c239514 --- /dev/null +++ b/client/src/translations/rules/Pawnsking/en.pug @@ -0,0 +1,21 @@ +p.boxed + | Win by crossing the board. + +figure.diagram-container + .diagram + | fen:4k3/pppppppp/8/8/8/8/PPPPPPPP/4K3: + figcaption Initial position + +p + | This is an extension of the + a(href="/#/variants/Pawns") Pawns + | Game. A king is added to its starting square. He moves as usual. + | The first person to reach the other side with a pawn or king is the winner. + | You can also win if you capture the enemy king. + +h3 Source + +p + a(href="https://chessplus.net/interactive-games/") + | The Pawns Game with a King + | on chessplus.net. diff --git a/client/src/translations/rules/Pawnsking/es.pug b/client/src/translations/rules/Pawnsking/es.pug new file mode 100644 index 00000000..01178951 --- /dev/null +++ b/client/src/translations/rules/Pawnsking/es.pug @@ -0,0 +1,22 @@ +p.boxed + | Gana cruzando el tablero de ajedrez. + +figure.diagram-container + .diagrama + | fen:4k3/pppppppp/8/8/8/8/PPPPPPPPP/4K3: + figcaption Posición inicial + +p + | Es una extensión de la variante. + a(href="/#/variants/Pawns") Pawns + | . Se agrega un rey a su casilla inicial. Se mueve como siempre. + | La primera persona que llega al otro lado del tablero con un peón + | o el rey es declarado la ganadora. + | También puedes ganar capturando al rey contrario. + +h3 Fuente + +p + a(href="https://chessplus.net/interactive-games/") + | The Pawns Game with a King + | en chessplus.net. diff --git a/client/src/translations/rules/Pawnsking/fr.pug b/client/src/translations/rules/Pawnsking/fr.pug new file mode 100644 index 00000000..4f1a9f89 --- /dev/null +++ b/client/src/translations/rules/Pawnsking/fr.pug @@ -0,0 +1,22 @@ +p.boxed + | Gagnez en traversant l'échiquier. + +figure.diagram-container + .diagram + | fen:4k3/pppppppp/8/8/8/8/PPPPPPPP/4K3: + figcaption Position initiale + +p + | C'est une extension de la variante + a(href="/#/variants/Pawns") Pawns + | . Un roi est ajouté sur sa case initiale. Il se déplace comme d'habitude. + | La première personne à atteindre l'autre côté de l'échiquier avec un pion + | ou le roi est déclarée gagnante. + | Vous pouvez aussi gagner en capturant le roi adverse. + +h3 Source + +p + a(href="https://chessplus.net/interactive-games/") + | The Pawns Game with a King + | sur chessplus.net. diff --git a/client/src/translations/rules/Progressive/en.pug b/client/src/translations/rules/Progressive/en.pug new file mode 100644 index 00000000..325b7342 --- /dev/null +++ b/client/src/translations/rules/Progressive/en.pug @@ -0,0 +1,35 @@ +p.boxed + | White plays one move, then black play twice, + | then white plays three moves... + +p. + At the very first move of the game, white make only one move - as usual. + However, after that and for all the game, each side must play as many moves + as the opponent just played plus one. + +p. + If a move gives check, then the sequence stops here, but the opponent can + still play as many moves as would be theoretically possible. + Also, if a checkmate or stalemate situation occurs before the maximal number + of moves are played, the game ends. + There are no en-passant captures. + +figure.diagram-container + .diagram + | fen:rnbqk2r/pppp2pp/4p3/8/1b1P4/4pN2/PPP1PPPP/RN1QKB1R: + figcaption "Mate in 1" + +p. + On the diagram white mates with the sequence of 5 moves c3 Ne5 Qd3 Qf5 Qf7. + Moves' notation is replaced by ∞ (infinity) when there are four moves + or more to print. + +h3 More information + +p + | You can start from the + a(href="https://en.wikipedia.org/wiki/Progressive_chess") + | Wikipedia page + | , which points to + a(href="http://users.ics.aalto.fi/tho/chess.html") this page + | with several commented games. diff --git a/client/src/translations/rules/Progressive/es.pug b/client/src/translations/rules/Progressive/es.pug new file mode 100644 index 00000000..68d25f99 --- /dev/null +++ b/client/src/translations/rules/Progressive/es.pug @@ -0,0 +1,35 @@ +p.boxed + | Las blancas juegan un movimiento, luego las negras juegan dos veces, + | entonces las blancas juegan tres movimientos... + +p. + En la primera jugada de la partida, las blancas solo juegan una vez - + como de costumbre. Sin embargo, después de eso y por el resto del juego, + cada lado debe jugar tantos movimientos como el oponente haya jugado más uno. + +p. + Si una jugaga da jaque, la secuencia termina aquÃ, pero el oponente + todavÃa puede jugar tantos movimientos como hubiera sido teóricamente + posible. Además, si un lado es mat o empate antes del número máximo de + movimientos se juega, el juego termina. + No hay capturas en-passant. + +figure.diagram-container + .diagram + | fen:rnbqk2r/pppp2pp/4p3/8/1b1P4/4pN2/PPP1PPPP/RN1QKB1R: + figcaption "Mate en 1" + +p. + En el diagrama, las blancas matan con la secuencia de 5 jugadas + c3 Ne5 Qd3 Qf5 Qf7. La notación de movimiento se reemplaza por ∞ + (infinito) cuando hay cuatro o más jugadas para mostrar. + +h3 Más información + +p + | Puedes comenzar con la + a(href="https://en.wikipedia.org/wiki/Progressive_chess") + | página Wikipedia + | , que apunta a + a(href="http://users.ics.aalto.fi/tho/chess.html") esta página + | con varias partidas comentadas. diff --git a/client/src/translations/rules/Progressive/fr.pug b/client/src/translations/rules/Progressive/fr.pug new file mode 100644 index 00000000..ca102deb --- /dev/null +++ b/client/src/translations/rules/Progressive/fr.pug @@ -0,0 +1,35 @@ +p.boxed + | Les blancs jouent un coup, puis les noirs jouent deux fois, + | ensuite les blancs jouent trois coups... + +p. + Au tout premier coup de la partie, les blancs ne jouent qu'une fois - + comme d'habitude. Cependant, après après cela et pour le reste du jeu, chaque + camp doit jouer autant de coups que l'adversaire vient de jouer plus un. + +p. + Si un coup donne échec, alors la séquence s'arrête ici, mais l'adversaire + peut toujours jouer autant de coups qu'il aurait été théoriquement possible. + De plus, si un camp est mat ou pat avant que le nombre maximal de coups + soit joué, la partie s'arrête. + Il n'y a pas de prises en passant. + +figure.diagram-container + .diagram + | fen:rnbqk2r/pppp2pp/4p3/8/1b1P4/4pN2/PPP1PPPP/RN1QKB1R: + figcaption "Mat en 1" + +p. + Sur le diagramme les blancs matent avec la séquence de 5 coups + c3 Ne5 Qd3 Qf5 Qf7. La notation des coups est remplacée par ∞ (infini) + quand il y a quatre coups ou plus à afficher. + +h3 Plus d'informations + +p + | Vous pouvez commencer par la + a(href="https://en.wikipedia.org/wiki/Progressive_chess") + | page Wikipedia + | , qui pointe vers + a(href="http://users.ics.aalto.fi/tho/chess.html") cette page + | avec plusieurs parties commentées. diff --git a/client/src/translations/rules/Rookpawns/en.pug b/client/src/translations/rules/Rookpawns/en.pug new file mode 100644 index 00000000..e489d602 --- /dev/null +++ b/client/src/translations/rules/Rookpawns/en.pug @@ -0,0 +1,19 @@ +p.boxed + | A rook versus five pawns. + +figure.diagram-container + .diagram + | fen:8/ppppp3/8/8/8/8/8/7R: + figcaption Initial position + +p. + The pawns win if one reaches the other end + without being immediately captured. + The rook wins if it captures all the pawns. + +h3 Source + +p + a(href="https://chessplus.net/interactive-games/") + | Rook vs 5 Pawns + | on chessplus.net. diff --git a/client/src/translations/rules/Rookpawns/es.pug b/client/src/translations/rules/Rookpawns/es.pug new file mode 100644 index 00000000..3f753389 --- /dev/null +++ b/client/src/translations/rules/Rookpawns/es.pug @@ -0,0 +1,19 @@ +p.boxed + | Una torre contra cinco peones. + +figure.diagram-container + .diagram + | fen:8/ppp5/8/8/8/8/8/5B2: + figcaption Posición inicial + +p. + Los peones ganan si uno de ellos llega al otro lado sin ser + inmediatamente capturado. + La torre gana si se come todos los peones. + +h3 Fuente + +p + a(href="https://chessplus.net/interactive-games/") + | Rook vs 5 Pawns + | en chessplus.net. diff --git a/client/src/translations/rules/Rookpawns/fr.pug b/client/src/translations/rules/Rookpawns/fr.pug new file mode 100644 index 00000000..a4f26b3d --- /dev/null +++ b/client/src/translations/rules/Rookpawns/fr.pug @@ -0,0 +1,19 @@ +p.boxed + | Une tour contre cinq pions. + +figure.diagram-container + .diagram + | fen:8/ppp5/8/8/8/8/8/7R: + figcaption Position initiale + +p. + Les pions gagnent si l'un d'eux arrive de l'autre côté sans être + immédiatement capturé. + La tour gagne si elle mange tous les pions. + +h3 Source + +p + a(href="https://chessplus.net/interactive-games/") + | Rook vs 5 Pawns + | sur chessplus.net. diff --git a/client/src/translations/variants/en.pug b/client/src/translations/variants/en.pug new file mode 100644 index 00000000..d41e2df3 --- /dev/null +++ b/client/src/translations/variants/en.pug @@ -0,0 +1,395 @@ +p.text-center + a(href="https://www.chessvariants.com/what.html") What is a chess variant? + | + a(href="https://www.chessvariants.com/why.html") Why play chess variants? + +p + a(href="/#/variants/Chess960") Chess960 + | variant allows to play under standard rules, with a random + | (or not) symmetric (or not) initial position. + +h3 For beginners, to learn the game + +p Variants with very few different pieces, and a simplified goal. +- + var varlist = [ + "Bishopawns", + "Discoduel", + "Knightpawns", + "Pawns", + "Pawnsking", + "Rookpawns" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Forced captures + +p. + In a given position, there are generally less possible moves than in the + orthodox games since you must capture. +- + var varlist = [ + "Arena", + "Capture", + "Interweave", + "Losers", + "Suicide" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Transformations + +p Pieces generally transform when capturing. +- + var varlist = [ + "Absorption", + "Cannibal" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Modified boundaries + +p Boards which communicating sides. +- + var varlist = [ + "Circular", + "Cylinder" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Different pawn movements + +p Everything is as in the orthodox game, but pawns move unusually. +- + var varlist = [ + "Berolina", + "Diamond" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Different armies + +p Standard pieces versus a team of different pieces. +- + var varlist = [ + "Colorbound", + "Horde", + "Orda" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Inspired by ball games + +p Variants involving a ball, abstract or not, which must cross the board. +- + var varlist = [ + "Ball", + "Football", + "Rugby" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 New pieces + +p. + A large variety of fairy pieces can be defined. + Some very powerful like the Amazon, some rather weak like the Grasshopper. +- + var varlist = [ + "Eightpieces", + "Grand", + "Grasshopper", + "Omega", + "Perfect", + "Schess", + "Shako", + "Tencubed", + "Wildebeest" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Several royal pieces + +p In these games you must take care of two or more "kings". +- + var varlist = [ + "Coregal", + "Twokings", + "Antiking1", + "Antiking2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Unorthodox captures + +p Non-standard captures, but using known mechanisms. +- + var varlist = [ + "Enpassant", + "Rifle", + "Zen" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +p. + Captures are generally achieved without replacement. That is to say, + you don't replace the enemy piece on its square to capture it. +- + var varlist = [ + "Allmate1", + "Allmate2", + "Baroque", + "Dynamo", + "Fugue", + "Rococo", + "Maxima" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Pieces changing side + +p Pieces' owners (color) may change during the game +- + var varlist = [ + "Benedict", + "Checkered1", + "Checkered2", + "Pacifist1", + "Pacifist2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Incomplete information + +p. + Some speculation is required in these variants, + where some game informations are hidden. +- + var varlist = [ + "Apocalypse", + "Dark", + "Hidden", + "Hiddenqueen", + "Synchrone" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Random factors + +p. + These games include random effects, + which can be funny, frustrating or both :) +- + var varlist = [ + "Chakart", + "Dice" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Inpired by knight movement + +p. + Variants based on the knight move, + which augment or transform pieces' abilities. +- + var varlist = [ + "Balaklava", + "Knightmate", + "Knightrelay1", + "Knightrelay2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Unusual initial setup + +p Pawns and / or pieces are switched, which result in a very different game. +- + var varlist = [ + "Upsidedown", + "Pawnmassacre" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 "Easy" variants: simple rules + +p. + Only minor changes are made to the orthodox rules, + resulting in a very similar game. +- + var varlist = [ + "Coronation", + "Pocketknight" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +p ...Or leading to a very different strategy: +- + var varlist = [ + "Antimatter", + "Atomic", + "Checkless" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +//h3 Initially empty board +// +//Parachute +//"Crown chess" (place all units at move 1) + +h3 Repositioning + +p Pieces can be drop on the board, either immediately or later in the game. +- + var varlist = [ + "Clorange", + "Crazyhouse", + "Madhouse", + "Rampage", + "Recycle", + "Teleport" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Immobilization + +p Pieces can be paralyzed under certain circumstances. +- + var varlist = [ + "Koopa", + "Madrasi" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Regional and historical variants + +p (Partial) Game evolution in time and space. +- + var varlist = [ + "Makruk", + "Minishogi", + "Shatranj", + "Shogi", + "Sittuyin" + ] + //Chinese chess (TODO) +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Kings race + +p The goal is to cross the board with your king. +- + var varlist = [ + "Racingkings", + "Royalrace" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Several moves in one turn + +p In these variants, you can play two or more moves per turn. +- + var varlist = [ + "Doublemove1", + "Doublemove2", + "Monster", + "Progressive" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Exchanging pieces positions + +p Some or all pieces can be swapped. +- + var varlist = [ + "Suction", + "Swap", + "Switching" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Different objective + +p Orthodox rules, but the goal is not checkmate (or not only). +- + var varlist = [ + "Extinction", + "Threechecks", + "Kinglet", + "Koth" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Miscelleanous + +p. + These variants are not classified yet, generally because they are the only + one of their kind on this website. +- + var varlist = [ + "Alice", + "Ambiguous", + "Bicolour", + "Doublearmy", + "Forward", + "Freecapture", + "Gridolina", + "Hamilton", + "Magnetic", + "Monochrome", + "Parachute", + "Takenmake", + "Wormhole" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] diff --git a/client/src/translations/variants/es.pug b/client/src/translations/variants/es.pug new file mode 100644 index 00000000..5d257638 --- /dev/null +++ b/client/src/translations/variants/es.pug @@ -0,0 +1,406 @@ +p.text-center + a(href="https://www.chessvariants.com/what.html") ¿Qué es una variante? + | + a(href="https://www.chessvariants.com/why.html") + | ¿Por qué jugar las variantes? + +p + | La variante + a(href="/#/variants/Chess960") Chess960 + | te permite jugar con reglas estándar, desde una posición + | inicial aleatorio (o no) simétrico (o no). + +h3 Para principiantes, aprender el juego. + +p Variantes con muy pocas piezas diferentes y un propósito simplificado. +- + var varlist = [ + "Bishopawns", + "Discoduel", + "Knightpawns", + "Pawns", + "Pawnsking", + "Rookpawns" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Capturas obligatorias + +p. + En una posición dada, generalmente hay menos movimientos posibles que + en juego ortodoxo ya que tienes que capturar. +- + var varlist = [ + "Arena", + "Capture", + "Interweave", + "Losers", + "Suicide" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Transformaciones + +p En general, las piezas se transforman mediante la captura. +- + var varlist = [ + "Absorption", + "Cannibal" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Bordes modificados + +p Tableros de ajedrez con bordes comunicantes. +- + var varlist = [ + "Circular", + "Cylinder" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Diferentes movimientos de peones + +p. + Todo va como en el juego ortodoxo, + pero los peones se mueven de una manera inusual. +- + var varlist = [ + "Berolina", + "Diamond" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Diferentes ejércitos + +p Piezas estándar contra un equipo de diferentes piezas. +- + var varlist = [ + "Colorbound", + "Horde", + "Orda" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Inspirado por juegos de pelota + +p. + Variantes que usan un globo, abstracto o no, + quien tiene que cruzar el tablero de ajedrez. +- + var varlist = [ + "Ball", + "Football", + "Rugby" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Piezas nuevas + +p. + Se puede introducir una amplia gama de piezas mágicas. + Algunas son muy poderosos como la Amazona, + otros bastante débiles como el Saltamontes. +- + var varlist = [ + "Eightpieces", + "Grand", + "Grasshopper", + "Omega", + "Perfect", + "Schess", + "Shako", + "Tencubed", + "Wildebeest" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Varias piezas reales + +p En estos juegos debes mantener a salvo a dos o más "reyes". +- + var varlist = [ + "Coregal", + "Twokings", + "Antiking1", + "Antiking2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Capturas no ortodoxas + +p Capturas no estándar, pero utilizando mecanismos conocidos. +- + var varlist = [ + "Enpassant", + "Rifle", + "Zen" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +p. + Las capturas generalmente se realizan sin reemplazo. Es decir + que no reemplaces las piezas opuestas en su espacio de captura. +- + var varlist = [ + "Allmate1", + "Allmate2", + "Baroque", + "Dynamo", + "Fugue", + "Rococo", + "Maxima" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Piezas que cambian de lado + +p Los propietarios (colores) de las piezas pueden cambiar durante el juego. +- + var varlist = [ + "Benedict", + "Checkered1", + "Checkered2", + "Pacifist1", + "Pacifist2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Información incompleta + +p. + Se requiere cierta especulación para estas variantes, + donde se oculta alguna información sobre el juego. +- + var varlist = [ + "Apocalypse", + "Dark", + "Hidden", + "Hiddenqueen", + "Synchrone" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Factores aleatorios + +p. + Estos juegos incluyen efectos aleatorios, + que puede ser divertido, frustrante o ambos :) +- + var varlist = [ + "Chakart", + "Dice" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Inspiradas por el movimiento del caballo + +p. + Variantes basadas en el movimiento del caballo, + que aumenta o transforma las capacidades de las piezas. +- + var varlist = [ + "Balaklava", + "Knightmate", + "Knightrelay1", + "Knightrelay2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Disposición inicial inusual + +p. + Los peones y / o piezas se intercambian, + resultando en un juego muy diferente. +- + var varlist = [ + "Upsidedown", + "Pawnmassacre" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Variantes "fáciles": reglas simples + +p. + Las reglas ortodoxas solo cambian ligeramente, + lo que da un juego muy similar. +- + var varlist = [ + "Coronation", + "Pocketknight" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +p ...O conduce a estrategias muy diferentes: +- + var varlist = [ + "Antimatter", + "Atomic", + "Checkless" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +//h3 Initially empty board +// +//Parachute +//"Crown chess" (place all units at move 1) + +h3 Reposicionamiento + +p. + Las piezas se pueden dejar caer en el tablero de ajedrez, + ya sea inmediatamente o más tarde en el juego. +- + var varlist = [ + "Clorange", + "Crazyhouse", + "Madhouse", + "Rampage", + "Recycle", + "Teleport" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Inmovilización + +p Las piezas pueden paralizarse en ciertas circunstancias. +- + var varlist = [ + "Koopa", + "Madrasi" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Variantes regionales e históricas + +p Evolución (parcial) del juego en espacio y tiempo. +- + var varlist = [ + "Makruk", + "Minishogi", + "Shatranj", + "Shogi", + "Sittuyin" + ] + //Chinese chess (TODO) +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Carrera de reyes + +p El objetivo es cruzar el tablero de ajedrez con tu rey. +- + var varlist = [ + "Racingkings", + "Royalrace" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Varias jugadas por turno + +p En estas variantes, puedes jugar dos o más movimientos por turno. +- + var varlist = [ + "Doublemove1", + "Doublemove2", + "Monster", + "Progressive" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Intercambio de posiciones de piezas + +p Algunas o todas las piezas pueden intercambiarse. +- + var varlist = [ + "Suction", + "Swap", + "Switching" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Objetivo diferente + +p Reglas ortodoxas, pero el objetivo no es jaque mate (o no solo). +- + var varlist = [ + "Extinction", + "Threechecks", + "Kinglet", + "Koth" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Varios + +p. + Estas variantes aún no están clasificadas, en general porque son + el único representante de su tipo en este sitio. +- + var varlist = [ + "Alice", + "Ambiguous", + "Bicolour", + "Doublearmy", + "Forward", + "Freecapture", + "Gridolina", + "Hamilton", + "Magnetic", + "Monochrome", + "Parachute", + "Takenmake", + "Wormhole" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] diff --git a/client/src/translations/variants/fr.pug b/client/src/translations/variants/fr.pug new file mode 100644 index 00000000..3962fb6a --- /dev/null +++ b/client/src/translations/variants/fr.pug @@ -0,0 +1,405 @@ +p.text-center + a(href="https://www.chessvariants.com/what.html") Qu'est-ce qu'une variante ? + | + a(href="https://www.chessvariants.com/why.html") Pourquoi jouer aux variantes ? + +p + | La variante + a(href="/#/variants/Chess960") Chess960 + | permet de jouer avec les règles standard, depuis une position + | initiale aléatoire (ou non) symétrique (ou non). + +h3 Pour les débutants, pour apprendre le jeu. + +p Variantes avec très peu de pièces différentes, et un but simplifié. +- + var varlist = [ + "Bishopawns", + "Discoduel", + "Knightpawns", + "Pawns", + "Pawnsking", + "Rookpawns" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Captures obligatoires + +p. + Dans une position donnée, il y a généralement moins de coups possibles que + dans le jeu orthodoxe puisque vous devez capturer. +- + var varlist = [ + "Arena", + "Capture", + "Interweave", + "Losers", + "Suicide" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Transformations + +p En général les pièces se transforment en capturant. +- + var varlist = [ + "Absorption", + "Cannibal" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Frontières modifiées + +p Ãchiquiers aux bords communiquants. +- + var varlist = [ + "Circular", + "Cylinder" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Différents coups de pions + +p. + Tout se déroule comme au jeu orthodoxe, + mais les pions se déplacent d'une manière inhabituelle. +- + var varlist = [ + "Berolina", + "Diamond" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Armées différentes + +p Pièces standard contre une équipe de pièces différentes. +- + var varlist = [ + "Colorbound", + "Horde", + "Orda" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Inspirées par des jeux de ballon + +p. + Variantes utilisant un ballon, abstrait ou non, + qui doit traverser l'échiquier. +- + var varlist = [ + "Ball", + "Football", + "Rugby" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Nouvelles pièces + +p. + Une large gamme de pièces féériques peuvent être introduites. + Certaines sont très puissantes comme l'Amazone, + d'autres plutôt faibles comme la Sauterelle. +- + var varlist = [ + "Eightpieces", + "Grand", + "Grasshopper", + "Omega", + "Perfect", + "Schess", + "Shako", + "Tencubed", + "Wildebeest" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Plusieurs pièces royales + +p Dans ces jeux vous devez garder à l'abri deux "rois" ou plus. +- + var varlist = [ + "Coregal", + "Twokings", + "Antiking1", + "Antiking2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Captures non orthodoxes + +p Captures non-standard, mais utilisant des mécanismes connus. +- + var varlist = [ + "Enpassant", + "Rifle", + "Zen" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +p. + Les captures s'effectuent généralement sans remplacement. C'est-à -dire + que vous ne remplacez pas les pièces adverses sur leur case de capture. +- + var varlist = [ + "Allmate1", + "Allmate2", + "Baroque", + "Dynamo", + "Fugue", + "Rococo", + "Maxima" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Pièces changeant de camp + +p Les propriétaires (couleurs) des pièces peuvent changer pendant la partie. +- + var varlist = [ + "Benedict", + "Checkered1", + "Checkered2", + "Pacifist1", + "Pacifist2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Information incomplète + +p. + Une part de spéculation est requise pour ces variantes, + où certaines informations sur le jeu sont cachées. +- + var varlist = [ + "Apocalypse", + "Dark", + "Hidden", + "Hiddenqueen", + "Synchrone" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Facteurs aléatoires + +p. + Ces jeux incluent des effets aléatoires, + qui peuvent être amusants, frustrants ou bien les deux :) +- + var varlist = [ + "Chakart", + "Dice" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Inspirées par le déplacement du cavalier + +p. + Variantes basées sur le coup de cavalier, + qui augmente ou transforme les capacités des pièces. +- + var varlist = [ + "Balaklava", + "Knightmate", + "Knightrelay1", + "Knightrelay2" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Arrangement initial inhabituel + +p. + Les pions et / ou les pièces sont échangés, + résultant en un jeu très différent. +- + var varlist = [ + "Upsidedown", + "Pawnmassacre" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Variantes "faciles" : règles simples + +p. + Les règles orthodoxes ne sont que légèrement modifiées, + ce qui donne un jeu très similaire. +- + var varlist = [ + "Coronation", + "Pocketknight" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +p ...Ou mène à des stratégies très différentes : +- + var varlist = [ + "Antimatter", + "Atomic", + "Checkless" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +//h3 Initially empty board +// +//Parachute +//"Crown chess" (place all units at move 1) + +h3 Repositionnement + +p. + Les pièces peuvent être parachutées sur l'échiquier, + soit immédiatement soit plus tard dans la partie. +- + var varlist = [ + "Clorange", + "Crazyhouse", + "Madhouse", + "Rampage", + "Recycle", + "Teleport" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Immobilisation + +p Les pièces peuvent être paralysées dans certaines circonstances. +- + var varlist = [ + "Koopa", + "Madrasi" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Variantes régionales et historiques + +p Ãvolution (partielle) du jeu dans l'espace et le temps. +- + var varlist = [ + "Makruk", + "Minishogi", + "Shatranj", + "Shogi", + "Sittuyin" + ] + //Chinese chess (TODO) +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Course de rois + +p L'objectif est de traverser l'échiquier avec votre roi. +- + var varlist = [ + "Racingkings", + "Royalrace" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Plusieurs coups par tour + +p Dans ces variantes, vous pouvez jouer deux coups ou plus par tour. +- + var varlist = [ + "Doublemove1", + "Doublemove2", + "Monster", + "Progressive" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Ãchange des positions des pièces + +p Certaines ou toutes les pièces peuvent être échangées. +- + var varlist = [ + "Suction", + "Swap", + "Switching" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Objectif différent + +p Règles orthodoxes, mais le but n'est pas de mater (ou pas seulement). +- + var varlist = [ + "Extinction", + "Threechecks", + "Kinglet", + "Koth" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] + +h3 Divers + +p. + Ces variantes ne sont pas encore classées, en général car elles sont + l'unique représentant de leur type sur ce site. +- + var varlist = [ + "Alice", + "Ambiguous", + "Bicolour", + "Doublearmy", + "Forward", + "Freecapture", + "Gridolina", + "Hamilton", + "Magnetic", + "Monochrome", + "Parachute", + "Takenmake", + "Wormhole" + ] +ul + for v in varlist + li #[a(href="/#/variants/"+v) #{v}] diff --git a/client/src/utils/notation.js b/client/src/utils/notation.js index 4402e269..3d566c8a 100644 --- a/client/src/utils/notation.js +++ b/client/src/utils/notation.js @@ -2,11 +2,15 @@ export function getFullNotation(move, type) { if (!type) type = "notation"; if (Array.isArray(move)) { - let notation = ""; - for (let i=0; i<move.length; i++) - notation += move[i][type] + ","; - // Remove last comma: - return notation.slice(0,-1); + if (move.length <= 3) { + let notation = ""; + for (let i=0; i<move.length; i++) + notation += move[i][type] + ","; + // Remove last comma: + return notation.slice(0,-1); + } + // Four sub-moves or more: + return "∞"; } // Simple (usual) case return move[type]; diff --git a/client/src/variants/Bishopawns.js b/client/src/variants/Bishopawns.js new file mode 100644 index 00000000..1ee9b97a --- /dev/null +++ b/client/src/variants/Bishopawns.js @@ -0,0 +1,51 @@ +import { ChessRules } from "@/base_rules"; + +export class BishopawnsRules extends ChessRules { + static get PawnSpecs() { + return Object.assign( + {}, + ChessRules.PawnSpecs, + // The promotion piece doesn't matter, the game is won + { promotions: [V.QUEEN] } + ); + } + + static get HasFlags() { + return false; + } + + scanKings() {} + + static GenRandInitFen() { + return "8/ppp5/8/8/8/8/8/5B2 w 0 -"; + } + + filterValid(moves) { + return moves; + } + + getCheckSquares() { + return []; + } + + getCurrentScore() { + // If all pieces of some color vanished, the opponent wins: + for (let c of ['w', 'b']) { + if (this.board.every(b => b.every(cell => !cell || cell[0] != c))) + return (c == 'w' ? "0-1" : "1-0"); + } + // Did a black pawn promote? Can the bishop take it? + const qIdx = this.board[7].findIndex(cell => cell[1] == V.QUEEN); + if (qIdx >= 0 && !super.isAttackedByBishop([7, qIdx], 'w')) + return "0-1"; + if (!this.atLeastOneMove()) return "1/2"; + return "*"; + } + + postPlay() {} + postUndo() {} + + static get SEARCH_DEPTH() { + return 4; + } +}; diff --git a/client/src/variants/Dark.js b/client/src/variants/Dark.js index cb073cfd..65934e69 100644 --- a/client/src/variants/Dark.js +++ b/client/src/variants/Dark.js @@ -109,7 +109,7 @@ export class DarkRules extends ChessRules { postPlay(move) { super.postPlay(move); - if (move.vanish.length >= 2 && move.vanish[1].p == V.KING) + if (move.vanish.length == 2 && move.vanish[1].p == V.KING) // We took opponent king (because if castle vanish[1] is a rook) this.kingPos[this.turn] = [-1, -1]; @@ -119,11 +119,9 @@ export class DarkRules extends ChessRules { postUndo(move) { super.postUndo(move); - const c = move.vanish[0].c; - const oppCol = V.GetOppCol(c); - if (this.kingPos[oppCol][0] < 0) + if (move.vanish.length == 2 && move.vanish[1].p == V.KING) // Last move took opponent's king: - this.kingPos[oppCol] = [move.vanish[1].x, move.vanish[1].y]; + this.kingPos[move.vanish[1].c] = [move.vanish[1].x, move.vanish[1].y]; // Update lights for both colors: this.updateEnlightened(); diff --git a/client/src/variants/Discoduel.js b/client/src/variants/Discoduel.js new file mode 100644 index 00000000..ea522df5 --- /dev/null +++ b/client/src/variants/Discoduel.js @@ -0,0 +1,50 @@ +import { ChessRules } from "@/base_rules"; + +export class DiscoduelRules extends ChessRules { + static get PawnSpecs() { + return Object.assign( + {}, + ChessRules.PawnSpecs, + { promotions: [V.PAWN] } + ); + } + + static get HasFlags() { + return false; + } + + scanKings() {} + + static GenRandInitFen() { + return "1n4n1/8/8/8/8/8/PPPPPPPP/8 w 0 -"; + } + + getPotentialMovesFrom(sq) { + const moves = super.getPotentialMovesFrom(sq); + if (this.turn == 'b') + // Prevent pawn captures on last rank: + return moves.filter(m => m.vanish.length == 1 || m.vanish[1].x != 0); + return moves; + } + + filterValid(moves) { + return moves; + } + + getCheckSquares() { + return []; + } + + getCurrentScore() { + // No real winning condition (promotions count...) + if (!this.atLeastOneMove()) return "1/2"; + return "*"; + } + + postPlay() {} + postUndo() {} + + static get SEARCH_DEPTH() { + return 4; + } +}; diff --git a/client/src/variants/Doublemove1.js b/client/src/variants/Doublemove1.js index f51dd7ac..6999eb40 100644 --- a/client/src/variants/Doublemove1.js +++ b/client/src/variants/Doublemove1.js @@ -1,5 +1,4 @@ import { ChessRules } from "@/base_rules"; -import { randInt } from "@/utils/alea"; export class Doublemove1Rules extends ChessRules { static IsGoodEnpassant(enpassant) { @@ -88,8 +87,15 @@ export class Doublemove1Rules extends ChessRules { this.epSquares.push([epSq]); this.movesCount = 1; } - // Does this move give check on subturn 1? If yes, skip subturn 2 - else if (this.subTurn == 1 && this.underCheck(V.GetOppCol(this.turn))) { + // Does this move give check on subturn 1 or reach stalemate? + // If yes, skip subturn 2 + else if ( + this.subTurn == 1 && + ( + this.underCheck(V.GetOppCol(this.turn)) || + !this.atLeastOneMove() + ) + ) { this.turn = V.GetOppCol(this.turn); this.epSquares.push([epSq]); move.checkOnSubturn1 = true; @@ -115,7 +121,7 @@ export class Doublemove1Rules extends ChessRules { const piece = move.vanish[0].p; const firstRank = c == "w" ? V.size.x - 1 : 0; - if (piece == V.KING && move.appear.length > 0) { + if (piece == V.KING) { this.kingPos[c][0] = move.appear[0].x; this.kingPos[c][1] = move.appear[0].y; this.castleFlags[c] = [V.size.y, V.size.y]; @@ -130,7 +136,7 @@ export class Doublemove1Rules extends ChessRules { const flagIdx = (move.start.y == this.castleFlags[c][0] ? 0 : 1); this.castleFlags[c][flagIdx] = V.size.y; } - else if ( + if ( move.end.x == oppFirstRank && //we took opponent rook? this.castleFlags[oppCol].includes(move.end.y) ) { @@ -206,43 +212,39 @@ export class Doublemove1Rules extends ChessRules { }; const moves11 = this.getAllValidMoves(); - let doubleMoves = []; + let doubleMove = null; + let bestEval = Number.POSITIVE_INFINITY * (color == 'w' ? -1 : 1); // Rank moves using a min-max at depth 2 for (let i = 0; i < moves11.length; i++) { this.play(moves11[i]); if (this.turn != color) { // We gave check with last move: search the best opponent move - doubleMoves.push({ moves: [moves11[i]], eval: getBestMoveEval() }); + const evalM = getBestMoveEval() + 0.05 - Math.random() / 10; + if ( + (color == 'w' && evalM > bestEval) || + (color == 'b' && evalM < bestEval) + ) { + doubleMove = moves11[i]; + bestEval = evalM; + } } else { let moves12 = this.getAllValidMoves(); for (let j = 0; j < moves12.length; j++) { this.play(moves12[j]); - doubleMoves.push({ - moves: [moves11[i], moves12[j]], - eval: getBestMoveEval() + 0.05 - Math.random() / 10 - }); + const evalM = getBestMoveEval() + 0.05 - Math.random() / 10 + if ( + (color == 'w' && evalM > bestEval) || + (color == 'b' && evalM < bestEval) + ) { + doubleMove = [moves11[i], moves12[j]]; + bestEval = evalM; + } this.undo(moves12[j]); } } this.undo(moves11[i]); } - - // TODO: array + sort + candidates logic not required when adding small - // fluctuations to the eval function (could also be generalized). - doubleMoves.sort((a, b) => { - return (color == "w" ? 1 : -1) * (b.eval - a.eval); - }); - let candidates = [0]; //indices of candidates moves - for ( - let i = 1; - i < doubleMoves.length && doubleMoves[i].eval == doubleMoves[0].eval; - i++ - ) { - candidates.push(i); - } - const selected = doubleMoves[randInt(candidates.length)].moves; - if (selected.length == 1) return selected[0]; - return selected; + return doubleMove; } }; diff --git a/client/src/variants/Doublemove2.js b/client/src/variants/Doublemove2.js index 4801d367..f9d5e4f1 100644 --- a/client/src/variants/Doublemove2.js +++ b/client/src/variants/Doublemove2.js @@ -127,7 +127,7 @@ export class Doublemove2Rules extends ChessRules { const piece = move.vanish[0].p; const firstRank = c == "w" ? V.size.x - 1 : 0; - if (piece == V.KING && move.appear.length > 0) { + if (piece == V.KING) { this.kingPos[c] = [move.appear[0].x, move.appear[0].y]; this.castleFlags[c] = [V.size.y, V.size.y]; return; @@ -146,7 +146,7 @@ export class Doublemove2Rules extends ChessRules { const flagIdx = (move.start.y == this.castleFlags[c][0] ? 0 : 1); this.castleFlags[c][flagIdx] = V.size.y; } - else if ( + if ( move.end.x == oppFirstRank && //we took opponent rook? this.castleFlags[oppCol].includes(move.end.y) ) { @@ -210,34 +210,28 @@ export class Doublemove2Rules extends ChessRules { if (this.movesCount == 0) // First white move at random: return moves11[randInt(moves11.length)]; - let doubleMoves = []; + let doubleMove = null; + let bestEval = Number.POSITIVE_INFINITY * (color == 'w' ? -1 : 1); // Rank moves using a min-max at depth 2 for (let i = 0; i < moves11.length; i++) { this.play(moves11[i]); const moves12 = this.getAllValidMoves(); for (let j = 0; j < moves12.length; j++) { this.play(moves12[j]); - doubleMoves.push({ - moves: [moves11[i], moves12[j]], - // Small fluctuations to uniformize play a little - eval: getBestMoveEval() + 0.05 - Math.random() / 10 - }); + // Small fluctuations to uniformize play a little + const evalM = getBestMoveEval() + 0.05 - Math.random() / 10 + if ( + (color == 'w' && evalM > bestEval) || + (color == 'b' && evalM < bestEval) + ) { + doubleMove = [moves11[i], moves12[j]]; + bestEval = evalM; + } this.undo(moves12[j]); } this.undo(moves11[i]); } - - doubleMoves.sort((a, b) => { - return (color == "w" ? 1 : -1) * (b.eval - a.eval); - }); - let candidates = [0]; //indices of candidates moves - for ( - let i = 1; - i < doubleMoves.length && doubleMoves[i].eval == doubleMoves[0].eval; - i++ - ) { - candidates.push(i); - } - return doubleMoves[randInt(candidates.length)].moves; + // TODO: not always the best move played (why ???) + return doubleMove; } }; diff --git a/client/src/variants/Eightpieces.js b/client/src/variants/Eightpieces.js index 6efb182f..a232890c 100644 --- a/client/src/variants/Eightpieces.js +++ b/client/src/variants/Eightpieces.js @@ -557,6 +557,7 @@ export class EightpiecesRules extends ChessRules { const L = this.sentryPush.length; const color = this.getColor(x, y); const dirCode = this.board[x][y][1]; + const curDir = V.LANCER_DIRS[dirCode]; if (!!this.sentryPush[L-1]) { // Maybe I was pushed const pl = this.sentryPush[L-1].length; @@ -567,7 +568,6 @@ export class EightpiecesRules extends ChessRules { // I was pushed: allow all directions (for this move only), but // do not change direction after moving, *except* if I keep the // same orientation in which I was pushed. - const curDir = V.LANCER_DIRS[dirCode]; // Also allow simple reorientation ("capturing king"): if (!V.OnBoard(x + curDir[0], y + curDir[1])) { const kp = this.kingPos[color]; @@ -647,10 +647,11 @@ export class EightpiecesRules extends ChessRules { }); return moves; } else { - // I'm pushed: add potential nudges + // I'm pushed: add potential nudges, except for current orientation let potentialNudges = []; for (let step of V.steps[V.ROOK].concat(V.steps[V.BISHOP])) { if ( + (step[0] != curDir[0] || step[1] != curDir[1]) && V.OnBoard(x + step[0], y + step[1]) && this.board[x + step[0]][y + step[1]] == V.EMPTY ) { @@ -842,9 +843,21 @@ export class EightpiecesRules extends ChessRules { coord.x += step[0]; coord.y += step[1]; } + const L = this.sentryPush.length; + const pl = (!!this.sentryPush[L-1] ? this.sentryPush[L-1].length : 0); for (let xy of lancerPos) { const dir = V.LANCER_DIRS[this.board[xy.x][xy.y].charAt(1)]; - if (dir[0] == -step[0] && dir[1] == -step[1]) return true; + if ( + (dir[0] == -step[0] && dir[1] == -step[1]) || + // If the lancer was just pushed, this is an attack too: + ( + !!this.sentryPush[L-1] && + this.sentryPush[L-1][pl-1].x == xy.x && + this.sentryPush[L-1][pl-1].y == xy.y + ) + ) { + return true; + } } } return false; diff --git a/client/src/variants/Knightpawns.js b/client/src/variants/Knightpawns.js new file mode 100644 index 00000000..6b7415cc --- /dev/null +++ b/client/src/variants/Knightpawns.js @@ -0,0 +1,47 @@ +import { ChessRules } from "@/base_rules"; + +export class KnightpawnsRules extends ChessRules { + static get PawnSpecs() { + return Object.assign( + {}, + ChessRules.PawnSpecs, + // The promotion piece doesn't matter, the game is won + { promotions: [V.QUEEN] } + ); + } + + static get HasFlags() { + return false; + } + + scanKings() {} + + static GenRandInitFen() { + return "8/ppp5/8/8/8/8/8/6N1 w 0 -"; + } + + filterValid(moves) { + return moves; + } + + getCheckSquares() { + return []; + } + + getCurrentScore() { + // If all pieces of some color vanished, the opponent wins: + for (let c of ['w', 'b']) { + if (this.board.every(b => b.every(cell => !cell || cell[0] != c))) + return (c == 'w' ? "0-1" : "1-0"); + } + // Did a black pawn promote? Can the rook take it? + const qIdx = this.board[7].findIndex(cell => cell[1] == V.QUEEN); + if (qIdx >= 0 && !super.isAttackedByKnight([7, qIdx], 'w')) + return "0-1"; + if (!this.atLeastOneMove()) return "1/2"; + return "*"; + } + + postPlay() {} + postUndo() {} +}; diff --git a/client/src/variants/Pawnmassacre.js b/client/src/variants/Pawnmassacre.js new file mode 100644 index 00000000..563fd00b --- /dev/null +++ b/client/src/variants/Pawnmassacre.js @@ -0,0 +1,18 @@ +import { ChessRules } from "@/base_rules"; + +export class PawnmassacreRules extends ChessRules { + static get HasFlags() { + return false; + } + + static GenRandInitFen(randomness) { + return ( + ChessRules.GenRandIntFen(randomness) + // Remove castle flags + .slice(0, -6).concat("-") + .replace("PPPPPPPP", "pppppppp") + // Next replacement is OK because only acts on first occurrence + .replace("pppppppp", "PPPPPPPP") + ); + } +}; diff --git a/client/src/variants/Pawns.js b/client/src/variants/Pawns.js index 83ccca70..1dca994d 100644 --- a/client/src/variants/Pawns.js +++ b/client/src/variants/Pawns.js @@ -14,6 +14,8 @@ export class PawnsRules extends ChessRules { return false; } + scanKings() {} + static GenRandInitFen() { return "8/pppppppp/8/8/8/8/PPPPPPPP/8 w 0 -"; } @@ -36,4 +38,11 @@ export class PawnsRules extends ChessRules { if (!this.atLeastOneMove()) return "1/2"; return "*"; } + + postPlay() {} + postUndo() {} + + static get SEARCH_DEPTH() { + return 4; + } }; diff --git a/client/src/variants/Pawnsking.js b/client/src/variants/Pawnsking.js new file mode 100644 index 00000000..76d03efa --- /dev/null +++ b/client/src/variants/Pawnsking.js @@ -0,0 +1,56 @@ +import { ChessRules } from "@/base_rules"; + +export class PawnskingRules extends ChessRules { + static get PawnSpecs() { + return Object.assign( + {}, + ChessRules.PawnSpecs, + // The promotion piece doesn't matter, the game is won + { promotions: [V.QUEEN] } + ); + } + + static get HasFlags() { + return false; + } + + static GenRandInitFen() { + return "4k3/pppppppp/8/8/8/8/PPPPPPPP/4K3 w 0 -"; + } + + filterValid(moves) { + return moves; + } + + getCheckSquares() { + return []; + } + + getCurrentScore() { + const color = this.turn; + if (this.kingPos[color][0] < 0) return (color == "w" ? "0-1" : "1-0"); + const oppCol = V.GetOppCol(color); + const lastRank = (oppCol == 'w' ? 0 : 7); + if (this.board[lastRank].some(cell => cell[0] == oppCol)) + // The opposing edge is reached! + return (oppCol == "w" ? "1-0" : "0-1"); + if (this.atLeastOneMove()) return "*"; + return "1/2"; + } + + postPlay(move) { + super.postPlay(move); + if (move.vanish.length == 2 && move.vanish[1].p == V.KING) + this.kingPos[this.turn] = [-1, -1]; + } + + postUndo(move) { + super.postUndo(move); + if (move.vanish.length == 2 && move.vanish[1].p == V.KING) + this.kingPos[move.vanish[1].c] = [move.vanish[1].x, move.vanish[1].y]; + } + + static get SEARCH_DEPTH() { + return 4; + } +}; diff --git a/client/src/variants/Progressive.js b/client/src/variants/Progressive.js new file mode 100644 index 00000000..67654286 --- /dev/null +++ b/client/src/variants/Progressive.js @@ -0,0 +1,111 @@ +import { ChessRules } from "@/base_rules"; +import { randInt } from "@/utils/alea"; + +export class ProgressiveRules extends ChessRules { + static get HasEnpassant() { + return false; + } + + setOtherVariables(fen) { + super.setOtherVariables(fen); + this.subTurn = 1; + } + + filterValid(moves) { + if (moves.length == 0) return []; + const color = this.turn; + return moves.filter(m => { + // Not using this.play() (would result ininfinite recursive calls) + V.PlayOnBoard(this.board, m); + if (m.appear[0].p == V.KING) + this.kingPos[color] = [m.appear[0].x, m.appear[0].y]; + const res = !this.underCheck(color); + V.UndoOnBoard(this.board, m); + if (m.appear[0].p == V.KING) + this.kingPos[color] = [m.vanish[0].x, m.vanish[0].y]; + return res; + }); + } + + play(move) { + move.flags = JSON.stringify(this.aggregateFlags()); + const color = this.turn; + const oppCol = V.GetOppCol(color); + move.turn = [color, this.subTurn]; + V.PlayOnBoard(this.board, move); + if ( + this.subTurn > this.movesCount || + this.underCheck(oppCol) || + !this.atLeastOneMove() + ) { + this.turn = oppCol; + this.subTurn = 1; + this.movesCount++; + } + else this.subTurn++; + this.postPlay(move); + } + + postPlay(move) { + const c = move.turn[0]; + const piece = move.vanish[0].p; + const firstRank = c == "w" ? V.size.x - 1 : 0; + + if (piece == V.KING && move.appear.length > 0) { + this.kingPos[c][0] = move.appear[0].x; + this.kingPos[c][1] = move.appear[0].y; + this.castleFlags[c] = [V.size.y, V.size.y]; + return; + } + const oppCol = V.GetOppCol(c); + const oppFirstRank = V.size.x - 1 - firstRank; + if ( + move.start.x == firstRank && //our rook moves? + this.castleFlags[c].includes(move.start.y) + ) { + const flagIdx = (move.start.y == this.castleFlags[c][0] ? 0 : 1); + this.castleFlags[c][flagIdx] = V.size.y; + } + if ( + move.end.x == oppFirstRank && //we took opponent rook? + this.castleFlags[oppCol].includes(move.end.y) + ) { + const flagIdx = (move.end.y == this.castleFlags[oppCol][0] ? 0 : 1); + this.castleFlags[oppCol][flagIdx] = V.size.y; + } + } + + undo(move) { + this.disaggregateFlags(JSON.parse(move.flags)); + V.UndoOnBoard(this.board, move); + if (this.turn != move.turn[0]) this.movesCount--; + this.turn = move.turn[0]; + this.subTurn = move.turn[1]; + super.postUndo(move); + } + + static get VALUES() { + return { + p: 1, + r: 5, + n: 3, + b: 3, + q: 7, //slightly less than in orthodox game + k: 1000 + }; + } + + // Random moves (too high branching factor otherwise). TODO + getComputerMove() { + let res = []; + const color = this.turn; + while (this.turn == color) { + const moves = this.getAllValidMoves(); + const m = moves[randInt(moves.length)]; + res.push(m); + this.play(m); + } + for (let i=res.length - 1; i>= 0; i--) this.undo(res[i]); + return res; + } +}; diff --git a/client/src/variants/Rookpawns.js b/client/src/variants/Rookpawns.js new file mode 100644 index 00000000..abbd7853 --- /dev/null +++ b/client/src/variants/Rookpawns.js @@ -0,0 +1,51 @@ +import { ChessRules } from "@/base_rules"; + +export class RookpawnsRules extends ChessRules { + static get PawnSpecs() { + return Object.assign( + {}, + ChessRules.PawnSpecs, + // The promotion piece doesn't matter, the game is won + { promotions: [V.QUEEN] } + ); + } + + static get HasFlags() { + return false; + } + + scanKings() {} + + static GenRandInitFen() { + return "8/ppppp3/8/8/8/8/8/7R w 0 -"; + } + + filterValid(moves) { + return moves; + } + + getCheckSquares() { + return []; + } + + getCurrentScore() { + // If all pieces of some color vanished, the opponent wins: + for (let c of ['w', 'b']) { + if (this.board.every(b => b.every(cell => !cell || cell[0] != c))) + return (c == 'w' ? "0-1" : "1-0"); + } + // Did a black pawn promote? Can the rook take it? + const qIdx = this.board[7].findIndex(cell => cell[1] == V.QUEEN); + if (qIdx >= 0 && !super.isAttackedByRook([7, qIdx], 'w')) + return "0-1"; + if (!this.atLeastOneMove()) return "1/2"; + return "*"; + } + + postPlay() {} + postUndo() {} + + static get SEARCH_DEPTH() { + return 4; + } +}; diff --git a/client/src/views/VariantList.vue b/client/src/views/VariantList.vue new file mode 100644 index 00000000..e5d02856 --- /dev/null +++ b/client/src/views/VariantList.vue @@ -0,0 +1,96 @@ +<template lang="pug"> +main + .row + .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 + input#prefixFilter( + v-model="curPrefix" + @input="setCurPrefix($event)" + :placeholder="st.tr['Prefix?']" + ) + .variant.col-sm-12.col-md-5.col-lg-4( + v-for="(v,idx) in filteredVariants" + :class="getVclasses(filteredVariants, idx)" + ) + router-link(:to="getLink(v.name)") + h4.boxtitle.text-center {{ v.name }} + p.description.text-center {{ st.tr[v.desc] }} +</template> + +<script> +import { store } from "@/store"; +export default { + name: "my-variants", + data: function() { + return { + curPrefix: "", + st: store.state + }; + }, + mounted: function() { + document.getElementById("prefixFilter").focus(); + }, + computed: { + filteredVariants: function() { + const capitalizedPrefix = this.curPrefix.replace(/^\w/, c => + c.toUpperCase() + ); + const variants = this.st.variants + .filter(v => { + return v.name.startsWith(capitalizedPrefix); + }) + .map(v => { + return { + name: v.name, + desc: v.description + }; + }) + .sort((a, b) => { + return a.name.localeCompare(b.name); + }); + return variants; + } + }, + methods: { + // oninput listener, required for smartphones: + setCurPrefix: function(e) { + this.curPrefix = e.target.value; + }, + getLink: function(vname) { + return "/variants/" + vname; + }, + getVclasses: function(varray, idx) { + const idxMod2 = idx % 2; + return { + 'col-md-offset-1': idxMod2 == 0, + 'col-lg-offset-2': idxMod2 == 0, + 'last-noneighb': idxMod2 == 0 && idx == varray.length - 1 + }; + }, + } +}; +</script> + +<style lang="sass" scoped> +input#prefixFilter + display: block + margin: 0 auto + +.variant + box-sizing: border-box + border: 1px solid brown + background-color: lightyellow + &:hover + background-color: yellow + a + color: #663300 + text-decoration: none + .boxtitle + font-weight: bold + margin-bottom: 0 + .description + @media screen and (max-width: 767px) + margin-top: 0 + +.last-noneighb + margin: 0 auto +</style> diff --git a/client/src/views/Variants.vue b/client/src/views/Variants.vue index e5d02856..d638b075 100644 --- a/client/src/views/Variants.vue +++ b/client/src/views/Variants.vue @@ -2,18 +2,9 @@ main .row .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 - input#prefixFilter( - v-model="curPrefix" - @input="setCurPrefix($event)" - :placeholder="st.tr['Prefix?']" - ) - .variant.col-sm-12.col-md-5.col-lg-4( - v-for="(v,idx) in filteredVariants" - :class="getVclasses(filteredVariants, idx)" - ) - router-link(:to="getLink(v.name)") - h4.boxtitle.text-center {{ v.name }} - p.description.text-center {{ st.tr[v.desc] }} + a#mainLink(href="/#/variants/list") + | {{ st.tr["View alphabetical variants list"] }} + div(v-html="content") </template> <script> @@ -22,32 +13,20 @@ export default { name: "my-variants", data: function() { return { - curPrefix: "", st: store.state }; }, - mounted: function() { - document.getElementById("prefixFilter").focus(); - }, computed: { - filteredVariants: function() { - const capitalizedPrefix = this.curPrefix.replace(/^\w/, c => - c.toUpperCase() + content: function() { + // (AJAX) Request to get rules content (plain text, HTML) + return ( + require("raw-loader!@/translations/variants/" + this.st.lang + ".pug") + // Next two lines fix a weird issue after last update (2019-11) + .replace(/\\n/g, " ") + .replace(/\\"/g, '"') + .replace('module.exports = "', "") + .replace(/"$/, "") ); - const variants = this.st.variants - .filter(v => { - return v.name.startsWith(capitalizedPrefix); - }) - .map(v => { - return { - name: v.name, - desc: v.description - }; - }) - .sort((a, b) => { - return a.name.localeCompare(b.name); - }); - return variants; } }, methods: { @@ -71,26 +50,9 @@ export default { </script> <style lang="sass" scoped> -input#prefixFilter +a#mainLink display: block - margin: 0 auto - -.variant - box-sizing: border-box - border: 1px solid brown - background-color: lightyellow - &:hover - background-color: yellow - a - color: #663300 - text-decoration: none - .boxtitle - font-weight: bold - margin-bottom: 0 - .description - @media screen and (max-width: 767px) - margin-top: 0 - -.last-noneighb - margin: 0 auto + margin: 10px auto + text-align: center + font-size: 1.3em </style> diff --git a/server/db/populate.sql b/server/db/populate.sql index a44a3ab5..6b664a55 100644 --- a/server/db/populate.sql +++ b/server/db/populate.sql @@ -26,6 +26,7 @@ insert or ignore into Variants (name, description) values ('Benedict', 'Change colors'), ('Berolina', 'Pawns move diagonally'), ('Bicolour', 'Harassed kings'), + ('Bishopawns', 'Bishop versus pawns'), ('Cannibal', 'Capture powers'), ('Capture', 'Mandatory captures'), ('Checkered1', 'Shared pieces (v1)'), @@ -40,6 +41,7 @@ insert or ignore into Variants (name, description) values ('Crazyhouse', 'Captures reborn'), ('Cylinder', 'Neverending rows'), ('Diamond', 'Rotating board'), + ('Discoduel', 'Enter the disco'), ('Doublearmy', '64 pieces on the board'), ('Doublemove1', 'Double moves (v1)'), ('Doublemove2', 'Double moves (v2)'), @@ -58,6 +60,7 @@ insert or ignore into Variants (name, description) values ('Interweave', 'Interweaved colorbound teams'), ('Kinglet', 'Protect your pawns'), ('Knightmate', 'Mate the knight'), + ('Knightpawns', 'Knight versus pawns'), ('Knightrelay1', 'Move like a knight (v1)'), ('Knightrelay2', 'Move like a knight (v2)'), ('Koopa', 'Stun & kick pieces'), @@ -77,14 +80,18 @@ insert or ignore into Variants (name, description) values ('Pacifist1', 'Convert & support (v1)'), ('Pacifist2', 'Convert & support (v2)'), ('Parachute', 'Landing on the board'), - ('Pawns', 'Reach the last rank'), + ('Pawnmassacre', 'Pieces upside down'), + ('Pawns', 'Reach the last rank (v1)'), + ('Pawnsking', 'Reach the last rank (v2)'), ('Perfect', 'Powerful pieces'), ('Pocketknight', 'Knight in pocket'), + ('Progressive', 'Play more and more moves'), ('Racingkings', 'Kings cross the 8x8 board'), ('Rampage', 'Move under cover'), ('Rifle', 'Shoot pieces'), ('Recycle', 'Reuse pieces'), ('Rococo', 'Capture on the edge'), + ('Rookpawns', 'Rook versus pawns'), ('Royalrace', 'Kings cross the 11x11 board'), ('Rugby', 'Transform an essay'), ('Schess', 'Seirawan-Harper Chess'), -- 2.44.0