Add Copycat, reduce Bario image size
authorBenjamin Auder <benjamin.auder@somewhere>
Thu, 18 Mar 2021 09:44:26 +0000 (10:44 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Thu, 18 Mar 2021 09:44:26 +0000 (10:44 +0100)
14 files changed:
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Bario/en.pug
client/src/translations/rules/Bario/es.pug
client/src/translations/rules/Bario/fr.pug
client/src/translations/rules/Copycat/en.pug [new file with mode: 0644]
client/src/translations/rules/Copycat/es.pug [new file with mode: 0644]
client/src/translations/rules/Copycat/fr.pug [new file with mode: 0644]
client/src/translations/variants/en.pug
client/src/translations/variants/es.pug
client/src/translations/variants/fr.pug
client/src/variants/Copycat.js [new file with mode: 0644]
server/db/populate.sql

index 50f648a..555606b 100644 (file)
@@ -183,6 +183,7 @@ export const translations = {
   "Big board": "Big board",
   "Bishop versus pawns": "Bishop versus pawns",
   "Board upside down": "Board upside down",
   "Big board": "Big board",
   "Bishop versus pawns": "Bishop versus pawns",
   "Board upside down": "Board upside down",
+  "Borrow powers": "Borrow powers",
   "Both sides of the mirror": "Both sides of the mirror",
   "Build towers (v1)": "Build towers (v1)",
   "Build towers (v2)": "Build towers (v2)",
   "Both sides of the mirror": "Both sides of the mirror",
   "Build towers (v1)": "Build towers (v1)",
   "Build towers (v2)": "Build towers (v2)",
index 74414b9..d64bda1 100644 (file)
@@ -183,6 +183,7 @@ export const translations = {
   "Big board": "Gran tablero",
   "Bishop versus pawns": "Alfil contra peones",
   "Board upside down": "Tablero al revés",
   "Big board": "Gran tablero",
   "Bishop versus pawns": "Alfil contra peones",
   "Board upside down": "Tablero al revés",
+  "Borrow powers": "Pedir prestado poderes",
   "Both sides of the mirror": "Ambos lados del espejo",
   "Build towers (v1)": "Construir torres (v1)",
   "Build towers (v2)": "Construir torres (v2)",
   "Both sides of the mirror": "Ambos lados del espejo",
   "Build towers (v1)": "Construir torres (v1)",
   "Build towers (v2)": "Construir torres (v2)",
index 521df05..c516cb2 100644 (file)
@@ -183,6 +183,7 @@ export const translations = {
   "Big board": "Grand échiquier",
   "Bishop versus pawns": "Fou contre pions",
   "Board upside down": "Échiquier à l'envers",
   "Big board": "Grand échiquier",
   "Bishop versus pawns": "Fou contre pions",
   "Board upside down": "Échiquier à l'envers",
+  "Borrow powers": "Empruntez les pouvoir",
   "Both sides of the mirror": "Les deux côté du miroir",
   "Build towers (v1)": "Bâtissez des tours (v1)",
   "Build towers (v2)": "Bâtissez des tours (v2)",
   "Both sides of the mirror": "Les deux côté du miroir",
   "Build towers (v1)": "Bâtissez des tours (v1)",
   "Build towers (v2)": "Bâtissez des tours (v2)",
index 0b76180..93ecc9d 100644 (file)
@@ -12,7 +12,7 @@ p
   | .
 
 figure
   | .
 
 figure
-  img.img-center(src="/variants/Bario/chessboard2.jpg")
+  img.img-center(src="/variants/Bario/chessboard2.jpg" style="width:75%")
   figcaption.text-center.
     [With author's permission]
     Undefined pieces on first ranks.
   figcaption.text-center.
     [With author's permission]
     Undefined pieces on first ranks.
index 19c339e..733a3f5 100644 (file)
@@ -12,7 +12,7 @@ p
   | .
 
 figure
   | .
 
 figure
-  img.img-center(src="/variants/Bario/chessboard2.jpg")
+  img.img-center(src="/variants/Bario/chessboard2.jpg" style="width:75%")
   figcaption.text-center.
     [Con permiso del autor]
     Piezas no definidas en las primeras filas.
   figcaption.text-center.
     [Con permiso del autor]
     Piezas no definidas en las primeras filas.
index a8bb3b3..e1126c0 100644 (file)
@@ -12,7 +12,7 @@ p
   | .
 
 figure
   | .
 
 figure
-  img.img-center(src="/variants/Bario/chessboard2.jpg")
+  img.img-center(src="/variants/Bario/chessboard2.jpg" style="width:75%")
   figcaption.text-center.
     [Avec la permission de l'auteur]
     Pièces indéfinies sur les premières rangées.
   figcaption.text-center.
     [Avec la permission de l'auteur]
     Pièces indéfinies sur les premières rangées.
diff --git a/client/src/translations/rules/Copycat/en.pug b/client/src/translations/rules/Copycat/en.pug
new file mode 100644 (file)
index 0000000..15765b0
--- /dev/null
@@ -0,0 +1,28 @@
+p.boxed
+  | If A attacks B, then A can moves like B.
+
+p.
+  This game follows the orthodox chess rules, with one addition:
+  if a piece attacks another friendly one, it borrows powers from it and
+  can move (and capture) like it. This does not apply to pawns and kings,
+  which can neither move like another piece or share their abilities.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:1r3k1r/2p3pp/2P5/p2p4/Pp1Q13/4N3/1PP1PP1P/4K3:
+  .diagram.diag22
+    | fen:1r3k1r/2p3pp/2P1Q3/p2p4/Pp6/4N3/1PP1PP1P/4K3:
+  figcaption Before and after Qe6#
+
+p.
+  On the example above, the queen is attacking the knight and can therefore
+  move like it on both diagrams, so this is checkmate after Qe6.
+
+h3 More information
+
+p
+  | Join the Copycat 
+  a(href="https://discord.gg/tv9hVkQKa9") Discord server
+  | &nbsp;:-)
+
+p Inventors: students at xxNarcissus school.
diff --git a/client/src/translations/rules/Copycat/es.pug b/client/src/translations/rules/Copycat/es.pug
new file mode 100644 (file)
index 0000000..089b338
--- /dev/null
@@ -0,0 +1,28 @@
+p.boxed
+  | Si A ataca a B, entonces A puede moverse como B.
+
+p.
+  Este juego sigue las reglas del ajedrez ortodoxo, con una adición: si una
+  pieza ataca a otra pieza amiga, toma prestados sus poderes y puede ser
+  mover (y capturar) como ella. Esto no se aplica a peones y reyes,
+  que no pueden imitar otras piezas ni compartir sus habilidades.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:1r3k1r/2p3pp/2P5/p2p4/Pp1Q13/4N3/1PP1PP1P/4K3:
+  .diagram.diag22
+    | fen:1r3k1r/2p3pp/2P1Q3/p2p4/Pp6/4N3/1PP1PP1P/4K3:
+  figcaption Antes y después Qe6#
+
+p.
+  En el ejemplo anterior, la reina ataca al caballo y luego puede moverse
+  como él en los dos diagramas: por lo tanto, es mate después de Qe6.
+
+h3 Más información
+
+p
+  | Únete al 
+  a(href="https://discord.gg/tv9hVkQKa9") servidor Discord
+  | &nbsp;Copycat :-)
+
+p Inventores: alumnos de la escuela de xxNarcissus.
diff --git a/client/src/translations/rules/Copycat/fr.pug b/client/src/translations/rules/Copycat/fr.pug
new file mode 100644 (file)
index 0000000..e29e35b
--- /dev/null
@@ -0,0 +1,28 @@
+p.boxed
+  | Si A attaque B, alors A peut bouger comme B.
+
+p.
+  Ce jeu suit les règles des échecs orthodoxes, à un ajout près : si une
+  pièce attaque une autre pièce amie, elle emprunte ses pouvoirs et peut se
+  déplacer (et capturer) comme elle. Cela ne s'applique pas aux pions et rois,
+  qui ne peuvent pas imiter d'autres pièces ni partager leurs capacités.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:1r3k1r/2p3pp/2P5/p2p4/Pp1Q13/4N3/1PP1PP1P/4K3:
+  .diagram.diag22
+    | fen:1r3k1r/2p3pp/2P1Q3/p2p4/Pp6/4N3/1PP1PP1P/4K3:
+  figcaption Avant et après Qe6#
+
+p.
+  Sur l'exemple ci-dessus, la dame attaque le cavalier et peut alors se
+  déplacer comme lui sur les deux diagrammes : c'est donc mat après Qe6.
+
+h3 Plus d'information
+
+p
+  | Rejoignez le 
+  a(href="https://discord.gg/tv9hVkQKa9") serveur Discord
+  | &nbsp;Copycat :-)
+
+p Inventeurs : étudiants à l'école de xxNarcissus.
index c384bab..6432c80 100644 (file)
@@ -465,6 +465,7 @@ p.
     "Bario",
     "Bicolour",
     "Convert",
     "Bario",
     "Bicolour",
     "Convert",
+    "Copycat",
     "Evolution",
     "Forward",
     "Fusion",
     "Evolution",
     "Forward",
     "Fusion",
index d8151ef..ebf9d74 100644 (file)
@@ -475,6 +475,7 @@ p.
     "Bario",
     "Bicolour",
     "Convert",
     "Bario",
     "Bicolour",
     "Convert",
+    "Copycat",
     "Evolution",
     "Forward",
     "Fusion",
     "Evolution",
     "Forward",
     "Fusion",
index 19a799d..7eb09e9 100644 (file)
@@ -473,6 +473,7 @@ p.
     "Bario",
     "Bicolour",
     "Convert",
     "Bario",
     "Bicolour",
     "Convert",
+    "Copycat",
     "Evolution",
     "Forward",
     "Fusion",
     "Evolution",
     "Forward",
     "Fusion",
diff --git a/client/src/variants/Copycat.js b/client/src/variants/Copycat.js
new file mode 100644 (file)
index 0000000..089b92f
--- /dev/null
@@ -0,0 +1,144 @@
+import { ChessRules } from "@/base_rules";
+
+export class CopycatRules extends ChessRules {
+
+  getPotentialMovesFrom([x, y]) {
+    let moves = super.getPotentialMovesFrom([x, y]);
+    // Expand potential moves if attacking friendly pieces.
+    const piece = this.getPiece(x,y);
+    if ([V.PAWN, V.KING].includes(piece)) return moves;
+    const color = this.turn;
+    const oneStep = (piece == V.PAWN);
+    let movements = {},
+        steps = [];
+    if (piece == V.QUEEN) steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
+    else steps = V.steps[piece];
+    steps.forEach(s => {
+      let [i, j] = [x + s[0], y + s[1]];
+      while (
+        V.OnBoard(i, j) &&
+        this.board[i][j] == V.EMPTY &&
+        piece != V.KNIGHT
+      ) {
+        i += s[0];
+        j += s[1];
+      }
+      if (V.OnBoard(i, j) && this.getColor(i, j) == color) {
+        const attacked = this.getPiece(i, j);
+        if ([V.ROOK, V.BISHOP, V.KNIGHT].includes(attacked)) {
+          if (!movements[attacked]) movements[attacked] = true;
+        }
+        else if (attacked == V.QUEEN) {
+          if (!movements[V.ROOK]) movements[V.ROOK] = true;
+          if (!movements[V.BISHOP]) movements[V.BISHOP] = true;
+        }
+      }
+    });
+    Object.keys(movements).forEach(type => {
+      if (
+        (piece != V.QUEEN && type != piece) ||
+        (piece == V.QUEEN && type == V.KNIGHT)
+      ) {
+        Array.prototype.push.apply(moves,
+          this.getSlideNJumpMoves([x, y], V.steps[type], type == V.KNIGHT));
+      }
+    });
+    return moves;
+  }
+
+  // Detect indirect attacks:
+  isAttackedBy_aux(
+    [x, y], color, steps1, oneStep1, piece1, steps2, oneStep2, pieces2)
+  {
+    for (let s1 of steps1) {
+      let i = x + s1[0],
+          j = y + s1[1];
+      while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY && !oneStep1) {
+        i += s1[0];
+        j += s1[1];
+      }
+      if (
+        V.OnBoard(i, j) &&
+        this.board[i][j] != V.EMPTY &&
+        this.getPiece(i, j) == piece1 &&
+        this.getColor(i, j) == color
+      ) {
+        // Continue to detect "copycat" attacks
+        for (let s2 of steps2) {
+          let ii = i + s2[0],
+              jj = j + s2[1];
+          while (
+            V.OnBoard(ii, jj) &&
+            this.board[ii][jj] == V.EMPTY &&
+            !oneStep2
+          ) {
+            ii += s2[0];
+            jj += s2[1];
+          }
+          if (
+            V.OnBoard(ii, jj) &&
+            this.board[ii][jj] != V.EMPTY &&
+            pieces2.includes(this.getPiece(ii, jj)) &&
+            this.getColor(ii, jj) == color
+          ) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  isAttackedByKnight(sq, color) {
+    if (super.isAttackedByKnight(sq, color)) return true;
+    return (
+      this.isAttackedBy_aux(sq, color,
+        V.steps[V.ROOK], false, V.KNIGHT,
+        V.steps[V.KNIGHT], true, [V.ROOK, V.QUEEN]
+      ) ||
+      this.isAttackedBy_aux(sq, color,
+        V.steps[V.BISHOP], false, V.KNIGHT,
+        V.steps[V.KNIGHT], true, [V.BISHOP, V.QUEEN]
+      )
+    );
+  }
+
+  isAttackedByRook(sq, color) {
+    if (super.isAttackedByRook(sq, color)) return true;
+    return (
+      this.isAttackedBy_aux(sq, color,
+        V.steps[V.KNIGHT], true, V.ROOK,
+        V.steps[V.ROOK], false, [V.KNIGHT]
+      ) ||
+      this.isAttackedBy_aux(sq, color,
+        V.steps[V.BISHOP], false, V.ROOK,
+        V.steps[V.ROOK], false, [V.BISHOP, V.QUEEN]
+      )
+    );
+  }
+
+  isAttackedByBishop(sq, color) {
+    if (super.isAttackedByBishop(sq, color)) return true;
+    return (
+      this.isAttackedBy_aux(sq, color,
+        V.steps[V.KNIGHT], true, V.BISHOP,
+        V.steps[V.BISHOP], false, [V.KNIGHT]
+      ) ||
+      this.isAttackedBy_aux(sq, color,
+        V.steps[V.ROOK], false, V.BISHOP,
+        V.steps[V.BISHOP], false, [V.ROOK, V.QUEEN]
+      )
+    );
+  }
+
+  isAttackedByQueen(sq, color) {
+    if (super.isAttackedByQueen(sq, color)) return true;
+    return (
+      this.isAttackedBy_aux(sq, color,
+        V.steps[V.KNIGHT], true, V.QUEEN,
+        V.steps[V.ROOK].concat(V.steps[V.BISHOP]), false, [V.KNIGHT]
+      )
+    );
+  }
+
+};
index aa0dace..5634772 100644 (file)
@@ -49,6 +49,7 @@ insert or ignore into Variants (name, description) values
   ('Clorange', 'A Clockwork Orange'),
   ('Colorbound', 'The colorbound clobberers'),
   ('Convert', 'Convert enemy pieces'),
   ('Clorange', 'A Clockwork Orange'),
   ('Colorbound', 'The colorbound clobberers'),
   ('Convert', 'Convert enemy pieces'),
+  ('Copycat', 'Borrow powers'),
   ('Coregal', 'Two royal pieces'),
   ('Coronation', 'Long live the Queen'),
   ('Crazyhouse', 'Captures reborn'),
   ('Coregal', 'Two royal pieces'),
   ('Coronation', 'Long live the Queen'),
   ('Crazyhouse', 'Captures reborn'),