rules: rework castling rules
This commit is contained in:
parent
cef59b9913
commit
b334d55abf
42
src/rules.rs
42
src/rules.rs
|
@ -39,7 +39,14 @@ pub const CASTLING_BL_MASK: u8 = 0b00001100;
|
||||||
pub const CASTLING_K_MASK: u8 = 0b00000101;
|
pub const CASTLING_K_MASK: u8 = 0b00000101;
|
||||||
pub const CASTLING_Q_MASK: u8 = 0b00001010;
|
pub const CASTLING_Q_MASK: u8 = 0b00001010;
|
||||||
pub const CASTLING_MASK: u8 = 0b00001111;
|
pub const CASTLING_MASK: u8 = 0b00001111;
|
||||||
pub const CASTLING_SIDES: [(i8, u8); 2] = [(5i8, CASTLING_K_MASK), (3i8, CASTLING_Q_MASK)];
|
|
||||||
|
/// Castling sides parameters.
|
||||||
|
///
|
||||||
|
/// For both sides, the 3-uple contains files that should be empty
|
||||||
|
/// and not attacked, an optional file that should be empty for
|
||||||
|
/// queen-side, and the castling side-mask.
|
||||||
|
pub const CASTLING_SIDES: [([i8; 2], Option<i8>, u8); 2] =
|
||||||
|
[([5i8, 6i8], None, CASTLING_K_MASK), ([3i8, 2i8], Some(1i8), CASTLING_Q_MASK)];
|
||||||
|
|
||||||
pub const START_WH_K_POS: Pos = pos("e1");
|
pub const START_WH_K_POS: Pos = pos("e1");
|
||||||
pub const START_BL_K_POS: Pos = pos("e8");
|
pub const START_BL_K_POS: Pos = pos("e8");
|
||||||
|
@ -447,24 +454,39 @@ fn get_king_moves(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check for castling if the king is on its castling rank (R1)
|
// Check for castling if the king is on its castling rank (R1)
|
||||||
// and is not in check (R4)
|
// and is not in check (R4).
|
||||||
if
|
if
|
||||||
*r == castling_rank &&
|
*r == castling_rank &&
|
||||||
!is_attacked(board, game_state, at)
|
!is_attacked(board, game_state, at)
|
||||||
{
|
{
|
||||||
// Check for both castling sides.
|
// Check for both castling sides.
|
||||||
for (through_f, castling_side_mask) in CASTLING_SIDES.iter() {
|
for (path_files, opt_empty_file, castling_side_mask) in CASTLING_SIDES.iter() {
|
||||||
// Check for castling availability for this color and side.
|
// Check for castling availability for this color and side.
|
||||||
if (game_state.castling & castling_color_mask & castling_side_mask) != 0 {
|
if (game_state.castling & castling_color_mask & castling_side_mask) != 0 {
|
||||||
// R3, R5, R6: check that files on the way are empty and not attacked.
|
// Check that squares in the king's path are empty and not attacked (R3.1, R5, R6).
|
||||||
let p = (*through_f, castling_rank);
|
let mut path_is_clear = true;
|
||||||
if is_empty(board, &p) && !is_illegal(board, game_state, &(*at, p, None)) {
|
for path_f in path_files {
|
||||||
let castle = CASTLING_K_MASK & castling_color_mask;
|
let p = (*path_f, castling_rank);
|
||||||
let m = get_castle_move(castle);
|
if !is_empty(board, &p) || is_illegal(board, game_state, &(*at, p, None)) {
|
||||||
if can_register(commit, board, game_state, &m) {
|
path_is_clear = false;
|
||||||
moves.push(m);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !path_is_clear {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Check that rook jumps over an empty square on queen-side (R3.2).
|
||||||
|
if let Some(rook_path_f) = opt_empty_file {
|
||||||
|
let p = (*rook_path_f, castling_rank);
|
||||||
|
if !is_empty(board, &p) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let castle = castling_side_mask & castling_color_mask;
|
||||||
|
let m = get_castle_move(castle);
|
||||||
|
if can_register(commit, board, game_state, &m) {
|
||||||
|
moves.push(m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue