control flow
This commit is contained in:
parent
34df546eaa
commit
89e77fb977
2 changed files with 101 additions and 124 deletions
31
src/moves.rs
31
src/moves.rs
|
|
@ -7,8 +7,9 @@ use crate::position::*;
|
||||||
use crate::san::*;
|
use crate::san::*;
|
||||||
use crate::uci::*;
|
use crate::uci::*;
|
||||||
|
|
||||||
use std::iter::ExactSizeIterator;
|
use std::convert::Infallible;
|
||||||
use std::iter::FusedIterator;
|
use std::iter::{ExactSizeIterator, FusedIterator};
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
/// A legal move.
|
/// A legal move.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|
@ -101,7 +102,7 @@ impl<'l> Move<'l> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<const ROLE: u8> MoveGen for MoveGenImpl<ROLE> {
|
impl<const ROLE: u8> MoveGen<Infallible> for MoveGenImpl<ROLE> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn roles(&self, role: Role) -> bool {
|
fn roles(&self, role: Role) -> bool {
|
||||||
role as u8 == ROLE
|
role as u8 == ROLE
|
||||||
|
|
@ -111,11 +112,7 @@ impl<'l> Move<'l> {
|
||||||
self.to
|
self.to
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_check(&mut self) {}
|
fn extend<I>(&mut self, iter: I) -> ControlFlow<Infallible>
|
||||||
#[inline]
|
|
||||||
fn en_passant_is_legal(&mut self) {}
|
|
||||||
#[inline]
|
|
||||||
fn extend<I>(&mut self, iter: I)
|
|
||||||
where
|
where
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
|
|
@ -124,6 +121,7 @@ impl<'l> Move<'l> {
|
||||||
debug_assert!(self.to.contains(raw.to()));
|
debug_assert!(self.to.contains(raw.to()));
|
||||||
self.candidates.insert(raw.from);
|
self.candidates.insert(raw.from);
|
||||||
});
|
});
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
San {
|
San {
|
||||||
|
|
@ -153,7 +151,7 @@ impl<'l> Move<'l> {
|
||||||
_ => {
|
_ => {
|
||||||
fn aux<const ROLE: u8>(m: &Move) -> SanInner {
|
fn aux<const ROLE: u8>(m: &Move) -> SanInner {
|
||||||
let mut moves = MoveGenImpl::<ROLE>::new(m.to());
|
let mut moves = MoveGenImpl::<ROLE>::new(m.to());
|
||||||
m.position().generate_moves(&mut moves);
|
let ControlFlow::Continue(()) = m.position().generate_moves(&mut moves);
|
||||||
let candidates = moves.candidates;
|
let candidates = moves.candidates;
|
||||||
let (file, rank) = if candidates == m.from().bitboard() {
|
let (file, rank) = if candidates == m.from().bitboard() {
|
||||||
(None, None)
|
(None, None)
|
||||||
|
|
@ -186,7 +184,7 @@ impl<'l> Move<'l> {
|
||||||
suffix: {
|
suffix: {
|
||||||
let pos = self.make();
|
let pos = self.make();
|
||||||
let mut moves = MateMoveGenImpl::new();
|
let mut moves = MateMoveGenImpl::new();
|
||||||
pos.generate_moves(&mut moves);
|
let ControlFlow::Continue(()) = pos.generate_moves(&mut moves);
|
||||||
let MateMoveGenImpl { is_check, is_mate } = moves;
|
let MateMoveGenImpl { is_check, is_mate } = moves;
|
||||||
match (is_check, is_mate) {
|
match (is_check, is_mate) {
|
||||||
(false, _) => None,
|
(false, _) => None,
|
||||||
|
|
@ -210,21 +208,24 @@ pub struct Moves<'l> {
|
||||||
array: ArrayVec<RawMove, MAX_LEGAL_MOVES>,
|
array: ArrayVec<RawMove, MAX_LEGAL_MOVES>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'l> MoveGen for Moves<'l> {
|
impl<'l> MoveGen<Infallible> for Moves<'l> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_check(&mut self) {
|
fn is_check(&mut self) -> ControlFlow<Infallible> {
|
||||||
self.is_check = true;
|
self.is_check = true;
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn en_passant_is_legal(&mut self) {
|
fn en_passant_is_legal(&mut self) -> ControlFlow<Infallible> {
|
||||||
self.en_passant_is_legal = true;
|
self.en_passant_is_legal = true;
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extend<I>(&mut self, iter: I)
|
fn extend<I>(&mut self, iter: I) -> ControlFlow<Infallible>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
iter.for_each(|raw| unsafe { self.array.push_unchecked(raw) });
|
iter.for_each(|raw| unsafe { self.array.push_unchecked(raw) });
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,7 +233,7 @@ impl<'l> Moves<'l> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn compute(position: &'l Position) -> Moves<'l> {
|
pub(crate) fn compute(position: &'l Position) -> Moves<'l> {
|
||||||
fn aux(position: &Position, moves: &mut Moves) {
|
fn aux(position: &Position, moves: &mut Moves) {
|
||||||
position.generate_moves(moves);
|
let ControlFlow::Continue(()) = position.generate_moves(moves);
|
||||||
}
|
}
|
||||||
let mut moves = Moves {
|
let mut moves = Moves {
|
||||||
position,
|
position,
|
||||||
|
|
|
||||||
194
src/position.rs
194
src/position.rs
|
|
@ -8,8 +8,9 @@ use crate::san::*;
|
||||||
use crate::setup::*;
|
use crate::setup::*;
|
||||||
use crate::uci::*;
|
use crate::uci::*;
|
||||||
|
|
||||||
use std::iter::ExactSizeIterator;
|
use std::convert::Infallible;
|
||||||
use std::iter::FusedIterator;
|
use std::iter::{ExactSizeIterator, FusedIterator};
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
/// **A chess position.**
|
/// **A chess position.**
|
||||||
///
|
///
|
||||||
|
|
@ -115,31 +116,25 @@ impl Position {
|
||||||
Self { len: 0 }
|
Self { len: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl MoveGen for MoveGenImpl {
|
impl MoveGen<Infallible> for MoveGenImpl {
|
||||||
#[inline]
|
fn extend<I>(&mut self, iter: I) -> ControlFlow<Infallible>
|
||||||
fn is_check(&mut self) {}
|
|
||||||
#[inline]
|
|
||||||
fn en_passant_is_legal(&mut self) {}
|
|
||||||
#[inline]
|
|
||||||
fn extend<I>(&mut self, iter: I)
|
|
||||||
where
|
where
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
self.len += iter.len();
|
self.len += iter.len();
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut moves = MoveGenImpl::new();
|
let mut moves = MoveGenImpl::new();
|
||||||
self.generate_moves(&mut moves);
|
let ControlFlow::Continue(()) = self.generate_moves(&mut moves);
|
||||||
moves.len
|
moves.len
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the king is in check.
|
/// Returns `true` if the king is in check.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_check(&self) -> bool {
|
pub fn is_check(&self) -> bool {
|
||||||
struct MoveGenImpl {
|
struct MoveGenImpl;
|
||||||
is_check: bool,
|
impl MoveGen<()> for MoveGenImpl {
|
||||||
}
|
|
||||||
impl MoveGen for MoveGenImpl {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn roles(&self, _role: Role) -> bool {
|
fn roles(&self, _role: Role) -> bool {
|
||||||
false
|
false
|
||||||
|
|
@ -153,21 +148,11 @@ impl Position {
|
||||||
Bitboard::new()
|
Bitboard::new()
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_check(&mut self) {
|
fn is_check(&mut self) -> ControlFlow<()> {
|
||||||
self.is_check = true;
|
ControlFlow::Break(())
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn en_passant_is_legal(&mut self) {}
|
|
||||||
#[inline]
|
|
||||||
fn extend<I>(&mut self, _iter: I)
|
|
||||||
where
|
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut moves = MoveGenImpl { is_check: false };
|
self.generate_moves(&mut MoveGenImpl).is_break()
|
||||||
self.generate_moves(&mut moves);
|
|
||||||
moves.is_check
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if there is no legal move on the position.
|
/// Returns `true` if there is no legal move on the position.
|
||||||
|
|
@ -184,9 +169,8 @@ impl Position {
|
||||||
}
|
}
|
||||||
struct MoveGenImpl {
|
struct MoveGenImpl {
|
||||||
to: Bitboard,
|
to: Bitboard,
|
||||||
en_passant_is_legal: bool,
|
|
||||||
}
|
}
|
||||||
impl MoveGen for MoveGenImpl {
|
impl MoveGen<()> for MoveGenImpl {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn roles(&self, role: Role) -> bool {
|
fn roles(&self, role: Role) -> bool {
|
||||||
match role {
|
match role {
|
||||||
|
|
@ -203,24 +187,14 @@ impl Position {
|
||||||
self.to
|
self.to
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_check(&mut self) {}
|
fn en_passant_is_legal(&mut self) -> ControlFlow<()> {
|
||||||
#[inline]
|
ControlFlow::Break(())
|
||||||
fn en_passant_is_legal(&mut self) {
|
|
||||||
self.en_passant_is_legal = true;
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn extend<I>(&mut self, _iter: I)
|
|
||||||
where
|
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut moves = MoveGenImpl {
|
let mut moves = MoveGenImpl {
|
||||||
to: self.as_setup().en_passant.bitboard(),
|
to: self.as_setup().en_passant.bitboard(),
|
||||||
en_passant_is_legal: false,
|
|
||||||
};
|
};
|
||||||
self.generate_moves(&mut moves);
|
self.generate_moves(&mut moves).is_break()
|
||||||
moves.en_passant_is_legal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Discards the en passant target square.
|
/// Discards the en passant target square.
|
||||||
|
|
@ -315,20 +289,14 @@ impl Position {
|
||||||
role: Role,
|
role: Role,
|
||||||
from: Bitboard,
|
from: Bitboard,
|
||||||
to: Bitboard,
|
to: Bitboard,
|
||||||
found: Option<RawMove>,
|
|
||||||
}
|
}
|
||||||
impl<const ROLE: u8> MoveGenImpl<ROLE> {
|
impl<const ROLE: u8> MoveGenImpl<ROLE> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(role: Role, from: Bitboard, to: Bitboard) -> Self {
|
fn new(role: Role, from: Bitboard, to: Bitboard) -> Self {
|
||||||
Self {
|
Self { role, from, to }
|
||||||
role,
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
found: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<const ROLE: u8> MoveGen for MoveGenImpl<ROLE> {
|
impl<const ROLE: u8> MoveGen<RawMove> for MoveGenImpl<ROLE> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn roles(&self, role: Role) -> bool {
|
fn roles(&self, role: Role) -> bool {
|
||||||
role as u8 == ROLE
|
role as u8 == ROLE
|
||||||
|
|
@ -342,23 +310,19 @@ impl Position {
|
||||||
self.to
|
self.to
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_check(&mut self) {}
|
fn extend<I>(&mut self, iter: I) -> ControlFlow<RawMove>
|
||||||
#[inline]
|
|
||||||
fn en_passant_is_legal(&mut self) {}
|
|
||||||
#[inline]
|
|
||||||
fn extend<I>(&mut self, iter: I)
|
|
||||||
where
|
where
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
iter.for_each(|raw| {
|
for raw in iter {
|
||||||
debug_assert!(raw.role() as u8 == ROLE);
|
debug_assert!(raw.role() as u8 == ROLE);
|
||||||
debug_assert!(self.from.contains(raw.from()));
|
debug_assert!(self.from.contains(raw.from()));
|
||||||
debug_assert!(self.to.contains(raw.to()));
|
debug_assert!(self.to.contains(raw.to()));
|
||||||
if raw.role == self.role {
|
if raw.role == self.role {
|
||||||
debug_assert!(self.found.is_none());
|
return ControlFlow::Break(raw);
|
||||||
self.found = Some(raw);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let UciMove {
|
let UciMove {
|
||||||
|
|
@ -375,8 +339,10 @@ impl Position {
|
||||||
to: Square,
|
to: Square,
|
||||||
) -> Result<Move<'l>, InvalidUciMove> {
|
) -> Result<Move<'l>, InvalidUciMove> {
|
||||||
let mut moves = MoveGenImpl::<ROLE>::new(role, from.bitboard(), to.bitboard());
|
let mut moves = MoveGenImpl::<ROLE>::new(role, from.bitboard(), to.bitboard());
|
||||||
position.generate_moves(&mut moves);
|
let raw = position
|
||||||
let raw = moves.found.ok_or(InvalidUciMove::Illegal)?;
|
.generate_moves(&mut moves)
|
||||||
|
.break_value()
|
||||||
|
.ok_or(InvalidUciMove::Illegal)?;
|
||||||
Ok(unsafe { Move::new_unchecked(position, raw) })
|
Ok(unsafe { Move::new_unchecked(position, raw) })
|
||||||
}
|
}
|
||||||
let promotion = if role == Role::Pawn {
|
let promotion = if role == Role::Pawn {
|
||||||
|
|
@ -409,7 +375,7 @@ impl Position {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<const ROLE: u8> MoveGen for MoveGenImpl<ROLE> {
|
impl<const ROLE: u8> MoveGen<Infallible> for MoveGenImpl<ROLE> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn roles(&self, role: Role) -> bool {
|
fn roles(&self, role: Role) -> bool {
|
||||||
role as u8 == ROLE
|
role as u8 == ROLE
|
||||||
|
|
@ -423,11 +389,7 @@ impl Position {
|
||||||
self.to
|
self.to
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_check(&mut self) {}
|
fn extend<I>(&mut self, iter: I) -> ControlFlow<Infallible>
|
||||||
#[inline]
|
|
||||||
fn en_passant_is_legal(&mut self) {}
|
|
||||||
#[inline]
|
|
||||||
fn extend<I>(&mut self, iter: I)
|
|
||||||
where
|
where
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
|
|
@ -442,6 +404,7 @@ impl Position {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (role, promotion, from, to) = match san.inner {
|
let (role, promotion, from, to) = match san.inner {
|
||||||
|
|
@ -486,7 +449,7 @@ impl Position {
|
||||||
to: Bitboard,
|
to: Bitboard,
|
||||||
) -> Result<Move<'l>, InvalidSan> {
|
) -> Result<Move<'l>, InvalidSan> {
|
||||||
let mut moves = MoveGenImpl::<ROLE>::new(role, from, to);
|
let mut moves = MoveGenImpl::<ROLE>::new(role, from, to);
|
||||||
position.generate_moves(&mut moves);
|
let ControlFlow::Continue(()) = position.generate_moves(&mut moves);
|
||||||
match moves.found {
|
match moves.found {
|
||||||
None => Err(InvalidSan::Illegal),
|
None => Err(InvalidSan::Illegal),
|
||||||
Some(raw) => match moves.found_other {
|
Some(raw) => match moves.found_other {
|
||||||
|
|
@ -569,7 +532,7 @@ impl RawMove {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait MoveGen {
|
pub(crate) trait MoveGen<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn roles(&self, _role: Role) -> bool {
|
fn roles(&self, _role: Role) -> bool {
|
||||||
true
|
true
|
||||||
|
|
@ -583,11 +546,20 @@ pub(crate) trait MoveGen {
|
||||||
!Bitboard::new()
|
!Bitboard::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_check(&mut self);
|
#[inline]
|
||||||
fn en_passant_is_legal(&mut self);
|
fn is_check(&mut self) -> ControlFlow<S> {
|
||||||
fn extend<I>(&mut self, iter: I)
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn en_passant_is_legal(&mut self) -> ControlFlow<S> {
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
|
fn extend<I>(&mut self, _iter: I) -> ControlFlow<S>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator;
|
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
||||||
|
{
|
||||||
|
ControlFlow::Continue(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Position {
|
impl Position {
|
||||||
|
|
@ -596,9 +568,9 @@ impl Position {
|
||||||
Self(setup)
|
Self(setup)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn generate_moves<T>(&self, moves: &mut T)
|
pub(crate) fn generate_moves<S, T>(&self, moves: &mut T) -> ControlFlow<S>
|
||||||
where
|
where
|
||||||
T: MoveGen,
|
T: MoveGen<S>,
|
||||||
{
|
{
|
||||||
let global_mask_from = moves.from();
|
let global_mask_from = moves.from();
|
||||||
let global_mask_to = moves.to();
|
let global_mask_to = moves.to();
|
||||||
|
|
@ -673,7 +645,7 @@ impl Position {
|
||||||
to,
|
to,
|
||||||
role: Role::King,
|
role: Role::King,
|
||||||
}),
|
}),
|
||||||
);
|
)?;
|
||||||
// castling
|
// castling
|
||||||
if castling_rights.get(turn, CastlingSide::Short) {
|
if castling_rights.get(turn, CastlingSide::Short) {
|
||||||
let (x, y) = match turn {
|
let (x, y) = match turn {
|
||||||
|
|
@ -692,7 +664,7 @@ impl Position {
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
role: Role::King,
|
role: Role::King,
|
||||||
}))
|
}))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -713,15 +685,15 @@ impl Position {
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
role: Role::King,
|
role: Role::King,
|
||||||
}))
|
}))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if checkers.len() > 1 {
|
if checkers.len() > 1 {
|
||||||
moves.is_check();
|
moves.is_check()?;
|
||||||
return;
|
return ControlFlow::Continue(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let blockers_x_ray = blockers & !(x | y);
|
let blockers_x_ray = blockers & !(x | y);
|
||||||
|
|
@ -762,7 +734,7 @@ impl Position {
|
||||||
from: unsafe { to.trans_unchecked(!forward) },
|
from: unsafe { to.trans_unchecked(!forward) },
|
||||||
to,
|
to,
|
||||||
role: Role::Pawn,
|
role: Role::Pawn,
|
||||||
}));
|
}))?;
|
||||||
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
|
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
|
||||||
RawMove {
|
RawMove {
|
||||||
kind: MoveType::PawnAdvancePromotion,
|
kind: MoveType::PawnAdvancePromotion,
|
||||||
|
|
@ -770,7 +742,7 @@ impl Position {
|
||||||
to,
|
to,
|
||||||
role: Role::Pawn,
|
role: Role::Pawn,
|
||||||
}
|
}
|
||||||
})));
|
})))?;
|
||||||
}
|
}
|
||||||
// pawn attacks kingside
|
// pawn attacks kingside
|
||||||
{
|
{
|
||||||
|
|
@ -784,7 +756,7 @@ impl Position {
|
||||||
from: unsafe { to.trans_unchecked(!kside) },
|
from: unsafe { to.trans_unchecked(!kside) },
|
||||||
to,
|
to,
|
||||||
role: Role::Pawn,
|
role: Role::Pawn,
|
||||||
}));
|
}))?;
|
||||||
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
|
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
|
||||||
RawMove {
|
RawMove {
|
||||||
kind: MoveType::PawnAttackPromotion,
|
kind: MoveType::PawnAttackPromotion,
|
||||||
|
|
@ -792,7 +764,7 @@ impl Position {
|
||||||
to,
|
to,
|
||||||
role: Role::Pawn,
|
role: Role::Pawn,
|
||||||
}
|
}
|
||||||
})));
|
})))?;
|
||||||
}
|
}
|
||||||
// pawn attacks queenside
|
// pawn attacks queenside
|
||||||
{
|
{
|
||||||
|
|
@ -806,7 +778,7 @@ impl Position {
|
||||||
from: unsafe { to.trans_unchecked(!qside) },
|
from: unsafe { to.trans_unchecked(!qside) },
|
||||||
to,
|
to,
|
||||||
role: Role::Pawn,
|
role: Role::Pawn,
|
||||||
}));
|
}))?;
|
||||||
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
|
moves.extend(MoveAndPromote::new((targets & promotion).map(|to| {
|
||||||
RawMove {
|
RawMove {
|
||||||
kind: MoveType::PawnAttackPromotion,
|
kind: MoveType::PawnAttackPromotion,
|
||||||
|
|
@ -814,7 +786,7 @@ impl Position {
|
||||||
to,
|
to,
|
||||||
role: Role::Pawn,
|
role: Role::Pawn,
|
||||||
}
|
}
|
||||||
})));
|
})))?;
|
||||||
}
|
}
|
||||||
// pawn double advances
|
// pawn double advances
|
||||||
moves.extend(
|
moves.extend(
|
||||||
|
|
@ -826,7 +798,7 @@ impl Position {
|
||||||
role: Role::Pawn,
|
role: Role::Pawn,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
)?;
|
||||||
// en passant
|
// en passant
|
||||||
if let Some(to) = en_passant.try_into_square() {
|
if let Some(to) = en_passant.try_into_square() {
|
||||||
if global_mask_to.contains(to) {
|
if global_mask_to.contains(to) {
|
||||||
|
|
@ -846,18 +818,18 @@ impl Position {
|
||||||
) & theirs.rook())
|
) & theirs.rook())
|
||||||
.map(|sq| lookup::segment(king_square, sq))
|
.map(|sq| lookup::segment(king_square, sq))
|
||||||
.reduce_or();
|
.reduce_or();
|
||||||
(global_mask_from
|
for from in global_mask_from
|
||||||
& candidates
|
& candidates
|
||||||
& (!pinned | lookup::segment(king_square, to)))
|
& (!pinned | lookup::segment(king_square, to))
|
||||||
.for_each(|from| {
|
{
|
||||||
moves.en_passant_is_legal();
|
moves.en_passant_is_legal()?;
|
||||||
moves.extend(std::iter::once(RawMove {
|
moves.extend(std::iter::once(RawMove {
|
||||||
kind: MoveType::EnPassant,
|
kind: MoveType::EnPassant,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
role: Role::Pawn,
|
role: Role::Pawn,
|
||||||
}))
|
}))?;
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -876,26 +848,27 @@ impl Position {
|
||||||
role,
|
role,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)?;
|
||||||
}
|
}
|
||||||
|
ControlFlow::Continue(())
|
||||||
};
|
};
|
||||||
if moves.roles(Role::Knight) {
|
if moves.roles(Role::Knight) {
|
||||||
aux(moves, Role::Knight)
|
aux(moves, Role::Knight)?;
|
||||||
}
|
}
|
||||||
if moves.roles(Role::Bishop) {
|
if moves.roles(Role::Bishop) {
|
||||||
aux(moves, Role::Bishop)
|
aux(moves, Role::Bishop)?;
|
||||||
}
|
}
|
||||||
if moves.roles(Role::Rook) {
|
if moves.roles(Role::Rook) {
|
||||||
aux(moves, Role::Rook)
|
aux(moves, Role::Rook)?;
|
||||||
}
|
}
|
||||||
if moves.roles(Role::Queen) {
|
if moves.roles(Role::Queen) {
|
||||||
aux(moves, Role::Queen)
|
aux(moves, Role::Queen)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if checker.is_some() {
|
if checker.is_some() {
|
||||||
moves.is_check();
|
moves.is_check()?;
|
||||||
return;
|
return ControlFlow::Continue(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// pinned pieces
|
// pinned pieces
|
||||||
|
|
@ -911,19 +884,22 @@ impl Position {
|
||||||
role,
|
role,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)?;
|
||||||
}
|
}
|
||||||
|
ControlFlow::Continue(())
|
||||||
};
|
};
|
||||||
if moves.roles(Role::Bishop) {
|
if moves.roles(Role::Bishop) {
|
||||||
aux(moves, Role::Bishop, lookup::bishop_lines(king_square));
|
aux(moves, Role::Bishop, lookup::bishop_lines(king_square))?;
|
||||||
}
|
}
|
||||||
if moves.roles(Role::Rook) {
|
if moves.roles(Role::Rook) {
|
||||||
aux(moves, Role::Rook, lookup::rook_lines(king_square));
|
aux(moves, Role::Rook, lookup::rook_lines(king_square))?;
|
||||||
}
|
}
|
||||||
if moves.roles(Role::Queen) {
|
if moves.roles(Role::Queen) {
|
||||||
aux(moves, Role::Queen, !Bitboard::new());
|
aux(moves, Role::Queen, !Bitboard::new())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -1094,19 +1070,19 @@ impl MateMoveGenImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl MoveGen for MateMoveGenImpl {
|
impl MoveGen<Infallible> for MateMoveGenImpl {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_check(&mut self) {
|
fn is_check(&mut self) -> ControlFlow<Infallible> {
|
||||||
self.is_check = true;
|
self.is_check = true;
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn en_passant_is_legal(&mut self) {}
|
fn extend<I>(&mut self, iter: I) -> ControlFlow<Infallible>
|
||||||
#[inline]
|
|
||||||
fn extend<I>(&mut self, iter: I)
|
|
||||||
where
|
where
|
||||||
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
I: Iterator<Item = RawMove> + ExactSizeIterator,
|
||||||
{
|
{
|
||||||
self.is_mate &= iter.len() == 0;
|
self.is_mate &= iter.len() == 0;
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue