import { ChessRules, PiPo } from "@/base_rules";
export class KoopaRules extends ChessRules {
+
static get HasEnpassant() {
return false;
}
// stand for stunned indicator.
scanKings(fen) {
- this.INIT_COL_KING = { w: -1, b: -1 };
// Squares of white and black king:
this.kingPos = { w: [-1, -1], b: [-1, -1] };
const fenRows = V.ParseFen(fen).position.split("/");
case "k":
case "l":
this.kingPos["b"] = [i, k];
- this.INIT_COL_KING["b"] = k;
break;
case "K":
case "L":
this.kingPos["w"] = [i, k];
- this.INIT_COL_KING["w"] = k;
break;
default: {
const num = parseInt(fenRows[i].charAt(j), 10);
}
getPotentialMovesFrom([x, y]) {
- let moves = super.getPotentialMovesFrom([x, y]);
+ let moves = super.getPotentialMovesFrom([x, y]).filter(m => {
+ if (
+ m.vanish[0].p != V.PAWN ||
+ m.appear[0].p == V.PAWN ||
+ m.vanish.length == 1
+ ) {
+ return true;
+ }
+ // Pawn promotion, "capturing": remove duplicates
+ return m.appear[0].p == V.QUEEN;
+ });
// Complete moves: stuns & kicks
let promoteAfterStun = [];
const color = this.turn;
m.appear[0].x = i;
m.appear[0].y = j;
// Is it a pawn on last rank?
- if ((color == 'w' && i == 0) || (color == 'b' && i == 7)) {
+ if (
+ m.appear[0].p == V.PAWN &&
+ ((color == 'w' && i == 0) || (color == 'b' && i == 7))
+ ) {
m.appear[0].p = V.ROOK;
for (let ppiece of [V.KNIGHT, V.BISHOP, V.QUEEN]) {
let mp = JSON.parse(JSON.stringify(m));
return moves.concat(promoteAfterStun);
}
+ getPotentialKingMoves(sq) {
+ return (
+ this.getSlideNJumpMoves(
+ sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP]), 1
+ ).concat(super.getCastleMoves(sq, null, true, ['r']))
+ );
+ }
+
filterValid(moves) {
// Forbid kicking own king out
const color = this.turn;
return moves.filter(m => {
- const kingAppear = m.appear.some(a => a.c == color && a.p == V.KING);
- return m.vanish.every(v => {
- return (
- v.c != color ||
- !["k", "l"].includes(v.p) ||
- (v.p == "k" && kingAppear)
- );
- });
+ const kingVanish =
+ m.vanish.some(v => v.c == color && ['k', 'l'].includes(v.p));
+ if (kingVanish) {
+ const kingAppear =
+ m.appear.some(a => a.c == color && ['k', 'l'].includes(a.p));
+ return kingAppear;
+ }
+ return true;
});
}
// Base method is fine because a stunned king (which won't be detected)
// can still castle after going back to normal.
super.postPlay(move);
- const kIdx = move.vanish.findIndex(v => v.p == "l");
- if (kIdx >= 0)
- // A stunned king vanish (game over)
- this.kingPos[move.vanish[kIdx].c] = [-1, -1];
+ const color = this.turn;
+ const kp = this.kingPos[color];
+ if (
+ this.board[kp[0], kp[1]] == V.EMPTY ||
+ !['k', 'l'].includes(this.getPiece(kp[0], kp[1])) ||
+ this.getColor(kp[0], kp[1]) != color
+ ) {
+ // King didn't move by itself, and vanished => game over
+ this.kingPos[color] = [-1, -1];
+ }
move.stunned = JSON.stringify(this.stunned);
// Array of stunned stage 1 pieces (just back to normal then)
Object.keys(this.stunned).forEach(square => {
postUndo(move) {
super.postUndo(move);
- const kIdx = move.vanish.findIndex(v => v.p == "l");
- if (kIdx >= 0) {
- // A stunned king vanished
- this.kingPos[move.vanish[kIdx].c] =
- [move.vanish[kIdx].x, move.vanish[kIdx].y];
+ const oppCol = V.GetOppCol(this.turn);
+ if (this.kingPos[oppCol][0] < 0) {
+ // Opponent's king vanished
+ const psq =
+ move.vanish.find((v,i) => i >= 1 && ['k', 'l'].includes(v.p));
+ this.kingPos[oppCol] = [psq.x, psq.y];
}
this.stunned = JSON.parse(move.stunned);
for (let i=0; i<8; i++) {
}
return notation;
}
+
};