for (let x=0; x<this.size.x; x++) {
for (let y=0; y<this.size.y; y++) {
if (!this.enlightened[x][y] && this.oldEnlightened[x][y]) {
- let elt = document.getElementById(this.coordsToId(x, y));
+ let elt = document.getElementById(this.coordsToId({x: x, y: y}));
elt.classList.add("in-shadow");
if (this.g_pieces[x][y])
this.g_pieces[x][y].classList.add("hidden");
}
else if (this.enlightened[x][y] && !this.oldEnlightened[x][y]) {
- let elt = document.getElementById(this.coordsToId(x, y));
+ let elt = document.getElementById(this.coordsToId({x: x, y: y}));
elt.classList.remove("in-shadow");
if (this.g_pieces[x][y])
this.g_pieces[x][y].classList.remove("hidden");
// Piece type on square (i,j)
getPieceType(i, j) {
- const p = (typeof i == "string" ? j : this.board[i][j].charAt(1));
+ const p = this.getPiece(i, j);
return C.CannibalKings[p] || p; //a cannibal king move as...
}
"#": "r",
"$": "n",
"%": "b",
- "*": "q"
+ "*": "q",
+ "k": "k"
};
}
}
isKing(symbol) {
- return (
- symbol == 'k' ||
- (this.options["cannibal"] && C.CannibalKings[symbol])
- );
+ return !!C.CannibalKings[symbol];
}
// For Madrasi:
let moves = [];
// Find reverse captures (opponent takes)
const color = this.getColor(x, y);
- const pieceType = this.getPieceType(x, y);
const oppCol = C.GetOppCol(color);
for (let i=0; i<this.size.x; i++) {
for (let j=0; j<this.size.y; j++) {
this.canTake([i, j], [x, y]) &&
!this.isImmobilized([i, j])
) {
- const piece = this.getPieceType(i, j);
- if (zen && C.CannibalKingCode[piece])
+ if (zen && this.isKing(this.getPiece(i, j)))
continue; //king not captured in this way
- const stepSpec = this.pieces(oppCol, i, j)[piece];
+ const stepSpec = this.pieces(oppCol, i, j)[this.getPieceType(i, j)];
const attacks = stepSpec.attack || stepSpec.moves;
for (let a of attacks) {
for (let s of a.steps) {
let square = kingPos,
res = true; //a priori valid
if (m.vanish.some(v => {
- return (v.p == "k" || C.CannibalKings[v.p]) && v.c == color;
+ return C.CannibalKings[v.p] && v.c == color;
})) {
// Search king in appear array:
const newKingIdx =
m.appear.findIndex(a => {
- return (a.p == "k" || C.CannibalKings[a.p]) && a.c == color;
+ return C.CannibalKings[a.p] && a.c == color;
});
if (newKingIdx >= 0)
square = [m.appear[newKingIdx].x, m.appear[newKingIdx].y];
// Apply a move on board
playOnBoard(move) {
- for (let psq of move.vanish) this.board[psq.x][psq.y] = "";
- for (let psq of move.appear) this.board[psq.x][psq.y] = psq.c + psq.p;
+ for (let psq of move.vanish)
+ this.board[psq.x][psq.y] = "";
+ for (let psq of move.appear)
+ this.board[psq.x][psq.y] = psq.c + psq.p;
}
// Un-apply the played move
undoOnBoard(move) {
- for (let psq of move.appear) this.board[psq.x][psq.y] = "";
- for (let psq of move.vanish) this.board[psq.x][psq.y] = psq.c + psq.p;
+ for (let psq of move.appear)
+ this.board[psq.x][psq.y] = "";
+ for (let psq of move.vanish)
+ this.board[psq.x][psq.y] = psq.c + psq.p;
}
updateCastleFlags(move) {
return (color == "w" ? "0-1" : "1-0");
}
- // NOTE: quite suboptimal for eg. Benedict (not a big deal I think)
playVisual(move, r) {
move.vanish.forEach(v => {
// TODO: next "if" shouldn't be required
return false;
}
- canTake() {
- return false;
- }
-
// Find potential captures from a square
// follow steps from x,y until something is met.
findAttacks([x, y]) {
let [i, j] = [x + step[0], this.computeY(y + step[1])];
let nbSteps = 1;
while (this.onBoard(i, j) && this.board[i][j] == "") {
- if (a.range <= nbSteps++) continue outerLoop;
+ if (a.range <= nbSteps++)
+ continue outerLoop;
i += step[0];
j = this.computeY(j + step[1]);
}
- if (this.onBoard(i, j) && this.getColor(i, j) == oppCol)
+ if (
+ this.onBoard(i, j) && this.getColor(i, j) == oppCol &&
+ (!this.options["zen"] || this.getPieceType(i, j) == "k")
+ ) {
squares[C.CoordsToSquare({x: i, y: j})] = true;
+ }
}
}
return Object.keys(squares);
}
postProcessPotentialMoves(moves) {
- if (moves.length == 0) return moves;
- const [x, y] = [moves[0].end.x, moves[0].end.y];
+ if (moves.length == 0)
+ return moves;
const color = this.getColor(moves[0].start.x, moves[0].start.y);
const oppCol = C.GetOppCol(color);
- moves = super.postProcessPotentialMoves(moves);
+ // Remove captures (NOTE: altering canTake has side effects,
+ // Benedict is still based on captures even if they are forbidden):
+ moves = super.postProcessPotentialMoves(moves)
+ .filter(m => this.board[m.end.x][m.end.y] == "");
moves.forEach(m => {
- this.playOnBoard(m);
- let attacks;
+ super.playOnBoard(m);
+ let attacks = this.findAttacks([m.end.x, m.end.y])
if (this.options["zen"]) {
let endSquares = {};
- super.getZenCaptures(x, y).forEach(c => {
+ super.findCapturesOn([m.end.x, m.end.y], true).forEach(c => {
endSquares[C.CoordsToSquare(c.end)] = true;
});
- attacks = Object.keys(endSquares);
+ Array.prototype.push.apply(attacks, Object.keys(endSquares));
}
- else attacks = this.findAttacks([m.end.x, m.end.y])
- this.undoOnBoard(m);
+ super.undoOnBoard(m);
+ m.flips = [];
attacks.map(C.SquareToCoords).forEach(a => {
- const p = this.getPiece(a.x, a.y);
- m.appear.push(new PiPo({x: a.x, y: a.y, c: color, p: p}));
- m.vanish.push(new PiPo({x: a.x, y: a.y, c: oppCol, p: p}));
+ m.flips.push({x: a.x, y: a.y});
});
});
return moves;
}
- // Moves cannot flip our king's color, so (almost) all are valid
+ playOnBoard(move) {
+ super.playOnBoard(move);
+ this.flipColorOf(move.flips);
+ }
+ undoOnBoard(move) {
+ super.undoOnBoard(move);
+ this.flipColorOf(move.flips);
+ }
+
+ flipColorOf(flips) {
+ for (let xy of flips) {
+ const newColor = C.GetOppCol(this.getColor(xy.x, xy.y));
+ this.board[xy.x][xy.y] = newColor + this.board[xy.x][xy.y][1];
+ }
+ }
+
+ postPlay(move) {
+ if (this.options["balance"] && [1, 3].includes(this.movesCount)) {
+ // If enemy king is flipped: game over
+ const oppCol = C.GetOppCol(move.vanish[0].c);
+ const oppKingPos = this.searchKingPos(oppCol);
+ if (oppKingPos[0] < 0) {
+ this.turn = oppCol;
+ this.movesCount++;
+ return;
+ }
+ }
+ super.postPlay(move);
+ }
+
+ // Moves cannot flip our king's color, so all are valid
filterValid(moves) {
- if (this.options["balance"] && [1, 3].includes(this.movesCount))
- return moves.filter(m => m.vanish.every(v => v.p != C.KING));
return moves;
}
- // Since it's used just for the king, and there are no captures:
+ // A king under (regular) check flips color, and the game is over.
underCheck(square, color) {
return false;
}
+ playVisual(move, r) {
+ super.playVisual(move, r);
+ move.flips.forEach(f => {
+ this.g_pieces[f.x][f.y].classList.toggle("white");
+ this.g_pieces[f.x][f.y].classList.toggle("black");
+ });
+ }
+
};