// Eryn Wells use super::Pieces; use crate::bitboard::BitBoard; use crate::piece::{Color, Piece, PiecePlacementError, PlacedPiece, Shape}; use crate::Square; use std::fmt; use std::fmt::Write; #[derive(Clone, Eq, Hash, PartialEq)] pub struct Position { color_to_move: Color, /// Composite bitboards for all the pieces of a particular color. pieces_per_color: [BitBoard; 2], /// Bitboards representing positions of particular piece types per color. pieces_per_type: [[BitBoard; 6]; 2], } impl Position { pub fn empty() -> Position { Position { color_to_move: Color::White, pieces_per_color: [BitBoard::empty(), BitBoard::empty()], pieces_per_type: [ [ BitBoard::empty(), BitBoard::empty(), BitBoard::empty(), BitBoard::empty(), BitBoard::empty(), BitBoard::empty(), ], [ BitBoard::empty(), BitBoard::empty(), BitBoard::empty(), BitBoard::empty(), BitBoard::empty(), BitBoard::empty(), ], ], } } /// Return a starting position. pub fn starting() -> Position { let white_pieces = [ BitBoard::from_bit_field(0x00FF000000000000), BitBoard::from_bit_field(0x4200000000000000), BitBoard::from_bit_field(0x2400000000000000), BitBoard::from_bit_field(0x8100000000000000), BitBoard::from_bit_field(0x1000000000000000), BitBoard::from_bit_field(0x0800000000000000), ]; let black_pieces = [ BitBoard::from_bit_field(0xFF00), BitBoard::from_bit_field(0x0042), BitBoard::from_bit_field(0x0024), BitBoard::from_bit_field(0x0081), BitBoard::from_bit_field(0x0010), BitBoard::from_bit_field(0x0008), ]; Position { color_to_move: Color::White, pieces_per_color: [ white_pieces.iter().fold(BitBoard::empty(), |a, b| a | b), black_pieces.iter().fold(BitBoard::empty(), |a, b| a | b), ], pieces_per_type: [white_pieces, black_pieces], } } pub fn place_piece( &mut self, piece: &Piece, square: &Square, ) -> Result<(), PiecePlacementError> { let type_bb = self.bitboard_for_piece_mut(piece); if type_bb.has_piece_at(&square) { return Err(PiecePlacementError::ExistsOnSquare); } type_bb.place_piece_at(&square); let color_bb = &mut self.bitboard_for_color_mut(piece.color); color_bb.place_piece_at(&square); Ok(()) } pub(crate) fn bitboard_for_piece(&self, piece: Piece) -> &BitBoard { &self.pieces_per_type[piece.color as usize][piece.shape as usize] } fn bitboard_for_piece_mut(&mut self, piece: &Piece) -> &mut BitBoard { &mut self.pieces_per_type[piece.color as usize][piece.shape as usize] } pub(self) fn bitboard_for_color(&self, color: Color) -> &BitBoard { &self.pieces_per_color[color as usize] } pub(self) fn bitboard_for_color_mut(&mut self, color: Color) -> &mut BitBoard { &mut self.pieces_per_color[color as usize] } pub fn piece_on_square(&self, sq: Square) -> Option { for color in Color::iter() { for shape in Shape::iter() { let piece = Piece::new(color, shape); let bb = self.bitboard_for_piece(piece); if bb.has_piece_at(&sq) { return Some(PlacedPiece::new(piece, sq)); } } } None } pub fn pieces(&self, color: Color) -> Pieces { Pieces::new(&self, color) } } impl fmt::Debug for Position { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut output = String::new(); output.push_str("Position {\n"); write!(output, " color_to_move: {:?},\n", self.color_to_move)?; output.push_str(" pieces_per_color: [\n"); for bb in self.pieces_per_color { write!(output, " {bb:?},\n")?; } output.push_str(" ],\n"); output.push_str(" pieces_per_type: [\n"); for color_bbs in self.pieces_per_type { output.push_str(" [\n"); for bb in color_bbs { write!(output, " {bb:?},\n")?; } output.push_str(" ],\n"); } output.push_str(" ],\n}"); write!(f, "{}", output) } } #[cfg(test)] mod tests { use super::*; use crate::piece::Shape; #[test] fn place_piece() { let mut position = Position::empty(); let piece = Piece::new(Color::White, Shape::Queen); let square = Square::e4(); position .place_piece(&piece, &square) .expect("Unable to place white queen on e4"); assert_eq!( position.bitboard_for_color(piece.color).clone(), BitBoard::from_bit_field(1 << 28) ); assert_eq!( position.bitboard_for_piece(piece).clone(), BitBoard::from_bit_field(1 << 28) ); position .place_piece(&piece, &square) .expect_err("Placed white queen on e4 a second time?!"); } }