Skip to content

Commit

Permalink
Simplifies the castling code.
Browse files Browse the repository at this point in the history
  • Loading branch information
aryann committed Oct 17, 2024
1 parent d66bb5c commit bf4eb91
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 66 deletions.
18 changes: 10 additions & 8 deletions engine/src/board.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ describe("castling rights", () => {
});

describe("castling", () => {
it("K king side", () => {
it("K", () => {
const board = new BoardState();

// Make space for a castle:
Expand All @@ -526,14 +526,15 @@ describe("castling", () => {
board.move({ type: "normal", from: "c7", to: "c6" });

// Castling move:
board.move({ type: "normal", from: "e1", to: "g1" });
board.move({ type: "castling", from: "e1", to: "g1", side: "K" });

assert.equal(
board.fen(),
"rnbqkbnr/3ppppp/ppp5/8/8/4PN2/PPPPBPPP/RNBQ1RK1 b kq - 1 4"
);
});

it("K queen side", () => {
it("Q", () => {
const board = new BoardState();

// Make space for a castle:
Expand All @@ -547,14 +548,15 @@ describe("castling", () => {
board.move({ type: "normal", from: "d7", to: "d6" });

// Castling move:
board.move({ type: "normal", from: "e1", to: "c1" });
board.move({ type: "castling", from: "e1", to: "c1", side: "Q" });

assert.equal(
board.fen(),
"rnbqkbnr/4pppp/pppp4/8/8/2NPB3/PPPQPPPP/2KR1BNR b kq - 1 5"
);
});

it("k king side", () => {
it("k", () => {
const board = new BoardState();

// Make space for a castle:
Expand All @@ -567,15 +569,15 @@ describe("castling", () => {
board.move({ type: "normal", from: "d2", to: "d3" });

// Castling move:
board.move({ type: "normal", from: "e8", to: "g8" });
board.move({ type: "castling", from: "e8", to: "g8", side: "k" });

assert.equal(
board.fen(),
"rnbq1rk1/ppppbppp/4pn2/8/8/PPPP4/4PPPP/RNBQKBNR w KQ - 1 5"
);
});

it("k queen side", () => {
it("q", () => {
const board = new BoardState();

// Make space for a castle:
Expand All @@ -590,7 +592,7 @@ describe("castling", () => {
board.move({ type: "normal", from: "e2", to: "e3" });

// Castling move:
board.move({ type: "normal", from: "e8", to: "c8" });
board.move({ type: "castling", from: "e8", to: "c8", side: "q" });

assert.equal(
board.fen(),
Expand Down
46 changes: 9 additions & 37 deletions engine/src/board.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CASTLING_ROOK_MOVES } from "./castling.ts";
import {
getFile,
getRank,
Expand Down Expand Up @@ -117,8 +118,8 @@ export class BoardState {
case "castling":
this.board[toIndex] = this.board[fromIndex];

const rookFromIndex = this.toIndex(move.rook.from);
const rookToIndex = this.toIndex(move.rook.to);
const rookFromIndex = this.toIndex(CASTLING_ROOK_MOVES[move.side].from);
const rookToIndex = this.toIndex(CASTLING_ROOK_MOVES[move.side].to);
this.board[rookToIndex] = this.board[rookFromIndex];

this.board[fromIndex] = 0;
Expand All @@ -134,7 +135,6 @@ export class BoardState {
}
this.isWhiteTurn = !this.isWhiteTurn;

this.maybeMakeCastlingMove(from, to);
this.updateCastlingRights(from);
this.updateEnPassant(from, to, piece);

Expand Down Expand Up @@ -192,8 +192,12 @@ export class BoardState {
case "castling":
this.board[fromIndex] = this.board[toIndex];

const rookFromIndex = this.toIndex(state.move.rook.from);
const rookToIndex = this.toIndex(state.move.rook.to);
const rookFromIndex = this.toIndex(
CASTLING_ROOK_MOVES[state.move.side].from
);
const rookToIndex = this.toIndex(
CASTLING_ROOK_MOVES[state.move.side].to
);
this.board[rookFromIndex] = this.board[rookToIndex];

this.board[toIndex] = 0;
Expand Down Expand Up @@ -286,38 +290,6 @@ export class BoardState {
return castlingRights.join("");
}

// TODO(aryann): Remove this helper. All this logic has been moved to the move
// generator. We retain this logic here because the unit tests currently
// depend on them.
private maybeMakeCastlingMove(from: TSquare, to: TSquare) {
const fromIndex = this.toIndex(from);
const castlingRights = this.castlingRights;

if (
(from === "e1" && to === "g1" && castlingRights.K) ||
(from === "e8" && to === "g8" && castlingRights.k)
) {
const right = fromIndex + 1;
const rookIndex = fromIndex + 3;
if (!this.board[right]) {
this.board[right] = this.board[rookIndex];
this.board[rookIndex] = 0;
}
}

if (
(from === "e1" && to === "c1" && castlingRights.Q) ||
(from === "e8" && to === "c8" && castlingRights.q)
) {
const left = fromIndex - 1;
const rookIndex = fromIndex - 4;
if (!this.board[left]) {
this.board[left] = this.board[rookIndex];
this.board[rookIndex] = 0;
}
}
}

// Updates the castling rights. This function assumes that the move has
// already been determined to be valid.
private updateCastlingRights(from: TSquare) {
Expand Down
10 changes: 10 additions & 0 deletions engine/src/castling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { TCastlingSides, TSquare } from "./types";

export const CASTLING_ROOK_MOVES: {
[key in TCastlingSides]: { from: TSquare; to: TSquare };
} = {
K: { from: "h1", to: "f1" },
Q: { from: "a1", to: "d1" },
k: { from: "h8", to: "f8" },
q: { from: "a8", to: "d8" },
};
16 changes: 8 additions & 8 deletions engine/src/moves.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -979,13 +979,13 @@ describe("castling", () => {
type: "castling",
from: "e1",
to: "g1",
rook: { from: "h1", to: "f1" },
side: "K",
},
{
type: "castling",
from: "e1",
to: "c1",
rook: { from: "a1", to: "d1" },
side: "Q",
},
]);
});
Expand All @@ -1000,7 +1000,7 @@ describe("castling", () => {
type: "castling",
from: "e1",
to: "g1",
rook: { from: "h1", to: "f1" },
side: "K",
},
]);
});
Expand All @@ -1015,7 +1015,7 @@ describe("castling", () => {
type: "castling",
from: "e1",
to: "c1",
rook: { from: "a1", to: "d1" },
side: "Q",
},
]);
});
Expand All @@ -1030,13 +1030,13 @@ describe("castling", () => {
type: "castling",
from: "e8",
to: "g8",
rook: { from: "h8", to: "f8" },
side: "k",
},
{
type: "castling",
from: "e8",
to: "c8",
rook: { from: "a8", to: "d8" },
side: "q",
},
]);
});
Expand All @@ -1051,7 +1051,7 @@ describe("castling", () => {
type: "castling",
from: "e8",
to: "g8",
rook: { from: "h8", to: "f8" },
side: "k",
},
]);
});
Expand All @@ -1066,7 +1066,7 @@ describe("castling", () => {
type: "castling",
from: "e8",
to: "c8",
rook: { from: "a8", to: "d8" },
side: "q",
},
]);
});
Expand Down
10 changes: 2 additions & 8 deletions engine/src/moves.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,7 @@ export class MoveGenerator {
type: "castling",
from,
to: rightRight,
rook: {
from: (from === "e1" ? "h1" : "h8") as TSquare,
to: (from === "e1" ? "f1" : "f8") as TSquare,
},
side: getSide(piece) === "w" ? "K" : "k",
});
}
}
Expand All @@ -315,10 +312,7 @@ export class MoveGenerator {
type: "castling",
from,
to: leftLeft,
rook: {
from: (from === "e1" ? "a1" : "a8") as TSquare,
to: (from === "e1" ? "d1" : "d8") as TSquare,
},
side: getSide(piece) === "w" ? "Q" : "q",
});
}
}
Expand Down
9 changes: 4 additions & 5 deletions engine/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,11 @@ export type TCastlingRights = {
q: boolean;
};

export type TMove = {
from: TSquare;
to: TSquare;
} & (
export type TCastlingSides = "K" | "Q" | "k" | "q";

export type TMove = { from: TSquare; to: TSquare } & (
| { type: "normal" }
| { type: "promotion"; promoteTo: TPiece }
| { type: "enPassant" }
| { type: "castling"; rook: { from: TSquare; to: TSquare } }
| { type: "castling"; side: TCastlingSides }
);

0 comments on commit bf4eb91

Please sign in to comment.