Setup::validate -> Setup::into_position
This commit is contained in:
parent
0d22c59cc3
commit
6f409799db
5 changed files with 19 additions and 18 deletions
|
|
@ -14,7 +14,7 @@ use eschac::prelude::*;
|
||||||
|
|
||||||
// read a position from a text record
|
// read a position from a text record
|
||||||
let setup = "7k/4P1rp/5Q2/5p2/1Pp1bP2/8/r4K1P/6R1 w - -".parse::<Setup>()?;
|
let setup = "7k/4P1rp/5Q2/5p2/1Pp1bP2/8/r4K1P/6R1 w - -".parse::<Setup>()?;
|
||||||
let position = setup.validate()?;
|
let position = setup.into_position()?;
|
||||||
|
|
||||||
// read a move in algebraic notation
|
// read a move in algebraic notation
|
||||||
let san = "Ke1".parse::<San>()?;
|
let san = "Ke1".parse::<San>()?;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
//!
|
//!
|
||||||
//! // read a position from a text record
|
//! // read a position from a text record
|
||||||
//! let setup = "7k/4P1rp/5Q2/5p2/1Pp1bP2/8/r4K1P/6R1 w - -".parse::<Setup>()?;
|
//! let setup = "7k/4P1rp/5Q2/5p2/1Pp1bP2/8/r4K1P/6R1 w - -".parse::<Setup>()?;
|
||||||
//! let position = setup.validate()?;
|
//! let position = setup.into_position()?;
|
||||||
//!
|
//!
|
||||||
//! // read a move in algebraic notation
|
//! // read a move in algebraic notation
|
||||||
//! let san = "Ke1".parse::<San>()?;
|
//! let san = "Ke1".parse::<San>()?;
|
||||||
|
|
|
||||||
|
|
@ -82,12 +82,14 @@ impl Position {
|
||||||
/// ```
|
/// ```
|
||||||
/// # use eschac::setup::Setup;
|
/// # use eschac::setup::Setup;
|
||||||
/// # |s: &str| -> Option<eschac::position::Position> {
|
/// # |s: &str| -> Option<eschac::position::Position> {
|
||||||
/// s.parse::<Setup>().ok().and_then(|pos| pos.validate().ok())
|
/// s.parse::<Setup>().ok().and_then(|pos| pos.into_position().ok())
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_text_record(s: &str) -> Option<Self> {
|
pub fn from_text_record(s: &str) -> Option<Self> {
|
||||||
s.parse::<Setup>().ok().and_then(|pos| pos.validate().ok())
|
s.parse::<Setup>()
|
||||||
|
.ok()
|
||||||
|
.and_then(|pos| pos.into_position().ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all the legal moves on the position.
|
/// Returns all the legal moves on the position.
|
||||||
|
|
@ -196,8 +198,7 @@ impl Position {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a position to a [`Setup`], allowing to edit the position without enforcing its
|
/// Converts the position into the [`Setup`] type, allowing to edit it without enforcing its legality.
|
||||||
/// legality.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_setup(self) -> Setup {
|
pub fn into_setup(self) -> Setup {
|
||||||
self.0
|
self.0
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::position::*;
|
||||||
/// **A builder type for chess positions.**
|
/// **A builder type for chess positions.**
|
||||||
///
|
///
|
||||||
/// This type is useful to edit a position without having to ensure it stays legal at every step.
|
/// This type is useful to edit a position without having to ensure it stays legal at every step.
|
||||||
/// It must be validated and converted to a [`Position`] using the [`Setup::validate`] method
|
/// It must be validated and converted to a [`Position`] using the [`Setup::into_position`] method
|
||||||
/// before generating moves.
|
/// before generating moves.
|
||||||
///
|
///
|
||||||
/// This type implements [`FromStr`](std::str::FromStr) and [`Display`](std::fmt::Display) to parse
|
/// This type implements [`FromStr`](std::str::FromStr) and [`Display`](std::fmt::Display) to parse
|
||||||
|
|
@ -245,10 +245,10 @@ impl Setup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to validate the position, i.e. converting it to a [`Position`].
|
/// Tries to convert the position into the [`Position`] type.
|
||||||
///
|
///
|
||||||
/// See [`IllegalPositionReason`] for details.
|
/// Some unreachable positions are rejected, 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.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());
|
debug_assert!((self.p_b_q & self.n_b_k & self.r_q_k).is_empty());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ fn recursive_check_aux(position: Position, depth: usize) {
|
||||||
.to_string()
|
.to_string()
|
||||||
.parse::<Setup>()
|
.parse::<Setup>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.validate()
|
.into_position()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ fn recursive_check_aux(position: Position, depth: usize) {
|
||||||
.en_passant_target_square()
|
.en_passant_target_square()
|
||||||
.map(|square| square.mirror()),
|
.map(|square| square.mirror()),
|
||||||
);
|
);
|
||||||
setup.validate().unwrap()
|
setup.into_position().unwrap()
|
||||||
};
|
};
|
||||||
let expected_mirror = position.mirror();
|
let expected_mirror = position.mirror();
|
||||||
assert_eq!(computed_mirror, expected_mirror);
|
assert_eq!(computed_mirror, expected_mirror);
|
||||||
|
|
@ -75,7 +75,7 @@ fn recursive_check_aux(position: Position, depth: usize) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn recursive_check(record: &str) {
|
fn recursive_check(record: &str) {
|
||||||
recursive_check_aux(record.parse::<Setup>().unwrap().validate().unwrap(), 4);
|
recursive_check_aux(record.parse::<Setup>().unwrap().into_position().unwrap(), 4);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn recursive_check_1() {
|
fn recursive_check_1() {
|
||||||
|
|
@ -199,7 +199,7 @@ fn setup() {
|
||||||
record
|
record
|
||||||
.parse::<Setup>()
|
.parse::<Setup>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.validate()
|
.into_position()
|
||||||
.is_err_and(|e| e.reasons().contains(reason)),
|
.is_err_and(|e| e.reasons().contains(reason)),
|
||||||
"{record} should be invalid because of {reason:?}",
|
"{record} should be invalid because of {reason:?}",
|
||||||
);
|
);
|
||||||
|
|
@ -222,18 +222,18 @@ fn mirror() {
|
||||||
let position = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b Kq e3"
|
let position = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b Kq e3"
|
||||||
.parse::<Setup>()
|
.parse::<Setup>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.validate()
|
.into_position()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mirror = "rnbqkbnr/pppp1ppp/8/4p3/8/8/PPPPPPPP/RNBQKBNR w Qk e6"
|
let mirror = "rnbqkbnr/pppp1ppp/8/4p3/8/8/PPPPPPPP/RNBQKBNR w Qk e6"
|
||||||
.parse::<Setup>()
|
.parse::<Setup>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.validate()
|
.into_position()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(mirror, position.mirror());
|
assert_eq!(mirror, position.mirror());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perft_aux(record: &str, tests: &[u128]) {
|
fn perft_aux(record: &str, tests: &[u128]) {
|
||||||
let position = record.parse::<Setup>().unwrap().validate().unwrap();
|
let position = record.parse::<Setup>().unwrap().into_position().unwrap();
|
||||||
for (depth, value) in tests.iter().copied().enumerate() {
|
for (depth, value) in tests.iter().copied().enumerate() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
position.perft(depth),
|
position.perft(depth),
|
||||||
|
|
@ -275,7 +275,7 @@ fn san() {
|
||||||
let position = "8/2KN1p2/5p2/3N1B1k/5PNp/7P/7P/8 w - -"
|
let position = "8/2KN1p2/5p2/3N1B1k/5PNp/7P/7P/8 w - -"
|
||||||
.parse::<Setup>()
|
.parse::<Setup>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.validate()
|
.into_position()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let san1 = "N7xf6#".parse::<San>().unwrap();
|
let san1 = "N7xf6#".parse::<San>().unwrap();
|
||||||
let m1 = san1.to_move(&position).unwrap();
|
let m1 = san1.to_move(&position).unwrap();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue