rules: fix castling issue
This commit is contained in:
parent
659094b269
commit
25b1164644
47
src/rules.rs
47
src/rules.rs
|
@ -39,8 +39,7 @@ 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: [(std::ops::RangeInclusive<i8>, u8); 2] =
|
pub const CASTLING_SIDES: [(i8, u8); 2] = [(5i8, CASTLING_K_MASK), (3i8, CASTLING_Q_MASK)];
|
||||||
[(5..=6, CASTLING_K_MASK), (2..=3, 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");
|
||||||
|
@ -404,27 +403,19 @@ fn get_king_moves(
|
||||||
(7, CASTLING_BL_MASK)
|
(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
|
if
|
||||||
*r == castling_rank && // Part of R1 for the king.
|
*r == castling_rank &&
|
||||||
!is_attacked(board, game_state, at) // R4
|
!is_attacked(board, game_state, at)
|
||||||
{
|
{
|
||||||
// Check for both castling sides.
|
// 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.
|
// 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.
|
// R3, R5, R6: check that files on the way are empty and not attacked.
|
||||||
let mut clear_path = true;
|
let p = (*through_f, castling_rank);
|
||||||
for through_f in path.to_owned() {
|
if is_empty(board, &p) && !is_illegal(board, game_state, &(*at, p, None)) {
|
||||||
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 castle = CASTLING_K_MASK & castling_color_mask;
|
let castle = CASTLING_K_MASK & castling_color_mask;
|
||||||
let m = get_castle_move(castle);
|
let m = get_castle_move(castle);
|
||||||
if can_register(commit, board, game_state, &m) {
|
if can_register(commit, board, game_state, &m) {
|
||||||
|
@ -512,10 +503,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_castle() {
|
fn test_get_castle() {
|
||||||
assert_eq!(get_castle(&parse_move("e1a1")), Some(CASTLING_WH_Q));
|
assert_eq!(get_castle(&parse_move("e1c1")), Some(CASTLING_WH_Q));
|
||||||
assert_eq!(get_castle(&parse_move("e1h1")), Some(CASTLING_WH_K));
|
assert_eq!(get_castle(&parse_move("e1g1")), Some(CASTLING_WH_K));
|
||||||
assert_eq!(get_castle(&parse_move("e8a8")), Some(CASTLING_BL_Q));
|
assert_eq!(get_castle(&parse_move("e8c8")), Some(CASTLING_BL_Q));
|
||||||
assert_eq!(get_castle(&parse_move("e8h8")), Some(CASTLING_BL_K));
|
assert_eq!(get_castle(&parse_move("e8g8")), Some(CASTLING_BL_K));
|
||||||
assert_eq!(get_castle(&parse_move("d2d4")), None);
|
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("f8"));
|
||||||
clear_square(&mut b, &pos("g8"));
|
clear_square(&mut b, &pos("g8"));
|
||||||
// White queen-side castling.
|
// 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("c1")), SQ_WH_K));
|
||||||
assert!(is_piece(get_square(&b, &pos("d1")), SQ_WH_R));
|
assert!(is_piece(get_square(&b, &pos("d1")), SQ_WH_R));
|
||||||
assert!(is_empty(&b, &pos("a1")));
|
assert!(is_empty(&b, &pos("a1")));
|
||||||
assert!(is_empty(&b, &pos("e1")));
|
assert!(is_empty(&b, &pos("e1")));
|
||||||
assert_eq!(gs.castling, CASTLING_BL_MASK);
|
assert_eq!(gs.castling, CASTLING_BL_MASK);
|
||||||
// Black king-side castling.
|
// 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("g8")), SQ_BL_K));
|
||||||
assert!(is_piece(get_square(&b, &pos("f8")), SQ_BL_R));
|
assert!(is_piece(get_square(&b, &pos("f8")), SQ_BL_R));
|
||||||
assert!(is_empty(&b, &pos("h8")));
|
assert!(is_empty(&b, &pos("h8")));
|
||||||
|
@ -713,7 +704,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_king_moves() {
|
fn test_get_king_moves() {
|
||||||
let mut gs = GameState::new();
|
let mut gs = GameState::new();
|
||||||
return; // FIXME
|
|
||||||
|
|
||||||
// King can move 1 square in any direction.
|
// King can move 1 square in any direction.
|
||||||
let mut b = new_empty();
|
let mut b = new_empty();
|
||||||
|
@ -740,14 +730,17 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_filter_illegal_moves() {
|
fn test_filter_illegal_moves() {
|
||||||
let mut b = new_empty();
|
let mut b = new_empty();
|
||||||
let gs = GameState::new();
|
let mut gs = GameState::new();
|
||||||
|
|
||||||
// Place white's king on first rank.
|
// Place white's king on first rank.
|
||||||
set_square(&mut b, &pos("e1"), SQ_WH_K);
|
set_square(&mut b, &pos("e1"), SQ_WH_K);
|
||||||
// Place black rook in second rank: king can only move left or right.
|
// Place black rook in second rank: king can only move left or right.
|
||||||
set_square(&mut b, &pos("h2"), SQ_BL_R);
|
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);
|
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]
|
#[test]
|
||||||
|
|
Reference in a new issue