update docs
This commit is contained in:
parent
671ff331d3
commit
b45952b6b7
5 changed files with 47 additions and 43 deletions
18
src/board.rs
18
src/board.rs
|
|
@ -123,6 +123,9 @@ impl File {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## Safety
|
||||
///
|
||||
/// The caller must ensure that `index < 8`.
|
||||
#[inline]
|
||||
pub const unsafe fn new_unchecked(index: u8) -> Self {
|
||||
debug_assert!(index < 8);
|
||||
|
|
@ -135,9 +138,9 @@ impl File {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn from_ascii(c: u8) -> Option<Self> {
|
||||
if c <= b'h' {
|
||||
match c.checked_sub(b'a') {
|
||||
pub const fn from_ascii(file: u8) -> Option<Self> {
|
||||
if file <= b'h' {
|
||||
match file.checked_sub(b'a') {
|
||||
Some(i) => Some(unsafe { Self::new_unchecked(i) }),
|
||||
None => None,
|
||||
}
|
||||
|
|
@ -213,6 +216,9 @@ impl Rank {
|
|||
}
|
||||
}
|
||||
|
||||
/// ## Safety
|
||||
///
|
||||
/// The caller must ensure that `index < 8`.
|
||||
#[inline]
|
||||
pub const unsafe fn new_unchecked(index: u8) -> Self {
|
||||
debug_assert!(index < 8);
|
||||
|
|
@ -225,9 +231,9 @@ impl Rank {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn from_ascii(c: u8) -> Option<Self> {
|
||||
if c <= b'8' {
|
||||
match c.checked_sub(b'1') {
|
||||
pub const fn from_ascii(rank: u8) -> Option<Self> {
|
||||
if rank <= b'8' {
|
||||
match rank.checked_sub(b'1') {
|
||||
Some(i) => Some(unsafe { Self::new_unchecked(i) }),
|
||||
None => None,
|
||||
}
|
||||
|
|
|
|||
25
src/lib.rs
25
src/lib.rs
|
|
@ -5,19 +5,18 @@
|
|||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The most important type in eschac is [`Position`](position::Position), it represents a chess
|
||||
//! position from which legal moves are generated. [`Position::new`](position::Position::new)
|
||||
//! returns the starting position of a chess game, and arbitrary positions can be built using the
|
||||
//! [`Setup`](setup::Setup) type, but they must be validated and converted to a
|
||||
//! [`Position`](position::Position) to generate moves as eschac does not handle certain illegal --
|
||||
//! as in unreachable in a normal game -- positions (see
|
||||
//! [`IllegalPositionReason`](setup::IllegalPositionReason) to know more). Legal moves are then
|
||||
//! generated using the [`Position::legal_moves`](position::Position::legal_moves) method or
|
||||
//! obtained from chess notation like [`UciMove`](uci::UciMove) or [`San`](san::San). Moves are
|
||||
//! represented with the [`Move<'l>`](moves::Move) type, which holds a reference to the origin
|
||||
//! position (hence the lifetime), this ensures the move is played on the correct position.
|
||||
//! Finally, moves are played using the [`Move::make`](moves::Move::make) method which returns a new
|
||||
//! [`Position`](position::Position), and on it goes.
|
||||
//! In eschac, a chess position is represented with the [`Position`](position::Position) type.
|
||||
//! [`Position::new`](position::Position::new) returns the starting position of a chess game, and
|
||||
//! arbitrary positions can be built using the [`Setup`](setup::Setup) type. This type must be
|
||||
//! validated and converted to a [`Position`](position::Position) to generate moves as eschac does
|
||||
//! not handle certain unreachable positions (see
|
||||
//! [`Setup::into_position`](setup::Setup::into_position) to know more). Legal moves are generated
|
||||
//! using the [`Position::legal_moves`](position::Position::legal_moves) method or obtained from
|
||||
//! chess notation like [`UciMove`](uci::UciMove) or [`San`](san::San). Moves are represented with
|
||||
//! the [`Move<'l>`](moves::Move) type, which holds a reference to the origin position (this
|
||||
//! ensures the move is played on the correct position). Finally, moves are played with
|
||||
//! [`Move::make`](moves::Move::make) which returns a new [`Position`](position::Position), and on
|
||||
//! it goes.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
|
|
|
|||
|
|
@ -205,6 +205,8 @@ impl<'l> Move<'l> {
|
|||
/// [composition](https://lichess.org/editor/R6R/3Q4/1Q4Q1/4Q3/2Q4Q/Q4Q2/pp1Q4/kBNN1KB1_w_-_-_0_1)
|
||||
/// with 218 legal moves. 60 years later, this was proven to be optimal by
|
||||
/// [Tobs40](https://lichess.org/@/Tobs40/blog/why-a-reachable-position-can-have-at-most-218-playable-moves/a5xdxeqs).
|
||||
/// Even though the [`Position`] type can represent more positions than just reachable positions,
|
||||
/// the proof still holds, as its definition of a position is even less restrictive.
|
||||
#[must_use]
|
||||
pub struct Moves<'l> {
|
||||
position: &'l Position,
|
||||
|
|
|
|||
|
|
@ -31,16 +31,16 @@ use core::ops::ControlFlow;
|
|||
/// be applied unambiguously or when doing so enables some code optimisation. See
|
||||
/// [`IllegalPositionReason`] for details about rejected positions.
|
||||
///
|
||||
/// ## Move generation & play
|
||||
/// ## Move generation & Play
|
||||
///
|
||||
/// The [`legal_moves`](Position::legal_moves) method generates the list of all legal moves on the
|
||||
/// position. [`UciMove::to_move`] and [`San::to_move`] can also be used to convert chess notation
|
||||
/// to playable moves.
|
||||
///
|
||||
/// Playing a move is done through a copy-make interface. [`legal_moves`](Position::legal_moves)
|
||||
/// returns a sequence of [`Move`] objects. Moves hold a reference to the position from where they
|
||||
/// were computed. They can be played without further checks and without potential panics using
|
||||
/// [`Move::make`].
|
||||
/// returns a sequence of [`Move<'l>`](Move) objects. Moves hold a reference to the position
|
||||
/// from where they were computed. They can be played without further checks and without potential
|
||||
/// panics using [`Move::make`].
|
||||
///
|
||||
/// ## En passant & Equality
|
||||
///
|
||||
|
|
@ -197,10 +197,9 @@ impl Position {
|
|||
|
||||
/// Discards the en passant target square.
|
||||
///
|
||||
/// This function is useful to check for position equality, notably when implementing FIDE's
|
||||
/// draw by repetition rules. Note that this function will remove the en passant target square
|
||||
/// even if taking en passant is legal. If this is not desirable, it is the caller's
|
||||
/// responsibility to rule out the legality of en passant before calling this function.
|
||||
/// This function will remove the en passant target square even if taking en passant is legal.
|
||||
/// If this is not desirable, it is the caller's responsibility to rule out the legality of en
|
||||
/// passant before calling this function.
|
||||
#[inline]
|
||||
pub fn remove_en_passant_target_square(&mut self) {
|
||||
self.0.en_passant = OptionSquare::None;
|
||||
|
|
|
|||
30
src/setup.rs
30
src/setup.rs
|
|
@ -12,8 +12,8 @@ use alloc::string::String;
|
|||
/// **A builder type for chess positions.**
|
||||
///
|
||||
/// 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::into_position`] method
|
||||
/// before generating moves.
|
||||
/// It must be validated and converted to a [`Position`] using [`Setup::into_position`] before
|
||||
/// generating moves.
|
||||
///
|
||||
/// ## Text description
|
||||
///
|
||||
|
|
@ -21,8 +21,12 @@ use alloc::string::String;
|
|||
/// uses a slightly different notation, which simply removes the last two fields of the FEN record
|
||||
/// (i.e. the halfmove clock and the fullmove number) as the [`Position`] type does not keep
|
||||
/// track of those. For example, the starting position is recorded as
|
||||
/// `rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -`. [`Setup::from_text_record`] and
|
||||
/// [`Setup::to_text_record`] can be used to read and write these records.
|
||||
/// `rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -`.
|
||||
///
|
||||
/// [`Display`](core::fmt::Display) and [`FromStr`](alloc::str::FromStr) are purposely not
|
||||
/// implemented on [`Setup`] as there does not exist a truely canonical format for writing chess
|
||||
/// positions. The format described above is implemented in
|
||||
/// [`from_text_record`](Setup::from_text_record) and [`to_text_record`](Setup::to_text_record).
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Setup {
|
||||
pub(crate) w: Bitboard,
|
||||
|
|
@ -51,21 +55,14 @@ impl Setup {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reads a position from a text record.
|
||||
///
|
||||
/// This is a shortcut for:
|
||||
/// ```
|
||||
/// # use eschac::setup::Setup;
|
||||
/// # |record: &str| {
|
||||
/// Setup::from_ascii_record(record.as_bytes())
|
||||
/// # };
|
||||
/// ```
|
||||
/// Reads a position from a text record
|
||||
/// (see [`from_ascii_record`](Setup::from_ascii_record)).
|
||||
#[inline]
|
||||
pub fn from_text_record(record: &str) -> Result<Self, ParseRecordError> {
|
||||
Self::from_ascii_record(record.as_bytes())
|
||||
}
|
||||
|
||||
/// Reads a position from an ascii record.
|
||||
/// Reads a position from a text record.
|
||||
pub fn from_ascii_record(record: &[u8]) -> Result<Self, ParseRecordError> {
|
||||
let mut s = record.iter().copied().peekable();
|
||||
let mut setup = Setup::new();
|
||||
|
|
@ -146,7 +143,8 @@ impl Setup {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns the text record of the position.
|
||||
/// Returns the text record of the position
|
||||
/// (see [`write_text_record`](Setup::write_text_record)).
|
||||
pub fn to_text_record(&self) -> String {
|
||||
let mut record = String::with_capacity(81);
|
||||
self.write_text_record(&mut record).unwrap();
|
||||
|
|
@ -614,7 +612,7 @@ impl Iterator for IllegalPositionReasons {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reasons for illegal positions to be rejected by eschac.
|
||||
/// Reasons for an illegal position to be rejected by eschac.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum IllegalPositionReason {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue