"Both sides of the mirror": "Both sides of the mirror",
"Burmese chess": "Burmese chess",
"Capture all of a kind": "Capture all of a kind",
+ "Capture both colors": "Capture both colors",
"Capture en passant": "Capture en passant",
"Capture on the edge": "Capture on the edge",
"Capture powers": "Capture powers",
"Shoot pieces": "Shoot pieces",
"Squares disappear": "Squares disappear",
"Standard rules": "Standard rules",
+ "Stun & kick pieces": "Stun & kick pieces",
"Thai Chess": "Thai Chess",
"The colorbound clobberers": "The colorbound clobberers",
"The end of the world": "The end of the world",
"Both sides of the mirror": "Ambos lados del espejo",
"Burmese chess": "Ajedrez birmano",
"Capture all of a kind": "Capturar todo del mismo tipo",
+ "Capture both colors": "Captura ambos colores",
"Capture en passant": "Capturar en passant",
"Capture on the edge": "Capturar en el borde",
"Capture powers": "Capturar los poderes",
"Shoot pieces": "Tirar de las piezas",
"Squares disappear": "Las casillas desaparecen",
"Standard rules": "Reglas estandar",
+ "Stun & kick pieces": "Aturdir & patear piezas",
"Thai Chess": "Ajedrez tailandés",
"The colorbound clobberers": "Los batidores unicolor",
"The end of the world": "El fin del mundo",
"Both sides of the mirror": "Les deux côté du miroir",
"Burmese chess": "Échecs birmans",
"Capture all of a kind": "Capturez tout d'un même type",
+ "Capture both colors": "Capturer les deux couleurs",
"Capture en passant": "Capturer en passant",
"Capture on the edge": "Capturer sur le bord",
"Capture powers": "Capturer les pouvoirs",
"Shoot pieces": "Tirez sur les pièces",
"Squares disappear": "Les cases disparaissent",
"Standard rules": "Règles usuelles",
+ "Stun & kick pieces": "Étourdissez & frappez les pièces",
"Thai Chess": "Échecs thai",
"The colorbound clobberers": "Les tabasseurs unicolores",
"The end of the world": "La fin du monde",
--- /dev/null
+p.boxed.
+ Pieces can capture both colors.
+
+p.
+ This can be useful to open lines for attack, and it also eliminate
+ back rank mate threats for example.
+ On the diagram 1.Qh5 is possible because 1...Ra1+ 2.Kxh2.
+
+figure.diagram-container
+ .diagram.diag12
+ | fen:r5k1/5ppp/8/6N1/8/8/6PP/3Q3K:
+ .diagram.diag22
+ | fen:r5k1/5ppp/8/6NQ/8/8/6PP/7K:
+ figcaption Before and after 1.Qh5
+
+h3 Source
+
+p
+ |This variant is mentioned in
+ a(href="https://www.jsbeasley.co.uk/encyc.htm")
+ | The Classified Encyclopedia of Chess Variants
+ | .
+
+p Inventor: L. Tabi (1971)
--- /dev/null
+p.boxed.
+ Las piezas pueden capturar ambos colores.
+
+p.
+ Esto puede ser útil para abrir líneas de ataque, por ejemplo, y que
+ también elimina las amenazas de mate del corredor, por ejemplo.
+ En el diagrama 1.Qh5 es posible porque 1...Ra1+ 2.Kxh2.
+
+figure.diagram-container
+ .diagram.diag12
+ | fen:r5k1/5ppp/8/6N1/8/8/6PP/3Q3K:
+ .diagram.diag22
+ | fen:r5k1/5ppp/8/6NQ/8/8/6PP/7K:
+ figcaption Antes y después 1.Qh5
+
+h3 Fuente
+
+p
+ | Esta variante se menciona en
+ a(href="https://www.jsbeasley.co.uk/encyc.htm")
+ | The Classified Encyclopedia of Chess Variants
+ | .
+
+p Inventor: L. Tabi (1971)
--- /dev/null
+p.boxed.
+ Les pièces peuvent capturer les deux couleurs.
+
+p.
+ Cela peut être utile pour ouvrir des lignes d'attaque par exemple, et ça
+ élimine aussi les menaces de mat du couloir par exemple.
+ Sur le diagramme 1.Qh5 est possible car 1...Ra1+ 2.Kxh2.
+
+figure.diagram-container
+ .diagram.diag12
+ | fen:r5k1/5ppp/8/6N1/8/8/6PP/3Q3K:
+ .diagram.diag22
+ | fen:r5k1/5ppp/8/6NQ/8/8/6PP/7K:
+ figcaption Before and after 1.Qh5
+
+h3 Source
+
+p
+ | Cette variante est mentionnée dans
+ a(href="https://www.jsbeasley.co.uk/encyc.htm")
+ | The Classified Encyclopedia of Chess Variants
+ | .
+
+p Inventeur : L. Tabi (1971)
--- /dev/null
+import { ChessRules } from "@/base_rules";
+
+export class FreecaptureRules extends ChessRules {
+ canTake() {
+ // Can capture both colors:
+ return true;
+ }
+
+ static get SEARCH_DEPTH() {
+ return 2;
+ }
+};
--- /dev/null
+import { ChessRulesi, PiPo } from "@/base_rules";
+
+export class KoopaRules extends ChessRules {
+ static get HasEnpassant() {
+ return false;
+ }
+
+ // Between stun time and stun + 1 move
+ static get STUNNED_1() {
+ return ['s', 'u', 'o', 'c', 't', 'l'];
+ }
+
+ // Between stun + 1 move and stun + 2 moves
+ static get STUNNED_2() {
+ return ['v', 'x', 'a', 'd', 'w', 'm'];
+ }
+
+ static get PIECES() {
+ return ChessRules.PIECES.concat(V.STUNNED_1).concat(V.STUNNED_2);
+ }
+
+ getNormalizedStep(step) {
+ const [deltaX, deltaY] = [Math.abs(step[0]), Math.abs(step[1])];
+ if (deltaX == 0 || deltaY == 0 || deltaX == deltaY)
+ return [step[0] / deltaX || 0, step[1] / deltaY || 0];
+ // Knight:
+ const divisor = Math.min(deltaX, deltaY)
+ return [step[0] / divisor, step[1] / divisor];
+ }
+
+ getPotentialMovesFrom([x, y]) {
+ let moves = super.getPotentialMovesFrom([x, y]);
+ // Complete moves: stuns & kicks
+ const stun = V.STUNNED_1.concat(V.STUNNED_2);
+ moves.forEach(m => {
+ if (m.vanish.length == 2 && m.appear.length == 1) {
+ const step =
+ this.getNormalizedStep([m.end.x - m.start.x, m.end.y - m.start.y]);
+ // "Capture" something: is target stunned?
+ if (stun.includes(m.vanish[1].p)) {
+ // Kick it: continue movement in the same direction,
+ // destroying all on its path.
+ let [i, j] = [m.end.x + step[0], m.end.y + step[1]];
+ while (V.OnBoard(i, j)) {
+ if (this.board[i][j] != V.EMPTY) {
+ m.vanish.push(
+ new PiPo({
+ x: i,
+ y: j,
+ c: this.getColor(i, j),
+ p: this.getPiece(i, j)
+ })
+ );
+ }
+ i += step[0];
+ j += step[1];
+ }
+ }
+ else {
+ // The piece is now stunned
+ m.appear.push(m.vanish.pop());
+ const pIdx = ChessRules.PIECES.findIndex(p => p == m.appear[1].p);
+ m.appear[1].p = V.STUNNED_1[pIdx];
+ // And the capturer continue in the same direction until an empty
+ // square or the edge of the board, maybe stunning other pieces.
+ let [i, j] = [m.end.x + step[0], m.end.y + step[1]];
+ while (V.OnBoard(i, j) && this.board[i][j] != V.EMPTY) {
+ const colIJ = this.getColor(i, j);
+ const pieceIJ = this.getPiece(i, j);
+ m.vanish.push(
+ new PiPo({
+ x: i,
+ y: j,
+ c: colIJ,
+ p: pieceIJ
+ })
+ );
+ const pIdx = ChessRules.PIECES.findIndex(p => p == pieceIJ);
+ m.appear.push(
+ new PiPo({
+ x: i,
+ y: j,
+ c: colIJ,
+ p: V.STUNNED_1[pIdx]
+ })
+ );
+ i += step[0];
+ j += step[1];
+ }
+ if (V.OnBoard(i, j)) {
+ m.appear[0].x = i;
+ m.appear[0].y = j;
+ // Is it a pawn on last rank?
+ }
+ else {
+ // The piece is out
+ m.appear.shift();
+ }
+ }
+ }
+ });
+ return moves;
+ }
+
+ static GenRandInitFen(randomness) {
+ // No en-passant:
+ return ChessRules.GenRandInitFen(randomness).slice(0, -2);
+ }
+
+ filterValid(moves) {
+ // Forbid kicking own king out
+ const color = this.turn;
+ return moves.filter(m => {
+ return m.vanish.every(v => v.c != color || !(['l','m'].includes(v.p)));
+ });
+ }
+
+ getCheckSquares() {
+ return [];
+ }
+
+ getCurrentScore() {
+ if (this.kingPos['w'][0] < 0) return "0-1";
+ if (this.kingPos['b'][0] < 0) return "1-0";
+ if (!this.atLeastOneMove()) return "1/2";
+ return "*";
+ }
+
+ postPlay(move) {
+ // TODO: toutes les pièces "stunned" by me (turn) avancent d'un niveau
+ // --> alter board
+ move.wasStunned = array of stunned stage 2 pieces (just back to normal then)
+ }
+
+ postUndo(move) {
+ if (wasStunned
+ STUNNED_2
+ }
+};
('Enpassant', 'Capture en passant'),
('Extinction', 'Capture all of a kind'),
('Football', 'Score a goal'),
+ ('Freecapture', 'Capture both colors'),
('Grand', 'Big board'),
('Grasshopper', 'Long jumps over pieces'),
('Gridolina', 'Jump the borders'),
('Knightmate', 'Mate the knight'),
('Knightrelay1', 'Move like a knight (v1)'),
('Knightrelay2', 'Move like a knight (v2)'),
+ ('Koopa', 'Stun & kick pieces'),
('Koth', 'King of the Hill'),
('Losers', 'Get strong at self-mate'),
('Madrasi', 'Paralyzed pieces'),