check, mate & en passant methods
This commit is contained in:
parent
098071046d
commit
d66828c861
4 changed files with 115 additions and 20 deletions
|
|
@ -486,6 +486,11 @@ impl OptionSquare {
|
||||||
pub(crate) fn from_square(square: Square) -> Self {
|
pub(crate) fn from_square(square: Square) -> Self {
|
||||||
unsafe { std::mem::transmute(square) }
|
unsafe { std::mem::transmute(square) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn bitboard(&self) -> Bitboard {
|
||||||
|
Bitboard(1 << (*self as u8))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type of piece.
|
/// A type of piece.
|
||||||
|
|
|
||||||
18
src/moves.rs
18
src/moves.rs
|
|
@ -265,18 +265,24 @@ impl<'l> Moves<'l> {
|
||||||
self.array.len()
|
self.array.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if en passant is legal.
|
|
||||||
#[inline]
|
|
||||||
pub fn en_passant_is_legal(&self) -> bool {
|
|
||||||
self.en_passant_is_legal
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the king is in check.
|
/// Returns `true` if the king is in check.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_check(&self) -> bool {
|
pub fn is_check(&self) -> bool {
|
||||||
self.is_check
|
self.is_check
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if there is no legal move on the position.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_mate(&self) -> bool {
|
||||||
|
self.array.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if taking en passant is legal on the position.
|
||||||
|
#[inline]
|
||||||
|
pub fn en_passant_is_legal(&self) -> bool {
|
||||||
|
self.en_passant_is_legal
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the move at the given index, if it exists.
|
/// Returns the move at the given index, if it exists.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, index: usize) -> Option<Move<'l>> {
|
pub fn get(&self, index: usize) -> Option<Move<'l>> {
|
||||||
|
|
|
||||||
105
src/position.rs
105
src/position.rs
|
|
@ -77,21 +77,13 @@ impl Position {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all the legal moves on the position.
|
/// Returns the number of 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> {
|
||||||
Moves::compute(self)
|
Moves::compute(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Counts the legal moves on the position.
|
/// Counts the legal moves on the position.
|
||||||
///
|
|
||||||
/// This is equivalent but faster than:
|
|
||||||
/// ```
|
|
||||||
/// # use eschac::position::Position;
|
|
||||||
/// # |position: &Position| -> usize {
|
|
||||||
/// position.legal_moves().len()
|
|
||||||
/// # };
|
|
||||||
/// ```
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn count_legal_moves(&self) -> usize {
|
pub fn count_legal_moves(&self) -> usize {
|
||||||
|
|
@ -116,14 +108,101 @@ impl Position {
|
||||||
self.len += iter.len();
|
self.len += iter.len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn aux(position: &Position, moves: &mut MoveGenImpl) {
|
|
||||||
position.generate_moves(moves);
|
|
||||||
}
|
|
||||||
let mut moves = MoveGenImpl::new();
|
let mut moves = MoveGenImpl::new();
|
||||||
aux(self, &mut moves);
|
self.generate_moves(&mut moves);
|
||||||
moves.len
|
moves.len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the king is in check.
|
||||||
|
#[must_use]
|
||||||
|
pub fn is_check(&self) -> bool {
|
||||||
|
struct MoveGenImpl {
|
||||||
|
is_check: bool,
|
||||||
|
}
|
||||||
|
impl MoveGen for MoveGenImpl {
|
||||||
|
#[inline]
|
||||||
|
fn roles(&self, _role: Role) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn from(&self) -> Bitboard {
|
||||||
|
Bitboard::new()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn to(&self) -> Bitboard {
|
||||||
|
Bitboard::new()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_check(&mut self) {
|
||||||
|
self.is_check = true;
|
||||||
|
}
|
||||||
|
#[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 moves);
|
||||||
|
moves.is_check
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if there is no legal move on the position.
|
||||||
|
#[must_use]
|
||||||
|
pub fn is_mate(&self) -> bool {
|
||||||
|
self.count_legal_moves() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if taking en passant is legal on the position.
|
||||||
|
#[must_use]
|
||||||
|
pub fn en_passant_is_legal(&self) -> bool {
|
||||||
|
if self.as_setup().en_passant == OptionSquare::None {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct MoveGenImpl {
|
||||||
|
to: Bitboard,
|
||||||
|
en_passant_is_legal: bool,
|
||||||
|
}
|
||||||
|
impl MoveGen for MoveGenImpl {
|
||||||
|
#[inline]
|
||||||
|
fn roles(&self, role: Role) -> bool {
|
||||||
|
match role {
|
||||||
|
Role::Pawn => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn from(&self) -> Bitboard {
|
||||||
|
!Bitboard::new()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn to(&self) -> Bitboard {
|
||||||
|
self.to
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_check(&mut self) {}
|
||||||
|
#[inline]
|
||||||
|
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 {
|
||||||
|
to: self.as_setup().en_passant.bitboard(),
|
||||||
|
en_passant_is_legal: false,
|
||||||
|
};
|
||||||
|
self.generate_moves(&mut moves);
|
||||||
|
moves.en_passant_is_legal
|
||||||
|
}
|
||||||
|
|
||||||
/// Discards the en passant target square.
|
/// Discards the en passant target square.
|
||||||
///
|
///
|
||||||
/// This function is useful to check for position equality, notably when implementing FIDE's
|
/// This function is useful to check for position equality, notably when implementing FIDE's
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,12 @@ fn recursive_check_aux(position: Position, depth: usize) {
|
||||||
match depth.checked_sub(1) {
|
match depth.checked_sub(1) {
|
||||||
None => (),
|
None => (),
|
||||||
Some(depth) => {
|
Some(depth) => {
|
||||||
position.legal_moves().into_iter().for_each(|m| {
|
let moves = position.legal_moves();
|
||||||
|
assert_eq!(moves.len(), position.count_legal_moves());
|
||||||
|
assert_eq!(moves.is_check(), position.is_check());
|
||||||
|
assert_eq!(moves.is_mate(), position.is_mate());
|
||||||
|
assert_eq!(moves.en_passant_is_legal(), position.en_passant_is_legal());
|
||||||
|
moves.into_iter().for_each(|m| {
|
||||||
let uci = m.to_uci();
|
let uci = m.to_uci();
|
||||||
assert_eq!(uci, uci.to_move(&position).unwrap().to_uci());
|
assert_eq!(uci, uci.to_move(&position).unwrap().to_uci());
|
||||||
let san: San = m.to_san();
|
let san: San = m.to_san();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue