// Eryn Wells use super::{classical, move_generator_declaration, MoveGeneratorInternal, MoveSet, PieceSight}; use crate::{ piece::{Color, Piece, PlacedPiece}, Move, Position, }; move_generator_declaration!(ClassicalMoveGenerator); impl<'pos> MoveGeneratorInternal for ClassicalMoveGenerator<'pos> { fn piece(color: Color) -> Piece { Piece::rook(color) } fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet { let piece = placed_piece.piece(); let color = piece.color(); let square = placed_piece.square(); let blockers = position.occupied_squares(); let empty_squares = !blockers; let friendly_pieces = position.bitboard_for_color(color); let opposing_pieces = position.bitboard_for_color(color.other()); let all_moves = classical::RookSight.sight(square, position); let quiet_moves_bb = all_moves & (empty_squares | !friendly_pieces); let capture_moves_bb = all_moves & opposing_pieces; let map_to_move = |sq| Move::new(piece, square, sq); let quiet_moves = quiet_moves_bb.occupied_squares().map(map_to_move); let capture_moves = capture_moves_bb.occupied_squares().map(map_to_move); MoveSet::new(placed_piece) .quiet_moves(quiet_moves_bb, quiet_moves) .capture_moves(capture_moves_bb, capture_moves) } } #[cfg(test)] mod tests { use super::*; use crate::{ bitboard::BitBoard, piece::{Color, Piece}, position::DiagramFormatter, Position, Square, }; #[test] fn classical_single_rook_bitboard() { let mut pos = Position::empty(); [(Piece::rook(Color::White), Square::A1)] .into_iter() .for_each(|(p, sq)| { pos.place_piece(p, sq) .expect(&format!("Unable to place {:?} on {}", &p, &sq)) }); let generator = ClassicalMoveGenerator::new(&pos, Color::White); assert_eq!( generator.bitboard(), BitBoard::new( 0b00000001_00000001_00000001_00000001_00000001_00000001_00000001_11111110 ) ); } /// Test that a rook can move up to, but not onto, a friendly piece. #[test] fn classical_single_rook_with_same_color_blocker_bitboard() { let mut pos = Position::empty(); [ (Piece::rook(Color::White), Square::A1), (Piece::knight(Color::White), Square::E1), ] .into_iter() .for_each(|(p, sq)| { pos.place_piece(p, sq) .expect(&format!("Unable to place {} on {}", p, sq)) }); println!("{}", DiagramFormatter::new(&pos)); let generator = ClassicalMoveGenerator::new(&pos, Color::White); assert_eq!( generator.bitboard(), BitBoard::new( 0b00000001_00000001_00000001_00000001_00000001_00000001_00000001_00001110 ) ); } /// Test that a rook can move up to, and then capture, an enemy piece. #[test] fn classical_single_rook_with_opposing_color_blocker_bitboard() { let mut pos = Position::empty(); [ (Piece::rook(Color::White), Square::A1), (Piece::knight(Color::Black), Square::E1), ] .into_iter() .for_each(|(p, sq)| { pos.place_piece(p, sq) .expect(&format!("Unable to place {} on {}", p, sq)) }); let generator = ClassicalMoveGenerator::new(&pos, Color::White); assert_eq!( generator.bitboard(), BitBoard::new( 0b00000001_00000001_00000001_00000001_00000001_00000001_00000001_00011110 ) ); } #[test] fn classical_single_rook_in_center() { let mut pos = Position::empty(); [(Piece::rook(Color::White), Square::E4)] .into_iter() .for_each(|(p, sq)| { pos.place_piece(p, sq) .expect(&format!("Unable to place {} on {}", p, sq)) }); let generator = ClassicalMoveGenerator::new(&pos, Color::White); assert_eq!( generator.bitboard(), BitBoard::new( 0b00010000_00010000_00010000_00010000_11101111_00010000_00010000_00010000 ) ); } }