diff options
| author | eug-vs <eugene@eug-vs.xyz> | 2023-01-23 12:48:03 +0300 | 
|---|---|---|
| committer | eug-vs <eugene@eug-vs.xyz> | 2023-01-23 12:48:03 +0300 | 
| commit | e65b0854174c9c90d5eff850428fd07c6912960c (patch) | |
| tree | d281c0da8368da6b922eac8f12f65f4f4ae4281b /src | |
| parent | e6102cda73e854b3050cceb86b9f66bac0b81345 (diff) | |
| download | chessnost-e65b0854174c9c90d5eff850428fd07c6912960c.tar.gz | |
feat: basic En Passant implementation
Diffstat (limited to 'src')
| -rw-r--r-- | src/board.rs | 61 | ||||
| -rw-r--r-- | src/moves.rs | 1 | ||||
| -rw-r--r-- | src/square.rs | 16 | 
3 files changed, 71 insertions, 7 deletions
| diff --git a/src/board.rs b/src/board.rs index 186e569..58e4037 100644 --- a/src/board.rs +++ b/src/board.rs @@ -185,7 +185,7 @@ impl Board {                      };                      for source in serialize_bitboard(*piece & able_to_double_push_mask) {                          for target in serialize_bitboard(self.attacks.pawn_double_pushes[color as usize][source as usize] & empty) { -                            moves.push(Move { source, target, kind: MoveKind::Quiet }); +                            moves.push(Move { source, target, kind: MoveKind::DoublePush });                          };                      }                  } @@ -254,7 +254,7 @@ impl Board {          let move_target_bb = mov.target.to_bitboard();          // Remove existing piece (if any) from target square -        let captured_piece = match self.pieces +        let mut captured_piece = match self.pieces              .iter()              .enumerate()              .find(|(piece_type, bitboard)| *bitboard & mov.target.to_bitboard() > 0) @@ -266,6 +266,26 @@ impl Board {                  None => None,              }; +        // En Passant captures diffirently +        captured_piece = match mov.kind { +            MoveKind::EnPassant => { +                debug_assert!(captured_piece.is_none(), "No capture should be found at this point"); +                let captured_bb = Square::from(mov.source.rank() * 8 + mov.target.file()).to_bitboard(); +                match self.pieces +                    .iter() +                    .enumerate() +                    .find(|(piece_type, bitboard)| *bitboard & captured_bb > 0) +                { +                    Some((pawn_type, _)) => { +                        self.pieces[pawn_type] ^= captured_bb; +                        Some(PieceType::from(pawn_type)) +                    } +                    None => panic!("Pawn captured by En Passant was not found"), +                } +            }, +            _ => captured_piece, +        }; +          // Move a piece from source square to target          match self.pieces              .iter() @@ -282,13 +302,27 @@ impl Board {                  None => panic!("Move is malformed: source piece not found"),              }; +        // Double push should set En Passant target square +        match mov.kind { +            MoveKind::DoublePush => { +                self.ep_target = match mov.source.rank() { +                    1 => Some(mov.source.nort_one()), +                    6 => Some(mov.source.sout_one()), +                    rank => panic!("Double-push was used from invalid rank({}) when trying to make {:?}", rank, mov), +                }; +            }, +            _ => { +                self.ep_target = None +            }, +        } +          self.ply += 1;          captured_piece      }      /// Completely reverse make_move as if it never happened -    pub fn unmake_move(&mut self, mov: Move, captured_piece: Option<PieceType>) { +    pub fn unmake_move(&mut self, mov: Move, captured_piece: Option<PieceType>, previous_ep_target: Option<Square>) {          let move_source_bb = mov.source.to_bitboard();          let move_target_bb = mov.target.to_bitboard(); @@ -311,12 +345,24 @@ impl Board {          // Return captured piece to target square          match captured_piece {              Some(target_piece) => { -                self.pieces[target_piece as usize] |= move_target_bb; -                self.occupancy                     |= move_target_bb; +                match mov.kind { +                    // Return pawn captured by En Passant pawn if needed +                    MoveKind::EnPassant => { +                        let original_dead_pawn_bb = Square::from(mov.source.rank() * 8 + mov.target.file()).to_bitboard(); +                        self.pieces[target_piece as usize] |= original_dead_pawn_bb; +                        self.occupancy                     |= original_dead_pawn_bb; +                    }, +                    _ => { +                        self.pieces[target_piece as usize] |= move_target_bb; +                        self.occupancy                     |= move_target_bb; +                    }, +                }              },              None => {}          } + +        self.ep_target = previous_ep_target;          self.ply -= 1;      } @@ -338,6 +384,7 @@ impl Board {          let mut checks = 0;          for mov in moves { +            let ep_target_before = self.ep_target.clone();              let captured_piece = self.make_move(mov);              // King can not be in check after our own move              if !self.is_king_in_check(color) { @@ -357,7 +404,7 @@ impl Board {                  checks += children_checks;              } -            self.unmake_move(mov, captured_piece); +            self.unmake_move(mov, captured_piece, ep_target_before);          }          if print { @@ -539,7 +586,7 @@ mod tests {          let captured_piece = board.make_move(mov);          board.print(); -        board.unmake_move(mov, captured_piece); +        board.unmake_move(mov, captured_piece, None);          board.print();          assert_eq!(board, initial_board, "Board state after unmake_move should be the same as before make_move"); diff --git a/src/moves.rs b/src/moves.rs index d6695a1..d0e3eb6 100644 --- a/src/moves.rs +++ b/src/moves.rs @@ -6,6 +6,7 @@ pub enum MoveKind {      Capture,      Castle,      EnPassant, +    DoublePush,  }  #[derive(Debug, Clone, Copy)] diff --git a/src/square.rs b/src/square.rs index ed2877c..1adca83 100644 --- a/src/square.rs +++ b/src/square.rs @@ -19,6 +19,22 @@ impl Square {      pub fn to_bitboard(&self) -> Bitboard {          1u64 << *self as u8      } +    /// 0-based rank +    pub fn rank(&self) -> u8 { +        *self as u8 / 8 +    } +    /// 0-based file +    pub fn file(&self) -> u8 { +        *self as u8 % 8 +    } + +    pub fn nort_one(&self) -> Self { +        Self::from(*self as u8 + 8) +    } + +    pub fn sout_one(&self) -> Self { +        Self::from(*self as u8 - 8) +    }  } | 
