From 80b3283f4a2a09561abae1b7b981b7a3139f00e2 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Wed, 25 Jan 2023 07:50:44 +0300 Subject: refactor: implement piece_by_square --- src/board/mod.rs | 129 ++++++++++++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 68 deletions(-) (limited to 'src/board') diff --git a/src/board/mod.rs b/src/board/mod.rs index 2b580b5..67f7264 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -490,6 +490,14 @@ impl Board { mobility } + fn piece_by_square(&self, square: Square) -> Option { + self.pieces + .iter() + .enumerate() + .find(|(piece_type, bitboard)| *bitboard & square.to_bitboard() > 0) + .and_then(|(pt, _)| Some(PieceType::from(pt))) + } + /// *Blindlessly* apply a move without any validation /// Move should be validated beforehand pub fn make_move(&mut self, mov: Move) -> Result,MakeMoveError> { @@ -497,65 +505,53 @@ impl Board { let move_target_bb = mov.target.to_bitboard(); // Remove existing piece (if any) from target square - let mut captured_piece = match self.pieces - .iter() - .enumerate() - .find(|(piece_type, bitboard)| *bitboard & mov.target.to_bitboard() > 0) - { - Some((target_piece, _)) => { - self.pieces[target_piece] ^= move_target_bb; - self.hash ^= self.zobrist_seed[target_piece * 12 + mov.target as usize]; - Some(PieceType::from(target_piece)) - }, - None => None, - }; + let mut captured_piece = match self.piece_by_square(mov.target) { + Some(target_piece) => { + self.pieces[target_piece as usize] ^= move_target_bb; + self.hash ^= self.zobrist_seed[(target_piece as usize) * 12 + mov.target as usize]; + Some(target_piece) + }, + None => None, + }; // En Passant captures diffirently if mov.kind == MoveKind::EnPassant { debug_assert!(captured_piece.is_none(), "No capture should be found at this point"); let captured_square = Square::from_coords(mov.source.rank(), mov.target.file()); - let captured_bb = captured_square.to_bitboard(); - captured_piece = match self.pieces - .iter() - .enumerate() - .find(|(piece_type, bitboard)| *bitboard & captured_bb > 0) - { - Some((pawn_type, _)) => { - self.pieces[pawn_type] ^= captured_bb; - self.hash ^= self.zobrist_seed[pawn_type * 12 + captured_square as usize]; - Some(PieceType::from(pawn_type)) - } - None => { - return Err(MakeMoveError::PieceNotFound( - String::from("Pawn captured by En Passant was not found") - )) - } + captured_piece = match self.piece_by_square(captured_square) { + Some(pawn_type) => { + self.pieces[pawn_type as usize] ^= captured_square.to_bitboard(); + self.hash ^= self.zobrist_seed[pawn_type as usize* 12 + captured_square as usize]; + Some(pawn_type) } - } - - // Move a piece from source square to target - let source_piece = match self.pieces - .iter() - .enumerate() - .find(|(piece_type, bitboard)| *bitboard & mov.source.to_bitboard() > 0) - { - Some((source_piece, _)) => { - self.pieces[source_piece] ^= move_source_bb; - self.occupancy ^= move_source_bb; - self.hash ^= self.zobrist_seed[source_piece * 12 + mov.source as usize]; - - self.pieces[source_piece] |= move_target_bb; - self.occupancy |= move_target_bb; - self.hash ^= self.zobrist_seed[source_piece * 12 + mov.target as usize]; - PieceType::from(source_piece) - }, None => { - self.print(); return Err(MakeMoveError::PieceNotFound( - String::from("Source piece not found") - )) + String::from("Pawn captured by En Passant was not found") + )) } - }; + } + } + + // Move a piece from source square to target + let source_piece = match self.piece_by_square(mov.source) { + Some(source_piece) => { + let source_id = source_piece as usize; + self.pieces[source_id] ^= move_source_bb; + self.occupancy ^= move_source_bb; + self.hash ^= self.zobrist_seed[source_id * 12 + mov.source as usize]; + + self.pieces[source_id] |= move_target_bb; + self.occupancy |= move_target_bb; + self.hash ^= self.zobrist_seed[source_id * 12 + mov.target as usize]; + PieceType::from(source_piece) + }, + None => { + self.print(); + return Err(MakeMoveError::PieceNotFound( + String::from("Source piece not found") + )) + } + }; // When castling, also move a rook if mov.kind == MoveKind::Castle { @@ -571,22 +567,19 @@ impl Board { let rook_target_square = Square::from_coords(mov.target.rank(), rook_target_file); let rook_target_bb = rook_target_square.to_bitboard(); - match self.pieces - .iter() - .enumerate() - .find(|(rook_type, bitboard)| *bitboard & rook_source_bb > 0) - { - Some((rook_type, _)) => { - self.pieces[rook_type] ^= rook_source_bb; - self.occupancy ^= rook_source_bb; - self.hash ^= self.zobrist_seed[rook_type * 12 + rook_source_square as usize]; + match self.piece_by_square(rook_source_square) { + Some(rook_type) => { + let rook_id = rook_type as usize; + self.pieces[rook_id] ^= rook_source_bb; + self.occupancy ^= rook_source_bb; + self.hash ^= self.zobrist_seed[rook_id * 12 + rook_source_square as usize]; - self.pieces[rook_type] |= rook_target_bb; - self.occupancy |= rook_target_bb; - self.hash ^= self.zobrist_seed[rook_type * 12 + rook_target_square as usize]; - }, - None => panic!("Rook was not found when castling"), - } + self.pieces[rook_id] |= rook_target_bb; + self.occupancy |= rook_target_bb; + self.hash ^= self.zobrist_seed[rook_id * 12 + rook_target_square as usize]; + }, + None => panic!("Rook was not found when castling"), + } } // Double push should set En Passant target square @@ -856,7 +849,7 @@ mod tests { let black_move = Move { source: Square::F7, target: Square::F5, kind: MoveKind::Quiet }; println!("\n{:?}", black_move); - match board.make_move(black_move) { + match board.make_move(black_move).unwrap() { Some(..) => panic!("No piece should be captured"), None => {}, }; @@ -870,7 +863,7 @@ mod tests { let white_move = Move { source: Square::D2, target: Square::A5, kind: MoveKind::Capture }; println!("\n{:?}", white_move); - match board.make_move(white_move) { + match board.make_move(white_move).unwrap() { Some(captured) => assert!(captured == PieceType::PawnBlack), None => panic!("A piece should be captured"), }; @@ -894,7 +887,7 @@ mod tests { board.print(); - let captured_piece = board.make_move(mov); + let captured_piece = board.make_move(mov).unwrap(); board.print(); board.unmake_move(mov, captured_piece, None, board.castling_rights, initial_board.hash); -- cgit v1.2.3