1
0
Fork 0

update docs

This commit is contained in:
Paul-Nicolas Madelaine 2025-11-18 06:49:33 +01:00
parent 671ff331d3
commit b45952b6b7
5 changed files with 47 additions and 43 deletions

View file

@ -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,
}

View file

@ -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
//!

View file

@ -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,

View file

@ -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;

View file

@ -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 {