import { ChessRules, Move, PiPo } from "@/base_rules";
export class CannibalRules extends ChessRules {
+
static get KING_CODE() {
return {
'p': 's',
return (Object.keys(V.KING_DECODE).includes(b[1]) ? "Cannibal/" : "") + b;
}
+ static IsGoodPosition(position) {
+ if (position.length == 0) return false;
+ const rows = position.split("/");
+ if (rows.length != V.size.x) return false;
+ let kings = { "w": 0, "b": 0 };
+ const allPiecesCodes = V.PIECES.concat(Object.keys(V.KING_DECODE));
+ const kingBlackCodes = Object.keys(V.KING_DECODE).concat(['k']);
+ const kingWhiteCodes =
+ Object.keys(V.KING_DECODE).map(k => k.toUpperCase()).concat(['K']);
+ for (let row of rows) {
+ let sumElts = 0;
+ for (let i = 0; i < row.length; i++) {
+ if (kingBlackCodes.includes(row[i])) kings['b']++;
+ else if (kingWhiteCodes.includes(row[i])) kings['w']++;
+ if (allPiecesCodes.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;
+ }
+ // Both kings should be on board, only one of each color:
+ if (Object.values(kings).some(v => v != 1)) return false;
+ return true;
+ }
+
// Kings may be disguised:
setOtherVariables(fen) {
super.setOtherVariables(fen);
const color = (piece.charCodeAt(0) <= 90 ? 'w' : 'b');
this.kingPos[color] = [i, k];
} else {
- const num = parseInt(rows[i].charAt(j));
+ const num = parseInt(rows[i].charAt(j), 10);
if (!isNaN(num)) k += num - 1;
}
k++;
return moves.filter(m => m.vanish.length == 2 && m.appear.length == 1);
}
- // Stop at the first capture found (if any)
+ // Stop at the first capture found (if any)
atLeastOneCapture() {
const color = this.turn;
const oppCol = V.GetOppCol(color);
// Because of the disguised kings, getPiece() could be wrong:
// use board[x][y][1] instead (always valid).
getBasicMove([sx, sy], [ex, ey], tr) {
- const initColor = this.getColor(sx, sy);
- const initPiece = this.board[sx][sy].charAt(1);
- let mv = new Move({
- appear: [
- new PiPo({
- x: ex,
- y: ey,
- c: tr ? tr.c : initColor,
- p: tr ? tr.p : initPiece
- })
- ],
- vanish: [
- new PiPo({
- x: sx,
- y: sy,
- c: initColor,
- p: initPiece
- })
- ]
- });
-
- // The opponent piece disappears if we take it
- if (this.board[ex][ey] != V.EMPTY) {
- mv.vanish.push(
- new PiPo({
- x: ex,
- y: ey,
- c: this.getColor(ex, ey),
- p: this.board[ex][ey].charAt(1)
- })
- );
+ let mv = super.getBasicMove([sx, sy], [ex, ey], tr);
+ if (this.board[ex][ey] != V.EMPTY) {
// If the captured piece has a different nature: take it as well
if (mv.vanish[0].p != mv.vanish[1].p) {
if (
Object.keys(V.KING_DECODE).includes(mv.vanish[0].p)
) {
mv.appear[0].p = V.KING_CODE[mv.vanish[1].p];
- } else mv.appear[0].p = mv.vanish[1].p;
+ }
+ else mv.appear[0].p = mv.vanish[1].p;
}
}
else if (!!tr && mv.vanish[0].p != V.PAWN)
this.kingPos[c][0] = move.appear[0].x;
this.kingPos[c][1] = move.appear[0].y;
this.castleFlags[c] = [V.size.y, V.size.y];
- return;
}
+ // Next call is still required because the king may eat an opponent's rook
+ // TODO: castleFlags will be turned off twice then.
super.updateCastleFlags(move, piece);
}
};
}
- static get SEARCH_DEPTH() {
- return 4;
+ getNotation(move) {
+ let notation = super.getNotation(move);
+ const lastRank = (move.appear[0].c == "w" ? 0 : 7);
+ if (
+ move.end.x != lastRank &&
+ this.getPiece(move.start.x, move.start.y) == V.PAWN &&
+ move.vanish.length == 2 &&
+ move.appear[0].p != V.PAWN
+ ) {
+ // Fix "promotion" (transform indicator) from base_rules notation
+ notation = notation.slice(0, -2);
+ }
+ return notation;
}
+
};