[position] Add two new negative tests for making pawn moves
- Ensure you cannot move a pawn to the last rank without a promotion move. - Ensure a pawn cannot make an illegal move, and that the board state remains as it was before the move was attempted.
This commit is contained in:
		
							parent
							
								
									10ba21f7e3
								
							
						
					
					
						commit
						9a4fa827f9
					
				
					 1 changed files with 50 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
// Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
use crate::{movement::Movement, Position};
 | 
			
		||||
use chessfriend_board::{en_passant, CastleParameters, PlacePieceError, PlacePieceStrategy};
 | 
			
		||||
use chessfriend_core::{Color, Piece, Rank, Shape, Square, Wing};
 | 
			
		||||
use chessfriend_board::{PlacePieceError, PlacePieceStrategy};
 | 
			
		||||
use chessfriend_core::{Color, Piece, Rank, Square, Wing};
 | 
			
		||||
use chessfriend_moves::Move;
 | 
			
		||||
use thiserror::Error;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +55,9 @@ pub enum MakeMoveError {
 | 
			
		|||
 | 
			
		||||
    #[error("cannot promote on {0}")]
 | 
			
		||||
    InvalidPromotion(Square),
 | 
			
		||||
 | 
			
		||||
    #[error("move to {0} requires promotion")]
 | 
			
		||||
    PromotionRequired(Square),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum UnmakeMoveError {}
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +73,7 @@ impl Position {
 | 
			
		|||
        self.validate_move(ply, validate)?;
 | 
			
		||||
 | 
			
		||||
        if ply.is_quiet() {
 | 
			
		||||
            return self.make_quiet_move(ply.origin_square(), ply.target_square());
 | 
			
		||||
            return self.make_quiet_move(ply);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ply.is_double_push() {
 | 
			
		||||
| 
						 | 
				
			
			@ -98,13 +101,17 @@ impl Position {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
impl Position {
 | 
			
		||||
    fn make_quiet_move(&mut self, origin: Square, target: Square) -> MakeMoveResult {
 | 
			
		||||
    fn make_quiet_move(&mut self, ply: Move) -> MakeMoveResult {
 | 
			
		||||
        let origin = ply.origin_square();
 | 
			
		||||
 | 
			
		||||
        let piece = self
 | 
			
		||||
            .board
 | 
			
		||||
            .remove_piece(origin)
 | 
			
		||||
            .get_piece(origin)
 | 
			
		||||
            .ok_or(MakeMoveError::NoPiece(origin))?;
 | 
			
		||||
 | 
			
		||||
        self.place_active_piece(piece, target)?;
 | 
			
		||||
        let target = ply.target_square();
 | 
			
		||||
        self.place_piece_for_move(piece, target)?;
 | 
			
		||||
 | 
			
		||||
        self.remove_piece(origin);
 | 
			
		||||
 | 
			
		||||
        self.advance_clocks(HalfMoveClock::Advance);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +126,7 @@ impl Position {
 | 
			
		|||
            .ok_or(MakeMoveError::NoPiece(origin))?;
 | 
			
		||||
 | 
			
		||||
        let target = ply.target_square();
 | 
			
		||||
        self.place_active_piece(piece, target)?;
 | 
			
		||||
        self.place_piece_for_move(piece, target)?;
 | 
			
		||||
 | 
			
		||||
        self.board.en_passant_target = match target.rank() {
 | 
			
		||||
            Rank::FOUR => Some(Square::from_file_rank(target.file(), Rank::THREE)),
 | 
			
		||||
| 
						 | 
				
			
			@ -223,7 +230,11 @@ impl Position {
 | 
			
		|||
        self.get_piece(square).ok_or(MakeMoveError::NoPiece(square))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn place_active_piece(&mut self, piece: Piece, square: Square) -> MakeMoveResult {
 | 
			
		||||
    fn place_piece_for_move(&mut self, piece: Piece, square: Square) -> MakeMoveResult {
 | 
			
		||||
        if piece.is_pawn() && square.rank().is_promotable_rank() {
 | 
			
		||||
            return Err(MakeMoveError::PromotionRequired(square));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        self.place_piece(piece, square, PlacePieceStrategy::PreserveExisting)
 | 
			
		||||
            .map_err(MakeMoveError::PlacePieceError)
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -340,6 +351,20 @@ mod tests {
 | 
			
		|||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn make_invalid_quiet_pawn_move() {
 | 
			
		||||
        let mut pos = test_position!(White Pawn on C2);
 | 
			
		||||
 | 
			
		||||
        let ply = Move::quiet(Square::C2, Square::D2);
 | 
			
		||||
        let result = pos.make_move(ply, ValidateMove::Yes);
 | 
			
		||||
 | 
			
		||||
        assert!(result.is_err());
 | 
			
		||||
        assert_eq!(pos.get_piece(Square::C2), Some(piece!(White Pawn)));
 | 
			
		||||
        assert_eq!(pos.get_piece(Square::D2), None);
 | 
			
		||||
        assert_eq!(pos.board.active_color, Color::White);
 | 
			
		||||
        assert_eq!(pos.board.half_move_clock, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn make_capture_move() {
 | 
			
		||||
        let mut pos = test_position![
 | 
			
		||||
| 
						 | 
				
			
			@ -391,6 +416,22 @@ mod tests {
 | 
			
		|||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn make_last_rank_quiet_move_without_promotion() {
 | 
			
		||||
        let mut pos = test_position!(
 | 
			
		||||
            White Pawn on A7
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let ply = Move::quiet(Square::A7, Square::A8);
 | 
			
		||||
        let result = pos.make_move(ply, ValidateMove::Yes);
 | 
			
		||||
 | 
			
		||||
        assert!(result.is_err());
 | 
			
		||||
        assert_eq!(pos.board.active_color, Color::White);
 | 
			
		||||
        assert_eq!(pos.get_piece(Square::A7), Some(piece!(White Pawn)));
 | 
			
		||||
        assert_eq!(pos.get_piece(Square::A8), None);
 | 
			
		||||
        assert_eq!(pos.board.half_move_clock, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn make_promotion_move() -> MakeMoveResult {
 | 
			
		||||
        let mut pos = test_position![
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue