1
0
Fork 0
This commit is contained in:
Paul-Nicolas Madelaine 2025-10-22 01:33:53 +02:00
parent 8733993f1a
commit d9e3879937
4 changed files with 47 additions and 40 deletions

View file

@ -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::<San>()?;

View file

@ -90,14 +90,14 @@ impl Position {
/// ```
/// # use eschac::setup::Setup;
/// # |s: &str| -> Option<eschac::position::Position> {
/// 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<Self> {
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.

View file

@ -339,10 +339,44 @@ impl Setup {
}
}
/// Returns the bitboard of each kind of piece.
#[inline]
pub fn pieces(&self) -> ByColor<ByRole<Bitboard>> {
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<Position, IllegalPosition> {
pub fn into_position(self) -> Result<Position, IllegalPosition> {
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<ByRole<Bitboard>> {
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<Role> {
let mask = square.bitboard();
@ -514,6 +514,13 @@ impl Setup {
}
}
impl TryFrom<Setup> for Position {
type Error = IllegalPosition;
fn try_from(setup: Setup) -> Result<Position, IllegalPosition> {
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")

View file

@ -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:?}",
);