From ab55a7994c36ab0a3e6d16015cbbf3c7b9e95ccb Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Wed, 20 Dec 2023 11:45:12 -0800 Subject: [PATCH] [bitboard] Implement a Square type; fix all the build issues after adding a mod line to lib.rs --- bitboard/src/bitboard.rs | 2 +- bitboard/src/lib.rs | 13 ++--- bitboard/src/position.rs | 79 +++++++++++++++++++++++++----- bitboard/src/square.rs | 103 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 22 deletions(-) create mode 100644 bitboard/src/square.rs diff --git a/bitboard/src/bitboard.rs b/bitboard/src/bitboard.rs index 72687bf..68429fb 100644 --- a/bitboard/src/bitboard.rs +++ b/bitboard/src/bitboard.rs @@ -1,4 +1,4 @@ // Eryn Wells #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct BitBoard(u64); +pub struct BitBoard(pub u64); diff --git a/bitboard/src/lib.rs b/bitboard/src/lib.rs index 05aaacb..17ba31c 100644 --- a/bitboard/src/lib.rs +++ b/bitboard/src/lib.rs @@ -1,10 +1,3 @@ -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +mod bitboard; +mod position; +mod square; diff --git a/bitboard/src/position.rs b/bitboard/src/position.rs index 4bedbf7..7033a5f 100644 --- a/bitboard/src/position.rs +++ b/bitboard/src/position.rs @@ -1,17 +1,20 @@ // Eryn Wells +use crate::bitboard::BitBoard; +use std::fmt; + mod color { - const WHITE = 0; - const BLACK = 1; + const WHITE: u8 = 0; + const BLACK: u8 = 1; } mod piece { - const PAWN = 0; - const KNIGHT = 1; - const BISHOP = 2; - const ROOK = 3; - const QUEEN = 4; - const KING = 5; + const PAWN: u8 = 0; + const KNIGHT: u8 = 1; + const BISHOP: u8 = 2; + const ROOK: u8 = 3; + const QUEEN: u8 = 4; + const KING: u8 = 5; } #[derive(Clone, Debug, Eq, Hash, PartialEq)] @@ -24,10 +27,64 @@ pub struct Position { } impl Position { - static fn empty() -> Position { + fn empty() -> Position { Position { - pieces_per_color = [], - pieces_per_type = [], + pieces_per_color: [BitBoard(0), BitBoard(0)], + pieces_per_type: [ + [ + BitBoard(0), + BitBoard(0), + BitBoard(0), + BitBoard(0), + BitBoard(0), + BitBoard(0), + ], + [ + BitBoard(0), + BitBoard(0), + BitBoard(0), + BitBoard(0), + BitBoard(0), + BitBoard(0), + ], + ], } } + + /// Return a starting position. + fn starting() -> Position { + let white_pieces = [ + BitBoard(0x00FF000000000000), + BitBoard(0x4200000000000000), + BitBoard(0x2400000000000000), + BitBoard(0x8100000000000000), + BitBoard(0x1000000000000000), + BitBoard(0x8000000000000000), + ]; + + let black_pieces = [ + BitBoard(0xFF00), + BitBoard(0x0042), + BitBoard(0x0024), + BitBoard(0x0081), + BitBoard(0x0010), + BitBoard(0x0080), + ]; + + Position { + pieces_per_color: [ + BitBoard(white_pieces.iter().map(|bb| bb.0).fold(0, |a, b| a | b)), + BitBoard(black_pieces.iter().map(|bb| bb.0).fold(0, |a, b| a | b)), + ], + pieces_per_type: [white_pieces, black_pieces], + } + } + + fn piece_at_square(&self, sq: &str) {} +} + +impl fmt::Display for Position { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "abcdefg") + } } diff --git a/bitboard/src/square.rs b/bitboard/src/square.rs new file mode 100644 index 0000000..0adcf82 --- /dev/null +++ b/bitboard/src/square.rs @@ -0,0 +1,103 @@ +// Eryn Wells + +use std::str::FromStr; + +#[derive(Debug)] +struct ParseSquareError; + +#[derive(Debug)] +struct SquareIndexOutOfBoundsError; + +#[derive(Debug, Eq, PartialEq)] +struct Square { + rank: u8, + file: u8, +} + +impl Square { + fn from_index(index: u8) -> Result { + if index >= 64 { + return Err(SquareIndexOutOfBoundsError); + } + + Ok(Square { + rank: index / 8, + file: index % 8, + }) + } + + fn from_algebraic_string(s: &str) -> Result { + s.parse() + } + + fn rank_index(&self) -> usize { + self.rank.into() + } + + fn file_index(&self) -> usize { + self.file.into() + } +} + +impl FromStr for Square { + type Err = ParseSquareError; + + fn from_str(s: &str) -> Result { + if !s.is_ascii() || s.len() != 2 { + return Err(ParseSquareError); + } + + let chars: Vec = s.chars().collect(); + let rank_char = chars[0].to_ascii_lowercase(); + if !rank_char.is_ascii_lowercase() { + return Err(ParseSquareError); + } + + let rank = (rank_char as u8) - ('a' as u8) + 1; + if rank < 1 || rank > 8 { + return Err(ParseSquareError); + } + + let file = u8::try_from(chars[1].to_digit(10).ok_or(ParseSquareError)?) + .map_err(|_| ParseSquareError)?; + + Ok(Square { + rank: rank - 1, + file: file - 1, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn indexes() { + let sq1 = Square::from_algebraic_string("c5").expect("Failed to parse 'c5' square"); + assert_eq!(sq1.rank_index(), 2, "Rank doesn't match"); + assert_eq!(sq1.file_index(), 4, "File doesn't match"); + + let sq2 = Square::from_algebraic_string("b2").expect("Failed to parse 'b2' square"); + assert_eq!(sq2.rank_index(), 1, "Rank doesn't match"); + assert_eq!(sq2.file_index(), 1, "File doesn't match"); + } + + #[test] + fn parse_good_input() { + let sq1 = Square::from_algebraic_string("a4").expect("Failed to parse 'a4' square"); + assert_eq!(sq1.rank, 0); + assert_eq!(sq1.file, 3); + + let sq2 = Square::from_algebraic_string("B8").expect("Failed to parse 'B8' square"); + assert_eq!(sq2.rank, 1); + assert_eq!(sq2.file, 7); + } + + #[test] + fn from_index() { + let sq1 = Square::from_index(4).expect("Unable to get Square from index"); + assert_eq!(sq1.rank, 0); + assert_eq!(sq1.file, 4); + } +}