Add Twokings variant
authorBenjamin Auder <benjamin.auder@somewhere>
Fri, 20 Mar 2020 21:08:16 +0000 (22:08 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Fri, 20 Mar 2020 21:08:16 +0000 (22:08 +0100)
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Coregal/es.pug
client/src/translations/rules/Twokings/en.pug [new file with mode: 0644]
client/src/translations/rules/Twokings/es.pug [new file with mode: 0644]
client/src/translations/rules/Twokings/fr.pug [new file with mode: 0644]
client/src/variants/Coregal.js
client/src/variants/Twokings.js [new file with mode: 0644]
server/db/populate.sql

index ded2b8a..af674cc 100644 (file)
@@ -197,6 +197,7 @@ export const translations = {
   "Squares disappear": "Squares disappear",
   "Standard rules": "Standard rules",
   "Transform an essay": "Transform an essay",
   "Squares disappear": "Squares disappear",
   "Standard rules": "Standard rules",
   "Transform an essay": "Transform an essay",
+  "Two kings": "Two kings",
   "Two royal pieces": "Two royal pieces",
   "Unidentified pieces": "Unidentified pieces"
 };
   "Two royal pieces": "Two royal pieces",
   "Unidentified pieces": "Unidentified pieces"
 };
index c065cf0..183bd6f 100644 (file)
@@ -197,6 +197,7 @@ export const translations = {
   "Squares disappear": "Las casillas desaparecen",
   "Standard rules": "Reglas estandar",
   "Transform an essay": "Transformar un ensayo",
   "Squares disappear": "Las casillas desaparecen",
   "Standard rules": "Reglas estandar",
   "Transform an essay": "Transformar un ensayo",
+  "Two kings": "Dos reyes",
   "Two royal pieces": "Dos piezas reales",
   "Unidentified pieces": "Piezas no identificadas"
 };
   "Two royal pieces": "Dos piezas reales",
   "Unidentified pieces": "Piezas no identificadas"
 };
index 120571b..b317bb4 100644 (file)
@@ -197,6 +197,7 @@ export const translations = {
   "Squares disappear": "Les cases disparaissent",
   "Standard rules": "Règles usuelles",
   "Transform an essay": "Transformer un essai",
   "Squares disappear": "Les cases disparaissent",
   "Standard rules": "Règles usuelles",
   "Transform an essay": "Transformer un essai",
+  "Two kings": "Deux rois",
   "Two royal pieces": "Deux pièces royales",
   "Unidentified pieces": "Pièces non identifiées"
 };
   "Two royal pieces": "Deux pièces royales",
   "Unidentified pieces": "Pièces non identifiées"
 };
index 489775b..f7484e8 100644 (file)
@@ -15,7 +15,7 @@ p.
   jaque las dos piezas reales al mismo tiempo, como en el siguiente diagrama.
 
 figure.diagram-container
   jaque las dos piezas reales al mismo tiempo, como en el siguiente diagrama.
 
 figure.diagram-container
-  .diagrama
+  .diagram
     | fen:4Q3/4K3/8/8/3N4/5k2/2q5/8:
   figcaption Las blancas ganan porque el rey y la dama negra están en jaque.
 
     | fen:4Q3/4K3/8/8/3N4/5k2/2q5/8:
   figcaption Las blancas ganan porque el rey y la dama negra están en jaque.
 
@@ -32,7 +32,7 @@ p.
   un gran enroque negro con la dama:
 
 figure.diagram-container
   un gran enroque negro con la dama:
 
 figure.diagram-container
-  .diagrama
+  .diagram
     | fen:r4rq1/ppppppkp/6p1/8/8/8/PPPPPPPP/1QR2RK1:
   figcaption Después de dos pequeñas rocas blancas y un gran enroque negro.
 
     | fen:r4rq1/ppppppkp/6p1/8/8/8/PPPPPPPP/1QR2RK1:
   figcaption Después de dos pequeñas rocas blancas y un gran enroque negro.
 
