+ getCastleMoves([x, y]) {
+ const c = this.getColor(x, y);
+
+ // Castling ?
+ const oppCol = V.GetOppCol(c);
+ let moves = [];
+ let i = 0;
+ // King, then lancer:
+ 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, lancer and king are on initial position
+
+ const lancerPos = this.castleFlags[c][castleSide];
+ const castlingPiece = this.board[x][lancerPos].charAt(1);
+
+ // 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 || ![y, lancerPos].includes(i))
+ )
+ ) {
+ continue castlingCheck;
+ }
+ i += step;
+ } while (i != finalSquares[castleSide][0]);
+
+ // Nothing on final squares, except maybe king and castling lancer?
+ for (i = 0; i < 2; i++) {
+ if (
+ finalSquares[castleSide][i] != lancerPos &&
+ this.board[x][finalSquares[castleSide][i]] != V.EMPTY &&
+ (
+ finalSquares[castleSide][i] != y ||
+ this.getColor(x, finalSquares[castleSide][i]) != c
+ )
+ ) {
+ continue castlingCheck;
+ }
+ }
+
+ // If this code is reached, castle is valid
+ let allowedLancerDirs = [castlingPiece];
+ if (finalSquares[castleSide][1] != lancerPos) {
+ // It moved: allow reorientation
+ allowedLancerDirs =
+ x == 0
+ ? ['e', 'f', 'g', 'h', 'm']
+ : ['c', 'd', 'e', 'm', 'o'];
+ }
+ allowedLancerDirs.forEach(dir => {
+ 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: dir,
+ c: c
+ })
+ ],
+ vanish: [
+ new PiPo({ x: x, y: y, p: V.KING, c: c }),
+ new PiPo({ x: x, y: lancerPos, p: castlingPiece, c: c })
+ ],
+ end:
+ Math.abs(y - lancerPos) <= 2
+ ? { x: x, y: lancerPos }
+ : { x: x, y: y + 2 * (castleSide == 0 ? -1 : 1) }
+ })
+ );
+ });
+ }
+
+ return moves;
+ }
+