diff options
author | eug-vs <eugene@eug-vs.xyz> | 2023-01-26 17:52:34 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2023-01-26 17:52:34 +0300 |
commit | e7acc49c4891618f9a85427689f34eb807556e9c (patch) | |
tree | e8272b12919370666078843ea88ae0ebd6be7be8 /src/board | |
parent | 5645b7acf228d9f8127ad834023afc727ccb4f88 (diff) | |
download | chessnost-e7acc49c4891618f9a85427689f34eb807556e9c.tar.gz |
feat: implement promotions
Diffstat (limited to 'src/board')
-rw-r--r-- | src/board/mod.rs | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/src/board/mod.rs b/src/board/mod.rs index d8166c3..cce2ca7 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -246,8 +246,8 @@ impl Board { let available_targets = opponent_occupancy | empty; let player_pieces = self.pieces_by_color(color); - for (piece_type, piece) in player_pieces.iter().enumerate() { - match PieceType::from(piece_type) { + for (piece_id, piece) in player_pieces.iter().enumerate() { + match PieceType::from(piece_id) { PieceType::Pawn => { for source in serialize_bitboard(*piece) { let ep_bitboard = match self.ep_target { @@ -256,12 +256,30 @@ impl Board { }; for target in serialize_bitboard(self.attacks.pawn[color as usize][source as usize] & opponent_occupancy) { moves.push(Move { source, target, kind: MoveKind::Capture }); + if (target.rank() == 7) { + for promo_type in [PieceType::Bishop, PieceType::Knight, PieceType::Rook, PieceType::Queen] { + moves.push(Move { source, target, kind: MoveKind::Promotion(promo_type)}) + } + } else if (target.rank() == 0) { + for promo_type in [PieceType::BishopBlack, PieceType::KnightBlack, PieceType::RookBlack, PieceType::QueenBlack] { + moves.push(Move { source, target, kind: MoveKind::Promotion(promo_type)}) + } + } }; for target in serialize_bitboard(self.attacks.pawn[color as usize][source as usize] & ep_bitboard) { moves.push(Move { source, target, kind: MoveKind::EnPassant }); } for target in serialize_bitboard(self.attacks.pawn_pushes[color as usize][source as usize] & empty) { moves.push(Move { source, target, kind: MoveKind::Quiet }); + if (target.rank() == 7) { + for promo_type in [PieceType::Bishop, PieceType::Knight, PieceType::Rook, PieceType::Queen] { + moves.push(Move { source, target, kind: MoveKind::Promotion(promo_type)}) + } + } else if (target.rank() == 0) { + for promo_type in [PieceType::BishopBlack, PieceType::KnightBlack, PieceType::RookBlack, PieceType::QueenBlack] { + moves.push(Move { source, target, kind: MoveKind::Promotion(promo_type)}) + } + } }; } @@ -529,13 +547,27 @@ impl Board { 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 * 64 + mov.source as usize]; + match mov.kind { + MoveKind::Promotion(promotion_piece) => { + let promo_id = promotion_piece as usize; + self.pieces[source_id] ^= move_source_bb; + self.occupancy ^= move_source_bb; + self.hash ^= self.zobrist_seed[source_id * 64 + mov.source as usize]; + + self.pieces[promo_id] |= move_target_bb; + self.occupancy |= move_target_bb; + self.hash ^= self.zobrist_seed[promo_id * 64 + mov.target as usize]; + }, + _ => { + self.pieces[source_id] ^= move_source_bb; + self.occupancy ^= move_source_bb; + self.hash ^= self.zobrist_seed[source_id * 64 + mov.source as usize]; - self.pieces[source_id] |= move_target_bb; - self.occupancy |= move_target_bb; - self.hash ^= self.zobrist_seed[source_id * 64 + mov.target as usize]; + self.pieces[source_id] |= move_target_bb; + self.occupancy |= move_target_bb; + self.hash ^= self.zobrist_seed[source_id * 64 + mov.target as usize]; + } + } PieceType::from(source_piece) }, None => { @@ -595,11 +627,11 @@ impl Board { PieceType::Rook => { match mov.source.file() { 0 => { - self.castling_rights[Color::from_piece(source_piece) as usize][CastlingSide::Queen as usize] = false; + self.castling_rights[source_color][CastlingSide::Queen as usize] = false; self.hash ^= self.zobrist_seed[64 * 12 + source_color * 2 + CastlingSide::Queen as usize]; } 7 => { - self.castling_rights[Color::from_piece(source_piece) as usize][CastlingSide::King as usize] = false; + self.castling_rights[source_color][CastlingSide::King as usize] = false; self.hash ^= self.zobrist_seed[64 * 12 + source_color * 2 + CastlingSide::King as usize]; } _ => {}, @@ -627,20 +659,34 @@ impl Board { let move_target_bb = mov.target.to_bitboard(); // Move a piece from target square back to source square - match self.pieces - .iter() - .enumerate() - .find(|(piece_type, bitboard)| *bitboard & mov.target.to_bitboard() > 0) - { - Some((source_piece, _)) => { - self.pieces[source_piece] ^= move_target_bb; - self.occupancy ^= move_target_bb; - - self.pieces[source_piece] |= move_source_bb; - self.occupancy |= move_source_bb; - }, - None => panic!("Trying to unmake move which was not made: no piece was found on target square"), - }; + match self.piece_by_square(mov.target) { + Some(source_piece) => { + match mov.kind { + MoveKind::Promotion(promotion_piece) => { + let promo_id = promotion_piece as usize; + self.pieces[promo_id] ^= move_target_bb; + self.occupancy ^= move_target_bb; + + let source_id = match Color::from_piece(promotion_piece) { + Color::White => PieceType::Pawn, + Color::Black => PieceType::PawnBlack, + } as usize; + + self.pieces[source_id] |= move_source_bb; + self.occupancy |= move_source_bb; + } + _ => { + let source_id = source_piece as usize; + self.pieces[source_id] ^= move_target_bb; + self.occupancy ^= move_target_bb; + + self.pieces[source_id] |= move_source_bb; + self.occupancy |= move_source_bb; + } + } + }, + None => panic!("Trying to unmake move which was not made: no piece was found on target square"), + }; // If unmaking castle, also return rook to its place if mov.kind == MoveKind::Castle { |