diff --git a/client/src/translations/rules/Twokings/en.pug b/client/src/translations/rules/Twokings/en.pug
new file mode 100644 (file)
index 0000000..0303777
--- /dev/null
@@ -0,0 +1,32 @@
+p.boxed
+  | Each side has two kings. Mate any of them.
+
+p.
+  Both kings can be checked and mated. This adds a new option to win a game,
+  by attaking both kings at the same time, as illustrated below.
+
+figure.diagram-container
+  .diagram
+    | fen:6KK/8/2Q5/8/8/5k2/2k5/8:
+  figcaption Both black kings are in check: white wins.
+
+h3 Special moves
+
+p.
+  A pawn can promote into a king, which can be mated too.
+  Probably not useful in a real game, but interesting for problems.
+
+p.
+  You can castle with any king and rook, under the same conditions
+  as orthodox castling. However, castling long is possible only with one king.
+
+p.
+  Note: to castle in a game you need to select
+  the king or queen first, and then move it to a rook.
+
+h3 Source
+
+p
+  a(href="https://greenchess.net/rules.php?v=dual") Dual Chess
+  | &nbsp;on greenchess.net. Probably invented by the webmaster Uray M. János,
+  | inspired by Coregal chess from chessvariants.com.
diff --git a/client/src/translations/rules/Twokings/es.pug b/client/src/translations/rules/Twokings/es.pug
new file mode 100644 (file)
index 0000000..fe3f071
--- /dev/null
@@ -0,0 +1,34 @@
+p.boxed
+  | Cada campo tiene dos reyes. Mate a cualquiera.
+
+p.
+  Los dos reyes pueden estar en jaque (mate). Esto agrega un nuevo
+  opción de ganar una partida, como se muestra a continuación.
+
+figure.diagram-container
+  .diagram
+    | fen:6KK/8/2Q5/8/8/5k2/2k5/8:
+  figcaption Los dos reyes negros están en jaque: las blancas ganan.
+
+h3 Movimientos especiales
+
+p.
+  Un peón puede ser promovido a rey, que también puede estar en jaque.
+  Sin duda no es muy útil en partida, pero sí interesante por los problemas.
+
+p.
+  Puedes rocar con cualquier rey y torre, bajo las mismas
+  condiciones que al ajedrez ortodoxo. Sin embargo,
+  el enroque grande no es posible que con uno de los dos reyes.
+
+p.
+  Nota: para enrocar en una partida debes seleccionar el rey o la dama
+  primero, luego mueva la pieza a una torre.
+
+h3 Fuente
+
+p
+  | La 
+  a(href="https://greenchess.net/rules.php?v=dual") dariante Dual
+  | &nbsp;en greenchess.net. Probablemente inventado por el webmaster
+  | Uray M. János, inspirado por la variante Coregal en chessvariants.com.
diff --git a/client/src/translations/rules/Twokings/fr.pug b/client/src/translations/rules/Twokings/fr.pug
new file mode 100644 (file)
index 0000000..be6c14d
--- /dev/null
@@ -0,0 +1,34 @@
+p.boxed
+  | Chaque camp a deux rois. Matez n'importe lequel.
+
+p.
+  Les deux rois peuvent être mis en échec et matés. Cela ajoute une nouvelle
+  option pour gagner une partie, comme illustré ci-dessous.
+
+figure.diagram-container
+  .diagram
+    | fen:6KK/8/2Q5/8/8/5k2/2k5/8:
+  figcaption Les deux rois noirs sont en échec : les blancs gagnent.
+
+h3 Coups spéciaux
+
+p.
+  Un pion peut être promu en roi, qui pourra être maté également.
+  Sans doute peu utile en partie, mais intéressant pour les problèmes.
+
+p.
+  Vous pouvez roquer avec n'importe quel roi et tour, sous les mêmes
+  conditions qu'aux échecs orthodoxes. Cependant, le grand roque n'est possible
+  qu'avec un des deux rois.
+
+p.
+  Note : pour roquer dans une partie il faut sélectionner le roi ou la dame
+  d'abord, puis déplacer la pièce sur une tour.
+
+h3 Source
+
+p
+  | La 
+  a(href="https://greenchess.net/rules.php?v=dual") variante Dual
+  | &nbsp;sur greenchess.net. Probablement inventée par le webmaster
+  | Uray M. János, inspiré par la variante Coregal sur chessvariants.com.
index 704ce4c..e0729ac 100644 (file)
@@ -268,18 +268,21 @@ export class CoregalRules extends ChessRules {
     return false;
   }
 
     return false;
   }
 
