"Augmented Queens": "Augmented Queens",
"Balanced sliders & leapers": "Balanced sliders & leapers",
"Baroque Music": "Baroque Music",
- "Beware the bomb": "Beware the bomb",
+ "Beware the bomb (v1)": "Beware the bomb (v1)",
+ "Beware the bomb (v2)": "Beware the bomb (v2)",
"Big board": "Big board",
"Bishop versus pawns": "Bishop versus pawns",
"Board upside down": "Board upside down",
"New fairy pieces": "New fairy pieces",
"No paralyzed pieces": "No paralyzed pieces",
"No-check mode": "No-check mode",
- "Noise and confusion": "Noise and confusion",
+ "Noise and confusion (v1)": "Noise and confusion (v1)",
+ "Noise and confusion (v2)": "Noise and confusion (v2)",
"Non-conformism and utopia": "Non-conformism and utopia",
"Occupy the enemy palace": "Occupy the enemy palace",
"Paralyzed pieces": "Paralyzed pieces",
"Augmented Queens": "Damas aumentadas",
"Balanced sliders & leapers": "Modos de desplazamiento equilibrados",
"Baroque Music": "Música Barroca",
- "Beware the bomb": "Cuidado con la bomba",
+ "Beware the bomb (v1)": "Cuidado con la bomba (v1)",
+ "Beware the bomb (v2)": "Cuidado con la bomba (v2)",
"Big board": "Gran tablero",
"Bishop versus pawns": "Alfil contra peones",
"Board upside down": "Tablero al revés",
"New fairy pieces": "Nuevas piezas magicas",
"No paralyzed pieces": "No piezas paralizadas",
"No-check mode": "Modo sin jaque",
- "Noise and confusion": "Ruido y confusión",
+ "Noise and confusion (v1)": "Ruido y confusión (v1)",
+ "Noise and confusion (v2)": "Ruido y confusión (v2)",
"Non-conformism and utopia": "No-conformismo y utopía",
"Occupy the enemy palace": "Ocupar el palacio enemigo",
"Paralyzed pieces": "Piezas paralizadas",
"Augmented Queens": "Dames augmentées",
"Balanced sliders & leapers": "Modes de déplacement équilibrés",
"Baroque Music": "Musique Baroque",
- "Beware the bomb": "Attention à la bombe",
+ "Beware the bomb (v1)": "Attention à la bombe (v1)",
+ "Beware the bomb (v2)": "Attention à la bombe (v2)",
"Big board": "Grand échiquier",
"Bishop versus pawns": "Fou contre pions",
"Board upside down": "Échiquier à l'envers",
"New fairy pieces": "Nouvelles pièces féériques",
"No paralyzed pieces": "Pas de pièces paralysées",
"No-check mode": "Mode sans échec",
- "Noise and confusion": "Bruit et confusion",
+ "Noise and confusion (v1)": "Bruit et confusion (v1)",
+ "Noise and confusion (v2)": "Bruit et confusion (v2)",
"Non-conformism and utopia": "Non-conformisme et utopie",
"Occupy the enemy palace": "Occuper le palais ennemi",
"Paralyzed pieces": "Pièces paralysées",
--- /dev/null
+p.boxed
+ | All pieces can promote. Captured units can be dropped later.
+ | 10x8 board. Some new pieces.
+
+figure.diagram-container
+ .diagram
+ | fen:rnbqkmcbnr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR:
+ figcaption Initial deterministic position.
+
+p
+ a(href="/#/variants/Pandemonium1") Pandemonium1
+ | on a 10x8 board.
+ | Pawns move as in orthodox chess, and promotions
+ | occur only on the final rank.
--- /dev/null
+p.boxed
+ | Todas las piezas pueden promocionarse. Las unidades capturadas son
+ | en paracaídas más tarde. Tablero de ajedrez 10x8. Algunas piezas nuevas.
+
+figure.diagram-container
+ .diagram
+ | fen:rnbqkmcbnr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR:
+ figcaption Posición inicial determinista.
+
+p
+ a(href="/#/variants/Pandemonium1") Pandemonium1
+ | en un tablero 10x8.
+ | Los peones se mueven como en el ajedrez ortodoxo,
+ | y las promociones solo ocurren en la última fila.
--- /dev/null
+p.boxed
+ | Toutes les pièces peuvent être promues. Les unités capturées sont
+ | parachutées plus tard. Échiquier 10x8. Quelques nouvelles pièces.
+
+figure.diagram-container
+ .diagram
+ | fen:rnbqkmcbnr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR:
+ figcaption Position initiale déterministe.
+
+p
+ a(href="/#/variants/Pandemonium1") Pandemonium1
+ | sur un échiquier 10x8.
+ | Les pions se déplacent comme aux échecs orthodoxes,
+ | et les promotions ne surviennent que sur la dernière rangée.
| . This variant is Stealthbomber on
a(href="fishrandom.io") fishrandom.io
| , and "Stealthbomb" here... why not :-)
+
+p Inventor: Jim Winslow (1992)
| . Esta variante es Stealthbomber en
a(href="fishrandom.io") fishrandom.io
| , y "Stealthbomb" aquí... ¿Por qué no? :-)
+
+p Inventor: Jim Winslow (1992)
| . Cette variante est Stealthbomber sur
a(href="fishrandom.io") fishrandom.io
| , et "Stealthbomb" ici... pourquoi pas :-)
+
+p Inventeur : Jim Winslow (1992)
--- /dev/null
+p.boxed.
+ One pawn of each side hides a bomb,
+ which can be triggered instead of playing a move.
+
+p
+ a(href="/#/variants/Stealthbomb1") Stealthbomb1
+ | , where only pawns can hold a bomb.
--- /dev/null
+p.boxed.
+ Un peon de cada campamento esconde una bomba,
+ que se puede activar en lugar de ejecutar un movimiento.
+
+p
+ a(href="/#/variants/Stealthbomb1") Stealthbomb1
+ | , donde solo los peones pueden llevar una bomba.
--- /dev/null
+p.boxed.
+ Un pion de chaque camp cache une bombe,
+ qui peut être déclenchée au lieu de jouer un coup.
+
+p
+ a(href="/#/variants/Stealthbomb1") Stealthbomb1
+ | , où seuls les pions peuvent porter une bombe.
which will end next to him on the other side.
p.
- When a pawn reaches last rank, it can promote
- into a queen or a wildebeest (only).
+ When a pawn reaches the last rank, it promotes into a queen or a
+ wildebeest (only). Promotion is also possible (optionally) on 9th rank.
+ This is an experimental addition to the official rules.
h3 Source
el rey puede saltar cualquier número de casillas (libres) a la torre,
que terminará junto a él en el otro lado.
-p Un peón en la última fila es promovido a dama o ñu solamente.
+p.
+ Un peón que llega a la última fila es promovido a dama o ñu solamente.
+ La promoción también es posible (opcionalmente) en la novena fila.
+ Es una adición experimental a las reglas oficiales.
h3 Fuente
p.
Un pion arrivé sur la dernière rangée se promeut en une dame ou un gnou
- seulement.
+ seulement. La promotion est également possible (optionnellement)
+ sur la 9eme rangée. C'est un ajout expérimental aux règles officielles.
h3 Source
"Dark",
"Hidden",
"Hiddenqueen",
- "Stealthbomb",
+ "Stealthbomb1",
+ "Stealthbomb2",
"Synchrone1",
"Synchrone2"
]
"Iceage",
"Kingsmaker",
"Magnetic",
- "Pandemonium",
+ "Pandemonium1",
+ "Pandemonium2",
"Refusal1",
"Refusal2",
"Relayup",
"Dark",
"Hidden",
"Hiddenqueen",
- "Stealthbomb",
+ "Stealthbomb1",
+ "Stealthbomb2",
"Synchrone1",
"Synchrone2"
]
"Iceage",
"Kingsmaker",
"Magnetic",
- "Pandemonium",
+ "Pandemonium1",
+ "Pandemonium2",
"Refusal1",
"Refusal2",
"Relayup",
"Dark",
"Hidden",
"Hiddenqueen",
- "Stealthbomb",
+ "Stealthbomb1",
+ "Stealthbomb2",
"Synchrone1",
"Synchrone2"
]
"Iceage",
"Kingsmaker",
"Magnetic",
- "Pandemonium",
+ "Pandemonium1",
+ "Pandemonium2",
"Refusal1",
"Refusal2",
"Relayup",
--- /dev/null
+import { Pandemonium2Rules } from "@/variants/Pandemonium2";
+
+export class Pandemonium1Rules extends Pandemonium2Rules {
+
+ static get PawnSpecs() {
+ return Object.assign(
+ { },
+ Pandemonium2Rules.PawnSpecs,
+ { threeSquares: true }
+ );
+ }
+
+ static get size() {
+ return { x: 10, y: 10};
+ }
+
+ static IsGoodEnpassant(enpassant) {
+ if (enpassant != "-") {
+ const squares = enpassant.split(",");
+ if (squares.length > 2) return false;
+ for (let sq of squares) {
+ if (!sq.match(/[a-j0-9]/)) return false;
+ }
+ }
+ return true;
+ }
+
+ static GenRandInitFen(randomness) {
+ const baseFen = Pandemonium2Rules.GenRandInitFen(randomness)
+ return baseFen.substr(0, 22) + "91/91/" + baseFen.substr(22);
+ }
+
+ getEnpassantFen() {
+ const L = this.epSquares.length;
+ if (!this.epSquares[L - 1]) return "-"; //no en-passant
+ let res = "";
+ this.epSquares[L - 1].forEach(sq => {
+ res += V.CoordsToSquare(sq) + ",";
+ });
+ return res.slice(0, -1); //remove last comma
+ }
+
+ getEpSquare(moveOrSquare) {
+ if (!moveOrSquare) return undefined;
+ if (typeof moveOrSquare === "string") {
+ const square = moveOrSquare;
+ if (square == "-") return undefined;
+ let res = [];
+ square.split(",").forEach(sq => {
+ res.push(V.SquareToCoords(sq));
+ });
+ return res;
+ }
+ // Argument is a move:
+ const move = moveOrSquare;
+ const [sx, sy, ex] = [move.start.x, move.start.y, move.end.x];
+ if (this.getPiece(sx, sy) == V.PAWN && Math.abs(sx - ex) >= 2) {
+ const step = (ex - sx) / Math.abs(ex - sx);
+ let res = [{
+ x: sx + step,
+ y: sy
+ }];
+ if (sx + 2 * step != ex) {
+ // 3-squares jump
+ res.push({
+ x: sx + 2 * step,
+ y: sy
+ });
+ }
+ return res;
+ }
+ return undefined; //default
+ }
+
+ applyPromotions(moves, promoted) {
+ const lastRanks = (this.turn == 'w' ? [0, 1] : [V.size.x - 1, V.size.x]);
+ let promotions = [];
+ moves.forEach(m => {
+ if (lastRanks.includes(m.start.x) || lastRanks.includes(m.end.x)) {
+ let pMove = JSON.parse(JSON.stringify(m));
+ pMove.appear[0].p = promoted;
+ promotions.push(pMove);
+ }
+ });
+ Array.prototype.push.apply(moves, promotions);
+ }
+
+ addPawnMoves([x1, y1], [x2, y2], moves) {
+ const color = this.turn;
+ const lastRanks = (color == "w" ? [0, 1] : [V.size.x - 1, V.size.x - 2]);
+ if (!lastRanks.includes(x2)) {
+ moves.push(this.getBasicMove([x1, y1], [x2, y2]));
+ return;
+ }
+ let finalPieces = [V.GILDING];
+ if (x2 == lastRanks[1]) finalPieces.push(V.PAWN);
+ for (let piece of finalPieces) {
+ const tr = (piece != V.PAWN ? { c: color, p: piece } : null);
+ moves.push(this.getBasicMove([x1, y1], [x2, y2], tr));
+ }
+ }
+
+ getEnpassantCaptures([x, y], shiftX) {
+ const Lep = this.epSquares.length;
+ const epSquare = this.epSquares[Lep - 1];
+ let moves = [];
+ if (!!epSquare) {
+ for (let epsq of epSquare) {
+ // TODO: some redundant checks
+ if (epsq.x == x + shiftX && Math.abs(epsq.y - y) == 1) {
+ let enpassantMove = this.getBasicMove([x, y], [epsq.x, epsq.y]);
+ // WARNING: the captured pawn may be diagonally behind us,
+ // if it's a 3-squares jump and we take on 1st passing square
+ const px = this.board[x][epsq.y] != V.EMPTY ? x : x - shiftX;
+ enpassantMove.vanish.push({
+ x: px,
+ y: epsq.y,
+ p: "p",
+ c: this.getColor(px, epsq.y)
+ });
+ moves.push(enpassantMove);
+ }
+ }
+ }
+ return moves;
+ }
+
+};
import { randInt } from "@/utils/alea";
import { ArrayFun } from "@/utils/array";
-export class PandemoniumRules extends ChessRules {
+export class Pandemonium2Rules extends ChessRules {
+
+ static get PawnSpecs() {
+ return Object.assign(
+ { },
+ ChessRules.PawnSpecs,
+ { promotions: [V.GILDING] }
+ );
+ }
loseOnRepetition() {
// If current side is under check: lost
}
static get size() {
- return { x: 10, y: 10};
+ return { x: 8, y: 10};
}
getColor(i, j) {
};
}
- static IsGoodEnpassant(enpassant) {
- if (enpassant != "-") {
- const squares = enpassant.split(",");
- if (squares.length > 2) return false;
- for (let sq of squares) {
- if (!sq.match(/[a-j0-9]/)) return false;
- }
- }
- return true;
- }
-
static IsGoodFen(fen) {
if (!ChessRules.IsGoodFen(fen)) return false;
const fenParsed = V.ParseFen(fen);
static GenRandInitFen(randomness) {
if (randomness == 0) {
return (
- "rnbqkmcbnr/pppppppppp/91/91/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR " +
+ "rnbqkmcbnr/pppppppppp/91/91/91/91/PPPPPPPPPP/RNBQKMCBNR " +
"w 0 ajaj - 00000000000000"
);
}
);
}
- getEnpassantFen() {
- const L = this.epSquares.length;
- if (!this.epSquares[L - 1]) return "-"; //no en-passant
- let res = "";
- this.epSquares[L - 1].forEach(sq => {
- res += V.CoordsToSquare(sq) + ",";
- });
- return res.slice(0, -1); //remove last comma
- }
-
- getEpSquare(moveOrSquare) {
- if (!moveOrSquare) return undefined;
- if (typeof moveOrSquare === "string") {
- const square = moveOrSquare;
- if (square == "-") return undefined;
- let res = [];
- square.split(",").forEach(sq => {
- res.push(V.SquareToCoords(sq));
- });
- return res;
- }
- // Argument is a move:
- const move = moveOrSquare;
- const [sx, sy, ex] = [move.start.x, move.start.y, move.end.x];
- if (this.getPiece(sx, sy) == V.PAWN && Math.abs(sx - ex) >= 2) {
- const step = (ex - sx) / Math.abs(ex - sx);
- let res = [{
- x: sx + step,
- y: sy
- }];
- if (sx + 2 * step != ex) {
- // 3-squares jump
- res.push({
- x: sx + 2 * step,
- y: sy
- });
- }
- return res;
- }
- return undefined; //default
- }
-
getReservePpath(index, color) {
const p = V.RESERVE_PIECES[index];
const prefix = (ChessRules.PIECES.includes(p) ? "" : "Pandemonium/");
};
}
+ applyPromotions(moves, promoted) {
+ const lastRank = (this.turn == 'w' ? 0 : V.size.x - 1);
+ let promotions = [];
+ moves.forEach(m => {
+ if ([m.start.x, m.end.x].includes(lastRank)) {
+ let pMove = JSON.parse(JSON.stringify(m));
+ pMove.appear[0].p = promoted;
+ promotions.push(pMove);
+ }
+ });
+ Array.prototype.push.apply(moves, promotions);
+ }
+
getPotentialMovesFrom([x, y]) {
const c = this.getColor(x, y);
const oppCol = V.GetOppCol(c);
})
];
}
- const firstRank = (this.movesCount == 0 ? 9 : 0);
+ const firstRank = (this.movesCount == 0 ? V.size.x - 1 : 0);
if (x != firstRank || this.getPiece(x, y) != V.KNIGHT) return [];
// Swap with who? search for matching bishop:
let knights = [],
bishops = [];
- for (let i = 0; i < 10; i++) {
+ for (let i = 0; i < V.size.y; i++) {
const elt = this.board[x][i][1];
if (elt == 'n') knights.push(i);
else if (elt == 'b') bishops.push(i);
break;
}
// Maybe apply promotions:
- if (Object.keys(V.PromoteMap).includes(p)) {
- const promoted = V.PromoteMap[p];
- const lastRanks = (c == 'w' ? [0, 1] : [9, 8]);
- let promotions = [];
- moves.forEach(m => {
- if (lastRanks.includes(m.start.x) || lastRanks.includes(m.end.x)) {
- let pMove = JSON.parse(JSON.stringify(m));
- pMove.appear[0].p = promoted;
- promotions.push(pMove);
- }
- });
- Array.prototype.push.apply(moves, promotions);
- }
- return moves;
- }
-
- addPawnMoves([x1, y1], [x2, y2], moves) {
- const color = this.turn;
- const lastRanks = (color == "w" ? [0, 1] : [9, 8]);
- if (!lastRanks.includes(x2)) {
- moves.push(this.getBasicMove([x1, y1], [x2, y2]));
- return;
- }
- let finalPieces = [V.GILDING];
- if (x2 == lastRanks[1]) finalPieces.push(V.PAWN);
- for (let piece of finalPieces) {
- const tr = (piece != V.PAWN ? { c: color, p: piece } : null);
- moves.push(this.getBasicMove([x1, y1], [x2, y2], tr));
- }
- }
-
- getPotentialPawnMoves([x, y]) {
- const color = this.turn;
- const shiftX = (color == 'w' ? -1 : 1);
- let moves = [];
- if (this.board[x + shiftX][y] == V.EMPTY) {
- this.addPawnMoves([x, y], [x + shiftX, y], moves);
- if ((color == 'w' && x >= V.size.x - 3) || (color == 'b' && x <= 2)) {
- if (this.board[x + 2 * shiftX][y] == V.EMPTY) {
- moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
- if (
- (
- (color == 'w' && x == V.size.x - 2) ||
- (color == 'b' && x == 1)
- )
- &&
- this.board[x + 3 * shiftX][y] == V.EMPTY
- ) {
- moves.push(this.getBasicMove([x, y], [x + 3 * shiftX, y]));
- }
- }
- }
- }
- for (let shiftY of [-1, 1]) {
- if (y + shiftY >= 0 && y + shiftY < V.size.y) {
- if (
- this.board[x + shiftX][y + shiftY] != V.EMPTY &&
- this.canTake([x, y], [x + shiftX, y + shiftY])
- ) {
- this.addPawnMoves([x, y], [x + shiftX, y + shiftY], moves);
- }
- }
- }
- Array.prototype.push.apply(
- moves,
- this.getEnpassantCaptures([x, y], shiftX)
- );
+ if (Object.keys(V.PromoteMap).includes(p))
+ this.applyPromotions(moves, V.PromoteMap[p]);
return moves;
}
this.getSlideNJumpMoves(sq, V.steps[V.BISHOP], "oneStep"));
}
- getEnpassantCaptures([x, y], shiftX) {
- const Lep = this.epSquares.length;
- const epSquare = this.epSquares[Lep - 1];
- let moves = [];
- if (!!epSquare) {
- for (let epsq of epSquare) {
- // TODO: some redundant checks
- if (epsq.x == x + shiftX && Math.abs(epsq.y - y) == 1) {
- let enpassantMove = this.getBasicMove([x, y], [epsq.x, epsq.y]);
- // WARNING: the captured pawn may be diagonally behind us,
- // if it's a 3-squares jump and we take on 1st passing square
- const px = this.board[x][epsq.y] != V.EMPTY ? x : x - shiftX;
- enpassantMove.vanish.push({
- x: px,
- y: epsq.y,
- p: "p",
- c: this.getColor(px, epsq.y)
- });
- moves.push(enpassantMove);
- }
- }
- }
- return moves;
- }
-
getPotentialKingMoves(sq) {
// Initialize with normal moves
let moves = this.getSlideNJumpMoves(
import { ChessRules, Move, PiPo } from "@/base_rules";
-export class StealthbombRules extends ChessRules {
+export class Stealthbomb1Rules extends ChessRules {
static get CanAnalyze() {
return false;
this.movesCount >= 2 ||
(
(c == 'w' && square[0] < 6) ||
- (c == 'b' && square[0] > 2)
+ (c == 'b' && square[0] > 1)
)
) {
return null;
return new Move({
appear: [ new PiPo({ x: x, y: y, c: c, p: V.BOMB_CODE[piece] }) ],
vanish: [ new PiPo({ x: x, y: y, c: c, p: piece }) ],
- start: { x: -1, y: -1 }
+ start: { x: -1, y: -1 },
+ end: { x: x, y: y, noHighlight: true }
});
}
--- /dev/null
+import { Move, PiPo } from "@/base_rules";
+import { Stealthbomb1Rules } from "@/variants/Stealthbomb1";
+
+export class Stealthbomb2Rules extends Stealthbomb1Rules {
+
+ // Initiate the game by choosing a square for the bomb:
+ doClick(square) {
+ const c = this.turn;
+ if (
+ this.movesCount >= 2 ||
+ (
+ (c == 'w' && square[0] != 6) ||
+ (c == 'b' && square[0] != 1)
+ )
+ ) {
+ return null;
+ }
+ const [x, y] = square;
+ return new Move({
+ appear: [ new PiPo({ x: x, y: y, c: c, p: 's' }) ],
+ vanish: [ new PiPo({ x: x, y: y, c: c, p: 'p' }) ],
+ start: { x: -1, y: -1 },
+ end: { x: x, y: y, noHighlight: true }
+ });
+ }
+
+};
const [sizeX, sizeY] = [V.size.x, V.size.y];
const shiftX = color == "w" ? -1 : 1;
const startRanks = color == "w" ? [sizeX - 2, sizeX - 3] : [1, 2];
- const lastRank = color == "w" ? 0 : sizeX - 1;
- const finalPieces = x + shiftX == lastRank
- ? [V.WILDEBEEST, V.QUEEN]
- : [V.PAWN];
+ const lastRanks = color == "w" ? [0, 1] : [sizeX - 1, sizeX -2];
+ let finalPieces = [V.PAWN];
+ if (x + shiftX == lastRanks[1])
+ Array.prototype.push.apply(finalPieces, [V.WILDEBEEST, V.QUEEN]);
+ else if (x + shiftX == lastRanks[0])
+ finalPieces = [V.WILDEBEEST, V.QUEEN];
if (this.board[x + shiftX][y] == V.EMPTY) {
// One square forward
('Pacifist1', 'Convert & support (v1)'),
('Pacifist2', 'Convert & support (v2)'),
('Pacosako', 'Dance with the King'),
- ('Pandemonium', 'Noise and confusion'),
+ ('Pandemonium1', 'Noise and confusion (v1)'),
+ ('Pandemonium2', 'Noise and confusion (v2)'),
('Parachute', 'Landing on the board'),
('Pawnmassacre', 'Pieces upside down'),
('Pawns', 'Reach the last rank (v1)'),
('Spartan', 'Spartan versus Persians'),
('Squatter1', 'Squat last rank (v1)'),
('Squatter2', 'Squat last rank (v2)'),
- ('Stealthbomb', 'Beware the bomb'),
+ ('Stealthbomb1', 'Beware the bomb (v1)'),
+ ('Stealthbomb2', 'Beware the bomb (v2)'),
('Suicide', 'Lose all pieces'),
('Suction', 'Attract opposite king'),
('Swap', 'Dangerous captures'),