diff --git a/src/board.rs b/src/board.rs index a23adf5..19435c7 100644 --- a/src/board.rs +++ b/src/board.rs @@ -363,11 +363,18 @@ impl Board { self.transform(Bitboard::rotate_270); } - /// Makes black pieces white and vice versa. + /// Swap piece colors, making black pieces white and vice versa. pub fn swap_colors(&mut self) { self.by_color.swap(); } + /// Mirror the board vertically and swap piece colors, so that the resulting + /// board is equivalent modulo color. + pub fn mirror(&mut self) { + self.flip_vertical(); + self.swap_colors(); + } + pub fn pop_front(&mut self) -> Option<(Square, Piece)> { self.occupied .first() diff --git a/src/position.rs b/src/position.rs index 126ad89..dae0276 100644 --- a/src/position.rs +++ b/src/position.rs @@ -633,7 +633,8 @@ pub trait Position { } } - /// Swap turns. This is sometimes called "playing a null move". + /// Swap turns and discard en passant rights. This is sometimes called + /// "playing a null move". /// /// # Errors /// diff --git a/src/setup.rs b/src/setup.rs index 6b27f01..dba671f 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -110,11 +110,31 @@ impl Setup { } } + /// Swap turns and discard en passant rights. This is sometimes called + /// "playing a null move". pub fn swap_turn(&mut self) { self.turn = !self.turn; self.ep_square = None; } + /// Mirror vertically and swap turns and all piece colors, so that the + /// resulting setup is equivalent modulo color. + /// + /// Move counters remain unchanged. + pub fn mirror(&mut self) { + self.board.mirror(); + self.promoted = self.promoted.flip_vertical(); + if let Some(pockets) = &mut self.pockets { + pockets.swap(); + } + self.turn = !self.turn; + self.castling_rights = self.castling_rights.flip_vertical(); + self.ep_square = self.ep_square.map(Square::flip_vertical); + if let Some(remaining_checks) = &mut self.remaining_checks { + remaining_checks.swap(); + } + } + pub fn position(self, mode: CastlingMode) -> Result> { P::from_setup(self, mode) }