diff --git a/src/board.rs b/src/board.rs index 2230f20..c5b1787 100644 --- a/src/board.rs +++ b/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 { - if c <= b'h' { - match c.checked_sub(b'a') { + pub const fn from_ascii(file: u8) -> Option { + 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 { - if c <= b'8' { - match c.checked_sub(b'1') { + pub const fn from_ascii(rank: u8) -> Option { + if rank <= b'8' { + match rank.checked_sub(b'1') { Some(i) => Some(unsafe { Self::new_unchecked(i) }), None => None, } diff --git a/src/lib.rs b/src/lib.rs index 2f39977..76f737a 100644 --- a/src/lib.rs +++ b/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 //! diff --git a/src/moves.rs b/src/moves.rs index 272e078..f7815f4 100644 --- a/src/moves.rs +++ b/src/moves.rs @@ -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, diff --git a/src/position.rs b/src/position.rs index 874fbcb..9e30677 100644 --- a/src/position.rs +++ b/src/position.rs @@ -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; diff --git a/src/setup.rs b/src/setup.rs index f181f00..826ca9c 100644 --- a/src/setup.rs +++ b/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::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 { 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 {