// 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. 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(0x8000000000000000), ]; 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(0x0080), ]; 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 bitboard = self.bitboard_for_piece_mut(piece); if bitboard.has_piece_at(&square) { return Err(PiecePlacementError::ExistsOnSquare); } bitboard.place_piece_at(&square); Ok(()) } pub(super) 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 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_at() { let mut position = Position::empty(); let piece = Piece::new(Color::White, Shape::Queen); let square = Square::from_algebraic_str("e4").expect("Unable to get e4 square"); position .place_piece(&piece, &square) .expect("Unable to place white queen on e4"); position .place_piece(&piece, &square) .expect_err("Placed white queen on e4 a second time?!"); println!("{:?}", position); } }