diff --git a/bitboard/src/bitboard.rs b/bitboard/src/bitboard.rs index b2e1a4c..2f9740d 100644 --- a/bitboard/src/bitboard.rs +++ b/bitboard/src/bitboard.rs @@ -18,6 +18,9 @@ macro_rules! moves_getter { } impl BitBoard { + pub const EMPTY: BitBoard = BitBoard(0); + pub const FULL: BitBoard = BitBoard(0xFFFFFFFFFFFFFFFF); + pub const fn empty() -> BitBoard { BitBoard(0) } diff --git a/position/src/move_generator.rs b/position/src/move_generator.rs index eef5fcf..7e193c1 100644 --- a/position/src/move_generator.rs +++ b/position/src/move_generator.rs @@ -17,6 +17,7 @@ use self::{ rook::ClassicalMoveGenerator as RookMoveGenerator, }; use crate::{Move, Position}; +use chessfriend_bitboard::BitBoard; use chessfriend_core::{Color, Piece, PlacedPiece, Shape, Square}; use std::collections::BTreeMap; @@ -47,10 +48,12 @@ macro_rules! move_generator_declaration { pub(super) fn new( position: &$crate::Position, color: chessfriend_core::Color, + capture_mask: chessfriend_bitboard::BitBoard, + push_mask: chessfriend_bitboard::BitBoard, ) -> $name { $name { color, - move_sets: Self::move_sets(position, color), + move_sets: Self::move_sets(position, color, capture_mask, push_mask), } } } @@ -83,21 +86,32 @@ pub(self) use move_generator_declaration; trait MoveGeneratorInternal { fn piece(color: Color) -> Piece; - fn move_sets(position: &Position, color: Color) -> BTreeMap { + fn move_sets( + position: &Position, + color: Color, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> BTreeMap { let piece = Self::piece(color); BTreeMap::from_iter( position .bitboard_for_piece(piece) .occupied_squares() - .map(|sq| { - let placed_piece = PlacedPiece::new(piece, sq); - let move_set = Self::move_set_for_piece(position, placed_piece); - (sq, move_set) + .map(|square| { + let piece = PlacedPiece::new(piece, square); + let move_set = + Self::move_set_for_piece(position, piece, capture_mask, push_mask); + (square, move_set) }), ) } - fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet; + fn move_set_for_piece( + position: &Position, + piece: PlacedPiece, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> MoveSet; } #[derive(Clone, Debug, Eq, PartialEq)] @@ -111,14 +125,19 @@ pub struct Moves { } impl Moves { - pub fn new(position: &Position, color: Color) -> Moves { + pub fn new( + position: &Position, + color: Color, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> Moves { Moves { - pawn_moves: PawnMoveGenerator::new(position, color), - knight_moves: KnightMoveGenerator::new(position, color), - bishop_moves: BishopMoveGenerator::new(position, color), - rook_moves: RookMoveGenerator::new(position, color), - queen_moves: QueenMoveGenerator::new(position, color), - king_moves: KingMoveGenerator::new(position, color), + pawn_moves: PawnMoveGenerator::new(position, color, capture_mask, push_mask), + knight_moves: KnightMoveGenerator::new(position, color, capture_mask, push_mask), + bishop_moves: BishopMoveGenerator::new(position, color, capture_mask, push_mask), + rook_moves: RookMoveGenerator::new(position, color, capture_mask, push_mask), + queen_moves: QueenMoveGenerator::new(position, color, capture_mask, push_mask), + king_moves: KingMoveGenerator::new(position, color, capture_mask, push_mask), } } diff --git a/position/src/move_generator/bishop.rs b/position/src/move_generator/bishop.rs index 3eb1405..ec6a96a 100644 --- a/position/src/move_generator/bishop.rs +++ b/position/src/move_generator/bishop.rs @@ -12,7 +12,12 @@ impl MoveGeneratorInternal for ClassicalMoveGenerator { Piece::bishop(color) } - fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet { + fn move_set_for_piece( + position: &Position, + placed_piece: PlacedPiece, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> MoveSet { let piece = placed_piece.piece(); let square = placed_piece.square(); @@ -64,7 +69,8 @@ mod tests { White Bishop on A1, ]; - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), @@ -84,7 +90,8 @@ mod tests { println!("{}", DiagramFormatter::new(&pos)); - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), @@ -102,7 +109,8 @@ mod tests { Black Knight on C3, ]; - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), @@ -120,7 +128,8 @@ mod tests { println!("{}", DiagramFormatter::new(&pos)); - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let bitboard = generator.bitboard(); let expected = BitBoard::new( 0b00000001_10000010_01000100_00101000_00000000_00101000_01000100_10000010, diff --git a/position/src/move_generator/king.rs b/position/src/move_generator/king.rs index 5867876..7941bf3 100644 --- a/position/src/move_generator/king.rs +++ b/position/src/move_generator/king.rs @@ -17,7 +17,12 @@ impl MoveGeneratorInternal for KingMoveGenerator { Piece::king(color) } - fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet { + fn move_set_for_piece( + position: &Position, + placed_piece: PlacedPiece, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> MoveSet { let piece = placed_piece.piece(); let color = piece.color(); let square = placed_piece.square(); @@ -61,7 +66,7 @@ mod tests { fn one_king() { let pos = position![White King on E4]; - let generator = KingMoveGenerator::new(&pos, Color::White); + let generator = KingMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), @@ -88,7 +93,7 @@ mod tests { fn one_king_corner() { let pos = position![White King on A1]; - let generator = KingMoveGenerator::new(&pos, Color::White); + let generator = KingMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let generated_bitboard = generator.bitboard(); let expected_bitboard = bitboard![A2, B2, B1]; @@ -132,7 +137,7 @@ mod tests { assert!(pos.is_king_in_check()); - let generator = KingMoveGenerator::new(&pos, Color::Black); + let generator = KingMoveGenerator::new(&pos, Color::Black, BitBoard::FULL, BitBoard::FULL); let generated_moves = generator.bitboard(); let expected_moves = bitboard![F8, F7, F6, D6, D7, D8]; @@ -151,7 +156,7 @@ mod tests { assert!(pos.player_can_castle(Color::White, Castle::KingSide)); assert!(pos.player_can_castle(Color::White, Castle::QueenSide)); - let generator = KingMoveGenerator::new(&pos, Color::White); + let generator = KingMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let generated_moves: HashSet = generator.iter().collect(); let king = piece!(White King); @@ -179,7 +184,7 @@ mod tests { assert!(pos.player_can_castle(Color::White, Castle::KingSide)); assert!(!pos.player_can_castle(Color::White, Castle::QueenSide)); - let generator = KingMoveGenerator::new(&pos, Color::White); + let generator = KingMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let generated_moves: HashSet = generator.iter().collect(); let king = piece!(White King); @@ -207,7 +212,7 @@ mod tests { assert!(!pos.player_can_castle(Color::White, Castle::KingSide)); assert!(pos.player_can_castle(Color::White, Castle::QueenSide)); - let generator = KingMoveGenerator::new(&pos, Color::White); + let generator = KingMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let generated_moves: HashSet = generator.iter().collect(); let king = piece!(White King); diff --git a/position/src/move_generator/knight.rs b/position/src/move_generator/knight.rs index aa2a7af..0f5bca3 100644 --- a/position/src/move_generator/knight.rs +++ b/position/src/move_generator/knight.rs @@ -12,7 +12,12 @@ impl MoveGeneratorInternal for KnightMoveGenerator { Piece::knight(color) } - fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet { + fn move_set_for_piece( + position: &Position, + placed_piece: PlacedPiece, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> MoveSet { let opposing_pieces = position.bitboard_for_color(placed_piece.piece().color().other()); let empty_squares = position.empty_squares(); let knight_moves = BitBoard::knight_moves(placed_piece.square()); @@ -39,7 +44,8 @@ mod tests { White Knight on E4, ]; - let generator = KnightMoveGenerator::new(&pos, Color::White); + let generator = + KnightMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); /* let bb = generator.bitboard(); diff --git a/position/src/move_generator/pawn.rs b/position/src/move_generator/pawn.rs index 728ba05..9bfbbd5 100644 --- a/position/src/move_generator/pawn.rs +++ b/position/src/move_generator/pawn.rs @@ -15,7 +15,12 @@ impl MoveGeneratorInternal for PawnMoveGenerator { Piece::pawn(color) } - fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet { + fn move_set_for_piece( + position: &Position, + placed_piece: PlacedPiece, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> MoveSet { let capture_moves = Self::attacks(position, placed_piece); let quiet_moves = Self::pushes(position, placed_piece); @@ -65,7 +70,7 @@ mod tests { fn one_2square_push() { let pos = test_position![White Pawn on E2]; - let generator = PawnMoveGenerator::new(&pos, Color::White); + let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let expected_moves = HashSet::from_iter([ MoveBuilder::new(piece!(White Pawn), Square::E2, Square::E3).build(), @@ -81,7 +86,7 @@ mod tests { fn one_1square_push() { let pos = test_position![White Pawn on E3]; - let generator = PawnMoveGenerator::new(&pos, Color::White); + let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let expected_moves = HashSet::from_iter([MoveBuilder::new( Piece::pawn(Color::White), @@ -104,7 +109,7 @@ mod tests { println!("{}", DiagramFormatter::new(&pos)); - let generator = PawnMoveGenerator::new(&pos, Color::White); + let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let expected_moves = HashSet::from_iter([MoveBuilder::new( Piece::pawn(Color::White), @@ -125,7 +130,7 @@ mod tests { White Knight on E3, ]; - let generator = PawnMoveGenerator::new(&pos, Color::White); + let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let generated_moves: HashSet = generator.iter().collect(); let expected_moves: HashSet = HashSet::new(); @@ -141,7 +146,7 @@ mod tests { Black Knight on D5, ]; - let generator = PawnMoveGenerator::new(&pos, Color::White); + let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let expected_moves = HashSet::from_iter( @@ -164,7 +169,7 @@ mod tests { Black Queen on F5, ]; - let generator = PawnMoveGenerator::new(&pos, Color::White); + let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let expected_moves = HashSet::from_iter([ MoveBuilder::new(piece!(White Pawn), Square::E4, Square::D5) diff --git a/position/src/move_generator/queen.rs b/position/src/move_generator/queen.rs index 737686c..943b46d 100644 --- a/position/src/move_generator/queen.rs +++ b/position/src/move_generator/queen.rs @@ -12,7 +12,12 @@ impl MoveGeneratorInternal for ClassicalMoveGenerator { Piece::queen(color) } - fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet { + fn move_set_for_piece( + position: &Position, + placed_piece: PlacedPiece, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> MoveSet { let piece = placed_piece.piece(); let color = piece.color(); let square = placed_piece.square(); @@ -68,7 +73,8 @@ mod tests { fn classical_single_queen_bitboard() { let pos = position![White Queen on B2]; - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let bitboard = generator.bitboard(); let expected = bitboard![ A2, C2, D2, E2, F2, G2, H2, // Rank @@ -94,7 +100,8 @@ mod tests { println!("{}", DiagramFormatter::new(&pos)); - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); let bitboard = generator.bitboard(); let expected = BitBoard::new( 0b10000001_01000001_00100001_00010001_00001001_00000101_00000011_00001110, @@ -116,7 +123,8 @@ mod tests { ]; println!("{}", DiagramFormatter::new(&pos)); - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), @@ -134,7 +142,8 @@ mod tests { let pos = position![White Queen on D3]; println!("{}", DiagramFormatter::new(&pos)); - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), diff --git a/position/src/move_generator/rook.rs b/position/src/move_generator/rook.rs index 72f237b..1389b11 100644 --- a/position/src/move_generator/rook.rs +++ b/position/src/move_generator/rook.rs @@ -12,7 +12,12 @@ impl MoveGeneratorInternal for ClassicalMoveGenerator { Piece::rook(color) } - fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet { + fn move_set_for_piece( + position: &Position, + placed_piece: PlacedPiece, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> MoveSet { let piece = placed_piece.piece(); let color = piece.color(); let square = placed_piece.square(); @@ -64,7 +69,8 @@ mod tests { fn classical_single_rook_bitboard() { let pos = test_position![White Rook on A2]; - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), @@ -82,7 +88,8 @@ mod tests { println!("{}", DiagramFormatter::new(&pos)); - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), @@ -100,7 +107,8 @@ mod tests { Black Knight on E1, ]; - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), @@ -112,7 +120,8 @@ mod tests { fn classical_single_rook_in_center() { let pos = test_position![White Rook on D4]; - let generator = ClassicalMoveGenerator::new(&pos, Color::White); + let generator = + ClassicalMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL); assert_eq!( generator.bitboard(), diff --git a/position/src/position/position.rs b/position/src/position/position.rs index 0443929..31e772d 100644 --- a/position/src/position/position.rs +++ b/position/src/position/position.rs @@ -136,7 +136,7 @@ impl Position { pub fn moves(&self) -> &Moves { self.moves - .get_or_init(|| Moves::new(self, self.color_to_move)) + .get_or_init(|| Moves::new(self, self.color_to_move, BitBoard::FULL, BitBoard::FULL)) } /// Return a BitBoard representing the set of squares containing a piece.