refactor: make square idx size type a variable
This commit is contained in:
parent
a36aa3b0c6
commit
3dac0e4388
10
src/fen.rs
10
src/fen.rs
@ -1,4 +1,4 @@
|
|||||||
use crate::{Board, ColPiece, Color, Square, BOARD_HEIGHT, BOARD_WIDTH};
|
use crate::{Board, ColPiece, Color, Square, SquareIdx, BOARD_HEIGHT, BOARD_WIDTH};
|
||||||
|
|
||||||
pub const START_POSITION: &str = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
pub const START_POSITION: &str = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ impl FromFen for Board {
|
|||||||
parse_space_and_goto!(FenState::HalfMove);
|
parse_space_and_goto!(FenState::HalfMove);
|
||||||
}
|
}
|
||||||
'a'..='h' => {
|
'a'..='h' => {
|
||||||
pos.ep_square = Some(Square(c as usize - 'a' as usize));
|
pos.ep_square = Some(Square(c as SquareIdx - b'a'));
|
||||||
parser_state = FenState::EnPassantFile;
|
parser_state = FenState::EnPassantFile;
|
||||||
}
|
}
|
||||||
_ => return bad_char!(i, c),
|
_ => return bad_char!(i, c),
|
||||||
@ -188,8 +188,8 @@ impl FromFen for Board {
|
|||||||
FenState::EnPassantFile => {
|
FenState::EnPassantFile => {
|
||||||
if let Some(digit) = c.to_digit(10) {
|
if let Some(digit) = c.to_digit(10) {
|
||||||
pos.ep_square = Some(Square(
|
pos.ep_square = Some(Square(
|
||||||
usize::from(pos.ep_square.unwrap_or(Square(0)))
|
SquareIdx::from(pos.ep_square.unwrap_or(Square(0)))
|
||||||
+ (digit as usize - 1) * 8,
|
+ (digit as SquareIdx - 1) * 8,
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
return bad_char!(i, c);
|
return bad_char!(i, c);
|
||||||
@ -287,7 +287,7 @@ mod tests {
|
|||||||
let fen = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1";
|
let fen = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1";
|
||||||
let board = Board::from_fen(fen.into()).unwrap();
|
let board = Board::from_fen(fen.into()).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(0..N_SQUARES)
|
(0..SquareIdx::try_from(N_SQUARES).unwrap())
|
||||||
.map(Square)
|
.map(Square)
|
||||||
.map(|i| board.get_piece(i))
|
.map(|i| board.get_piece(i))
|
||||||
.map(ColPiece::opt_to_char)
|
.map(ColPiece::opt_to_char)
|
||||||
|
44
src/lib.rs
44
src/lib.rs
@ -109,11 +109,13 @@ impl ColPiece {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SquareIdx = u8;
|
||||||
|
|
||||||
/// Square index newtype.
|
/// Square index newtype.
|
||||||
///
|
///
|
||||||
/// A1 is (0, 0) -> 0, A2 is (0, 1) -> 2, and H8 is (7, 7) -> 63.
|
/// A1 is (0, 0) -> 0, A2 is (0, 1) -> 2, and H8 is (7, 7) -> 63.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Square(usize);
|
pub struct Square(SquareIdx);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SquareError {
|
pub enum SquareError {
|
||||||
@ -121,11 +123,11 @@ pub enum SquareError {
|
|||||||
InvalidCharacter(char),
|
InvalidCharacter(char),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<usize> for Square {
|
impl TryFrom<SquareIdx> for Square {
|
||||||
type Error = SquareError;
|
type Error = SquareError;
|
||||||
|
|
||||||
fn try_from(value: usize) -> Result<Self, Self::Error> {
|
fn try_from(value: SquareIdx) -> Result<Self, Self::Error> {
|
||||||
if (0..N_SQUARES).contains(&value) {
|
if (0..N_SQUARES).contains(&value.into()) {
|
||||||
Ok(Square(value))
|
Ok(Square(value))
|
||||||
} else {
|
} else {
|
||||||
Err(SquareError::OutOfBounds)
|
Err(SquareError::OutOfBounds)
|
||||||
@ -141,7 +143,7 @@ macro_rules! sq_try_from {
|
|||||||
fn try_from(value: $T) -> Result<Self, Self::Error> {
|
fn try_from(value: $T) -> Result<Self, Self::Error> {
|
||||||
if let Ok(upper_bound) = <$T>::try_from(N_SQUARES) {
|
if let Ok(upper_bound) = <$T>::try_from(N_SQUARES) {
|
||||||
if (0..upper_bound).contains(&value) {
|
if (0..upper_bound).contains(&value) {
|
||||||
return Ok(Square(value as usize));
|
return Ok(Square(value as SquareIdx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(SquareError::OutOfBounds)
|
Err(SquareError::OutOfBounds)
|
||||||
@ -150,13 +152,20 @@ macro_rules! sq_try_from {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sq_try_from!(i8);
|
||||||
sq_try_from!(i32);
|
sq_try_from!(i32);
|
||||||
sq_try_from!(isize);
|
sq_try_from!(isize);
|
||||||
sq_try_from!(i8);
|
sq_try_from!(usize);
|
||||||
|
|
||||||
|
impl From<Square> for SquareIdx {
|
||||||
|
fn from(value: Square) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Square> for usize {
|
impl From<Square> for usize {
|
||||||
fn from(value: Square) -> Self {
|
fn from(value: Square) -> Self {
|
||||||
value.0
|
value.0.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,10 +190,10 @@ impl Square {
|
|||||||
}
|
}
|
||||||
fn to_row_col(self) -> (usize, usize) {
|
fn to_row_col(self) -> (usize, usize) {
|
||||||
//! Get row, column from index
|
//! Get row, column from index
|
||||||
let div = self.0 / BOARD_WIDTH;
|
let div = usize::from(self.0) / BOARD_WIDTH;
|
||||||
let rem = self.0 % BOARD_WIDTH;
|
let rem = usize::from(self.0) % BOARD_WIDTH;
|
||||||
assert!(div <= 7);
|
debug_assert!(div <= 7);
|
||||||
assert!(rem <= 7);
|
debug_assert!(rem <= 7);
|
||||||
(div, rem)
|
(div, rem)
|
||||||
}
|
}
|
||||||
fn to_row_col_signed(self) -> (isize, isize) {
|
fn to_row_col_signed(self) -> (isize, isize) {
|
||||||
@ -313,7 +322,7 @@ impl Iterator for BitboardIterator {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let next_idx = self.remaining.0.trailing_zeros() as usize;
|
let next_idx = self.remaining.0.trailing_zeros() as usize;
|
||||||
let sq = Square(next_idx);
|
let sq = Square(next_idx.try_into().unwrap());
|
||||||
self.remaining.off_sq(sq);
|
self.remaining.off_sq(sq);
|
||||||
Some(sq)
|
Some(sq)
|
||||||
}
|
}
|
||||||
@ -620,10 +629,10 @@ mod tests {
|
|||||||
try_type!(i32);
|
try_type!(i32);
|
||||||
try_type!(i8);
|
try_type!(i8);
|
||||||
try_type!(isize);
|
try_type!(isize);
|
||||||
try_type!(usize);
|
try_type!(u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
let good_cases = 0..N_SQUARES;
|
let good_cases = 0..SquareIdx::try_from(N_SQUARES).unwrap();
|
||||||
for tc in good_cases {
|
for tc in good_cases {
|
||||||
macro_rules! try_type {
|
macro_rules! try_type {
|
||||||
($T: ty) => {
|
($T: ty) => {
|
||||||
@ -635,7 +644,7 @@ mod tests {
|
|||||||
try_type!(i32);
|
try_type!(i32);
|
||||||
try_type!(i8);
|
try_type!(i8);
|
||||||
try_type!(isize);
|
try_type!(isize);
|
||||||
try_type!(usize);
|
try_type!(u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,10 +662,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bitboard_iteration() {
|
fn test_bitboard_iteration() {
|
||||||
let indices = [
|
let indices = [0, 5, 17, 24, 34, 39, 42, 45, 49, 50, 63];
|
||||||
0usize, 5usize, 17usize, 24usize, 34usize, 39usize, 42usize, 45usize, 49usize, 50usize,
|
|
||||||
63usize,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut bitboard = Bitboard::default();
|
let mut bitboard = Bitboard::default();
|
||||||
|
|
||||||
|
@ -228,8 +228,8 @@ impl Move {
|
|||||||
);
|
);
|
||||||
// square to actually capture at
|
// square to actually capture at
|
||||||
let ep_capture = Square::try_from(match pc_src.col {
|
let ep_capture = Square::try_from(match pc_src.col {
|
||||||
Color::White => self.dest.0 - BOARD_WIDTH,
|
Color::White => usize::from(self.dest.0) - BOARD_WIDTH,
|
||||||
Color::Black => self.dest.0 + BOARD_WIDTH,
|
Color::Black => usize::from(self.dest.0) + BOARD_WIDTH,
|
||||||
})
|
})
|
||||||
.expect("En-passant capture square should be valid");
|
.expect("En-passant capture square should be valid");
|
||||||
|
|
||||||
@ -302,14 +302,16 @@ impl Move {
|
|||||||
Color::White => {
|
Color::White => {
|
||||||
if self.src == Square(0) {
|
if self.src == Square(0) {
|
||||||
castle.q = false;
|
castle.q = false;
|
||||||
} else if self.src == Square(BOARD_WIDTH - 1) {
|
} else if self.src == Square::try_from(BOARD_WIDTH - 1).unwrap() {
|
||||||
castle.k = false;
|
castle.k = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Color::Black => {
|
Color::Black => {
|
||||||
if self.src == Square((BOARD_HEIGHT - 1) * BOARD_WIDTH) {
|
if self.src
|
||||||
|
== Square::try_from((BOARD_HEIGHT - 1) * BOARD_WIDTH).unwrap()
|
||||||
|
{
|
||||||
castle.q = false;
|
castle.q = false;
|
||||||
} else if self.src == Square(N_SQUARES - 1) {
|
} else if self.src == Square::try_from(N_SQUARES - 1).unwrap() {
|
||||||
castle.k = false;
|
castle.k = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -722,7 +724,7 @@ pub fn perft(depth: usize, pos: &mut Board) -> usize {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::fen::{ToFen, START_POSITION, FromFen};
|
use crate::fen::{FromFen, ToFen, START_POSITION};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
/// Ensure that bitboard properly reflects captures.
|
/// Ensure that bitboard properly reflects captures.
|
||||||
|
Loading…
Reference in New Issue
Block a user