Delete the position::r#move module
This commit is contained in:
parent
d77345901c
commit
63c03fb879
1 changed files with 0 additions and 602 deletions
|
@ -1,602 +0,0 @@
|
||||||
// Eryn Wells <eryn@erynwells.me>
|
|
||||||
|
|
||||||
use chessfriend_core::{Piece, PlacedPiece, Rank, Shape, Square};
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
pub use castle::Castle;
|
|
||||||
pub(crate) use move_formatter::AlgebraicMoveFormatter;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
||||||
pub enum MakeMoveError {
|
|
||||||
PlayerOutOfTurn,
|
|
||||||
NoPiece,
|
|
||||||
NoCapturedPiece,
|
|
||||||
NoLegalMoves,
|
|
||||||
IllegalCastle,
|
|
||||||
IllegalSquare(Square),
|
|
||||||
}
|
|
||||||
|
|
||||||
mod castle {
|
|
||||||
use chessfriend_bitboard::BitBoard;
|
|
||||||
use chessfriend_core::{Color, Square};
|
|
||||||
|
|
||||||
#[repr(u16)]
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
||||||
pub enum Castle {
|
|
||||||
KingSide = 0b10,
|
|
||||||
QueenSide = 0b11,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct CastlingParameters {
|
|
||||||
clear_squares: BitBoard,
|
|
||||||
check_squares: BitBoard,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(crate) struct Squares {
|
|
||||||
pub king: Square,
|
|
||||||
pub rook: Square,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Castle {
|
|
||||||
pub const ALL: [Castle; 2] = [Castle::KingSide, Castle::QueenSide];
|
|
||||||
|
|
||||||
const STARTING_SQUARES: [[Squares; 2]; 2] = [
|
|
||||||
[
|
|
||||||
Squares {
|
|
||||||
king: Square::E1,
|
|
||||||
rook: Square::H1,
|
|
||||||
},
|
|
||||||
Squares {
|
|
||||||
king: Square::E1,
|
|
||||||
rook: Square::A1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
Squares {
|
|
||||||
king: Square::E8,
|
|
||||||
rook: Square::H8,
|
|
||||||
},
|
|
||||||
Squares {
|
|
||||||
king: Square::E8,
|
|
||||||
rook: Square::A8,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
const TARGET_SQUARES: [[Squares; 2]; 2] = [
|
|
||||||
[
|
|
||||||
Squares {
|
|
||||||
king: Square::G1,
|
|
||||||
rook: Square::F1,
|
|
||||||
},
|
|
||||||
Squares {
|
|
||||||
king: Square::C1,
|
|
||||||
rook: Square::D1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
Squares {
|
|
||||||
king: Square::G8,
|
|
||||||
rook: Square::F8,
|
|
||||||
},
|
|
||||||
Squares {
|
|
||||||
king: Square::C8,
|
|
||||||
rook: Square::D8,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
pub(crate) fn starting_squares(&self, color: Color) -> &'static Squares {
|
|
||||||
&Castle::STARTING_SQUARES[color as usize][self.into_index()]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn target_squares(&self, color: Color) -> &'static Squares {
|
|
||||||
&Castle::TARGET_SQUARES[color as usize][self.into_index()]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn into_index(&self) -> usize {
|
|
||||||
match self {
|
|
||||||
Castle::KingSide => 0,
|
|
||||||
Castle::QueenSide => 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn parameters(&self) -> CastlingParameters {
|
|
||||||
match self {
|
|
||||||
Castle::KingSide => CastlingParameters {
|
|
||||||
clear_squares: BitBoard::new(0b01100000),
|
|
||||||
check_squares: BitBoard::new(0b01110000),
|
|
||||||
},
|
|
||||||
Castle::QueenSide => CastlingParameters {
|
|
||||||
clear_squares: BitBoard::new(0b00001110),
|
|
||||||
check_squares: BitBoard::new(0b00011100),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CastlingParameters {
|
|
||||||
pub fn clear_squares(&self) -> &BitBoard {
|
|
||||||
&self.clear_squares
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_squares(&self) -> &BitBoard {
|
|
||||||
&self.check_squares
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(u16)]
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
||||||
pub enum PromotableShape {
|
|
||||||
Knight = 0b00,
|
|
||||||
Bishop = 0b01,
|
|
||||||
Rook = 0b10,
|
|
||||||
Queen = 0b11,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<Shape> for PromotableShape {
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
fn try_from(value: Shape) -> Result<Self, Self::Error> {
|
|
||||||
match value {
|
|
||||||
Shape::Knight => Ok(PromotableShape::Knight),
|
|
||||||
Shape::Bishop => Ok(PromotableShape::Bishop),
|
|
||||||
Shape::Rook => Ok(PromotableShape::Rook),
|
|
||||||
Shape::Queen => Ok(PromotableShape::Queen),
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(u16)]
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
||||||
enum Kind {
|
|
||||||
Quiet = 0b00,
|
|
||||||
DoublePush = 0b01,
|
|
||||||
Castle(Castle),
|
|
||||||
Capture(PlacedPiece) = 0b0100,
|
|
||||||
EnPassantCapture(PlacedPiece) = 0b0101,
|
|
||||||
Promotion(PromotableShape) = 0b1000,
|
|
||||||
CapturePromotion(PlacedPiece, PromotableShape) = 0b1100,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Kind {
|
|
||||||
fn bits(&self) -> u16 {
|
|
||||||
match self {
|
|
||||||
Self::Promotion(shape) => self.discriminant() | *shape as u16,
|
|
||||||
Self::CapturePromotion(_, shape) => self.discriminant() | *shape as u16,
|
|
||||||
Self::Castle(castle) => *castle as u16,
|
|
||||||
_ => self.discriminant(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the discriminant value. This implementation is copied from the Rust docs.
|
|
||||||
/// See https://doc.rust-lang.org/std/mem/fn.discriminant.html
|
|
||||||
fn discriminant(&self) -> u16 {
|
|
||||||
unsafe { *<*const _>::from(self).cast::<u16>() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Kind {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Quiet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A single player's move. In chess parlance, this is a "ply".
|
|
||||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
|
|
||||||
pub struct Move(u16);
|
|
||||||
|
|
||||||
impl Move {
|
|
||||||
pub fn from_square(&self) -> Square {
|
|
||||||
((self.0 >> 4) & 0b111111).try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_square(&self) -> Square {
|
|
||||||
(self.0 >> 10).try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_quiet(&self) -> bool {
|
|
||||||
self.flags() == Kind::Quiet.discriminant()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_double_push(&self) -> bool {
|
|
||||||
self.flags() == Kind::DoublePush.discriminant()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_castle(&self) -> bool {
|
|
||||||
self.castle().is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn castle(&self) -> Option<Castle> {
|
|
||||||
match self.flags() {
|
|
||||||
0b0010 => Some(Castle::KingSide),
|
|
||||||
0b0011 => Some(Castle::QueenSide),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_capture(&self) -> bool {
|
|
||||||
(self.0 & 0b0100) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_en_passant(&self) -> bool {
|
|
||||||
self.flags() == 0b0101
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_promotion(&self) -> bool {
|
|
||||||
(self.0 & 0b1000) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn promotion(&self) -> Option<Shape> {
|
|
||||||
if !self.is_promotion() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(match self.special() {
|
|
||||||
0b00 => Shape::Knight,
|
|
||||||
0b01 => Shape::Bishop,
|
|
||||||
0b10 => Shape::Rook,
|
|
||||||
0b11 => Shape::Queen,
|
|
||||||
_ => unreachable!(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn flags(&self) -> u16 {
|
|
||||||
self.0 & 0b1111
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn special(&self) -> u16 {
|
|
||||||
self.0 & 0b11
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Move {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.debug_tuple("Move")
|
|
||||||
.field(&format_args!("{:08b}", &self.0))
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct MoveBuilder {
|
|
||||||
piece: Piece,
|
|
||||||
from: Square,
|
|
||||||
to: Square,
|
|
||||||
kind: Kind,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MoveBuilder {
|
|
||||||
pub fn new(piece: Piece, from: Square, to: Square) -> Self {
|
|
||||||
let kind = match piece.shape() {
|
|
||||||
Shape::Pawn => {
|
|
||||||
let from_rank = from.rank();
|
|
||||||
let to_rank = to.rank();
|
|
||||||
let is_white_double_push = from_rank == Rank::TWO && to_rank == Rank::FOUR;
|
|
||||||
let is_black_double_push = from_rank == Rank::SEVEN && to_rank == Rank::FIVE;
|
|
||||||
if is_white_double_push || is_black_double_push {
|
|
||||||
Kind::DoublePush
|
|
||||||
} else {
|
|
||||||
Kind::Quiet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Kind::Quiet,
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
piece,
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
kind,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn castle(mut self, castle: Castle) -> Self {
|
|
||||||
self.kind = Kind::Castle(castle);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn capturing(mut self, captured_piece: PlacedPiece) -> Self {
|
|
||||||
self.kind = match self.kind {
|
|
||||||
Kind::Promotion(shape) => Kind::CapturePromotion(captured_piece, shape),
|
|
||||||
_ => Kind::Capture(captured_piece),
|
|
||||||
};
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn capturing_en_passant(mut self, captured_piece: PlacedPiece) -> Self {
|
|
||||||
self.kind = Kind::EnPassantCapture(captured_piece);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn promoting_to(mut self, shape: Shape) -> Self {
|
|
||||||
if let Some(shape) = PromotableShape::try_from(shape).ok() {
|
|
||||||
self.kind = match self.kind {
|
|
||||||
Kind::Capture(piece) => Kind::CapturePromotion(piece, shape),
|
|
||||||
Kind::CapturePromotion(piece, _) => Kind::CapturePromotion(piece, shape),
|
|
||||||
_ => Kind::Promotion(shape),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(&self) -> Move {
|
|
||||||
Move(
|
|
||||||
self.kind.bits()
|
|
||||||
| ((self.from as u16 & 0b111111) << 4)
|
|
||||||
| ((self.to as u16 & 0b111111) << 10),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod move_formatter {
|
|
||||||
use super::{Castle, Move};
|
|
||||||
use crate::Position;
|
|
||||||
use chessfriend_core::Shape;
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
enum Style {
|
|
||||||
Short,
|
|
||||||
Long,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Style {
|
|
||||||
fn default() -> Self {
|
|
||||||
Style::Long
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct AlgebraicMoveFormatter<'m, 'pos> {
|
|
||||||
position: &'pos Position,
|
|
||||||
r#move: &'m Move,
|
|
||||||
style: Style,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'pos, 'm> AlgebraicMoveFormatter<'m, 'pos> {
|
|
||||||
pub(crate) fn new(
|
|
||||||
mv: &'m Move,
|
|
||||||
position: &'pos Position,
|
|
||||||
) -> AlgebraicMoveFormatter<'m, 'pos> {
|
|
||||||
AlgebraicMoveFormatter {
|
|
||||||
position,
|
|
||||||
r#move: mv,
|
|
||||||
style: Style::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn style(mut self, style: Style) -> Self {
|
|
||||||
self.style = style;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_kingside_castle(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "0-0")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_queenside_castle(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "0-0-0")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_short(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_long(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
// TODO: Figure out how to write the short algebraic form, where a
|
|
||||||
// disambiguating coordiate is specified when two of the same piece
|
|
||||||
// cam move to the same square.
|
|
||||||
|
|
||||||
// TODO: Write better pawn moves.
|
|
||||||
|
|
||||||
let mv = self.r#move;
|
|
||||||
let from_square = mv.from_square();
|
|
||||||
let to_square = mv.to_square();
|
|
||||||
|
|
||||||
let piece = self
|
|
||||||
.position
|
|
||||||
.piece_on_square(from_square)
|
|
||||||
.expect(&format!("No piece on {}", from_square));
|
|
||||||
if piece.shape() != Shape::Pawn {
|
|
||||||
write!(f, "{}", piece.shape())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}{}{}",
|
|
||||||
from_square,
|
|
||||||
if mv.is_capture() { 'x' } else { '-' },
|
|
||||||
to_square,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if let Some(promotion) = mv.promotion() {
|
|
||||||
write!(f, "={}", promotion)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Write check (+) and checkmate (#) symbols
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'pos, 'mv> fmt::Display for AlgebraicMoveFormatter<'mv, 'pos> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
let mv = self.r#move;
|
|
||||||
match mv.castle() {
|
|
||||||
Some(Castle::KingSide) => return self.fmt_kingside_castle(f),
|
|
||||||
Some(Castle::QueenSide) => return self.fmt_queenside_castle(f),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.style {
|
|
||||||
Style::Short => self.fmt_short(f),
|
|
||||||
Style::Long => self.fmt_long(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::{AlgebraicMoveFormatter, Style};
|
|
||||||
use crate::position;
|
|
||||||
use chessfriend_core::piece;
|
|
||||||
|
|
||||||
macro_rules! chess_move {
|
|
||||||
($color:ident $shape:ident $from_square:ident - $to_square:ident) => {
|
|
||||||
$crate::MoveBuilder::new(
|
|
||||||
chessfriend_core::Piece::new(
|
|
||||||
chessfriend_core::Color::$color,
|
|
||||||
chessfriend_core::Shape::$shape,
|
|
||||||
),
|
|
||||||
chessfriend_core::Square::$from_square,
|
|
||||||
chessfriend_core::Square::$to_square,
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
};
|
|
||||||
($color:ident $shape:ident $from_square:ident x $to_square:ident, $captured_color:ident $captured_shape:ident) => {
|
|
||||||
$crate::MoveBuilder::new(
|
|
||||||
chessfriend_core::Piece::new(
|
|
||||||
chessfriend_core::Color::$color,
|
|
||||||
chessfriend_core::Shape::$shape,
|
|
||||||
),
|
|
||||||
chessfriend_core::Square::$from_square,
|
|
||||||
chessfriend_core::Square::$to_square,
|
|
||||||
)
|
|
||||||
.capturing(chessfriend_core::PlacedPiece::new(
|
|
||||||
chessfriend_core::Piece::new(
|
|
||||||
chessfriend_core::Color::$captured_color,
|
|
||||||
chessfriend_core::Shape::$captured_shape,
|
|
||||||
),
|
|
||||||
chessfriend_core::Square::$to_square,
|
|
||||||
))
|
|
||||||
.build()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! test_algebraic_formatter {
|
|
||||||
($test_name:ident, $style:ident, $color:ident $shape:ident $from_square:ident x $to_square:ident, $captured_color:ident $captured_shape:ident, $output:expr) => {
|
|
||||||
#[test]
|
|
||||||
fn $test_name() {
|
|
||||||
let pos = position![
|
|
||||||
$color $shape on $from_square,
|
|
||||||
$captured_color $captured_shape on $to_square,
|
|
||||||
];
|
|
||||||
let mv = chess_move!(
|
|
||||||
$color $shape $from_square x $to_square,
|
|
||||||
$captured_color $captured_shape
|
|
||||||
);
|
|
||||||
|
|
||||||
println!("{:?}", &mv);
|
|
||||||
|
|
||||||
let formatter = AlgebraicMoveFormatter::new(&mv, &pos).style(Style::$style);
|
|
||||||
assert_eq!(format!("{}", formatter), $output);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
($test_name:ident, $style:ident, $color:ident $shape:ident $from_square:ident - $to_square:ident, $output:expr) => {
|
|
||||||
#[test]
|
|
||||||
fn $test_name() {
|
|
||||||
let pos = position![
|
|
||||||
$color $shape on $from_square,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mv = chess_move!($color $shape $from_square-$to_square);
|
|
||||||
println!("{:?}", &mv);
|
|
||||||
|
|
||||||
let formatter = AlgebraicMoveFormatter::new(&mv, &pos).style(Style::$style);
|
|
||||||
assert_eq!(format!("{}", formatter), $output);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
test_algebraic_formatter!(long_pawn_move, Long, White Pawn E4 - E5, "e4-e5");
|
|
||||||
test_algebraic_formatter!(long_bishop_move, Long, White Bishop A4 - D7, "Ba4-d7");
|
|
||||||
test_algebraic_formatter!(long_bishop_capture, Long, White Bishop A2 x E6, Black Knight, "Ba2xe6");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use chessfriend_core::piece;
|
|
||||||
|
|
||||||
macro_rules! assert_flag {
|
|
||||||
($move:expr, $left:expr, $right:expr, $desc:expr) => {
|
|
||||||
assert_eq!($left, $right, "{:?} -> {}", $move, stringify!($desc))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! assert_flags {
|
|
||||||
($move:expr, $quiet:expr, $double_push:expr, $en_passant:expr, $capture:expr, $castle:expr, $promotion:expr) => {
|
|
||||||
assert_flag!($move, $move.is_quiet(), $quiet, "is_quiet");
|
|
||||||
assert_flag!(
|
|
||||||
$move,
|
|
||||||
$move.is_double_push(),
|
|
||||||
$double_push,
|
|
||||||
"is_double_push"
|
|
||||||
);
|
|
||||||
assert_flag!($move, $move.is_en_passant(), $en_passant, "is_en_passant");
|
|
||||||
assert_flag!($move, $move.is_capture(), $capture, "is_capture");
|
|
||||||
assert_flag!($move, $move.is_castle(), $castle, "is_castle");
|
|
||||||
assert_flag!($move, $move.is_promotion(), $promotion, "is_promotion");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn move_flags_quiet() {
|
|
||||||
let mv = MoveBuilder::new(piece!(White Pawn), Square::A4, Square::A5).build();
|
|
||||||
assert_flags!(mv, true, false, false, false, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn move_flags_double_push() {
|
|
||||||
let mv = MoveBuilder::new(piece!(White Pawn), Square::C2, Square::C4).build();
|
|
||||||
assert_flags!(mv, false, true, false, false, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn move_flags_capture() {
|
|
||||||
let mv = MoveBuilder::new(piece!(White Pawn), Square::A4, Square::B5)
|
|
||||||
.capturing(piece!(Black Bishop on B5))
|
|
||||||
.build();
|
|
||||||
assert_flags!(mv, false, false, false, true, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn move_flags_en_passant_capture() {
|
|
||||||
let mv = MoveBuilder::new(piece!(White Pawn), Square::A5, Square::B6)
|
|
||||||
.capturing_en_passant(piece!(Black Pawn on B5))
|
|
||||||
.build();
|
|
||||||
assert_flags!(mv, false, false, true, true, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn move_flags_promotion() {
|
|
||||||
let mv = MoveBuilder::new(piece!(White Pawn), Square::H7, Square::H8)
|
|
||||||
.promoting_to(Shape::Queen)
|
|
||||||
.build();
|
|
||||||
assert_flags!(mv, false, false, false, false, false, true);
|
|
||||||
assert_eq!(mv.promotion(), Some(Shape::Queen));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn move_flags_capture_promotion() {
|
|
||||||
let mv = MoveBuilder::new(piece!(White Pawn), Square::H7, Square::G8)
|
|
||||||
.capturing(piece!(Black Knight on G8))
|
|
||||||
.promoting_to(Shape::Queen)
|
|
||||||
.build();
|
|
||||||
assert_flags!(mv, false, false, false, true, false, true);
|
|
||||||
assert_eq!(mv.promotion(), Some(Shape::Queen));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn move_flags_castle() {
|
|
||||||
let mv = MoveBuilder::new(piece!(Black King), Square::E8, Square::G8)
|
|
||||||
.castle(Castle::KingSide)
|
|
||||||
.build();
|
|
||||||
assert_flags!(mv, false, false, false, false, true, false);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue