// Variants boxes:
"64 pieces on the board": "64 pieces on the board",
+ "A pawns cloud": "A pawns cloud",
"Ancient rules": "Ancient rules",
"Attract opposite king": "Attract opposite king",
"Balanced sliders & leapers": "Balanced sliders & leapers",
// Variants boxes:
"64 pieces on the board": "64 piezas en el tablero",
+ "A pawns cloud": "Une nube de peones",
"Ancient rules": "Viejas reglas",
"Attract opposite king": "Atraer al rey contrario",
"Balanced sliders & leapers": "Modos de desplazamiento equilibrados",
// Variants boxes:
"64 pieces on the board": "64 pièces sur l'échiquier",
+ "A pawns cloud": "Une nuée de pions",
"Ancient rules": "Règles anciennes",
"Attract opposite king": "Attirer le roi adverse",
"Balanced sliders & leapers": "Modes de déplacement équilibrés",
--- /dev/null
+p.boxed
+ | A horde of 36 pawns is fighting to checkmate the king.
+ | Black goal is to eliminate all white pieces.
+
+p.
+ The initial configuration shows 36 white pawns, filling the four first ranks
+ and half of the fifth:
+
+figure.diagram-container
+ .diagram
+ | fen:rnbqkbnr/pppppppp/8/1PP2PP1/PPPPPPPP/PPPPPPPP/PPPPPPPP/PPPPPPPP:
+ figcaption Deterministic starting position.
+
+p.
+ From white perspective, the material is unusual but the goal is the same as
+ in orthodox chess. Since there is no white king, black wins by capturing all
+ white pieces.
+
+p.
+ There is no castling, but en-passant captures may be executed after each two
+ squares pawn move, either from the first or second rank.
+
+h3 Source
+
+p
+ | This variant is inspired by
+ a(href="https://www.chessvariants.com/unequal.dir/dunsany.html")
+ | Dunsany's Chess
+ | , invented by Lord Dunsany in 1942. The additional white pawns are here to
+ | balance the game. See also
+ a(href="https://lichess.org/variant/horde") Horde on lichess.org
+ | and
+ a(href="https://docs.google.com/document/d/136BCRPzm1QH_OBK3qjKwlmK3MIji7ZmLZPMYgDpmOCU/edit")
+ | this document
+ | about the strategy to adopt for both sides.
--- /dev/null
+p.boxed
+ | Una horda de 36 peones lucha para dar jaque mate al rey contrario.
+ | El objetivo de las negras es eliminar todas las piezas blancas.
+
+p.
+ 36 peones blancos están presentes en la configuración inicial,
+ llenando las primeras cuatro filas y la mitad de la quinta:
+
+figure.diagram-container
+ .diagrama
+ | fen:rnbqkbnr/pppppppp/8/1PP2PP1/PPPPPPPP/PPPPPPPP/PPPPPPPP/PPPPPPPPP:
+ figcaption Posición de inicio determinista.
+
+p.
+ Desde un punto de vista blanco, el material es inusual pero el objetivo sigue
+ siendo lo mismo que el ajedrez ortodoxo. Como no hay un rey blanco, las
+ negras gana capturando todas las piezas blancas.
+
+p.
+ El enroque no es posible, pero las capturas al pasar pueden ser
+ ejecutado después de cualquier movimiento de peón por dos espacios, desde el
+ primera o segunda fila.
+
+h3 Fuente
+
+p
+ | Esta variante está inspirada por el
+ a(href="https://www.chessvariants.com/unequal.dir/dunsany.html")
+ | Ajedrez de Dunsany
+ | , inventado por Lord Dunsany en 1942. Peones blancos adicionales
+ | sirven para equilibrar el juego. Ver también
+ a(href="https://lichess.org/variant/horde") Horda en lichess.org
+ | y
+ a(href="https://docs.google.com/document/d/136BCRPzm1QH_OBK3qjKwlmK3MIji7ZmLZPMYgDpmOCU/edit")
+ | este documento
+ | sobre la estrategia a adoptar para cada campamento.
--- /dev/null
+p.boxed
+ | Une horde de 36 pions combat pour mater le roi adverse.
+ | L'objectif des noirs est d'éliminer toutes les pièces blanches.
+
+p.
+ 36 pions blancs sont présents dans la configuration initiale,
+ remplissant les quatre premières rangées et la moitié de la cinquième :
+
+figure.diagram-container
+ .diagram
+ | fen:rnbqkbnr/pppppppp/8/1PP2PP1/PPPPPPPP/PPPPPPPP/PPPPPPPP/PPPPPPPP:
+ figcaption Position de départ déterministe.
+
+p.
+ Du point de vue des blancs, le matériel est inhabituel mais l'objectif reste
+ le même qu'aux échecs orthodoxes. Puisqu'il n'y a pas de roi blanc, les noirs
+ gagnent en capturant toutes les pièces blanches.
+
+p.
+ Le roque n'est pas possible, mais les prises en passant peuvent être
+ exécutées après n'importe quel déplacement de pion de deux cases, depuis la
+ première ou seconde rangée.
+
+h3 Source
+
+p
+ | Cette variante est inspirée par les
+ a(href="https://www.chessvariants.com/unequal.dir/dunsany.html")
+ | Échecs de Dunsany
+ | , inventés par Lord Dunsany en 1942. Les pions blancs supplémentaires
+ | servent à équilibrer le jeu. Voir aussi la
+ a(href="https://lichess.org/variant/horde") Horde sur lichess.org
+ | et
+ a(href="https://docs.google.com/document/d/136BCRPzm1QH_OBK3qjKwlmK3MIji7ZmLZPMYgDpmOCU/edit")
+ | ce document
+ | sur la stratégie à adopter pour chaque camp.
if (
this.subTurn == 2 &&
square.x == this.firstMove.end.x &&
- square.y == this.firstMove.end.y)
+ square.y == this.firstMove.end.y
) {
return {
appear: [],
if (this.getColor(x, y) != color)
// The only moves possible with enemy pieces are pulls and pushes:
return this.getPactions([x, y], color);
- else {
- // Playing my pieces: either on their own, or pushed by another
- // If subTurn == 2 then we should have a first move,
- // TODO = use it to allow some type of action
- if (this.subTurn == 2) {
- return (
- this.moveOnSubturn1.isAnAction
- ? super.getPotentialMovesFrom([x, y])
- : this.getPactions([x, y], color, TODO_arg)
- );
- } else {
- // Both options are possible at subTurn1: normal move, or push
- moves =
- super.getPotentialMovesFrom([x, y])
- .concat(this.getPactions([x, y], color, "push");
- // TODO: discard moves that let the king underCheck, and no second
- // move can counter check. Example: pinned queen pushes pinned pawn.
- .filter(m => {
- this.play(m);
- const res = this.filterMoves(this.getPotentialMoves(/* TODO: args? */)).length > 0;
- this.undo(m);
- return res;
- });
- }
+ // Playing my pieces: either on their own, or pushed by another
+ // If subTurn == 2 then we should have a first move,
+ // TODO = use it to allow some type of action
+ if (this.subTurn == 2) {
+ return (
+ this.moveOnSubturn1.isAnAction
+ ? super.getPotentialMovesFrom([x, y])
+ : this.getPactions([x, y], color, TODO_arg)
+ );
}
- return moves;
+ // Both options are possible at subTurn1: normal move, or push
+ return (
+ super.getPotentialMovesFrom([x, y])
+ .concat(this.getPactions([x, y], color, "push"))
+ // TODO: discard moves that let the king underCheck, and no second
+ // move can counter check. Example: pinned queen pushes pinned pawn.
+ .filter(m => {
+ this.play(m);
+ const res = this.filterMoves(this.getPotentialMoves(/* TODO: args? */)).length > 0;
+ this.undo(m);
+ return res;
+ })
+ );
}
// TODO: track rooks locations, should be a field in FEN, in castleflags?
--- /dev/null
+import { ChessRules } from "@/base_rules";
+
+export class HordeRules extends ChessRules {
+ static get HasFlags() {
+ return false;
+ }
+
+ static IsGoodPosition() {
+ // At least one white unit, and exactly one black king:
+ if (position.length == 0) return false;
+ const rows = position.split("/");
+ if (rows.length != V.size.x) return false;
+ let things = { "k": 0, "w": false };
+ for (let row of rows) {
+ let sumElts = 0;
+ for (let i = 0; i < row.length; i++) {
+ if (row[i] == 'k') things['k']++;
+ if (V.PIECES.includes(row[i].toLowerCase())) {
+ const rowCharCode = row[i].charCodeAt(0);
+ if (rowCharCode >= 65 && rowCharCode <= 90) {
+ // No white king:
+ if (row[i] == 'K') return false;
+ if (!things['w']) things['w'] = true;
+ }
+ sumElts++;
+ } else {
+ const num = parseInt(row[i]);
+ if (isNaN(num)) return false;
+ sumElts += num;
+ }
+ }
+ if (sumElts != V.size.y) return false;
+ }
+ if (things[''] != 1 || !things['w']) return false;
+ return true;
+ }
+
+ static GenRandInitFen(randomness) {
+ if (randomness == 2) randomness--;
+ const fen = ChessRules.GenRandInitFen(randomness);
+ return (
+ // 27 first chars are 3 rows + 3 slashes
+ fen.substr(0, 27)
+ // En passant available, but no castle:
+ .concat("1PP2PP1/PPPPPPPP/PPPPPPPP/PPPPPPPP/PPPPPPPP w 0 -")
+ );
+ }
+
+ getCurrentScore() {
+ if (this.turn == 'w') {
+ // Do I have any unit remaining? If not, I lost.
+ // If yes and no available move, draw.
+ let somethingRemains = false;
+ outerLoop: for (let i=0; i<8; i++) {
+ for (let j=0; j<8; j++) {
+ if (this.board[i][j] != V.EMPTY && this.getColor(i, j) == 'w') {
+ somethingRemains = true;
+ break outerLoop;
+ }
+ }
+ }
+ if (!somethingRemains) return "0-1";
+ if (this.atLeastOneMove()) return "*";
+ return "1/2";
+ }
+ // From black side, just run usual checks:
+ return super.getCurrentScore();
+ }
+};
('Extinction', 'Capture all of a kind'),
('Grand', 'Big board'),
('Grasshopper', 'Long jumps over pieces'),
+ ('Horde', 'A pawns cloud'),
('Knightmate', 'Mate the knight'),
('Knightrelay1', 'Move like a knight (v1)'),
('Knightrelay2', 'Move like a knight (v2)'),