[board] Implement all the bit twiddling to track whether castling is allowed for each player and side of the board
This commit is contained in:
parent
8cc7e64ba6
commit
31e5771d30
3 changed files with 100 additions and 7 deletions
|
@ -7,9 +7,9 @@ use super::{move_generator_declaration, MoveGeneratorInternal, MoveSet};
|
|||
use crate::{
|
||||
bitboard::BitBoard,
|
||||
piece::{Color, Piece, PlacedPiece},
|
||||
Move, Position, Square,
|
||||
position::BoardSide,
|
||||
Move, Position,
|
||||
};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
move_generator_declaration!(KingMoveGenerator, struct);
|
||||
move_generator_declaration!(KingMoveGenerator, new);
|
||||
|
@ -17,13 +17,21 @@ move_generator_declaration!(KingMoveGenerator, getters);
|
|||
|
||||
impl<'a> KingMoveGenerator<'a> {
|
||||
#[allow(unused_variables)]
|
||||
fn king_side_castle(position: &Position) -> Option<Move> {
|
||||
fn king_side_castle(position: &Position, color: Color) -> Option<Move> {
|
||||
if !position.is_castling_allowed(color, BoardSide::King) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// TODO: Implement king side castle.
|
||||
None
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn queen_side_castle(position: &Position) -> Option<Move> {
|
||||
fn queen_side_castle(position: &Position, color: Color) -> Option<Move> {
|
||||
if !position.is_castling_allowed(color, BoardSide::Queen) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// TODO: Implement queen side castle.
|
||||
None
|
||||
}
|
||||
|
@ -51,8 +59,8 @@ impl<'pos> MoveGeneratorInternal for KingMoveGenerator<'pos> {
|
|||
|
||||
let map_to_move = |sq| Move::new(piece, square, sq);
|
||||
|
||||
let king_side_castle = Self::king_side_castle(position);
|
||||
let queen_side_castle = Self::queen_side_castle(position);
|
||||
let king_side_castle = Self::king_side_castle(position, color);
|
||||
let queen_side_castle = Self::queen_side_castle(position, color);
|
||||
let quiet_moves = quiet_moves_bb
|
||||
.occupied_squares()
|
||||
.map(map_to_move)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
mod diagram_formatter;
|
||||
mod pieces;
|
||||
mod position;
|
||||
|
@ -5,3 +7,5 @@ mod position;
|
|||
pub use diagram_formatter::DiagramFormatter;
|
||||
pub use pieces::Pieces;
|
||||
pub use position::Position;
|
||||
|
||||
pub(crate) use position::BoardSide;
|
||||
|
|
|
@ -10,10 +10,27 @@ use crate::{
|
|||
use std::fmt;
|
||||
use std::fmt::Write;
|
||||
|
||||
/// A lateral side of the board relative to the player. Kingside is the side the
|
||||
/// player's king starts on. Queenside is the side of the board the player's
|
||||
/// queen starts on.
|
||||
pub(crate) enum BoardSide {
|
||||
King,
|
||||
Queen,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub struct Position {
|
||||
color_to_move: Color,
|
||||
|
||||
/// Position flags indicating various bits of game state. The flags are as
|
||||
/// follows:
|
||||
///
|
||||
/// 0. white can castle king-side
|
||||
/// 1. white can castle queen-side
|
||||
/// 2. black can castle king-side
|
||||
/// 3. black can castle queen-side
|
||||
flags: u8,
|
||||
|
||||
/// Composite bitboards for all the pieces of a particular color.
|
||||
pieces_per_color: [BitBoard; 2],
|
||||
|
||||
|
@ -25,7 +42,8 @@ impl Position {
|
|||
pub fn empty() -> Position {
|
||||
Position {
|
||||
color_to_move: Color::White,
|
||||
pieces_per_color: [BitBoard::empty(), BitBoard::empty()],
|
||||
flags: 0b00001111,
|
||||
pieces_per_color: [BitBoard::empty(); 2],
|
||||
pieces_per_type: [
|
||||
[
|
||||
BitBoard::empty(),
|
||||
|
@ -69,6 +87,7 @@ impl Position {
|
|||
|
||||
Position {
|
||||
color_to_move: Color::White,
|
||||
flags: 0b00001111,
|
||||
pieces_per_color: [
|
||||
white_pieces.iter().fold(BitBoard::empty(), |a, b| a | *b),
|
||||
black_pieces.iter().fold(BitBoard::empty(), |a, b| a | *b),
|
||||
|
@ -77,6 +96,36 @@ impl Position {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the player has the right to castle on the given side of
|
||||
/// the board.
|
||||
///
|
||||
/// The right to castle on a particular side of the board is retained as
|
||||
/// long as the player has not moved their king, or the rook on that side of
|
||||
/// the board.
|
||||
///
|
||||
/// The following requirements must also be met:
|
||||
///
|
||||
/// 1. The spaces between the king and rook must be clear
|
||||
/// 2. The king must not be in check
|
||||
/// 3. In the course of castling on that side, the king must not pass
|
||||
/// through a square that an enemy piece can see
|
||||
pub(crate) fn player_has_right_to_castle(&self, color: Color, side: BoardSide) -> bool {
|
||||
(self.flags & (1 << Self::player_has_right_to_castle_flag_offset(color, side))) != 0
|
||||
}
|
||||
|
||||
fn set_player_has_right_to_castle_flag(&mut self, color: Color, side: BoardSide) {
|
||||
self.flags |= 1 << Self::player_has_right_to_castle_flag_offset(color, side);
|
||||
}
|
||||
|
||||
fn clear_player_has_right_to_castle_flag(&mut self, color: Color, side: BoardSide) {
|
||||
self.flags &= !(1 << Self::player_has_right_to_castle_flag_offset(color, side));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn player_has_right_to_castle_flag_offset(color: Color, side: BoardSide) -> u8 {
|
||||
((color as u8) << 1) + side as u8
|
||||
}
|
||||
|
||||
pub fn place_piece(&mut self, piece: Piece, square: Square) -> Result<(), PiecePlacementError> {
|
||||
let type_bb = self.bitboard_for_piece_mut(piece);
|
||||
|
||||
|
@ -200,4 +249,36 @@ mod tests {
|
|||
.place_piece(piece, square)
|
||||
.expect_err("Placed white queen on e4 a second time?!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn castle_flags() {
|
||||
assert_eq!(
|
||||
Position::player_has_right_to_castle_flag_offset(Color::White, BoardSide::King),
|
||||
0
|
||||
);
|
||||
assert_eq!(
|
||||
Position::player_has_right_to_castle_flag_offset(Color::White, BoardSide::Queen),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
Position::player_has_right_to_castle_flag_offset(Color::Black, BoardSide::King),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
Position::player_has_right_to_castle_flag_offset(Color::Black, BoardSide::Queen),
|
||||
3
|
||||
);
|
||||
|
||||
let mut pos = Position::starting();
|
||||
assert!(pos.player_has_right_to_castle(Color::White, BoardSide::King));
|
||||
assert!(pos.player_has_right_to_castle(Color::White, BoardSide::Queen));
|
||||
assert!(pos.player_has_right_to_castle(Color::Black, BoardSide::King));
|
||||
assert!(pos.player_has_right_to_castle(Color::Black, BoardSide::Queen));
|
||||
|
||||
pos.clear_player_has_right_to_castle_flag(Color::White, BoardSide::Queen);
|
||||
assert!(pos.player_has_right_to_castle(Color::White, BoardSide::King));
|
||||
assert!(!pos.player_has_right_to_castle(Color::White, BoardSide::Queen));
|
||||
assert!(pos.player_has_right_to_castle(Color::Black, BoardSide::King));
|
||||
assert!(pos.player_has_right_to_castle(Color::Black, BoardSide::Queen));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue