import { randInt } from "@/utils/alea";
export class ChakartRules extends ChessRules {
+
static get PawnSpecs() {
return SuicideRules.PawnSpecs;
}
return true;
}
- hoverHighlight(x, y) {
+ hoverHighlight([x, y]) {
if (this.subTurn == 1) return false;
const L = this.firstMove.length;
const fm = this.firstMove[L-1];
getPPpath(m) {
if (!!m.promoteInto) return m.promoteInto;
+ if (m.appear.length == 0 && m.vanish.length == 1)
+ // King 'remote shell capture', on an adjacent square:
+ return this.getPpath(m.vanish[0].c + m.vanish[0].p);
let piece = m.appear[0].p;
if (Object.keys(V.IMMOBILIZE_DECODE).includes(piece))
+ // Promotion by capture into immobilized piece: do not reveal!
piece = V.IMMOBILIZE_DECODE[piece];
return this.getPpath(m.appear[0].c + piece);
}
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]);
+ 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)
+ if (kings['k'] + kings['l'] == 0 || kings['K'] + kings['L'] == 0)
return false;
return true;
}
setOtherVariables(fen) {
super.setOtherVariables(fen);
- const fenParsed = V.ParseFen(fen);
// Initialize captured pieces' counts from FEN
+ const captured =
+ V.ParseFen(fen).captured.split("").map(x => parseInt(x, 10));
this.captured = {
w: {
- [V.ROOK]: parseInt(fenParsed.captured[0]),
- [V.KNIGHT]: parseInt(fenParsed.captured[1]),
- [V.BISHOP]: parseInt(fenParsed.captured[2]),
- [V.QUEEN]: parseInt(fenParsed.captured[3]),
- [V.KING]: parseInt(fenParsed.captured[4]),
- [V.PAWN]: parseInt(fenParsed.captured[5]),
+ [V.PAWN]: captured[0],
+ [V.ROOK]: captured[1],
+ [V.KNIGHT]: captured[2],
+ [V.BISHOP]: captured[3],
+ [V.QUEEN]: captured[4],
+ [V.KING]: captured[5]
},
b: {
- [V.ROOK]: parseInt(fenParsed.captured[6]),
- [V.KNIGHT]: parseInt(fenParsed.captured[7]),
- [V.BISHOP]: parseInt(fenParsed.captured[8]),
- [V.QUEEN]: parseInt(fenParsed.captured[9]),
- [V.KING]: parseInt(fenParsed.captured[10]),
- [V.PAWN]: parseInt(fenParsed.captured[11]),
+ [V.PAWN]: captured[6],
+ [V.ROOK]: captured[7],
+ [V.KNIGHT]: captured[8],
+ [V.BISHOP]: captured[9],
+ [V.QUEEN]: captured[10],
+ [V.KING]: captured[11]
}
};
this.firstMove = [];
const end = (color == 'b' && p == V.PAWN ? 7 : 8);
for (let i = start; i < end; i++) {
for (let j = 0; j < V.size.y; j++) {
- if (this.board[i][j] == V.EMPTY || this.getColor(i, j) == 'a') {
+ if (
+ this.board[i][j] == V.EMPTY ||
+ this.getColor(i, j) == 'a' ||
+ this.getPiece(i, j) == V.INVISIBLE_QUEEN
+ ) {
let m = this.getBasicMove({ p: p, x: i, y: j});
m.start = { x: x, y: y };
moves.push(m);
const L = this.firstMove.length;
const fm = this.firstMove[L-1];
switch (fm.end.effect) {
- // case 0: a click is required (banana or bomb)
case "kingboo":
// Exchange position with any piece,
// except pawns if arriving on last rank.
// Helper for getBasicMove()
getRandomSquare([x, y], steps) {
+ const color = this.turn;
const validSteps = steps.filter(s => {
const [i, j] = [x + s[0], y + s[1]];
return (
V.OnBoard(i, j) &&
- (this.board[i][j] == V.EMPTY || this.getColor(i, j) == 'a')
+ (this.board[i][j] == V.EMPTY || this.getColor(i, j) != color)
);
});
if (validSteps.length == 0)
return (
V.OnBoard(x + forward, y) &&
(
- this.board[x + forward][y] != oppCol ||
+ this.board[x + forward][y] == V.EMPTY ||
(
V.OnBoard(x + forward, y + 1) &&
this.board[x + forward][y + 1] != V.EMPTY &&
// If flag allows it, add 'remote shell captures'
if (this.powerFlags[this.turn][V.KING]) {
V.steps[V.ROOK].concat(V.steps[V.BISHOP]).forEach(step => {
- const [nextX, nextY] = [x + step[0], y + step[1]];
- if (
- V.OnBoard(nextX, nextY) &&
+ let [i, j] = [x + step[0], y + step[1]];
+ while (
+ V.OnBoard(i, j) &&
(
- this.board[nextX][nextY] == V.EMPTY ||
+ this.board[i][j] == V.EMPTY ||
(
- this.getColor(nextX, nextY) == 'a' &&
- [V.EGG, V.MUSHROOM].includes(this.getPiece(nextX, nextY))
+ this.getColor(i, j) == 'a' &&
+ [V.EGG, V.MUSHROOM].includes(this.getPiece(i, j))
)
)
) {
- let [i, j] = [x + 2 * step[0], y + 2 * step[1]];
- while (
- V.OnBoard(i, j) &&
- (
- this.board[i][j] == V.EMPTY ||
- (
- this.getColor(i, j) == 'a' &&
- [V.EGG, V.MUSHROOM].includes(this.getPiece(i, j))
- )
- )
- ) {
- i += step[0];
- j += step[1];
- }
- if (V.OnBoard(i, j)) {
- const colIJ = this.getColor(i, j);
- if (colIJ != color) {
- // May just destroy a bomb or banana:
- moves.push(
- new Move({
- start: { x: x, y: y},
- end: { x: i, y: j },
- appear: [],
- vanish: [
- new PiPo({
- x: i, y: j, c: colIJ, p: this.getPiece(i, j)
- })
- ]
- })
- );
- }
+ i += step[0];
+ j += step[1];
+ }
+ if (V.OnBoard(i, j)) {
+ const colIJ = this.getColor(i, j);
+ if (colIJ != color) {
+ // May just destroy a bomb or banana:
+ moves.push(
+ new Move({
+ start: { x: x, y: y},
+ end: { x: i, y: j },
+ appear: [],
+ vanish: [
+ new PiPo({
+ x: i, y: j, c: colIJ, p: this.getPiece(i, j)
+ })
+ ]
+ })
+ );
}
}
});
// Play a deterministic one: capture king or material if possible
return super.getComputerMove(deterministicMoves);
// Play a random effect move, at random:
- let move1 = randomMoves[randInt(moves.length)];
+ let move1 = randomMoves[randInt(randomMoves.length)];
this.play(move1);
let move2 = undefined;
if (this.subTurn == 2) {
)
);
}
- if (
- move.appear.length == 1 &&
- move.vanish.length == 1 &&
- move.appear[0].c == 'a' &&
- move.vanish[0].c == 'a'
- ) {
- // Bonus replacement:
- return move.appear[0].p.toUpperCase() + "@" + finalSquare;
+ if (move.appear.length == 1 && move.vanish.length == 1) {
+ const moveStart = move.appear[0].p.toUpperCase() + "@";
+ if (move.appear[0].c == 'a' && move.vanish[0].c == 'a')
+ // Bonus replacement:
+ return moveStart + finalSquare;
+ if (
+ move.vanish[0].p == V.INVISIBLE_QUEEN &&
+ move.appear[0].x == move.vanish[0].x &&
+ move.appear[0].y == move.vanish[0].y
+ ) {
+ // Toadette takes invisible queen
+ return moveStart + "Q" + finalSquare;
+ }
}
if (
move.appear.length == 2 &&
}
return notation;
}
+
};