"Mandatory captures": "Mandatory captures",
"Mate any piece (v1)": "Mate any piece (v1)",
"Mate any piece (v2)": "Mate any piece (v2)",
- "Mate the knight": "Mate the knight",
+ "Mate the knight (v1)": "Mate the knight (v1)",
+ "Mate the knight (v2)": "Mate the knight (v2)",
"Meet the Mammoth": "Meet the Mammoth",
"Middle battle": "Middle battle",
"Mind control (v1)": "Mind control (v1)",
"Mandatory captures": "Capturas obligatorias",
"Mate any piece (v1)": "Matar cualquier pieza (v1)",
"Mate any piece (v2)": "Matar cualquier pieza (v2)",
- "Mate the knight": "Matar el caballo",
+ "Mate the knight (v1)": "Matar el caballo (v1)",
+ "Mate the knight (v2)": "Matar el caballo (v2)",
"Meet the Mammoth": "Conoce al Mamut",
"Middle battle": "Batalla media",
"Mind control (v1)": "Control telepático(v1)",
"Mandatory captures": "Captures obligatoires",
"Mate any piece (v1)": "Matez n'importe quelle pièce (v1)",
"Mate any piece (v2)": "Matez n'importe quelle pièce (v2)",
- "Mate the knight": "Matez le cavalier",
+ "Mate the knight (v1)": "Matez le cavalier (v1)",
+ "Mate the knight (v2)": "Matez le cavalier (v2)",
"Meet the Mammoth": "Rencontrez le Mammouth",
"Middle battle": "Bataille du milieu",
"Mind control (v1)": "Contrôle télépathique (v1)",
h3 Source
p
- | Slightly simplified from
a(href="https://www.chessvariants.com/other.dir/clockworkorange.html")
| Clockwork Orange Chess
| on chessvariants.com.
h3 Fuente
p
- | Ligeramente simplificado desde
a(href="https://www.chessvariants.com/other.dir/clockworkorange.html")
| Clockwork Orange Chess
| en chessvariants.com.
h3 Source
p
- | Légèrement simplifié depuis
a(href="https://www.chessvariants.com/other.dir/clockworkorange.html")
| Clockwork Orange Chess
| sur chessvariants.com.
p.boxed
| Le roi se déplace comme un cavalier, et les cavaliers comme des rois.
- | l'objectif est encore de mater le roi.
+ | L'objectif est encore de mater le roi.
p.
Les "cavaliers se déplaçant comme des rois" sont alors assez logiquement
--- /dev/null
+p.boxed
+ | Kings move like knights, and knights move like kings.
+
+p
+ a(href="/#/variants/Knightmate1") Knightmate1
+ | , with two kings (moving like knights) and without castling.
+
+p.
+ As long as a side has two kings, they are considered like non-royal pieces
+ and one can be captured. Then, the remaining king is royal.
+
+figure.diagram-container
+ .diagram
+ | fen:r6r/1pp1qpp1/p1pcbk1p/2b1p1K1/4P3/2KPBP2/PPPQC1PP/R6R:
+ figcaption g5 king is mated, but the game is not over.
+
+p.
+ Checkmating both kings at the same time also counts as a win:
+ if both are under attacks, you must remove at least one attack.
--- /dev/null
+p.boxed
+ | Los reyes se mueven como caballos y los caballos como reyes.
+
+p
+ a(href="/#/variants/Knightmate1") Knightmate1
+ | , con dos reyes (muevense como caballos) y sin enroque.
+
+p.
+ Siempre que un lado tenga sus dos reyes, se consideran piezas normales:
+ se puede capturar uno de los dos. Entonces el rey restante
+ tiene estatus real.
+
+figure.diagram-container
+ .diagram
+ | fen:r6r/1pp1qpp1/p1pcbk1p/2b1p1K1/4P3/2KPBP2/PPPQC1PP/R6R:
+ figcaption El rey g5 está atrapado, pero el juego continúa.
+
+p.
+ Matar a ambos reyes al mismo tiempo también gana:
+ si ambos son atacados, debes reprimir al menos un ataque.
--- /dev/null
+p.boxed
+ | Les rois se déplacent comme des cavaliers, et les cavaliers comme des rois.
+
+p
+ a(href="/#/variants/Knightmate1") Knightmate1
+ | , avec deux rois (aux déplacements cavaliers) et sans roque.
+
+p.
+ Tant qu'un camp a ses deux rois, ils sont considérés comme des pièces
+ normales : l'un des deux peut être capturé. Ensuite, le roi restant
+ a un statut royal.
+
+figure.diagram-container
+ .diagram
+ | fen:r6r/1pp1qpp1/p1pcbk1p/2b1p1K1/4P3/2KPBP2/PPPQC1PP/R6R:
+ figcaption Le roi g5 est maté, mais la partie continue.
+
+p.
+ Mater les deux rois en même temps gagne également :
+ si les deux sont attaqués, vous devez supprimez au moins une attaque.
"Empire",
"Horde",
"Orda",
+ "Shinobi",
"Spartan",
"Synochess"
]
-
var varlist = [
"Balaklava",
- "Knightmate",
+ "Knightmate1",
+ "Knightmate2",
"Knightrelay1",
"Knightrelay2"
]
h3 Repositioning
-p Pieces can be drop on the board, either immediately or later in the game.
+p Pieces can be dropped on the board, either immediately or later in the game.
-
var varlist = [
"Clorange",
"Madhouse",
"Rampage",
"Recycle",
- "Shinobi",
"Shogun",
"Teleport"
]
"Empire",
"Horde",
"Orda",
+ "Shinobi",
"Spartan",
"Synochess"
]
-
var varlist = [
"Balaklava",
- "Knightmate",
+ "Knightmate1",
+ "Knightmate2",
"Knightrelay1",
"Knightrelay2"
]
"Madhouse",
"Rampage",
"Recycle",
- "Shinobi",
"Shogun",
"Teleport"
]
"Empire",
"Horde",
"Orda",
+ "Shinobi",
"Spartan",
"Synochess"
]
-
var varlist = [
"Balaklava",
- "Knightmate",
+ "Knightmate1",
+ "Knightmate2",
"Knightrelay1",
"Knightrelay2"
]
"Madhouse",
"Rampage",
"Recycle",
- "Shinobi",
"Shogun",
"Teleport"
]
import { ChessRules } from "@/base_rules";
-import { ArrayFun } from "@/utils/array";
-import { randInt } from "@/utils/alea";
-export class KnightmateRules extends ChessRules {
+export class Knightmate1Rules extends ChessRules {
static get COMMONER() {
return "c";
--- /dev/null
+import { ChessRules } from "@/base_rules";
+
+export class Knightmate2Rules extends ChessRules {
+
+ static get HasFlags() {
+ return false;
+ }
+
+ static get COMMONER() {
+ return "c";
+ }
+
+ static get PIECES() {
+ return ChessRules.PIECES.concat([V.COMMONER]);
+ }
+
+ getPpath(b) {
+ return ([V.KING, V.COMMONER].includes(b[1]) ? "Knightmate/" : "") + b;
+ }
+
+ static IsGoodPosition(position) {
+ if (position.length == 0) return false;
+ const rows = position.split("/");
+ if (rows.length != V.size.x) return false;
+ let kings = { "k": 0, "K": 0 };
+ for (let row of rows) {
+ let sumElts = 0;
+ for (let i = 0; i < row.length; i++) {
+ if (['K','k'].includes(row[i])) kings[row[i]]++;
+ if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
+ else {
+ const num = parseInt(row[i], 10);
+ if (isNaN(num) || num <= 0) return false;
+ sumElts += num;
+ }
+ }
+ if (sumElts != V.size.y) return false;
+ }
+ // 1 or 2 kings should be on board.
+ if (Object.values(kings).some(k => ![1, 2].includes(k))) return false;
+ return true;
+ }
+
+ scanKings() {}
+
+ static GenRandInitFen(randomness) {
+ return (
+ ChessRules.GenRandInitFen(randomness)
+ .replace(/k/g, 'c').replace(/K/g, 'C')
+ .replace(/n/g, 'k').replace(/N/g, 'K')
+ );
+ }
+
+ getPotentialMovesFrom([x, y]) {
+ switch (this.getPiece(x, y)) {
+ case V.COMMONER:
+ return this.getPotentialCommonerMoves([x, y]);
+ default:
+ return super.getPotentialMovesFrom([x, y]);
+ }
+ }
+
+ getPotentialCommonerMoves(sq) {
+ return this.getSlideNJumpMoves(
+ sq,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
+ "oneStep"
+ );
+ }
+
+ getPotentialKingMoves(sq) {
+ return super.getPotentialKnightMoves(sq);
+ }
+
+ isAttacked(sq, color) {
+ return (
+ this.isAttackedByCommoner(sq, color) ||
+ this.isAttackedByPawn(sq, color) ||
+ this.isAttackedByRook(sq, color) ||
+ this.isAttackedByBishop(sq, color) ||
+ this.isAttackedByQueen(sq, color) ||
+ this.isAttackedByKing(sq, color)
+ );
+ }
+
+ isAttackedByKing(sq, color) {
+ return this.isAttackedBySlideNJump(
+ sq,
+ color,
+ V.KING,
+ V.steps[V.KNIGHT],
+ "oneStep"
+ );
+ }
+
+ isAttackedByCommoner(sq, color) {
+ return this.isAttackedBySlideNJump(
+ sq,
+ color,
+ V.COMMONER,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
+ "oneStep"
+ );
+ }
+
+ postPlay() {}
+ postUndo() {}
+
+ // NOTE: 4 next functions (almost) copy-paste from Spartan Chess
+ getKingsPos(color) {
+ let kings = [];
+ 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) == color &&
+ this.getPiece(i, j) == V.KING
+ ) {
+ kings.push({ x: i, y: j });
+ }
+ }
+ }
+ return kings;
+ }
+
+ getCheckSquares() {
+ const color = this.turn;
+ const oppCol = V.GetOppCol(color);
+ const kings = this.getKingsPos(color);
+ let res = [];
+ for (let i of [0, 1]) {
+ if (
+ kings.length >= i+1 &&
+ super.isAttacked([kings[i].x, kings[i].y], oppCol)
+ ) {
+ res.push([kings[i].x, kings[i].y]);
+ }
+ }
+ return res;
+ }
+
+ filterValid(moves) {
+ if (moves.length == 0) return [];
+ const color = moves[0].vanish[0].c;
+ const oppCol = V.GetOppCol(color);
+ // Check if both kings under attack.
+ // If yes, moves must remove at least one attack.
+ const kings = this.getKingsPos(color);
+ return moves.filter(m => {
+ this.play(m);
+ let attacks = 0;
+ for (let k of kings) {
+ const curKingPos =
+ this.board[k.x][k.y] == V.EMPTY
+ ? [m.appear[0].x, m.appear[0].y] //king moved
+ : [k.x, k.y]
+ if (super.isAttacked(curKingPos, oppCol)) attacks++;
+ else break; //no need to check further
+ }
+ this.undo(m);
+ return (
+ (kings.length == 2 && attacks <= 1) ||
+ (kings.length == 1 && attacks == 0)
+ );
+ });
+ }
+
+ getCurrentScore() {
+ if (super.atLeastOneMove()) return "*";
+ // Count kings on board
+ const color = this.turn;
+ const oppCol = V.GetOppCol(color);
+ const kings = this.getKingsPos(color);
+ if (
+ super.isAttacked([kings[0].x, kings[0].y], oppCol) ||
+ (kings.length == 2 && super.isAttacked([kings[1].x, kings[1].y], oppCol))
+ ) {
+ return (color == 'w' ? "0-1" : "1-0");
+ }
+ return "1/2"; //stalemate
+ }
+
+ static get VALUES() {
+ return {
+ p: 1,
+ r: 5,
+ c: 5, //the commoner is valuable
+ b: 3,
+ q: 9,
+ k: 1000
+ };
+ }
+
+};
('Karouk', 'Thai Chess (v3)'),
('Kinglet', 'Protect your pawns'),
('Kingsmaker', 'Promote into kings'),
- ('Knightmate', 'Mate the knight'),
+ ('Knightmate1', 'Mate the knight (v1)'),
+ ('Knightmate2', 'Mate the knight (v2)'),
('Knightpawns', 'Knight versus pawns'),
('Knightrelay1', 'Move like a knight (v1)'),
('Knightrelay2', 'Move like a knight (v2)'),