From: Benjamin Auder Date: Thu, 18 Mar 2021 09:44:26 +0000 (+0100) Subject: Add Copycat, reduce Bario image size X-Git-Url: https://git.auder.net/%7B%7B%20asset%28%27mixstore/images/app_dev.php/current/git-logo.png?a=commitdiff_plain;h=b21e0e3a8f4af5c04b39c034d13bbb4e1e2abf18;p=vchess.git Add Copycat, reduce Bario image size --- diff --git a/client/src/translations/en.js b/client/src/translations/en.js index 50f648a7..555606b5 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -183,6 +183,7 @@ export const translations = { "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)", diff --git a/client/src/translations/es.js b/client/src/translations/es.js index 74414b94..d64bda16 100644 --- a/client/src/translations/es.js +++ b/client/src/translations/es.js @@ -183,6 +183,7 @@ export const translations = { "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)", diff --git a/client/src/translations/fr.js b/client/src/translations/fr.js index 521df052..c516cb21 100644 --- a/client/src/translations/fr.js +++ b/client/src/translations/fr.js @@ -183,6 +183,7 @@ export const translations = { "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)", diff --git a/client/src/translations/rules/Bario/en.pug b/client/src/translations/rules/Bario/en.pug index 0b76180f..93ecc9d7 100644 --- a/client/src/translations/rules/Bario/en.pug +++ b/client/src/translations/rules/Bario/en.pug @@ -12,7 +12,7 @@ p | . 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. diff --git a/client/src/translations/rules/Bario/es.pug b/client/src/translations/rules/Bario/es.pug index 19c339eb..733a3f5d 100644 --- a/client/src/translations/rules/Bario/es.pug +++ b/client/src/translations/rules/Bario/es.pug @@ -12,7 +12,7 @@ p | . 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. diff --git a/client/src/translations/rules/Bario/fr.pug b/client/src/translations/rules/Bario/fr.pug index a8bb3b36..e1126c00 100644 --- a/client/src/translations/rules/Bario/fr.pug +++ b/client/src/translations/rules/Bario/fr.pug @@ -12,7 +12,7 @@ p | . 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. diff --git a/client/src/translations/rules/Copycat/en.pug b/client/src/translations/rules/Copycat/en.pug new file mode 100644 index 00000000..15765b01 --- /dev/null +++ b/client/src/translations/rules/Copycat/en.pug @@ -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 + |  :-) + +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 index 00000000..089b3389 --- /dev/null +++ b/client/src/translations/rules/Copycat/es.pug @@ -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 + |  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 index 00000000..e29e35b3 --- /dev/null +++ b/client/src/translations/rules/Copycat/fr.pug @@ -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 + |  Copycat :-) + +p Inventeurs : étudiants à l'école de xxNarcissus. diff --git a/client/src/translations/variants/en.pug b/client/src/translations/variants/en.pug index c384bab9..6432c80e 100644 --- a/client/src/translations/variants/en.pug +++ b/client/src/translations/variants/en.pug @@ -465,6 +465,7 @@ p. "Bario", "Bicolour", "Convert", + "Copycat", "Evolution", "Forward", "Fusion", diff --git a/client/src/translations/variants/es.pug b/client/src/translations/variants/es.pug index d8151ef2..ebf9d74c 100644 --- a/client/src/translations/variants/es.pug +++ b/client/src/translations/variants/es.pug @@ -475,6 +475,7 @@ p. "Bario", "Bicolour", "Convert", + "Copycat", "Evolution", "Forward", "Fusion", diff --git a/client/src/translations/variants/fr.pug b/client/src/translations/variants/fr.pug index 19a799dd..7eb09e90 100644 --- a/client/src/translations/variants/fr.pug +++ b/client/src/translations/variants/fr.pug @@ -473,6 +473,7 @@ p. "Bario", "Bicolour", "Convert", + "Copycat", "Evolution", "Forward", "Fusion", diff --git a/client/src/variants/Copycat.js b/client/src/variants/Copycat.js new file mode 100644 index 00000000..089b92f8 --- /dev/null +++ b/client/src/variants/Copycat.js @@ -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] + ) + ); + } + +}; diff --git a/server/db/populate.sql b/server/db/populate.sql index aa0dace2..56347720 100644 --- a/server/db/populate.sql +++ b/server/db/populate.sql @@ -49,6 +49,7 @@ insert or ignore into Variants (name, description) values ('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'),