diff --git a/src/lib.rs b/src/lib.rs index 9fa13bd..1a90d16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ #![deny(rust_2018_idioms)] -use std::str::FromStr; use std::fmt::Display; +use std::str::FromStr; pub mod fen; pub mod movegen; @@ -157,15 +157,25 @@ impl From for usize { value.0 } } + +macro_rules! from_row_col_generic { + ($T: ty, $r: ident, $c: ident) => { + if !(0..(BOARD_HEIGHT as $T)).contains(&$r) || !(0..(BOARD_WIDTH as $T)).contains(&$c) { + Err(SquareError::OutOfBounds) + } else { + let ret = (BOARD_WIDTH as $T) * $r + $c; + ret.try_into() + } + }; +} + impl Square { fn from_row_col(r: usize, c: usize) -> Result { //! Get index of square based on row and column. - let ret = BOARD_WIDTH * r + c; - ret.try_into() + from_row_col_generic!(usize, r, c) } fn from_row_col_signed(r: isize, c: isize) -> Result { - let ret = (BOARD_WIDTH as isize) * r + c; - ret.try_into() + from_row_col_generic!(isize, r, c) } fn to_row_col(self) -> (usize, usize) { //! Get row, column from index @@ -469,7 +479,10 @@ mod tests { macro_rules! try_type { ($T: ty) => { if let Ok(conv) = <$T>::try_from(tc) { - assert!(matches!(Square::try_from(conv), Err(SquareError::OutOfBounds))) + assert!(matches!( + Square::try_from(conv), + Err(SquareError::OutOfBounds) + )) } }; } diff --git a/src/movegen.rs b/src/movegen.rs index 1b266e5..2bd134b 100644 --- a/src/movegen.rs +++ b/src/movegen.rs @@ -44,7 +44,7 @@ impl From for Piece { } } -#[derive(PartialEq, Eq, PartialOrd, Ord)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] enum MoveType { /// Pawn promotes to another piece. Promotion(PromotePiece), @@ -54,7 +54,7 @@ enum MoveType { /// Pseudo-legal move. /// /// No checking is done when constructing this. -#[derive(PartialEq, Eq, PartialOrd, Ord)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] pub struct Move { src: Square, dest: Square, @@ -397,20 +397,33 @@ mod tests { /// Test that slider pieces can move and capture. #[test] fn test_slider_movegen() { - let test_cases = [( - // start position - "8/8/8/8/8/8/8/R7 w - - 0 1", - // expected moves - vec![( - // source piece - "a1", - // destination squares - vec![ - "a2", "a3", "a4", "a5", "a6", "a7", "a8", "b1", "c1", "d1", "e1", "f1", "g1", - "h1", - ], - )], - )]; + let test_cases = [ + ( + // start position + "8/8/8/8/8/8/8/R7 w - - 0 1", + // expected moves + vec![( + // source piece + "a1", + // destination squares + vec![ + "a2", "a3", "a4", "a5", "a6", "a7", "a8", "b1", "c1", "d1", "e1", "f1", + "g1", "h1", + ], + MoveType::Normal, + )], + ), + ( + "8/1p6/8/1R2p3/1p6/8/8/8 w - - 0 1", + vec![( + "b5", + vec![ + "b6", "b7", "b4", "a5", "c5", "d5", "e5", + ], + MoveType::Normal, + )], + ), + ]; for (fen, expected) in test_cases { let board = BoardState::from_fen(fen).unwrap(); @@ -419,7 +432,27 @@ mod tests { moves.sort_unstable(); let moves = moves; - let expected_moves = expected.iter().map(|(src, dests)| {}); + let mut expected_moves = expected + .iter() + .map(|(src, dests, move_type)| { + let src = src.parse::().unwrap(); + let dests = dests + .iter() + .map(|x| x.parse::()) + .map(|x| x.unwrap()); + dests.map(move |dest| Move { + src, + dest, + move_type: *move_type, + }) + }) + .flatten() + .collect::>(); + + expected_moves.sort_unstable(); + let expected_moves = expected_moves; + + assert_eq!(moves, expected_moves); } }