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