// Eryn Wells mod pieces; use self::pieces::Pieces; use crate::bitboard::BitBoard; use crate::piece::{Piece, PiecePlacementError}; use crate::square::Square; use std::fmt; use std::fmt::Write; #[derive(Clone, Eq, Hash, PartialEq)] pub struct Position { /// 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 { fn empty() -> Position { Position { 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 { 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], } } 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::PieceExistsOnSquare); } 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] } 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) } } impl fmt::Display for Position { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "abcdefg") #[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_string("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); } }