Add make_move related functions into move.rs
This commit is contained in:
244
src/board.rs
244
src/board.rs
@@ -4,14 +4,13 @@ use crate::attack::{
|
|||||||
fetch_bishop_attacks, fetch_king_attacks, fetch_knight_attacks, fetch_pawn_attacks,
|
fetch_bishop_attacks, fetch_king_attacks, fetch_knight_attacks, fetch_pawn_attacks,
|
||||||
fetch_queen_attacks, fetch_rook_attacks,
|
fetch_queen_attacks, fetch_rook_attacks,
|
||||||
};
|
};
|
||||||
use crate::bitboard::{have_common_bit, lsb, square_to_bitboard};
|
use crate::bitboard::have_common_bit;
|
||||||
use crate::movegen::{
|
use crate::movegen::{
|
||||||
bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves,
|
bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves,
|
||||||
queen_pseudo_moves, rook_pseudo_moves,
|
queen_pseudo_moves, rook_pseudo_moves,
|
||||||
};
|
};
|
||||||
use crate::r#move::{Move, MoveType, Promote};
|
use crate::r#move::Move;
|
||||||
use crate::square::Square;
|
use crate::state::State;
|
||||||
use crate::state::{Castle, State};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Board {
|
pub struct Board {
|
||||||
@@ -65,17 +64,6 @@ impl Board {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_piece(&mut self, piece: Piece) {
|
|
||||||
match piece.color {
|
|
||||||
Color::Black => self.black_pieces[piece.kind.idx()].bitboard |= piece.bitboard,
|
|
||||||
Color::White => self.white_pieces[piece.kind.idx()].bitboard |= piece.bitboard,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_state(&mut self, state: State) {
|
|
||||||
self.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn white_occupancies(&self) -> Bitboard {
|
pub fn white_occupancies(&self) -> Bitboard {
|
||||||
self.white_pieces.iter().fold(0, |acc, p| p.bitboard | acc)
|
self.white_pieces.iter().fold(0, |acc, p| p.bitboard | acc)
|
||||||
}
|
}
|
||||||
@@ -130,6 +118,7 @@ impl Board {
|
|||||||
moves.extend(self.pseudo_moves(color, Kind::King));
|
moves.extend(self.pseudo_moves(color, Kind::King));
|
||||||
moves
|
moves
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pseudo_moves(&self, color: Color, kind: Kind) -> Vec<Move> {
|
pub fn pseudo_moves(&self, color: Color, kind: Kind) -> Vec<Move> {
|
||||||
let all_occupancies = self.all_occupancies();
|
let all_occupancies = self.all_occupancies();
|
||||||
let (pieces, opponent_occupancies, own_occupancies) = match color {
|
let (pieces, opponent_occupancies, own_occupancies) = match color {
|
||||||
@@ -161,125 +150,15 @@ impl Board {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_move_and_reset(&mut self, mv: Move, color: Color) -> bool {
|
pub fn set_piece(&mut self, piece: Piece) {
|
||||||
let original_board = self.clone();
|
match piece.color {
|
||||||
let result = self.make_move(mv, color);
|
Color::Black => self.black_pieces[piece.kind.idx()].bitboard |= piece.bitboard,
|
||||||
*self = original_board;
|
Color::White => self.white_pieces[piece.kind.idx()].bitboard |= piece.bitboard,
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn make_move(&mut self, mv: Move, color: Color) -> bool {
|
|
||||||
self.update_board_state(&mv, color);
|
|
||||||
|
|
||||||
let pieces = match color {
|
|
||||||
Color::White => &self.white_pieces,
|
|
||||||
Color::Black => &self.black_pieces,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.state.update_castling_state_quiet(mv.src, color);
|
|
||||||
self.state
|
|
||||||
.update_castling_state_capture(mv.dst, Color::opponent_color(color));
|
|
||||||
self.state.change_side();
|
|
||||||
|
|
||||||
let own_king_square = lsb(pieces[Kind::King.idx()].bitboard);
|
|
||||||
self.is_move_legit(own_king_square, Color::opponent_color(color))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_board_state(&mut self, mv: &Move, color: Color) {
|
|
||||||
let (own_pieces, opponent_pieces) = match color {
|
|
||||||
Color::White => (&mut self.white_pieces, &mut self.black_pieces),
|
|
||||||
Color::Black => (&mut self.black_pieces, &mut self.white_pieces),
|
|
||||||
};
|
|
||||||
|
|
||||||
match &mv.move_type {
|
|
||||||
MoveType::Quiet => {
|
|
||||||
Self::move_piece(mv.src, mv.dst, own_pieces);
|
|
||||||
self.state.set_en_passant_target_square(None);
|
|
||||||
}
|
|
||||||
MoveType::Capture => {
|
|
||||||
Self::move_piece(mv.src, mv.dst, own_pieces);
|
|
||||||
Self::remove_piece(mv.dst, opponent_pieces);
|
|
||||||
self.state.set_en_passant_target_square(None);
|
|
||||||
}
|
|
||||||
MoveType::EnPassant => {
|
|
||||||
Self::move_piece(mv.src, mv.dst, own_pieces);
|
|
||||||
Self::remove_pawn_enpassant(mv.dst, opponent_pieces, color);
|
|
||||||
self.state.set_en_passant_target_square(None);
|
|
||||||
}
|
|
||||||
MoveType::DoublePush => {
|
|
||||||
Self::move_piece(mv.src, mv.dst, own_pieces);
|
|
||||||
let en_passant = match color {
|
|
||||||
Color::White => Some(mv.src + 8),
|
|
||||||
Color::Black => Some(mv.src - 8),
|
|
||||||
};
|
|
||||||
self.state.set_en_passant_target_square(en_passant);
|
|
||||||
}
|
|
||||||
MoveType::Promotion(promote) => {
|
|
||||||
Self::remove_piece(mv.src, own_pieces);
|
|
||||||
Self::promote_piece(mv.dst, own_pieces, *promote);
|
|
||||||
self.state.set_en_passant_target_square(None);
|
|
||||||
}
|
|
||||||
MoveType::PromotionCapture(promote) => {
|
|
||||||
Self::remove_piece(mv.src, own_pieces);
|
|
||||||
Self::remove_piece(mv.dst, opponent_pieces);
|
|
||||||
Self::promote_piece(mv.dst, own_pieces, *promote);
|
|
||||||
self.state.set_en_passant_target_square(None);
|
|
||||||
}
|
|
||||||
MoveType::Castle => {
|
|
||||||
Self::move_piece(mv.src, mv.dst, own_pieces);
|
|
||||||
Self::move_rook_castle(mv.dst, own_pieces);
|
|
||||||
self.state.set_en_passant_target_square(None);
|
|
||||||
self.state.set_castling_ability(color, Castle::None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn move_piece(src: usize, dst: usize, pieces: &mut [Piece; 6]) {
|
|
||||||
for p in pieces.iter_mut() {
|
|
||||||
if have_common_bit(p.bitboard, square_to_bitboard(src)) {
|
|
||||||
p.bitboard &= !square_to_bitboard(src);
|
|
||||||
p.bitboard |= square_to_bitboard(dst);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn move_rook_castle(king_dst: usize, pieces: &mut [Piece; 6]) {
|
|
||||||
let (rook_src, rook_dst) = match king_dst {
|
|
||||||
Square::C1 | Square::C8 => (king_dst - 2, king_dst + 1),
|
|
||||||
Square::G1 | Square::G8 => (king_dst + 1, king_dst - 1),
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
Self::move_piece(rook_src, rook_dst, pieces);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn promote_piece(square: usize, pieces: &mut [Piece; 6], promote: Promote) {
|
|
||||||
match promote {
|
|
||||||
Promote::Knight => pieces[Kind::Knight.idx()].bitboard |= square_to_bitboard(square),
|
|
||||||
Promote::Bishop => pieces[Kind::Bishop.idx()].bitboard |= square_to_bitboard(square),
|
|
||||||
Promote::Rook => pieces[Kind::Rook.idx()].bitboard |= square_to_bitboard(square),
|
|
||||||
Promote::Queen => pieces[Kind::Queen.idx()].bitboard |= square_to_bitboard(square),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_piece(square: usize, pieces: &mut [Piece; 6]) {
|
pub fn set_state(&mut self, state: State) {
|
||||||
for p in pieces.iter_mut() {
|
self.state = state;
|
||||||
if have_common_bit(p.bitboard, square_to_bitboard(square)) {
|
|
||||||
p.bitboard &= !(square_to_bitboard(square));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_pawn_enpassant(square: usize, pieces: &mut [Piece; 6], color: Color) {
|
|
||||||
let piece_to_remove = match color {
|
|
||||||
Color::White => square - 8,
|
|
||||||
Color::Black => square + 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
Self::remove_piece(piece_to_remove, pieces);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,107 +253,4 @@ mod tests {
|
|||||||
//TODO: make a MoveHistory/BoardHistory/GameHistory struct
|
//TODO: make a MoveHistory/BoardHistory/GameHistory struct
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
const FEN_QUIET: [&str; 2] = [
|
|
||||||
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1",
|
|
||||||
"r3k2r/2p1p1qp/2npb3/1p3p2/pP2P1pP/P1PB1Q2/3PNPP1/R3K2R b KQkq b3 0 1",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_make_move_quiet() -> Result<(), String> {
|
|
||||||
let mut game = from_fen(FEN_QUIET[0])?;
|
|
||||||
let mv = Move::new_with_type(9, 25, MoveType::DoublePush);
|
|
||||||
game.board.make_move(mv, Color::White);
|
|
||||||
assert_eq!(game, from_fen(FEN_QUIET[1])?);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
const FEN_CAPTURE: [&str; 2] = [
|
|
||||||
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1",
|
|
||||||
"r3k2r/2p1p1qp/2npb3/1p3Q2/p3P1pP/P1PB4/1P1PNPP1/R3K2R b KQkq - 0 1",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_make_move_capture() -> Result<(), String> {
|
|
||||||
let mut game = from_fen(FEN_CAPTURE[0])?;
|
|
||||||
let mv = Move::new_with_type(21, 37, MoveType::Capture);
|
|
||||||
game.board.make_move(mv, Color::White);
|
|
||||||
assert_eq!(game, from_fen(FEN_CAPTURE[1])?);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
const FEN_EN_PASSANT: [&str; 2] = [
|
|
||||||
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R b KQkq h3 0 1",
|
|
||||||
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P3/P1PB1Q1p/1P1PNPP1/R3K2R w KQkq - 0 1",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_make_move_en_passant() -> Result<(), String> {
|
|
||||||
let mut game = from_fen(FEN_EN_PASSANT[0])?;
|
|
||||||
let mv = Move::new_with_type(30, 23, MoveType::EnPassant);
|
|
||||||
game.board.make_move(mv, Color::Black);
|
|
||||||
assert_eq!(game, from_fen(FEN_EN_PASSANT[1])?);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
const FEN_DOUBLE_PUSH: [&str; 2] = [
|
|
||||||
"rnbqkbnr/p1pppppp/8/8/1p5P/8/PPPPPPP1/RNBQKBNR w KQkq - 0 1",
|
|
||||||
"rnbqkbnr/p1pppppp/8/8/1pP4P/8/PP1PPPP1/RNBQKBNR b KQkq c3 0 1",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_make_move_double_push() -> Result<(), String> {
|
|
||||||
let mut game = from_fen(FEN_DOUBLE_PUSH[0])?;
|
|
||||||
let mv = Move::new_with_type(10, 26, MoveType::DoublePush);
|
|
||||||
game.board.make_move(mv, Color::White);
|
|
||||||
assert_eq!(game, from_fen(FEN_DOUBLE_PUSH[1])?);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
const FEN_PROMOTION: [&str; 2] = [
|
|
||||||
"8/6P1/4n2b/1p6/1Kp5/6n1/4b3/1k6 w - - 0 1",
|
|
||||||
"6Q1/8/4n2b/1p6/1Kp5/6n1/4b3/1k6 b - - 0 1",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_make_move_promotion() -> Result<(), String> {
|
|
||||||
let mut game = from_fen(FEN_PROMOTION[0])?;
|
|
||||||
let mv = Move::new_with_type(54, 62, MoveType::Promotion(Promote::Queen));
|
|
||||||
game.board.make_move(mv, Color::White);
|
|
||||||
assert_eq!(game, from_fen(FEN_PROMOTION[1])?);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
const FEN_PROMOTION_CAPTURE: [&str; 2] = [
|
|
||||||
"5n2/6P1/7b/1p6/1Kp5/6n1/4b3/1k6 w - - 0 1",
|
|
||||||
"5Q2/8/7b/1p6/1Kp5/6n1/4b3/1k6 b - - 0 1",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_make_move_promotion_capture() -> Result<(), String> {
|
|
||||||
let mut game = from_fen(FEN_PROMOTION_CAPTURE[0])?;
|
|
||||||
let mv = Move::new_with_type(54, 61, MoveType::PromotionCapture(Promote::Queen));
|
|
||||||
game.board.make_move(mv, Color::White);
|
|
||||||
assert_eq!(game, from_fen(FEN_PROMOTION_CAPTURE[1])?);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
const FEN_CASTLE: [&str; 2] = [
|
|
||||||
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1",
|
|
||||||
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R4RK1 b kq - 0 1",
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_make_move_castle() -> Result<(), String> {
|
|
||||||
let mut game = from_fen(FEN_CASTLE[0])?;
|
|
||||||
let mv = Move::new_with_type(4, 6, MoveType::Castle);
|
|
||||||
game.board.make_move(mv, Color::White);
|
|
||||||
assert_eq!(game, from_fen(FEN_CASTLE[1])?);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
233
src/move.rs
233
src/move.rs
@@ -1,3 +1,10 @@
|
|||||||
|
use crate::{
|
||||||
|
bitboard::{have_common_bit, lsb, square_to_bitboard},
|
||||||
|
board::{Board, Color, Kind, Piece},
|
||||||
|
square::Square,
|
||||||
|
state::Castle,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||||
pub enum Promote {
|
pub enum Promote {
|
||||||
Knight,
|
Knight,
|
||||||
@@ -42,5 +49,229 @@ impl Move {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Board {
|
||||||
|
pub fn make_move(&mut self, mv: Move, color: Color) -> bool {
|
||||||
|
self.update_board_state(&mv, color);
|
||||||
|
|
||||||
|
let pieces = match color {
|
||||||
|
Color::White => &self.white_pieces,
|
||||||
|
Color::Black => &self.black_pieces,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.state.update_castling_state_quiet(mv.src, color);
|
||||||
|
self.state
|
||||||
|
.update_castling_state_capture(mv.dst, Color::opponent_color(color));
|
||||||
|
self.state.change_side();
|
||||||
|
|
||||||
|
let own_king_square = lsb(pieces[Kind::King.idx()].bitboard);
|
||||||
|
self.is_move_legit(own_king_square, Color::opponent_color(color))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_board_state(&mut self, mv: &Move, color: Color) {
|
||||||
|
let (own_pieces, opponent_pieces) = match color {
|
||||||
|
Color::White => (&mut self.white_pieces, &mut self.black_pieces),
|
||||||
|
Color::Black => (&mut self.black_pieces, &mut self.white_pieces),
|
||||||
|
};
|
||||||
|
|
||||||
|
match &mv.move_type {
|
||||||
|
MoveType::Quiet => {
|
||||||
|
Self::move_piece(mv.src, mv.dst, own_pieces);
|
||||||
|
self.state.set_en_passant_target_square(None);
|
||||||
|
}
|
||||||
|
MoveType::Capture => {
|
||||||
|
Self::move_piece(mv.src, mv.dst, own_pieces);
|
||||||
|
Self::remove_piece(mv.dst, opponent_pieces);
|
||||||
|
self.state.set_en_passant_target_square(None);
|
||||||
|
}
|
||||||
|
MoveType::EnPassant => {
|
||||||
|
Self::move_piece(mv.src, mv.dst, own_pieces);
|
||||||
|
Self::remove_pawn_enpassant(mv.dst, opponent_pieces, color);
|
||||||
|
self.state.set_en_passant_target_square(None);
|
||||||
|
}
|
||||||
|
MoveType::DoublePush => {
|
||||||
|
Self::move_piece(mv.src, mv.dst, own_pieces);
|
||||||
|
let en_passant = match color {
|
||||||
|
Color::White => Some(mv.src + 8),
|
||||||
|
Color::Black => Some(mv.src - 8),
|
||||||
|
};
|
||||||
|
self.state.set_en_passant_target_square(en_passant);
|
||||||
|
}
|
||||||
|
MoveType::Promotion(promote) => {
|
||||||
|
Self::remove_piece(mv.src, own_pieces);
|
||||||
|
Self::promote_piece(mv.dst, own_pieces, *promote);
|
||||||
|
self.state.set_en_passant_target_square(None);
|
||||||
|
}
|
||||||
|
MoveType::PromotionCapture(promote) => {
|
||||||
|
Self::remove_piece(mv.src, own_pieces);
|
||||||
|
Self::remove_piece(mv.dst, opponent_pieces);
|
||||||
|
Self::promote_piece(mv.dst, own_pieces, *promote);
|
||||||
|
self.state.set_en_passant_target_square(None);
|
||||||
|
}
|
||||||
|
MoveType::Castle => {
|
||||||
|
Self::move_piece(mv.src, mv.dst, own_pieces);
|
||||||
|
Self::move_rook_castle(mv.dst, own_pieces);
|
||||||
|
self.state.set_en_passant_target_square(None);
|
||||||
|
self.state.set_castling_ability(color, Castle::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_piece(src: usize, dst: usize, pieces: &mut [Piece; 6]) {
|
||||||
|
for p in pieces.iter_mut() {
|
||||||
|
if have_common_bit(p.bitboard, square_to_bitboard(src)) {
|
||||||
|
p.bitboard &= !square_to_bitboard(src);
|
||||||
|
p.bitboard |= square_to_bitboard(dst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_rook_castle(king_dst: usize, pieces: &mut [Piece; 6]) {
|
||||||
|
let (rook_src, rook_dst) = match king_dst {
|
||||||
|
Square::C1 | Square::C8 => (king_dst - 2, king_dst + 1),
|
||||||
|
Square::G1 | Square::G8 => (king_dst + 1, king_dst - 1),
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::move_piece(rook_src, rook_dst, pieces);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn promote_piece(square: usize, pieces: &mut [Piece; 6], promote: Promote) {
|
||||||
|
match promote {
|
||||||
|
Promote::Knight => pieces[Kind::Knight.idx()].bitboard |= square_to_bitboard(square),
|
||||||
|
Promote::Bishop => pieces[Kind::Bishop.idx()].bitboard |= square_to_bitboard(square),
|
||||||
|
Promote::Rook => pieces[Kind::Rook.idx()].bitboard |= square_to_bitboard(square),
|
||||||
|
Promote::Queen => pieces[Kind::Queen.idx()].bitboard |= square_to_bitboard(square),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_piece(square: usize, pieces: &mut [Piece; 6]) {
|
||||||
|
for p in pieces.iter_mut() {
|
||||||
|
if have_common_bit(p.bitboard, square_to_bitboard(square)) {
|
||||||
|
p.bitboard &= !(square_to_bitboard(square));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_pawn_enpassant(square: usize, pieces: &mut [Piece; 6], color: Color) {
|
||||||
|
let piece_to_remove = match color {
|
||||||
|
Color::White => square - 8,
|
||||||
|
Color::Black => square + 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::remove_piece(piece_to_remove, pieces);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {}
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
board::Color,
|
||||||
|
fen::from_fen,
|
||||||
|
r#move::{Move, MoveType, Promote},
|
||||||
|
};
|
||||||
|
|
||||||
|
const FEN_QUIET: [&str; 2] = [
|
||||||
|
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1",
|
||||||
|
"r3k2r/2p1p1qp/2npb3/1p3p2/pP2P1pP/P1PB1Q2/3PNPP1/R3K2R b KQkq b3 0 1",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_make_move_quiet() -> Result<(), String> {
|
||||||
|
let mut game = from_fen(FEN_QUIET[0])?;
|
||||||
|
let mv = Move::new_with_type(9, 25, MoveType::DoublePush);
|
||||||
|
game.board.make_move(mv, Color::White);
|
||||||
|
assert_eq!(game, from_fen(FEN_QUIET[1])?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const FEN_CAPTURE: [&str; 2] = [
|
||||||
|
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1",
|
||||||
|
"r3k2r/2p1p1qp/2npb3/1p3Q2/p3P1pP/P1PB4/1P1PNPP1/R3K2R b KQkq - 0 1",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_make_move_capture() -> Result<(), String> {
|
||||||
|
let mut game = from_fen(FEN_CAPTURE[0])?;
|
||||||
|
let mv = Move::new_with_type(21, 37, MoveType::Capture);
|
||||||
|
game.board.make_move(mv, Color::White);
|
||||||
|
assert_eq!(game, from_fen(FEN_CAPTURE[1])?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const FEN_EN_PASSANT: [&str; 2] = [
|
||||||
|
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R b KQkq h3 0 1",
|
||||||
|
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P3/P1PB1Q1p/1P1PNPP1/R3K2R w KQkq - 0 1",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_make_move_en_passant() -> Result<(), String> {
|
||||||
|
let mut game = from_fen(FEN_EN_PASSANT[0])?;
|
||||||
|
let mv = Move::new_with_type(30, 23, MoveType::EnPassant);
|
||||||
|
game.board.make_move(mv, Color::Black);
|
||||||
|
assert_eq!(game, from_fen(FEN_EN_PASSANT[1])?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const FEN_DOUBLE_PUSH: [&str; 2] = [
|
||||||
|
"rnbqkbnr/p1pppppp/8/8/1p5P/8/PPPPPPP1/RNBQKBNR w KQkq - 0 1",
|
||||||
|
"rnbqkbnr/p1pppppp/8/8/1pP4P/8/PP1PPPP1/RNBQKBNR b KQkq c3 0 1",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_make_move_double_push() -> Result<(), String> {
|
||||||
|
let mut game = from_fen(FEN_DOUBLE_PUSH[0])?;
|
||||||
|
let mv = Move::new_with_type(10, 26, MoveType::DoublePush);
|
||||||
|
game.board.make_move(mv, Color::White);
|
||||||
|
assert_eq!(game, from_fen(FEN_DOUBLE_PUSH[1])?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const FEN_PROMOTION: [&str; 2] = [
|
||||||
|
"8/6P1/4n2b/1p6/1Kp5/6n1/4b3/1k6 w - - 0 1",
|
||||||
|
"6Q1/8/4n2b/1p6/1Kp5/6n1/4b3/1k6 b - - 0 1",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_make_move_promotion() -> Result<(), String> {
|
||||||
|
let mut game = from_fen(FEN_PROMOTION[0])?;
|
||||||
|
let mv = Move::new_with_type(54, 62, MoveType::Promotion(Promote::Queen));
|
||||||
|
game.board.make_move(mv, Color::White);
|
||||||
|
assert_eq!(game, from_fen(FEN_PROMOTION[1])?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const FEN_PROMOTION_CAPTURE: [&str; 2] = [
|
||||||
|
"5n2/6P1/7b/1p6/1Kp5/6n1/4b3/1k6 w - - 0 1",
|
||||||
|
"5Q2/8/7b/1p6/1Kp5/6n1/4b3/1k6 b - - 0 1",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_make_move_promotion_capture() -> Result<(), String> {
|
||||||
|
let mut game = from_fen(FEN_PROMOTION_CAPTURE[0])?;
|
||||||
|
let mv = Move::new_with_type(54, 61, MoveType::PromotionCapture(Promote::Queen));
|
||||||
|
game.board.make_move(mv, Color::White);
|
||||||
|
assert_eq!(game, from_fen(FEN_PROMOTION_CAPTURE[1])?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const FEN_CASTLE: [&str; 2] = [
|
||||||
|
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R3K2R w KQkq - 0 1",
|
||||||
|
"r3k2r/2p1p1qp/2npb3/1p3p2/p3P1pP/P1PB1Q2/1P1PNPP1/R4RK1 b kq - 0 1",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_make_move_castle() -> Result<(), String> {
|
||||||
|
let mut game = from_fen(FEN_CASTLE[0])?;
|
||||||
|
let mv = Move::new_with_type(4, 6, MoveType::Castle);
|
||||||
|
game.board.make_move(mv, Color::White);
|
||||||
|
assert_eq!(game, from_fen(FEN_CASTLE[1])?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user