rules: fix castling issue

This commit is contained in:
dece 2020-06-06 01:27:19 +02:00
parent 659094b269
commit 25b1164644

View file

@ -39,8 +39,7 @@ pub const CASTLING_BL_MASK: u8 = 0b00001100;
pub const CASTLING_K_MASK: u8 = 0b00000101;
pub const CASTLING_Q_MASK: u8 = 0b00001010;
pub const CASTLING_MASK: u8 = 0b00001111;
pub const CASTLING_SIDES: [(std::ops::RangeInclusive<i8>, u8); 2] =
[(5..=6, CASTLING_K_MASK), (2..=3, CASTLING_Q_MASK)];
pub const CASTLING_SIDES: [(i8, u8); 2] = [(5i8, CASTLING_K_MASK), (3i8, CASTLING_Q_MASK)];
pub const START_WH_K_POS: Pos = pos("e1");
pub const START_BL_K_POS: Pos = pos("e8");
@ -404,27 +403,19 @@ fn get_king_moves(
(7, CASTLING_BL_MASK)
};
// Check for castling if the king is on its castling rank (R1) and is not in check (R4).
// Check for castling if the king is on its castling rank (R1)
// and is not in check (R4)
if
*r == castling_rank && // Part of R1 for the king.
!is_attacked(board, game_state, at) // R4
*r == castling_rank &&
!is_attacked(board, game_state, at)
{
// Check for both castling sides.
for (path, castling_side_mask) in CASTLING_SIDES.iter() {
for (through_f, castling_side_mask) in CASTLING_SIDES.iter() {
// 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.
let mut clear_path = true;
for through_f in path.to_owned() {
let p = (through_f, castling_rank);
if !is_empty(board, &p) || is_illegal(board, game_state, &(*at, p, None)) {
clear_path = false;
break;
}
}
// If the path is clear, the castling can be done.
if clear_path {
let p = (*through_f, castling_rank);
if is_empty(board, &p) && !is_illegal(board, game_state, &(*at, p, None)) {
let castle = CASTLING_K_MASK & castling_color_mask;
let m = get_castle_move(castle);
if can_register(commit, board, game_state, &m) {
@ -512,10 +503,10 @@ mod tests {
#[test]
fn test_get_castle() {
assert_eq!(get_castle(&parse_move("e1a1")), Some(CASTLING_WH_Q));
assert_eq!(get_castle(&parse_move("e1h1")), Some(CASTLING_WH_K));
assert_eq!(get_castle(&parse_move("e8a8")), Some(CASTLING_BL_Q));
assert_eq!(get_castle(&parse_move("e8h8")), Some(CASTLING_BL_K));
assert_eq!(get_castle(&parse_move("e1c1")), Some(CASTLING_WH_Q));
assert_eq!(get_castle(&parse_move("e1g1")), Some(CASTLING_WH_K));
assert_eq!(get_castle(&parse_move("e8c8")), Some(CASTLING_BL_Q));
assert_eq!(get_castle(&parse_move("e8g8")), Some(CASTLING_BL_K));
assert_eq!(get_castle(&parse_move("d2d4")), None);
}
@ -555,14 +546,14 @@ mod tests {
clear_square(&mut b, &pos("f8"));
clear_square(&mut b, &pos("g8"));
// White queen-side castling.
apply_move_to(&mut b, &mut gs, &parse_move("e1a1"));
apply_move_to(&mut b, &mut gs, &parse_move("e1c1"));
assert!(is_piece(get_square(&b, &pos("c1")), SQ_WH_K));
assert!(is_piece(get_square(&b, &pos("d1")), SQ_WH_R));
assert!(is_empty(&b, &pos("a1")));
assert!(is_empty(&b, &pos("e1")));
assert_eq!(gs.castling, CASTLING_BL_MASK);
// Black king-side castling.
apply_move_to(&mut b, &mut gs, &parse_move("e8h8"));
apply_move_to(&mut b, &mut gs, &parse_move("e8g8"));
assert!(is_piece(get_square(&b, &pos("g8")), SQ_BL_K));
assert!(is_piece(get_square(&b, &pos("f8")), SQ_BL_R));
assert!(is_empty(&b, &pos("h8")));
@ -713,7 +704,6 @@ mod tests {
#[test]
fn test_get_king_moves() {
let mut gs = GameState::new();
return; // FIXME
// King can move 1 square in any direction.
let mut b = new_empty();
@ -740,14 +730,17 @@ mod tests {
#[test]
fn test_filter_illegal_moves() {
let mut b = new_empty();
let gs = GameState::new();
let mut gs = GameState::new();
// Place white's king on first rank.
set_square(&mut b, &pos("e1"), SQ_WH_K);
// Place black rook in second rank: king can only move left or right.
set_square(&mut b, &pos("h2"), SQ_BL_R);
// No castling available.
gs.castling = 0;
// 5 moves in absolute but only 2 are legal.
let all_wh_moves = get_piece_moves(&b, &pos("e1"), &gs, true);
assert_eq!(all_wh_moves.len(), 2); // 5 moves in absolute but only 2 are legal.
assert_eq!(all_wh_moves.len(), 2);
}
#[test]