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

98 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, BoardSide},
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 pieces = BTreeMap::from_iter([
(
Square::KING_STARTING_SQUARES[Color::White as usize],
piece!(White King),
),
(
Square::KING_STARTING_SQUARES[Color::Black as usize],
piece!(Black King),
),
]);
Self {
player_to_move: Color::White,
flags: Flags::default(),
pieces: pieces,
kings: Square::KING_STARTING_SQUARES,
}
}
}
#[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));
}
}