1
0
Fork 0
This commit is contained in:
Paul-Nicolas Madelaine 2025-11-03 17:36:30 +01:00
parent e8a4a5dffb
commit 5764bc0fce

View file

@ -79,17 +79,17 @@ impl Position {
/// Returns all the legal moves on the position.
#[inline]
pub fn legal_moves<'l>(&'l self) -> Moves<'l> {
fn aux(position: &Position, visitor: &mut Moves) {
position.generate_moves(visitor);
fn aux(position: &Position, moves: &mut Moves) {
position.generate_moves(moves);
}
let mut visitor = Moves {
let mut moves = Moves {
position: self,
is_check: false,
en_passant_is_legal: false,
array: ArrayVec::new(),
};
aux(self, &mut visitor);
visitor
aux(self, &mut moves);
moves
}
/// Counts the legal moves on the position.
@ -103,33 +103,33 @@ impl Position {
/// ```
#[inline]
pub fn count_legal_moves(&self) -> usize {
struct VisitorImpl {
struct MoveGenImpl {
len: usize,
}
impl VisitorImpl {
impl MoveGenImpl {
fn new() -> Self {
Self { len: 0 }
}
}
impl Visitor for VisitorImpl {
impl MoveGen for MoveGenImpl {
#[inline]
fn is_check(&mut self) {}
#[inline]
fn en_passant_is_legal(&mut self) {}
#[inline]
fn moves<I>(&mut self, iter: I)
fn extend<I>(&mut self, iter: I)
where
I: Iterator<Item = RawMove> + ExactSizeIterator,
{
self.len += iter.len();
}
}
fn aux(position: &Position, visitor: &mut VisitorImpl) {
position.generate_moves(visitor);
fn aux(position: &Position, moves: &mut MoveGenImpl) {
position.generate_moves(moves);
}
let mut visitor = VisitorImpl::new();
aux(self, &mut visitor);
visitor.len
let mut moves = MoveGenImpl::new();
aux(self, &mut moves);
moves.len
}
/// Discards the optional en passant target square.
@ -221,13 +221,13 @@ impl Position {
}
pub(crate) fn move_from_uci<'l>(&'l self, uci: UciMove) -> Result<Move<'l>, InvalidUciMove> {
struct VisitorImpl<const ROLE: u8> {
struct MoveGenImpl<const ROLE: u8> {
role: Role,
from: Bitboard,
to: Bitboard,
found: Option<RawMove>,
}
impl<const ROLE: u8> VisitorImpl<ROLE> {
impl<const ROLE: u8> MoveGenImpl<ROLE> {
#[inline]
fn new(role: Role, from: Bitboard, to: Bitboard) -> Self {
Self {
@ -238,7 +238,7 @@ impl Position {
}
}
}
impl<const ROLE: u8> Visitor for VisitorImpl<ROLE> {
impl<const ROLE: u8> MoveGen for MoveGenImpl<ROLE> {
#[inline]
fn roles(&self, role: Role) -> bool {
role as u8 == ROLE
@ -256,7 +256,7 @@ impl Position {
#[inline]
fn en_passant_is_legal(&mut self) {}
#[inline]
fn moves<I>(&mut self, iter: I)
fn extend<I>(&mut self, iter: I)
where
I: Iterator<Item = RawMove> + ExactSizeIterator,
{
@ -284,9 +284,9 @@ impl Position {
from: Square,
to: Square,
) -> Result<Move<'l>, InvalidUciMove> {
let mut visitor = VisitorImpl::<ROLE>::new(role, from.bitboard(), to.bitboard());
position.generate_moves(&mut visitor);
let raw = visitor.found.ok_or(InvalidUciMove::Illegal)?;
let mut moves = MoveGenImpl::<ROLE>::new(role, from.bitboard(), to.bitboard());
position.generate_moves(&mut moves);
let raw = moves.found.ok_or(InvalidUciMove::Illegal)?;
Ok(Move { position, raw })
}
let promotion = if role == Role::Pawn {
@ -307,14 +307,14 @@ impl Position {
}
pub(crate) fn move_from_san<'l>(&'l self, san: &San) -> Result<Move<'l>, InvalidSan> {
struct VisitorImpl<const ROLE: u8> {
struct MoveGenImpl<const ROLE: u8> {
role: Role,
from: Bitboard,
to: Bitboard,
found: Option<RawMove>,
found_other: bool,
}
impl<const ROLE: u8> VisitorImpl<ROLE> {
impl<const ROLE: u8> MoveGenImpl<ROLE> {
#[inline]
fn new(role: Role, from: Bitboard, to: Bitboard) -> Self {
Self {
@ -326,7 +326,7 @@ impl Position {
}
}
}
impl<const ROLE: u8> Visitor for VisitorImpl<ROLE> {
impl<const ROLE: u8> MoveGen for MoveGenImpl<ROLE> {
#[inline]
fn roles(&self, role: Role) -> bool {
role as u8 == ROLE
@ -344,7 +344,7 @@ impl Position {
#[inline]
fn en_passant_is_legal(&mut self) {}
#[inline]
fn moves<I>(&mut self, iter: I)
fn extend<I>(&mut self, iter: I)
where
I: Iterator<Item = RawMove> + ExactSizeIterator,
{
@ -402,11 +402,11 @@ impl Position {
from: Bitboard,
to: Bitboard,
) -> Result<Move<'l>, InvalidSan> {
let mut visitor = VisitorImpl::<ROLE>::new(role, from, to);
position.generate_moves(&mut visitor);
match visitor.found {
let mut moves = MoveGenImpl::<ROLE>::new(role, from, to);
position.generate_moves(&mut moves);
match moves.found {
None => Err(InvalidSan::Illegal),
Some(raw) => match visitor.found_other {
Some(raw) => match moves.found_other {
true => Err(InvalidSan::Ambiguous),
false => Ok(Move { position, raw }),
},
@ -505,11 +505,11 @@ impl<'l> Move<'l> {
/// Returns the standard algebraic notation of the move.
pub fn to_san(self) -> San {
struct VisitorImpl<const ROLE: u8> {
struct MoveGenImpl<const ROLE: u8> {
to: Bitboard,
candidates: Bitboard,
}
impl<const ROLE: u8> VisitorImpl<ROLE> {
impl<const ROLE: u8> MoveGenImpl<ROLE> {
#[inline]
fn new(to: Square) -> Self {
Self {
@ -518,7 +518,7 @@ impl<'l> Move<'l> {
}
}
}
impl<const ROLE: u8> Visitor for VisitorImpl<ROLE> {
impl<const ROLE: u8> MoveGen for MoveGenImpl<ROLE> {
#[inline]
fn roles(&self, role: Role) -> bool {
role as u8 == ROLE
@ -532,7 +532,7 @@ impl<'l> Move<'l> {
#[inline]
fn en_passant_is_legal(&mut self) {}
#[inline]
fn moves<I>(&mut self, iter: I)
fn extend<I>(&mut self, iter: I)
where
I: Iterator<Item = RawMove> + ExactSizeIterator,
{
@ -569,9 +569,9 @@ impl<'l> Move<'l> {
}
_ => {
fn aux<const ROLE: u8>(m: &Move) -> SanInner {
let mut visitor = VisitorImpl::<ROLE>::new(m.to());
m.position().generate_moves(&mut visitor);
let candidates = visitor.candidates;
let mut moves = MoveGenImpl::<ROLE>::new(m.to());
m.position().generate_moves(&mut moves);
let candidates = moves.candidates;
let (file, rank) = if candidates == m.from().bitboard() {
(None, None)
} else if candidates & m.from().file().bitboard() == m.from().bitboard() {
@ -602,9 +602,9 @@ impl<'l> Move<'l> {
},
suffix: {
let pos = self.make();
let mut visitor = MateVisitorImpl::new();
pos.generate_moves(&mut visitor);
visitor.is_check.then(|| match visitor.is_mate {
let mut moves = MateMoveGenImpl::new();
pos.generate_moves(&mut moves);
moves.is_check.then(|| match moves.is_mate {
true => SanSuffix::Checkmate,
false => SanSuffix::Check,
})
@ -821,7 +821,7 @@ impl RawMove {
}
}
trait Visitor {
trait MoveGen {
#[inline]
fn roles(&self, _role: Role) -> bool {
true
@ -837,12 +837,12 @@ trait Visitor {
fn is_check(&mut self);
fn en_passant_is_legal(&mut self);
fn moves<I>(&mut self, iter: I)
fn extend<I>(&mut self, iter: I)
where
I: Iterator<Item = RawMove> + ExactSizeIterator;
}
impl<'l> Visitor for Moves<'l> {
impl<'l> MoveGen for Moves<'l> {
#[inline]
fn is_check(&mut self) {
self.is_check = true;
@ -852,7 +852,7 @@ impl<'l> Visitor for Moves<'l> {
self.en_passant_is_legal = true;
}
#[inline]
fn moves<I>(&mut self, iter: I)
fn extend<I>(&mut self, iter: I)
where
I: Iterator<Item = RawMove> + ExactSizeIterator,
{
@ -866,12 +866,12 @@ impl Position {
Self(setup)
}
fn generate_moves<T>(&self, visitor: &mut T)
fn generate_moves<T>(&self, moves: &mut T)
where
T: Visitor,
T: MoveGen,
{
let global_mask_from = visitor.from();
let global_mask_to = visitor.to();
let global_mask_from = moves.from();
let global_mask_to = moves.to();
let Setup {
w,
@ -918,7 +918,7 @@ impl Position {
| x & theirs.bishop()
| y & theirs.rook();
if visitor.roles(Role::King) && global_mask_from.contains(king_square) {
if moves.roles(Role::King) && global_mask_from.contains(king_square) {
let attacked = {
let blockers = blockers ^ ours.king();
theirs
@ -936,7 +936,7 @@ impl Position {
.reduce_or()
};
// king moves
visitor.moves(
moves.extend(
(global_mask_to & lookup::king(king_square) & !us & !attacked).map(|to| RawMove {
kind: MoveType::KingMove,
from: king_square,
@ -957,7 +957,7 @@ impl Position {
.trans_unchecked(Direction::East)
};
if global_mask_to.contains(to) {
visitor.moves(std::iter::once(RawMove {
moves.extend(std::iter::once(RawMove {
kind: MoveType::CastleShort,
from,
to,
@ -978,7 +978,7 @@ impl Position {
.trans_unchecked(Direction::West)
};
if global_mask_to.contains(to) {
visitor.moves(std::iter::once(RawMove {
moves.extend(std::iter::once(RawMove {
kind: MoveType::CastleLong,
from,
to,
@ -990,7 +990,7 @@ impl Position {
}
if checkers.len() > 1 {
visitor.is_check();
moves.is_check();
return;
}
@ -1007,7 +1007,7 @@ impl Position {
let target_mask = global_mask_to & block_check;
// pawns
if visitor.roles(Role::Pawn) {
if moves.roles(Role::Pawn) {
let kside = match turn {
Color::White => Direction::NorthEast,
Color::Black => Direction::SouthEast,
@ -1027,13 +1027,13 @@ impl Position {
// pawn advances
{
let targets = adv & target_mask;
visitor.moves((targets & !promotion).map(|to| RawMove {
moves.extend((targets & !promotion).map(|to| RawMove {
kind: MoveType::PawnAdvance,
from: unsafe { to.trans_unchecked(!forward) },
to,
role: Role::Pawn,
}));
visitor.moves(MoveAndPromote::new((targets & promotion).map(|to| {
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
RawMove {
kind: MoveType::PawnAdvancePromotion,
from: unsafe { to.trans_unchecked(!forward) },
@ -1049,13 +1049,13 @@ impl Position {
.trans(kside)
& them
& target_mask;
visitor.moves((targets & !promotion).map(|to| RawMove {
moves.extend((targets & !promotion).map(|to| RawMove {
kind: MoveType::PawnAttack,
from: unsafe { to.trans_unchecked(!kside) },
to,
role: Role::Pawn,
}));
visitor.moves(MoveAndPromote::new((targets & promotion).map(|to| {
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
RawMove {
kind: MoveType::PawnAttackPromotion,
from: unsafe { to.trans_unchecked(!kside) },
@ -1071,13 +1071,13 @@ impl Position {
.trans(qside)
& them
& target_mask;
visitor.moves((targets & !promotion).map(|to| RawMove {
moves.extend((targets & !promotion).map(|to| RawMove {
kind: MoveType::PawnAttack,
from: unsafe { to.trans_unchecked(!qside) },
to,
role: Role::Pawn,
}));
visitor.moves(MoveAndPromote::new((targets & promotion).map(|to| {
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
RawMove {
kind: MoveType::PawnAttackPromotion,
from: unsafe { to.trans_unchecked(!qside) },
@ -1087,7 +1087,7 @@ impl Position {
})));
}
// pawn double advances
visitor.moves(
moves.extend(
((adv & third_rank.bitboard()).trans(forward) & !blockers & target_mask).map(
|to| RawMove {
kind: MoveType::PawnDoubleAdvance,
@ -1120,8 +1120,8 @@ impl Position {
& candidates
& (!pinned | lookup::segment(king_square, to)))
.for_each(|from| {
visitor.en_passant_is_legal();
visitor.moves(std::iter::once(RawMove {
moves.en_passant_is_legal();
moves.extend(std::iter::once(RawMove {
kind: MoveType::EnPassant,
from,
to,
@ -1135,9 +1135,9 @@ impl Position {
// pieces not pinned
{
let aux = |visitor: &mut T, role| {
let aux = |moves: &mut T, role| {
for from in global_mask_from & *ours.get(role) & !pinned {
visitor.moves(
moves.extend(
(lookup::targets(role, from, blockers) & !us & target_mask).map(|to| {
RawMove {
kind: MoveType::PieceMove,
@ -1149,30 +1149,30 @@ impl Position {
)
}
};
if visitor.roles(Role::Knight) {
aux(visitor, Role::Knight)
if moves.roles(Role::Knight) {
aux(moves, Role::Knight)
}
if visitor.roles(Role::Bishop) {
aux(visitor, Role::Bishop)
if moves.roles(Role::Bishop) {
aux(moves, Role::Bishop)
}
if visitor.roles(Role::Rook) {
aux(visitor, Role::Rook)
if moves.roles(Role::Rook) {
aux(moves, Role::Rook)
}
if visitor.roles(Role::Queen) {
aux(visitor, Role::Queen)
if moves.roles(Role::Queen) {
aux(moves, Role::Queen)
}
}
if checker.is_some() {
visitor.is_check();
moves.is_check();
return;
}
// pinned pieces
{
let aux = |visitor: &mut T, role| {
let aux = |moves: &mut T, role| {
for from in global_mask_from & *ours.get(role) & pinned {
visitor.moves(
moves.extend(
(global_mask_to
& !us
& pinned
@ -1187,14 +1187,14 @@ impl Position {
)
}
};
if visitor.roles(Role::Bishop) {
aux(visitor, Role::Bishop);
if moves.roles(Role::Bishop) {
aux(moves, Role::Bishop);
}
if visitor.roles(Role::Rook) {
aux(visitor, Role::Rook);
if moves.roles(Role::Rook) {
aux(moves, Role::Rook);
}
if visitor.roles(Role::Queen) {
aux(visitor, Role::Queen);
if moves.roles(Role::Queen) {
aux(moves, Role::Queen);
}
}
}
@ -1354,11 +1354,11 @@ fn aux_play_castle(setup: &mut Setup, side: CastlingSide) {
setup.castling_rights.unset(setup.turn, CastlingSide::Long);
}
struct MateVisitorImpl {
struct MateMoveGenImpl {
is_check: bool,
is_mate: bool,
}
impl MateVisitorImpl {
impl MateMoveGenImpl {
#[inline]
fn new() -> Self {
Self {
@ -1367,7 +1367,7 @@ impl MateVisitorImpl {
}
}
}
impl Visitor for MateVisitorImpl {
impl MoveGen for MateMoveGenImpl {
#[inline]
fn is_check(&mut self) {
self.is_check = true;
@ -1375,7 +1375,7 @@ impl Visitor for MateVisitorImpl {
#[inline]
fn en_passant_is_legal(&mut self) {}
#[inline]
fn moves<I>(&mut self, iter: I)
fn extend<I>(&mut self, iter: I)
where
I: Iterator<Item = RawMove> + ExactSizeIterator,
{