import { ArrayFun } from "@/utils/array";
// NOTE: alternative implementation, probably cleaner = use only 1 board
-// TODO? atLeastOneMove() would be more efficient if rewritten here (less sideBoard computations)
-export const VariantRules = class AliceRules extends ChessRules {
+// TODO? atLeastOneMove() would be more efficient if rewritten here
+// (less sideBoard computations)
+export class AliceRules extends ChessRules {
static get ALICE_PIECES() {
return {
s: "p",
return (Object.keys(V.ALICE_PIECES).includes(b[1]) ? "Alice/" : "") + b;
}
+ getEpSquare(moveOrSquare) {
+ if (!moveOrSquare) return undefined;
+ if (typeof moveOrSquare === "string") {
+ const square = moveOrSquare;
+ if (square == "-") return undefined;
+ return V.SquareToCoords(square);
+ }
+ // Argument is a move:
+ const move = moveOrSquare;
+ const s = move.start,
+ e = move.end;
+ if (
+ s.y == e.y &&
+ Math.abs(s.x - e.x) == 2 &&
+ // Special conditions: a pawn can be on the other side
+ ['p','s'].includes(move.appear[0].p) &&
+ ['p','s'].includes(move.vanish[0].p)
+ ) {
+ return {
+ x: (s.x + e.x) / 2,
+ y: s.y
+ };
+ }
+ return undefined; //default
+ }
+
+ // king can be l or L (on the other mirror side)
+ 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, 'l': 0, 'L': 0 };
+ for (let row of rows) {
+ let sumElts = 0;
+ for (let i = 0; i < row.length; i++) {
+ if (['K','k','L','l'].includes(row[i])) kings[row[i]]++;
+ if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
+ else {
+ const num = parseInt(row[i], 10);
+ if (isNaN(num)) return false;
+ sumElts += num;
+ }
+ }
+ if (sumElts != V.size.y) return false;
+ }
+ if (kings['k'] + kings['l'] != 1 || kings['K'] + kings['L'] != 1)
+ return false;
+ return true;
+ }
+
setOtherVariables(fen) {
super.setOtherVariables(fen);
const rows = V.ParseFen(fen).position.split("/");
if (this.kingPos["w"][0] < 0 || this.kingPos["b"][0] < 0) {
- // INIT_COL_XXX won't be required if Alice kings are found (means 'king moved')
+ // INIT_COL_XXX won't be required if Alice kings are found
+ // (it means 'king moved')
for (let i = 0; i < rows.length; i++) {
let k = 0; //column index on board
for (let j = 0; j < rows[i].length; j++) {
this.kingPos["w"] = [i, k];
break;
default: {
- const num = parseInt(rows[i].charAt(j));
+ const num = parseInt(rows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
}
return sideBoard;
}
- // NOTE: castle & enPassant https://www.chessvariants.com/other.dir/alice.html
+ // NOTE: castle & enPassant
+ // https://www.chessvariants.com/other.dir/alice.html
getPotentialMovesFrom([x, y], sideBoard) {
const pieces = Object.keys(V.ALICE_CODES);
const codes = Object.keys(V.ALICE_PIECES);
if (m.appear.length == 2) {
// Castle: appear[i] must be an empty square on the other board
for (let psq of m.appear) {
- if (this.getSquareOccupation(psq.x, psq.y, 3 - mirrorSide) != V.EMPTY)
+ if (
+ this.getSquareOccupation(psq.x, psq.y, 3 - mirrorSide) != V.EMPTY
+ ) {
return false;
+ }
}
} else if (this.board[m.end.x][m.end.y] != V.EMPTY) {
// Attempt to capture
m.vanish.length == 2 &&
this.board[m.end.x][m.end.y] == V.EMPTY
) {
- m.vanish[1].c = V.GetOppCol(this.getColor(x, y));
- // In the special case of en-passant, if
- // - board1 takes board2 : vanish[1] --> Alice
- // - board2 takes board1 : vanish[1] --> normal
- let van = m.vanish[1];
- if (mirrorSide == 1 && codes.includes(this.getPiece(van.x, van.y)))
- van.p = V.ALICE_CODES[van.p];
- else if (
- mirrorSide == 2 &&
- pieces.includes(this.getPiece(van.x, van.y))
- )
- van.p = V.ALICE_PIECES[van.p];
+ m.vanish[1].c = V.GetOppCol(this.turn);
+ const [epX, epY] = [m.vanish[1].x, m.vanish[1].y];
+ m.vanish[1].p = this.getPiece(epX, epY);
}
return true;
});
return res;
}
- getCheckSquares(color) {
+ getCheckSquares() {
+ const color = this.turn;
const pieces = Object.keys(V.ALICE_CODES);
const kp = this.kingPos[color];
const mirrorSide = pieces.includes(this.getPiece(kp[0], kp[1])) ? 1 : 2;
return res;
}
- updateVariables(move) {
- super.updateVariables(move); //standard king
+ postPlay(move) {
+ super.postPlay(move); //standard king
const piece = move.vanish[0].p;
const c = move.vanish[0].c;
// "l" = Alice king
if (piece == "l") {
this.kingPos[c][0] = move.appear[0].x;
this.kingPos[c][1] = move.appear[0].y;
- this.castleFlags[c] = [false, false];
+ this.castleFlags[c] = [8, 8];
}
}
- unupdateVariables(move) {
- super.unupdateVariables(move);
+ postUndo(move) {
+ super.postUndo(move);
const c = move.vanish[0].c;
- if (move.vanish[0].p == "l") this.kingPos[c] = [move.start.x, move.start.y];
+ if (move.vanish[0].p == "l")
+ this.kingPos[c] = [move.start.x, move.start.y];
}
getCurrentScore() {
- if (this.atLeastOneMove())
- // game not over
- return "*";
-
+ if (this.atLeastOneMove()) return "*";
const pieces = Object.keys(V.ALICE_CODES);
const color = this.turn;
const kp = this.kingPos[color];
// Piece or pawn movement
let notation = piece.toUpperCase() + pawnMark + captureMark + finalSquare;
- if (["s", "p"].includes(piece) && !["s", "p"].includes(move.appear[0].p)) {
+ if (["s", "p"].includes(piece) && !["s", "p"].includes(move.appear[0].p))
// Promotion
notation += "=" + move.appear[0].p.toUpperCase();
- }
return notation;
}
};