[position] Implement FromFen for Position, Piece, and Color

I can now create Positions from FEN strings!
This commit is contained in:
Eryn Wells 2024-01-29 16:10:08 -08:00
parent 3239f288d7
commit 52b19b87d8
5 changed files with 187 additions and 13 deletions

View file

@ -13,7 +13,8 @@ pub struct Builder {
player_to_move: Color,
flags: Flags,
pieces: BTreeMap<Square, Piece>,
kings: [Square; 2],
kings: [Option<Square>; 2],
en_passant_square: Option<Square>,
ply_counter: u16,
move_number: u16,
}
@ -23,6 +24,18 @@ impl Builder {
Self::default()
}
pub(crate) fn empty() -> Self {
Self {
player_to_move: Color::default(),
flags: Flags::default(),
pieces: BTreeMap::default(),
kings: [None, None],
en_passant_square: None,
ply_counter: 0,
move_number: 1,
}
}
pub fn from_position(position: &Position) -> Self {
let pieces = BTreeMap::from_iter(
position
@ -38,7 +51,8 @@ impl Builder {
player_to_move: position.player_to_move(),
flags: position.flags(),
pieces,
kings: [white_king, black_king],
kings: [Some(white_king), Some(black_king)],
en_passant_square: position.en_passant_square(),
ply_counter: position.ply_counter(),
move_number: position.move_number(),
}
@ -59,6 +73,11 @@ impl Builder {
self
}
pub fn en_passant_square(&mut self, square: Option<Square>) -> &mut Self {
self.en_passant_square = square;
self
}
pub fn place_piece(&mut self, piece: PlacedPiece) -> &mut Self {
let square = piece.square();
let shape = piece.shape();
@ -66,8 +85,11 @@ impl Builder {
if shape == Shape::King {
let color = piece.color();
let color_index: usize = color as usize;
self.pieces.remove(&self.kings[color_index]);
self.kings[color_index] = square;
if let Some(king_square) = self.kings[color_index] {
self.pieces.remove(&king_square);
}
self.kings[color_index] = Some(square);
}
self.pieces.insert(square, *piece.piece());
@ -75,6 +97,17 @@ impl Builder {
self
}
pub fn player_can_castle(&mut self, color: Color, castle: Castle) -> &mut Self {
self.flags
.set_player_has_right_to_castle_flag(color, castle);
self
}
pub fn no_castling_rights(&mut self) -> &mut Self {
self.flags.clear_all_castling_rights();
self
}
pub fn build(&self) -> Position {
let pieces = PieceBitBoards::from_iter(
self.pieces
@ -93,7 +126,7 @@ impl Builder {
.get(&starting_squares.rook)
.is_some_and(|piece| piece.shape() == Shape::Rook);
let king_is_on_starting_square =
self.kings[color as usize] == starting_squares.king;
self.kings[color as usize] == Some(starting_squares.king);
if !king_is_on_starting_square || !has_rook_on_starting_square {
flags.clear_player_has_right_to_castle_flag(color, castle);
@ -105,7 +138,7 @@ impl Builder {
self.player_to_move,
flags,
pieces,
None,
self.en_passant_square,
self.ply_counter,
self.move_number,
)
@ -139,7 +172,8 @@ impl Default for Builder {
player_to_move: Color::White,
flags: Flags::default(),
pieces: pieces,
kings: [white_king_square, black_king_square],
kings: [Some(white_king_square), Some(black_king_square)],
en_passant_square: None,
ply_counter: 0,
move_number: 1,
}

View file

@ -24,6 +24,10 @@ impl Flags {
pub(super) fn clear_player_has_right_to_castle_flag(&mut self, color: Color, castle: Castle) {
self.0 &= !(1 << Self::player_has_right_to_castle_flag_offset(color, castle));
}
pub(super) fn clear_all_castling_rights(&mut self) {
self.0 &= 0b11111100;
}
}
impl fmt::Debug for Flags {

View file

@ -269,8 +269,8 @@ impl Position {
pieces,
sight: [OnceCell::new(), OnceCell::new()],
moves: OnceCell::new(),
half_move_counter: 0,
full_move_number: 1,
half_move_counter,
full_move_number,
}
}