chessfriend/board/src/position/builders/position_builder.rs

95 lines
2.5 KiB
Rust
Raw Normal View History

// Eryn Wells <eryn@erynwells.me>
use crate::{
bitboard::BitBoardBuilder,
piece::{PlacedPiece, Shape},
position::{flags::Flags, piece_sets::PieceBitBoards},
r#move::Castle,
square::{Direction, Rank},
BitBoard, Color, MakeMoveError, Move, Piece, Position, Square,
};
use std::collections::BTreeMap;
#[derive(Clone)]
pub struct Builder {
player_to_move: Color,
flags: Flags,
pieces: BTreeMap<Square, Piece>,
kings: [Square; 2],
}
impl Builder {
pub fn new() -> Self {
Self::default()
}
pub fn place_piece(&mut self, piece: PlacedPiece) -> &mut Self {
let square = piece.square();
if piece.shape() == Shape::King {
let color_index: usize = piece.color() as usize;
self.pieces.remove(&self.kings[color_index]);
self.kings[color_index] = square;
}
self.pieces.insert(square, *piece.piece());
self
}
pub fn build(&self) -> Position {
let pieces = PieceBitBoards::from_iter(
self.pieces
.iter()
.map(PlacedPiece::from)
.filter(Self::is_piece_placement_valid),
);
Position::new(self.player_to_move, self.flags, pieces, None)
}
}
impl Builder {
fn is_piece_placement_valid(piece: &PlacedPiece) -> bool {
if piece.shape() == Shape::Pawn {
// Pawns cannot be placed on the first (back) rank of their side,
// and cannot be placed on the final rank without a promotion.
let rank = piece.square().rank();
return rank != Rank::One && rank != Rank::Eight;
}
true
}
}
impl Default for Builder {
fn default() -> Self {
let white_king_square = Square::king_starting_square(Color::White);
let black_king_square = Square::king_starting_square(Color::Black);
let pieces = BTreeMap::from_iter([
(white_king_square, piece!(White King)),
(black_king_square, piece!(Black King)),
]);
Self {
player_to_move: Color::White,
flags: Flags::default(),
pieces: pieces,
kings: [white_king_square, black_king_square],
}
}
}
#[cfg(test)]
mod tests {
use crate::PositionBuilder;
#[test]
fn place_piece() {
let piece = piece!(White Queen on E4);
let builder = PositionBuilder::new().place_piece(piece).build();
assert_eq!(builder.piece_on_square(piece.square()), Some(piece));
}
}