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
 
-  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
-  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
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",
-  "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",
-  "Move like a knight": "Move like a knight",
   "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",
+  "The knight transfers its powers": "The knight transfers its powers",
   "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",
-  "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",
-  "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",
@@ -169,5 +168,6 @@ export const translations = {
   "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"
 };
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",
-  "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",
-  "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",
@@ -169,5 +168,6 @@ export const translations = {
   "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"
 };
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.
 
+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
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í.
 
+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
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.
 
+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
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) {
-    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;
   }
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 {
+  static get HasEnpassant() {
+    return false;
+  }
+
   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
@@ -86,6 +135,7 @@ export const VariantRules = class GrasshopperRules extends ChessRules {
 
   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/"
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) {
-      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
@@ -93,6 +93,83 @@ export const VariantRules = class HiddenqueenRules extends ChessRules {
     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));
@@ -152,4 +229,12 @@ export const VariantRules = class HiddenqueenRules extends ChessRules {
     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'),
-  ('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'),
-  ('Royalrace', 'King crosses the board'),
+  ('Royalrace', 'Kings cross the board'),
   ('Recycle', 'Reuse pieces'),
   ('Shatranj', 'Ancient rules'),
   ('Suction', 'Attract opposite king'),