diff --git a/src/lib.rs b/src/lib.rs index 4f55879..9cefaed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,7 +28,7 @@ //! //! // read a position from a text record //! let setup = Setup::from_text_record("7k/4P1rp/5Q2/5p2/1Pp1bP2/8/r4K1P/6R1 w - -")?; -//! let position = setup.validate()?; +//! let position = setup.try_into()?; //! //! // read a move in algebraic notation //! let san = "Ke1".parse::()?; diff --git a/src/position.rs b/src/position.rs index ec14742..523784a 100644 --- a/src/position.rs +++ b/src/position.rs @@ -90,14 +90,14 @@ impl Position { /// ``` /// # use eschac::setup::Setup; /// # |s: &str| -> Option { - /// Setup::from_text_record(s).ok().and_then(|pos| pos.validate().ok()) + /// Setup::from_text_record(s).ok().and_then(|setup| setup.try_into().ok()) /// # }; /// ``` #[inline] pub fn from_text_record(s: &str) -> Option { Setup::from_text_record(s) .ok() - .and_then(|pos| pos.validate().ok()) + .and_then(|setup| setup.try_into().ok()) } /// Returns the text record of the position. diff --git a/src/setup.rs b/src/setup.rs index 8be10f9..f2fc478 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -339,10 +339,44 @@ impl Setup { } } + /// Returns the bitboard of each kind of piece. + #[inline] + pub fn pieces(&self) -> ByColor> { + let Self { + w, + p_b_q, + n_b_k, + r_q_k, + .. + } = self.clone(); + let k = n_b_k & r_q_k; + let q = p_b_q & r_q_k; + let b = p_b_q & n_b_k; + let n = n_b_k ^ b ^ k; + let r = r_q_k ^ q ^ k; + let p = p_b_q ^ b ^ q; + ByColor::new(|color| { + let mask = match color { + Color::White => w, + Color::Black => !w, + }; + ByRole::new(|kind| { + mask & match kind { + Role::Pawn => p, + Role::Knight => n, + Role::Bishop => b, + Role::Rook => r, + Role::Queen => q, + Role::King => k, + } + }) + }) + } + /// Tries to validate the position, i.e. converting it to a [`Position`]. /// /// See [`IllegalPositionReason`] for details. - pub fn validate(self) -> Result { + pub fn into_position(self) -> Result { debug_assert!((self.w & !(self.p_b_q | self.n_b_k | self.r_q_k)).is_empty()); debug_assert!((self.p_b_q & self.n_b_k & self.r_q_k).is_empty()); @@ -467,40 +501,6 @@ impl Setup { } } - /// Returns the bitboard of each kind of piece. - #[inline] - pub fn pieces(&self) -> ByColor> { - let Self { - w, - p_b_q, - n_b_k, - r_q_k, - .. - } = self.clone(); - let k = n_b_k & r_q_k; - let q = p_b_q & r_q_k; - let b = p_b_q & n_b_k; - let n = n_b_k ^ b ^ k; - let r = r_q_k ^ q ^ k; - let p = p_b_q ^ b ^ q; - ByColor::new(|color| { - let mask = match color { - Color::White => w, - Color::Black => !w, - }; - ByRole::new(|kind| { - mask & match kind { - Role::Pawn => p, - Role::Knight => n, - Role::Bishop => b, - Role::Rook => r, - Role::Queen => q, - Role::King => k, - } - }) - }) - } - #[inline] pub(crate) fn get_role(&self, square: Square) -> Option { let mask = square.bitboard(); @@ -514,6 +514,13 @@ impl Setup { } } +impl TryFrom for Position { + type Error = IllegalPosition; + fn try_from(setup: Setup) -> Result { + setup.into_position() + } +} + impl std::fmt::Debug for Setup { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { f.debug_tuple("Setup") diff --git a/tests/tests.rs b/tests/tests.rs index 56b26fe..a62e13b 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -44,7 +44,7 @@ fn recursive_check_aux(position: Position, depth: usize) { .en_passant_target_square() .map(|square| square.mirror()), ); - setup.validate().unwrap() + setup.into_position().unwrap() }; let expected_mirror = position.mirror(); assert_eq!(computed_mirror, expected_mirror); @@ -192,7 +192,7 @@ fn setup() { assert!( Setup::from_text_record(record) .unwrap() - .validate() + .into_position() .is_err_and(|e| e.reasons().contains(reason)), "{record} should be invalid because of {reason:?}", );