- getCastleMoves([x, y], castleInCheck) {
- return [];
-// const c = this.getColor(x, y);
-// if (x != (c == "w" ? V.size.x - 1 : 0) || y != this.INIT_COL_KING[c])
-// return []; //x isn't first rank, or king has moved (shortcut)
-//
-// // Castling ?
-// const oppCol = V.GetOppCol(c);
-// let moves = [];
-// let i = 0;
-// // King, then rook:
-// const finalSquares = [
-// [2, 3],
-// [V.size.y - 2, V.size.y - 3]
-// ];
-// castlingCheck: for (
-// let castleSide = 0;
-// castleSide < 2;
-// castleSide++ //large, then small
-// ) {
-// if (this.castleFlags[c][castleSide] >= V.size.y) continue;
-// // If this code is reached, rooks and king are on initial position
-//
-// // NOTE: in some variants this is not a rook, but let's keep variable name
-// const rookPos = this.castleFlags[c][castleSide];
-// const castlingPiece = this.getPiece(x, rookPos);
-// if (this.getColor(x, rookPos) != c)
-// // Rook is here but changed color (see Benedict)
-// continue;
-//
-// // Nothing on the path of the king ? (and no checks)
-// const finDist = finalSquares[castleSide][0] - y;
-// let step = finDist / Math.max(1, Math.abs(finDist));
-// i = y;
-// do {
-// if (
-// (!castleInCheck && this.isAttacked([x, i], oppCol)) ||
-// (this.board[x][i] != V.EMPTY &&
-// // NOTE: next check is enough, because of chessboard constraints
-// (this.getColor(x, i) != c ||
-// ![V.KING, castlingPiece].includes(this.getPiece(x, i))))
-// ) {
-// continue castlingCheck;
-// }
-// i += step;
-// } while (i != finalSquares[castleSide][0]);
-//
-// // Nothing on the path to the rook?
-// step = castleSide == 0 ? -1 : 1;
-// for (i = y + step; i != rookPos; i += step) {
-// if (this.board[x][i] != V.EMPTY) continue castlingCheck;
-// }
-//
-// // Nothing on final squares, except maybe king and castling rook?
-// for (i = 0; i < 2; i++) {
-// if (
-// this.board[x][finalSquares[castleSide][i]] != V.EMPTY &&
-// this.getPiece(x, finalSquares[castleSide][i]) != V.KING &&
-// finalSquares[castleSide][i] != rookPos
-// ) {
-// continue castlingCheck;
-// }
-// }
-//
-// // If this code is reached, castle is valid
-// moves.push(
-// new Move({
-// appear: [
-// new PiPo({ x: x, y: finalSquares[castleSide][0], p: V.KING, c: c }),
-// new PiPo({ x: x, y: finalSquares[castleSide][1], p: castlingPiece, c: c })
-// ],
-// vanish: [
-// new PiPo({ x: x, y: y, p: V.KING, c: c }),
-// new PiPo({ x: x, y: rookPos, p: castlingPiece, c: c })
-// ],
-// end:
-// Math.abs(y - rookPos) <= 2
-// ? { x: x, y: rookPos }
-// : { x: x, y: y + 2 * (castleSide == 0 ? -1 : 1) }
-// })
-// );
-// }
-//
-// return moves;
+ getCastleMoves([x, y]) {
+ const c = this.getColor(x, y);
+ if (
+ x != (c == "w" ? V.size.x - 1 : 0) ||
+ !this.castleFlags[c].slice(1, 3).includes(y)
+ ) {
+ // x isn't first rank, or piece moved
+ return [];
+ }
+ const castlingPiece = this.getPiece(x, y);
+
+ // Relative position of the selected piece: left or right ?
+ // If left: small castle left, large castle right.
+ // If right: usual situation.
+ const relPos = (this.castleFlags[c][1] == y ? "left" : "right");
+
+ // Castling ?
+ const oppCol = V.GetOppCol(c);
+ let moves = [];
+ let i = 0;
+ // Castling piece, then rook:
+ const finalSquares = {
+ 0: (relPos == "left" ? [1, 2] : [2, 3]),
+ 3: (relPos == "right" ? [6, 5] : [5, 4])
+ };
+
+ // Left, then right castle:
+ castlingCheck: for (let castleSide of [0, 3]) {
+ if (this.castleFlags[c][castleSide] >= 8) continue;
+
+ // Rook and castling piece are on initial position
+ const rookPos = this.castleFlags[c][castleSide];
+
+ // Nothing on the path of the king ? (and no checks)
+ const finDist = finalSquares[castleSide][0] - y;
+ let step = finDist / Math.max(1, Math.abs(finDist));
+ i = y;
+ do {
+ if (
+ this.isAttacked([x, i], oppCol) ||
+ (this.board[x][i] != V.EMPTY &&
+ // NOTE: next check is enough, because of chessboard constraints
+ (this.getColor(x, i) != c ||
+ ![castlingPiece, V.ROOK].includes(this.getPiece(x, i))))
+ ) {
+ continue castlingCheck;
+ }
+ i += step;
+ } while (i != finalSquares[castleSide][0]);
+
+ // Nothing on the path to the rook?
+ step = castleSide == 0 ? -1 : 1;
+ for (i = y + step; i != rookPos; i += step) {
+ if (this.board[x][i] != V.EMPTY) continue castlingCheck;
+ }
+
+ // Nothing on final squares, except maybe castling piece and rook?
+ for (i = 0; i < 2; i++) {
+ if (
+ this.board[x][finalSquares[castleSide][i]] != V.EMPTY &&
+ ![y, rookPos].includes(finalSquares[castleSide][i])
+ ) {
+ continue castlingCheck;
+ }
+ }
+
+ // If this code is reached, castle is valid
+ moves.push(
+ new Move({
+ appear: [
+ new PiPo({ x: x, y: finalSquares[castleSide][0], p: castlingPiece, c: c }),
+ new PiPo({ x: x, y: finalSquares[castleSide][1], p: V.ROOK, c: c })
+ ],
+ vanish: [
+ new PiPo({ x: x, y: y, p: castlingPiece, c: c }),
+ new PiPo({ x: x, y: rookPos, p: V.ROOK, c: c })
+ ],
+ // In this variant, always castle by playing onto the rook
+ end: { x: x, y: rookPos }
+ })
+ );
+ }
+
+ return moves;