1
0
Fork 0

add details about the maximum number of moves

This commit is contained in:
Paul-Nicolas Madelaine 2025-11-17 22:07:05 +01:00
parent 7d7884326c
commit 36535f292a
3 changed files with 21 additions and 7 deletions

View file

@ -196,16 +196,21 @@ impl<'l> Move<'l> {
} }
} }
/// A list of legal moves on the same position. /// The list of all the legal moves on a position. It is returned by [`Position::legal_moves`].
/// ///
/// It can be obtained using the [`Position::legal_moves`] method. This type is an iterator over /// This type lies on the stack and has a fixed capacity of 218 moves, as there exists no reachable
/// [`Move`] objects. /// position with more legal moves[^1].
///
/// [^1]: In 1964, Nenad Petrović published a
/// [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).
#[must_use] #[must_use]
pub struct Moves<'l> { pub struct Moves<'l> {
position: &'l Position, position: &'l Position,
is_check: bool, is_check: bool,
en_passant_is_legal: bool, en_passant_is_legal: bool,
array: ArrayVec<RawMove, MAX_LEGAL_MOVES>, array: ArrayVec<RawMove, 218>,
} }
impl<'l> MoveGen<Infallible> for Moves<'l> { impl<'l> MoveGen<Infallible> for Moves<'l> {
@ -350,7 +355,7 @@ impl<'l> IntoIterator for &'l Moves<'l> {
/// An iterator over legal moves. /// An iterator over legal moves.
pub struct MovesIntoIter<'l> { pub struct MovesIntoIter<'l> {
position: &'l Position, position: &'l Position,
iter: ArrayVecIntoIter<RawMove, MAX_LEGAL_MOVES>, iter: ArrayVecIntoIter<RawMove, 218>,
} }
impl<'l> Iterator for MovesIntoIter<'l> { impl<'l> Iterator for MovesIntoIter<'l> {
type Item = Move<'l>; type Item = Move<'l>;

View file

@ -59,8 +59,6 @@ use core::ops::ControlFlow;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Position(Setup); pub struct Position(Setup);
pub(crate) const MAX_LEGAL_MOVES: usize = 218;
const PAWN: u8 = Role::Pawn as u8; const PAWN: u8 = Role::Pawn as u8;
const KNIGHT: u8 = Role::Knight as u8; const KNIGHT: u8 = Role::Knight as u8;
const BISHOP: u8 = Role::Bishop as u8; const BISHOP: u8 = Role::Bishop as u8;

View file

@ -318,3 +318,14 @@ fn san() {
Err(InvalidSan::Ambiguous), Err(InvalidSan::Ambiguous),
); );
} }
#[test]
fn max_legal_moves() {
let position = Setup::from_text_record("R6R/3Q4/1Q4Q1/4Q3/2Q4Q/Q4Q2/pp1Q4/kBNN1KB1 w - -")
.unwrap()
.into_position()
.unwrap();
assert_eq!(position.count_legal_moves(), 218);
assert_eq!(position.legal_moves().len(), 218);
assert_eq!(position.perft(2), 99);
}