-  updateCastleFlags(move, piece) {
+  // "twoKings" arg for the similar Twokings variant.
+  updateCastleFlags(move, piece, twoKings) {
     const c = V.GetOppCol(this.turn);
     const firstRank = (c == "w" ? V.size.x - 1 : 0);
     // Update castling flags if castling pieces moved or were captured
     const oppCol = V.GetOppCol(c);
     const oppFirstRank = V.size.x - 1 - firstRank;
     const c = V.GetOppCol(this.turn);
     const firstRank = (c == "w" ? V.size.x - 1 : 0);
     // Update castling flags if castling pieces moved or were captured
     const oppCol = V.GetOppCol(c);
     const oppFirstRank = V.size.x - 1 - firstRank;
-    if (move.start.x == firstRank && [V.KING, V.QUEEN].includes(piece)) {
-      if (this.castleFlags[c][1] == move.start.y)
-        this.castleFlags[c][1] = 8;
-      else if (this.castleFlags[c][2] == move.start.y)
-        this.castleFlags[c][2] = 8;
-      // Else: the flag is already turned off
+    if (move.start.x == firstRank) {
+      if (piece == V.KING || (!twoKings && piece == V.QUEEN)) {
+        if (this.castleFlags[c][1] == move.start.y)
+          this.castleFlags[c][1] = 8;
+        else if (this.castleFlags[c][2] == move.start.y)
+          this.castleFlags[c][2] = 8;
+        // Else: the flag is already turned off
+      }
     }
     else if (
       move.start.x == firstRank && //our rook moves?
     }
     else if (
       move.start.x == firstRank && //our rook moves?
diff --git a/client/src/variants/Twokings.js b/client/src/variants/Twokings.js
new file mode 100644 (file)
index 0000000..9e82a24
--- /dev/null
@@ -0,0 +1,83 @@
+import { ChessRules } from "@/base_rules";
+import { CoregalRules } from "@/variants/Coregal";
+
+export class TwokingsRules extends CoregalRules {
+  static get PawnSpecs() {
+    return Object.assign(
+      {},
+      ChessRules.PawnSpecs,
+      { promotions: ChessRules.PawnSpecs.promotions.concat([V.KING]) }
+    );
+  }
+
+  static IsGoodPosition(position) {
+    if (position.length == 0) return false;
+    const rows = position.split("/");
+    if (rows.length != V.size.x) return false;
+    let kings = { "w": 0, "b": 0 };
+    for (let row of rows) {
+      let sumElts = 0;
+      for (let i = 0; i < row.length; i++) {
+        if (['K','k'].includes(row[i])) kings[row[i]]++;
+        if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
+        else {
+          const num = parseInt(row[i]);
+          if (isNaN(num)) return false;
+          sumElts += num;
+        }
+      }
+      if (sumElts != V.size.y) return false;
+    }
+    // Two kings (at least) per side should be present:
+    if (Object.values(kings).some(v => v < 2)) return false;
+    return true;
+  }
+
+  // Not scanning king positions. In this variant, scan the board everytime.
+  scanKings(fen) {}
+
+  getCheckSquares(color) {
+    let squares = [];
+    const oppCol = V.GetOppCol(color);
+    for (let i=0; i<V.size.x; i++) {
+      for (let j=0; j<V.size.y; j++) {
+        if (
+          this.getColor(i, j) == color &&
+          this.getPiece(i, j) == V.KING &&
+          this.isAttacked([i, j], oppCol)
+        ) {
+          squares.push([i, j]);
+        }
+      }
+    }
+    return squares;
+  }
+
+  static GenRandInitFen(randomness) {
+    const fen = CoregalRules.GenRandInitFen(randomness);
+    return fen.replace("q", "k").replace("Q", "K");
+  }
+
+  underCheck(color) {
+    const oppCol = V.GetOppCol(color);
+    for (let i=0; i<V.size.x; i++) {
+      for (let j=0; j<V.size.y; j++) {
+        if (
+          this.getColor(i, j) == color &&
+          this.getPiece(i, j) == V.KING &&
+          this.isAttacked([i, j], oppCol)
+        ) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  postPlay(move) {
+    const piece = move.vanish[0].p;
+    super.updateCastleFlags(move, piece, "twoKings");
+  }
+
+  postUndo() {}
+};
index d656653..a842d3e 100644 (file)
@@ -44,6 +44,7 @@ insert or ignore into Variants (name,description) values
   ('Suicide', 'Lose all pieces'),
   ('Suction', 'Attract opposite king'),
   ('Threechecks', 'Give three checks'),
   ('Suicide', 'Lose all pieces'),
   ('Suction', 'Attract opposite king'),
   ('Threechecks', 'Give three checks'),
+  ('Twokings', 'Two kings'),
   ('Upsidedown', 'Board upside down'),
   ('Wildebeest', 'Balanced sliders & leapers'),
   ('Wormhole', 'Squares disappear'),
   ('Upsidedown', 'Board upside down'),
   ('Wildebeest', 'Balanced sliders & leapers'),
   ('Wormhole', 'Squares disappear'),