Fix some rules, complete rules translations
authorBenjamin Auder <benjamin.auder@somewhere>
Sun, 1 Mar 2020 22:52:36 +0000 (23:52 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Sun, 1 Mar 2020 22:52:36 +0000 (23:52 +0100)
20 files changed:
client/src/base_rules.js
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Check3/en.pug
client/src/translations/rules/Check3/es.pug
client/src/translations/rules/Check3/fr.pug
client/src/translations/rules/Grasshopper/en.pug
client/src/translations/rules/Grasshopper/es.pug
client/src/translations/rules/Grasshopper/fr.pug
client/src/translations/rules/Hiddenqueen/en.pug
client/src/translations/rules/Hiddenqueen/es.pug
client/src/translations/rules/Hiddenqueen/fr.pug
client/src/translations/rules/Knightmate/en.pug
client/src/translations/rules/Knightmate/es.pug
client/src/translations/rules/Knightmate/fr.pug
client/src/variants/Check3.js
client/src/variants/Grasshopper.js
client/src/variants/Hiddenqueen.js
server/db/populate.sql

index 149bb4d..5b335b0 100644 (file)
@@ -395,14 +395,12 @@ export const ChessRules = class ChessRules {
   //////////////////
   // INITIALIZATION
 
   //////////////////
   // INITIALIZATION
 
-  constructor(fen) {
-    // In printDiagram() fen isn't supply because only getPpath() is used
-    if (fen)
-      this.re_init(fen);
-  }
-
   // Fen string fully describes the game state
   // Fen string fully describes the game state
-  re_init(fen) {
+  constructor(fen) {
+    if (!fen)
+      // In printDiagram() fen isn't supply because only getPpath() is used
+      // TODO: find a better solution!
+      return;
     const fenParsed = V.ParseFen(fen);
     this.board = V.GetBoard(fenParsed.position);
     this.turn = fenParsed.turn[0]; //[0] to work with MarseilleRules
     const fenParsed = V.ParseFen(fen);
     this.board = V.GetBoard(fenParsed.position);
     this.turn = fenParsed.turn[0]; //[0] to work with MarseilleRules
index 190b412..635e44a 100644 (file)
@@ -150,14 +150,13 @@ export const translations = {
   "In the shadow": "In the shadow",
   "Give three checks": "Give three checks",
   "Keep antiking in check": "Keep antiking in check",
   "In the shadow": "In the shadow",
   "Give three checks": "Give three checks",
   "Keep antiking in check": "Keep antiking in check",
-  "King crosses the board": "King crosses the board",
+  "Kings cross the board": "Kings cross the board",
   "Laws of attraction": "Laws of attraction",
   "Long jumps over pieces": "Long jumps over pieces",
   "Lose all pieces": "Lose all pieces",
   "Mate any piece": "Mate any piece",
   "Mate the knight": "Mate the knight",
   "Middle battle": "Middle battle",
   "Laws of attraction": "Laws of attraction",
   "Long jumps over pieces": "Long jumps over pieces",
   "Lose all pieces": "Lose all pieces",
   "Mate any piece": "Mate any piece",
   "Mate the knight": "Mate the knight",
   "Middle battle": "Middle battle",
-  "Move like a knight": "Move like a knight",
   "Move twice": "Move twice",
   "Neverending rows": "Neverending rows",
   "Pawns move diagonally": "Pawns move diagonally",
   "Move twice": "Move twice",
   "Neverending rows": "Neverending rows",
   "Pawns move diagonally": "Pawns move diagonally",
@@ -169,5 +168,6 @@ export const translations = {
   "Shoot pieces": "Shoot pieces",
   "Squares disappear": "Squares disappear",
   "Standard rules": "Standard rules",
   "Shoot pieces": "Shoot pieces",
   "Squares disappear": "Squares disappear",
   "Standard rules": "Standard rules",
+  "The knight transfers its powers": "The knight transfers its powers",
   "Unidentified pieces": "Unidentified pieces"
 };
   "Unidentified pieces": "Unidentified pieces"
 };
index 94b8390..89f2d31 100644 (file)
@@ -150,14 +150,13 @@ export const translations = {
   "In the shadow": "En la sombra",
   "Give three checks": "Dar tres jaques",
   "Keep antiking in check": "Mantener el antirey en jaque",
   "In the shadow": "En la sombra",
   "Give three checks": "Dar tres jaques",
   "Keep antiking in check": "Mantener el antirey en jaque",
-  "King crosses the board": "El rey cruza el tablero",
+  "Kings cross the board": "Los reyes cruzan el tablero",
   "Laws of attraction": "Las leyes de las atracciones",
   "Long jumps over pieces": "Saltos largos sobre las piezas",
   "Lose all pieces": "Perder todas las piezas",
   "Mate any piece": "Matar cualquier pieza",
   "Mate the knight": "Matar el caballo",
   "Middle battle": "Batalla media",
   "Laws of attraction": "Las leyes de las atracciones",
   "Long jumps over pieces": "Saltos largos sobre las piezas",
   "Lose all pieces": "Perder todas las piezas",
   "Mate any piece": "Matar cualquier pieza",
   "Mate the knight": "Matar el caballo",
   "Middle battle": "Batalla media",
-  "Move like a knight": "Moverse como un caballo",
   "Move twice": "Mover dos veces",
   "Neverending rows": "Filas interminables",
   "Pawns move diagonally": "Peones se mueven en diagonal",
   "Move twice": "Mover dos veces",
   "Neverending rows": "Filas interminables",
   "Pawns move diagonally": "Peones se mueven en diagonal",
@@ -169,5 +168,6 @@ export const translations = {
   "Shoot pieces": "Tirar de las piezas",
   "Squares disappear": "Las casillas desaparecen",
   "Standard rules": "Reglas estandar",
   "Shoot pieces": "Tirar de las piezas",
   "Squares disappear": "Las casillas desaparecen",
   "Standard rules": "Reglas estandar",
+  "The knight transfers its powers": "El caballo transfiere sus poderes",
   "Unidentified pieces": "Piezas no identificadas"
 };
   "Unidentified pieces": "Piezas no identificadas"
 };
index c5d82e9..cc3a7b5 100644 (file)
@@ -150,14 +150,13 @@ export const translations = {
   "In the shadow": "Dans l'ombre",
   "Give three checks": "Donnez trois échecs",
   "Keep antiking in check": "Gardez l'antiroi en échec",
   "In the shadow": "Dans l'ombre",
   "Give three checks": "Donnez trois échecs",
   "Keep antiking in check": "Gardez l'antiroi en échec",
-  "King crosses the board": "Le roi traverse l'échiquier",
+  "Kings cross the board": "Les rois traversent l'échiquier",
   "Laws of attraction": "Les lois de l'attraction",
   "Long jumps over pieces": "Sauts longs par dessus les pièces",
   "Lose all pieces": "Perdez toutes les pièces",
   "Mate any piece": "Matez n'importe quelle pièce",
   "Mate the knight": "Matez le cavalier",
   "Middle battle": "Bataille du milieu",
   "Laws of attraction": "Les lois de l'attraction",
   "Long jumps over pieces": "Sauts longs par dessus les pièces",
   "Lose all pieces": "Perdez toutes les pièces",
   "Mate any piece": "Matez n'importe quelle pièce",
   "Mate the knight": "Matez le cavalier",
   "Middle battle": "Bataille du milieu",
-  "Move like a knight": "Bougez comme un cavalier",
   "Move twice": "Jouer deux coups",
   "Neverending rows": "Rangées sans fin",
   "Pawns move diagonally": "Les pions vont en diagonale",
   "Move twice": "Jouer deux coups",
   "Neverending rows": "Rangées sans fin",
   "Pawns move diagonally": "Les pions vont en diagonale",
@@ -169,5 +168,6 @@ export const translations = {
   "Shoot pieces": "Tirez sur les pièces",
   "Squares disappear": "Les cases disparaissent",
   "Standard rules": "Règles usuelles",
   "Shoot pieces": "Tirez sur les pièces",
   "Squares disappear": "Les cases disparaissent",
   "Standard rules": "Règles usuelles",
+  "The knight transfers its powers": "Le cavalier transfère ses pouvoirs",
   "Unidentified pieces": "Pièces non identifiées"
 };
   "Unidentified pieces": "Pièces non identifiées"
 };
index b5013b6..11d2441 100644 (file)
@@ -5,6 +5,16 @@ p.
   Orthodox rules apply, but giving three checks win the game.
   Since it is easier than checkmate, most games would end in this way.
 
   Orthodox rules apply, but giving three checks win the game.
   Since it is easier than checkmate, most games would end in this way.
 
+p.
+  In the diagram position, 2.Bb5+ c6 3.Bxc6+ is an excellent
+  sacrifice because now only one check will give white victory.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR:
+  figcaption.
+    After the moves 1.e4 d6??
+
 h3 Source
 
 p
 h3 Source
 
 p
index 1c0cf26..6019781 100644 (file)
@@ -6,6 +6,16 @@ p.
   la partida. Es más fácil que de matar, entonces la mayoría de las
   partidas deberían terminar así.
 
   la partida. Es más fácil que de matar, entonces la mayoría de las
   partidas deberían terminar así.
 
+p.
+  En la posición del diagrama, 2.Bb5+ c6 3.Bxc6+ es un excelente sacrificio,
+  porque ahora un solo jaque garantizará la victoria de las blancas.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR:
+  figcaption.
+    Despues de las jugadas 1.e4 d6??
+
 h3 Fuente
 
 p
 h3 Fuente
 
 p
index 1195a59..905be78 100644 (file)
@@ -6,6 +6,16 @@ p.
   la partie. C'est plus facile que de mater,
   donc la plupart des parties devraient s'achever ainsi.
 
   la partie. C'est plus facile que de mater,
   donc la plupart des parties devraient s'achever ainsi.
 
+p.
+  Dans la position du diagramme, 2.Bb5+ c6 3.Bxc6+ est un excellent sacrifice
+  car maintenant un unique échec assurera la victoire aux blancs.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/ppp1pppp/3p4/8/4P3/8/PPPP1PPP/RNBQKBNR:
+  figcaption.
+    Après les coups 1.e4 d6??
+
 h3 Source
 
 p
 h3 Source
 
 p
index 4f56997..70c31a9 100644 (file)
@@ -1 +1,28 @@
-p TODO
+p.boxed
+  | A new piece appears: the grasshopper (G), jumping over a piece and landing right after.
+
+p.
+  Each player begins with eight grasshoppers between the first rank and the
+  pawns on the third rank. The grasshopper moves potentially in all
+  directions, but needs the help of a piece for its movement :
+  it jumps over the first encountered piece (of any color),
+  and land on the very next square.
+  This square must be either empty or occupied by an enemy piece (which is eaten).
+
+figure.diagram-container
+  .diagram
+    | fen:8/5g2/ppppp3/8/2G2k2/1PPP4/4R3/8 a2,c2,c7,f7,g4:
+  figcaption Possible grasshopper moves from c4.
+
+p.
+  Note: grasshopper moves are not symmetric.
+  On the diagram the black grasshopper cannot capture on c4.
+
+h3 Source
+
+p
+  a(href="https://www.chessvariants.com/dpieces.dir/grashopper.html") Grasshopper Chess
+  | &nbsp;on chessvariants.com.
+  | This variant is also playable
+  a(href="https://greenchess.net/rules.php?v=grasshopper") on greenchess.net
+  | &nbsp;(with a deterministic initial position).
index 4f56997..99bf70c 100644 (file)
@@ -1 +1,35 @@
-p TODO
+p.boxed
+  | Aparece una nueva pieza: el saltamontes, saltando sobre una pieza
+  | aterrizar justo detrás.
+
+p.
+  Notación: 'G' como la primera carta de grasshopper,
+  que significa saltamontes en inglés.
+
+p.
+  Cada jugador comienza con ocho saltamontes colocadas entre las primeras
+  fila y los peones en el tercero.
+  El saltamontes se mueve potencialmente en todas las direcciones,
+  pero necesita la ayuda de una pieza para su movimiento:
+  el salta sobre la primera pieza encontrada (de cualquier color),
+  y aterriza en la casilla justo detrás.
+  Este última debe estar vacío u ocupado por el enemigo (que se encuentra comido).
+
+figure.diagram-container
+  .diagram
+    | fen:8/5g2/ppppp3/8/2G2k2/1PPP4/4R3/8 a2,c2,c7,f7,g4:
+  figcaption Posibles movimientos de saltamontes desde c4.
+
+p.
+  Nota: los movimientos de saltamontes no son simétricos.
+  En el diagrama, el saltamontes negro no puede capturar en c4.
+
+h3 Fuente
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/dpieces.dir/grashopper.html") variante Grasshopper
+  | &nbsp;en chessvariants.com.
+  | También podemos jugarlo
+  a(href="https://greenchess.net/rules.php?v=grasshopper") en greenchess.net
+  | &nbsp;(con una posición inicial determinista).
index 4f56997..650b41b 100644 (file)
@@ -1 +1,35 @@
-p TODO
+p.boxed
+  | Une nouvelle pièce apparaît : la sauterelle, sautant par dessus une pièce
+  | pour atterrir juste derrière.
+
+p.
+  Notation: 'G' comme la première lettre de grasshopper,
+  signifiant sauterelle en anglais.
+
+p.
+  Chaque joueur commence avec huit sauterelles placées entre la première
+  rangée et les pions sur la troisième.
+  La sauterelle se déplace potentiellement dans toutes les directions,
+  mais a besoin de l'aide d'une pièce pour son mouvement :
+  elle saute par dessus la première pièce rencontrée (de n'importe quelle couleur),
+  et atterrit sur la case située juste derrière.
+  Cette dernière doit être vide ou occupée par l'ennemi (qui se retrouve mangé).
+
+figure.diagram-container
+  .diagram
+    | fen:8/5g2/ppppp3/8/2G2k2/1PPP4/4R3/8 a2,c2,c7,f7,g4:
+  figcaption Possibles coups de sauterelle depuis c4.
+
+p.
+  Note : les coups de sauterelles ne sont pas symétriques.
+  Sur le diagramme la sauterelle noire ne peut pas capturer en c4.
+
+h3 Source
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/dpieces.dir/grashopper.html") variante Grasshopper
+  | &nbsp;sur chessvariants.com.
+  | On peut y jouer également
+  a(href="https://greenchess.net/rules.php?v=grasshopper") sur greenchess.net
+  | &nbsp;(avec une position initiale déterministe).
index 4f56997..08c08c1 100644 (file)
@@ -1 +1,25 @@
-p TODO
+p.boxed
+  | One of the pawns of each side is a disguised queen.
+  | She is revealed only when not moving like a pawn.
+
+p.
+  The hidden queen cannot give check (because the opponent cannot see her nature),
+  but she could sometimes capture the king. This capture ends the game.
+  Except that, everything goes as in orthodox chess.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/ppp1tppp/8/3P4/8/8/TPPP1PPP/RNBQKBNR:
+  figcaption After 1.e4 d5 2.exd5
+
+p.
+  In the diagram position, if the black hidden queen is on e7 then
+  they can play 2...Qxe1, revealing her identity and winning at the same time.
+
+h3 Source
+
+p
+  a(href="https://dames-cachees.herokuapp.com/rules") This website
+  | &nbsp;introduces the rules and allow to play in live,
+  | with a deterministic initial position but a user-defined
+  | location of the hiden queen.
index 4f56997..de5a988 100644 (file)
@@ -1 +1,26 @@
-p TODO
+p.boxed
+  | Uno de los peones de cada lado es en realidad una dama (disfrazada).
+  | Esta se revela cuando no se mueve como un peón.
+
+p.
+  La dama oculta no da jaque (porque el oponente no ve su naturaleza),
+  pero eventualmente puede capturar al rey. Esta captura termina el juego.
+  Aparte de eso, todo va como el ajedrez ortodoxo.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/ppp1tppp/8/3P4/8/8/TPPP1PPP/RNBQKBNR:
+  figcaption Después de 1.e4 d5 2.exd5
+
+p.
+  En la posición del diagrama, si la dama negra escondida está en e7
+  entonces pueden jugar 2...Dxe1, ciertamente revelando su identidad pero
+  ganando la victoria al pasar.
+
+h3 Fuente
+
+p
+  a(href = "https://dames-cachees.herokuapp.com/rules") Este sitio web
+  | &nbsp;presenta las reglas y te permite jugar en vivo,
+  | con una posición inicial determinista pero dejando elegir
+  | la ubicación de la dama escondida
index 4f56997..3341371 100644 (file)
@@ -1 +1,26 @@
-p TODO
+p.boxed
+  | Un des pions de chaque camp est en réalité une dame (déguisée).
+  | Celle-ci est révélée lorsqu'elle ne se déplace pas comme un pion.
+
+p.
+  La dame cachée ne donne pas échec (car l'adversaire ne voit pas sa nature),
+  mais elle peut éventuellement capturer le roi. Cette capture met fin à la partie.
+  À part ça tout se déroule comme aux échecs orthodoxes.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/ppp1tppp/8/3P4/8/8/TPPP1PPP/RNBQKBNR:
+  figcaption Après 1.e4 d5 2.exd5
+
+p.
+  Dans la position du diagramme, si la dame cachée des noirs est en e7
+  alors ils peuvent jouer 2...Dxe1, révélant certes son identité mais
+  emportant la victoire au passage.
+
+h3 Source
+
+p
+  a(href="https://dames-cachees.herokuapp.com/rules") Ce site web
+  | &nbsp;présente les règles et permet de jouer en direct,
+  | avec une position initiale déterministe mais en laissant choisir
+  | l'emplacement de la dame cachée.
index 4f56997..565d25e 100644 (file)
@@ -1 +1,30 @@
-p TODO
+p.boxed
+  | The king moves like a knight, and the knights like a king.
+  | The goal is still to checkmate the king.
+
+p "Knights moving like a king" are quite logically called "commoners".
+
+p Castling is still permitted, under the same conditions as in orthodox chess.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:7k/8/8/8/8/1r6/8/3K1r2:
+  .diagram.diag22
+    | fen:rcbqk1cr/pppp1ppp/8/2b1p3/2B1P3/5Q2/PPPP1PPP/RCB1K1CR:
+  figcaption.
+    Left: Royal knight version of the two-rooks mate.
+    Right: After 1.e4 e5 2.Bc4 Bc5 3.Qf3
+
+p.
+  On the right diagram, the threat is 4.Bxf7+ Cxf7 5.Qxf7+,
+  with more material and a winning attack.
+
+h3 Source
+
+p
+  a(href="https://www.chessvariants.com/diffobjective.dir/knightmate.html") 
+    | Knightmate Chess
+  | &nbsp;on chessvariants.com.
+  | This variant is also playable 
+  a(href="https://greenchess.net/rules.php?v=knightmate") on greenchess.net
+  | &nbsp;(with a deterministic initial position).
index 4f56997..bdfaba9 100644 (file)
@@ -1 +1,33 @@
-p TODO
+p.boxed
+  | El rey se mueve como un caballo, y los caballos como reyes.
+  | El objetivo sigue siendo matar al rey.
+
+p.
+  Los "caballos que se mueven como reyes" son entonces lógicamente
+  llamado "plebeyos", señaló 'C' para "commoner" en inglés.
+
+p El enroque todavía es posible, bajo las mismas condiciones que el ajedrez ortodoxo
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:7k/8/8/8/8/1r6/8/3K1r2:
+  .diagram.diag22
+    | fen:rcbqk1cr/pppp1ppp/8/2b1p3/2B1P3/5Q2/PPPP1PPP/RCB1K1CR:
+  figcaption.
+    Izquierda: versión "caballo real" del mate de las dos torres.
+    Derecha: después de 1.e4 e5 2.Bc4 Bc5 3.Qf3
+
+p.
+  En el diagrama de la derecha, la amenaza es 4.Bxf7+ Cxf7 5.Qxf7+
+  con la ventaja material y un ataque ganador.
+
+h3 Fuente
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/diffobjective.dir/knightmate.html")
+    | variante Knightmate
+  | &nbsp;en chessvariants.com.
+  | También podemos jugarlo
+  a(href="https://greenchess.net/rules.php?v=knightmate") en greenchess.net
+  | &nbsp;(con una posición inicial determinista).
index 4f56997..9704e92 100644 (file)
@@ -1 +1,33 @@
-p TODO
+p.boxed
+  | Le roi se déplace comme un cavalier, et les cavaliers comme des rois.
+  | l'objectif est encore de mater le roi.
+
+p.
+  Les "cavaliers se déplaçant comme des rois" sont alors assez logiquement
+  appelés des "roturiers", notés 'C' pour "commoner" en anglais.
+
+p Le roque est toujours possible, sous les mêmes conditions qu'aux échecs orthodoxes.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:7k/8/8/8/8/1r6/8/3K1r2:
+  .diagram.diag22
+    | fen:rcbqk1cr/pppp1ppp/8/2b1p3/2B1P3/5Q2/PPPP1PPP/RCB1K1CR:
+  figcaption.
+    Gauche : Version "cavalier royal" du mat des deux tours.
+    Droite : Après 1.e4 e5 2.Bc4 Bc5 3.Qf3
+
+p.
+  Sur le diagramme de droite, la menace est 4.Bxf7+ Cxf7 5.Qxf7+
+  avec l'avantage matériel et une attaque gagnante.
+
+h3 Source
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/diffobjective.dir/knightmate.html") 
+    | variante Knightmate
+  | &nbsp;sur chessvariants.com.
+  | On peut y jouer également 
+  a(href="https://greenchess.net/rules.php?v=knightmate") sur greenchess.net
+  | &nbsp;(avec une position initiale déterministe).
index a4b292a..ea5ab84 100644 (file)
@@ -25,7 +25,9 @@ export const VariantRules = class Check3Rules extends ChessRules {
   }
 
   getPpath(b) {
   }
 
   getPpath(b) {
-    if (b[1] == 'k' && this.checkFlags[b[0]] > 0)
+    // TODO: !!this.checkFlags condition for printDiagram, but clearly not good.
+    // This is just a temporary fix.
+    if (b[1] == 'k' && this.checkFlags && this.checkFlags[b[0]] > 0)
       return "Check3/" + b[0] + 'k_' + this.checkFlags[b[0]];
     return b;
   }
       return "Check3/" + b[0] + 'k_' + this.checkFlags[b[0]];
     return b;
   }
index 58b1240..8f24340 100644 (file)
@@ -3,6 +3,10 @@ import { ArrayFun } from "@/utils/array";
 import { randInt } from "@/utils/alea";
 
 export const VariantRules = class GrasshopperRules extends ChessRules {
 import { randInt } from "@/utils/alea";
 
 export const VariantRules = class GrasshopperRules extends ChessRules {
+  static get HasEnpassant() {
+    return false;
+  }
+
   static get GRASSHOPPER() {
     return "g";
   }
   static get GRASSHOPPER() {
     return "g";
   }
@@ -24,6 +28,51 @@ export const VariantRules = class GrasshopperRules extends ChessRules {
     }
   }
 
     }
   }
 
+  getPotentialPawnMoves([x, y]) {
+    const color = this.turn;
+    let moves = [];
+    const [sizeX, sizeY] = [V.size.x, V.size.y];
+    const shiftX = color == "w" ? -1 : 1;
+    const lastRank = color == "w" ? 0 : sizeX - 1;
+
+    const finalPieces =
+      x + shiftX == lastRank
+        ? [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN, V.GRASSHOPPER]
+        : [V.PAWN];
+    if (this.board[x + shiftX][y] == V.EMPTY) {
+      // One square forward
+      for (let piece of finalPieces) {
+        moves.push(
+          this.getBasicMove([x, y], [x + shiftX, y], {
+            c: color,
+            p: piece
+          })
+        );
+      }
+      // No 2-squares jump
+    }
+    // Captures
+    for (let shiftY of [-1, 1]) {
+      if (
+        y + shiftY >= 0 &&
+        y + shiftY < sizeY &&
+        this.board[x + shiftX][y + shiftY] != V.EMPTY &&
+        this.canTake([x, y], [x + shiftX, y + shiftY])
+      ) {
+        for (let piece of finalPieces) {
+          moves.push(
+            this.getBasicMove([x, y], [x + shiftX, y + shiftY], {
+              c: color,
+              p: piece
+            })
+          );
+        }
+      }
+    }
+
+    return moves;
+  }
+
   getPotentialGrasshopperMoves([x, y]) {
     let moves = [];
     // Look in every direction until an obstacle (to jump) is met
   getPotentialGrasshopperMoves([x, y]) {
     let moves = [];
     // Look in every direction until an obstacle (to jump) is met
@@ -86,6 +135,7 @@ export const VariantRules = class GrasshopperRules extends ChessRules {
 
   static GenRandInitFen() {
     return ChessRules.GenRandInitFen()
 
   static GenRandInitFen() {
     return ChessRules.GenRandInitFen()
+      .replace("w 0 1111 -", "w 0 1111")
       .replace(
         "/pppppppp/8/8/8/8/PPPPPPPP/",
         "/gggggggg/pppppppp/8/8/PPPPPPPP/GGGGGGGG/"
       .replace(
         "/pppppppp/8/8/8/8/PPPPPPPP/",
         "/gggggggg/pppppppp/8/8/PPPPPPPP/GGGGGGGG/"
index fe34fb2..4f66894 100644 (file)
@@ -78,7 +78,7 @@ export const VariantRules = class HiddenqueenRules extends ChessRules {
 
   getPotentialMovesFrom([x, y]) {
     if (this.getPiece(x, y) == V.HIDDEN_QUEEN) {
 
   getPotentialMovesFrom([x, y]) {
     if (this.getPiece(x, y) == V.HIDDEN_QUEEN) {
-      const pawnMoves = super.getPotentialPawnMoves([x, y]);
+      const pawnMoves = this.getPotentialPawnMoves([x, y]);
       let queenMoves = super.getPotentialQueenMoves([x, y]);
       // Remove from queen moves those corresponding to a pawn move:
       queenMoves = queenMoves
       let queenMoves = super.getPotentialQueenMoves([x, y]);
       // Remove from queen moves those corresponding to a pawn move:
       queenMoves = queenMoves
@@ -93,6 +93,83 @@ export const VariantRules = class HiddenqueenRules extends ChessRules {
     return super.getPotentialMovesFrom([x, y]);
   }
 
     return super.getPotentialMovesFrom([x, y]);
   }
 
+  // TODO: find a more general way to describe pawn movements to avoid
+  // re-writing almost the same function for several variants.
+  getPotentialPawnMoves([x, y]) {
+    const color = this.turn;
+    const piece = this.getPiece(x, y);
+    let moves = [];
+    const [sizeX, sizeY] = [V.size.x, V.size.y];
+    const shiftX = color == "w" ? -1 : 1;
+    const startRank = color == "w" ? sizeX - 2 : 1;
+    const lastRank = color == "w" ? 0 : sizeX - 1;
+
+    const finalPieces =
+      x + shiftX == lastRank
+        ? piece == V.PAWN
+          ? [V.ROOK, V.KNIGHT, V.BISHOP, V.QUEEN]
+          : [V.QUEEN] //hidden queen revealed
+        : piece;
+    if (this.board[x + shiftX][y] == V.EMPTY) {
+      // One square forward
+      for (let p of finalPieces) {
+        moves.push(
+          this.getBasicMove([x, y], [x + shiftX, y], {
+            c: color,
+            p: p
+          })
+        );
+      }
+      if (
+        x == startRank &&
+        this.board[x + 2 * shiftX][y] == V.EMPTY
+      ) {
+        // Two squares jump
+        moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
+      }
+    }
+    // Captures
+    for (let shiftY of [-1, 1]) {
+      if (
+        y + shiftY >= 0 &&
+        y + shiftY < sizeY &&
+        this.board[x + shiftX][y + shiftY] != V.EMPTY &&
+        this.canTake([x, y], [x + shiftX, y + shiftY])
+      ) {
+        for (let p of finalPieces) {
+          moves.push(
+            this.getBasicMove([x, y], [x + shiftX, y + shiftY], {
+              c: color,
+              p: p
+            })
+          );
+        }
+      }
+    }
+
+    if (V.HasEnpassant) {
+      // En passant
+      const Lep = this.epSquares.length;
+      const epSquare = this.epSquares[Lep - 1]; //always at least one element
+      if (
+        !!epSquare &&
+        epSquare.x == x + shiftX &&
+        Math.abs(epSquare.y - y) == 1
+      ) {
+        let enpassantMove = this.getBasicMove([x, y], [epSquare.x, epSquare.y]);
+        enpassantMove.vanish.push({
+          x: x,
+          y: epSquare.y,
+          p: "p",
+          c: this.getColor(x, epSquare.y)
+        });
+        moves.push(enpassantMove);
+      }
+    }
+
+    return moves;
+  }
+
   getPossibleMovesFrom(sq) {
     this.side = this.turn;
     return this.filterValid(this.getPotentialMovesFrom(sq));
   getPossibleMovesFrom(sq) {
     this.side = this.turn;
     return this.filterValid(this.getPotentialMovesFrom(sq));
@@ -152,4 +229,12 @@ export const VariantRules = class HiddenqueenRules extends ChessRules {
     this.side = this.turn;
     return super.getComputerMove();
   }
     this.side = this.turn;
     return super.getComputerMove();
   }
+
+  getNotation(move) {
+    const notation = super.getNotation(move);
+    if (notation.charAt(0) == 'T')
+      // Do not reveal hidden queens
+      return notation.substr(1);
+    return notation;
+  }
 };
 };
index 6ddedf6..60cd18e 100644 (file)
@@ -24,12 +24,12 @@ insert or ignore into Variants (name,description) values
   ('Hidden', 'Unidentified pieces'),
   ('Hiddenqueen', 'Queen disguised as a pawn'),
   ('Knightmate', 'Mate the knight'),
   ('Hidden', 'Unidentified pieces'),
   ('Hiddenqueen', 'Queen disguised as a pawn'),
   ('Knightmate', 'Mate the knight'),
-  ('Knightrelay', 'Move like a knight'),
+  ('Knightrelay', 'The knight transfers its powers'),
   ('Losers', 'Lose all pieces'),
   ('Magnetic', 'Laws of attraction'),
   ('Marseille', 'Move twice'),
   ('Rifle', 'Shoot pieces'),
   ('Losers', 'Lose all pieces'),
   ('Magnetic', 'Laws of attraction'),
   ('Marseille', 'Move twice'),
   ('Rifle', 'Shoot pieces'),
-  ('Royalrace', 'King crosses the board'),
+  ('Royalrace', 'Kings cross the board'),
   ('Recycle', 'Reuse pieces'),
   ('Shatranj', 'Ancient rules'),
   ('Suction', 'Attract opposite king'),
   ('Recycle', 'Reuse pieces'),
   ('Shatranj', 'Ancient rules'),
   ('Suction', 'Attract opposite king'),