aboutsummaryrefslogtreecommitdiff
path: root/src/board
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2023-01-26 17:52:34 +0300
committereug-vs <eugene@eug-vs.xyz>2023-01-26 17:52:34 +0300
commite7acc49c4891618f9a85427689f34eb807556e9c (patch)
treee8272b12919370666078843ea88ae0ebd6be7be8 /src/board
parent5645b7acf228d9f8127ad834023afc727ccb4f88 (diff)
downloadchessnost-e7acc49c4891618f9a85427689f34eb807556e9c.tar.gz
feat: implement promotions
Diffstat (limited to 'src/board')
-rw-r--r--src/board/mod.rs94
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 {