jordanbray / chess

A rust library to manage chess move generation
https://jordanbray.github.io/chess/
MIT License
231 stars 54 forks source link

Removing en passant doesn't work #65

Open analog-hors opened 2 years ago

analog-hors commented 2 years ago

Removing en passant moves doesn't work:

fn main() {
    let board = "8/8/5k2/8/3Pp3/8/2K5/8 b - d3 0 1".parse().unwrap();
    let mut moves = chess::MoveGen::new_legal(&board);
    let en_passant = "e4d3".parse().unwrap();
    moves.remove_move(en_passant);
    assert!(moves.find(|&mv| mv == en_passant).is_none()); //Assertion fails
}

The reason is because the code for removal makes the assumption that each SquareAndBitBoard has a unique source square, as it masks out the move and then returns: https://github.com/jordanbray/chess/blob/ad138579074ca1b0a88514626016d8e0b72d4ed3/src/movegen/movegen.rs#L140-L148 However, this assumption fails to hold when en passant is involved, as new SquareAndBitBoards are created for every en passant move. https://github.com/jordanbray/chess/blob/ad138579074ca1b0a88514626016d8e0b72d4ed3/src/movegen/piece_type.rs#L150-L194 This leads to remove_move returning early and never actually removing the move.