From 46abb37e60667445d10791553bdb307d52661180 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Wed, 1 Feb 2023 14:23:59 +0300 Subject: fix: do not overcount EP square in move generation --- src/board/engine.rs | 37 ++++++++++++++----------------------- src/board/mod.rs | 19 +++++++++++++++++-- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/board/engine.rs b/src/board/engine.rs index 6491289..18abaa0 100644 --- a/src/board/engine.rs +++ b/src/board/engine.rs @@ -244,16 +244,11 @@ impl Board { } /// Evaluate a position relative to the current player - pub fn evaluate(&self, precomputed_mobility: Option) -> f32 { + pub fn evaluate(&self) -> f32 { let color = self.color(); let opponent_color = color.flip(); - let opponent_mobility = self.mobility(opponent_color); - let player_mobility = match precomputed_mobility { - Some(m) => m, - None => self.mobility(color), - }; - let mobility_advantage = player_mobility - opponent_mobility as f32; + let mobility_advantage = self.mobility(color) - self.mobility(opponent_color); let opponent_material = self.material(opponent_color); let material_advantage = self.material(color) - opponent_material; @@ -477,11 +472,7 @@ impl Board { let mut moves = self.generate_pseudolegal_moves(color); moves = self.order_moves(moves, Vec::new()); - let queen_squares = match color { - Color::White => self.pieces[PieceType::Queen as usize], - Color::Black => self.pieces[PieceType::QueenBlack as usize], - }; - let stand_pat = self.evaluate(Some(moves.iter().filter(|m| m.source.to_bitboard() & queen_squares == 0).count() as f32)); + let stand_pat = self.evaluate(); if stand_pat >= beta { return beta; @@ -614,7 +605,7 @@ mod tests { assert_eq!(board.perft(1, false), PerftResult { leaf_nodes: 14, captures: 1, en_passants: 0, castles: 0 , checks: 2 }); assert_eq!(board.perft(2, false), PerftResult { leaf_nodes: 191, captures: 14, en_passants: 0, castles: 0 , checks: 10 }); - // assert_eq!(board.perft(3, false), PerftResult { leaf_nodes: 2182, captures: 209, en_passants: 2, castles: 0 , checks: 267 }); + // assert_eq!(board.perft(3, false), PerftResult { leaf_nodes: 2812, captures: 209, en_passants: 2, castles: 0 , checks: 267 }); } #[test] @@ -688,14 +679,14 @@ mod tests { #[test] fn initial_eval() { let board = Board::new(); - assert_eq!(board.evaluate(None), 0.0); + assert_eq!(board.evaluate(), 0.0); } #[test] fn king_tropism() { let mut board = Board::new(); board.make_move(Move { source: Square::D1, target: Square::F5, kind: MoveKind::Quiet }); - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); @@ -707,7 +698,7 @@ mod tests { fn white_winning() { let fen = String::from("8/5pk1/6p1/R4b1p/3P4/1P2N3/P1r2PPP/R5K1 b - - 1 27"); let board = Board::from_FEN(fen); - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); @@ -718,7 +709,7 @@ mod tests { fn black_winning() { let fen = String::from("8/p7/1k4K1/8/4P3/8/PP5r/8 b - - 1 38"); let board = Board::from_FEN(fen); - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); @@ -730,7 +721,7 @@ mod tests { let score1 = { let fen = String::from("rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2"); let board = Board::from_FEN(fen); - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); score @@ -739,7 +730,7 @@ mod tests { let score2 = { let fen = String::from("rnbqkbnr/pppp1ppp/8/4p3/2P5/8/PP1PPPPP/RNBQKBNR w KQkq - 0 2"); let board = Board::from_FEN(fen); - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); score @@ -753,7 +744,7 @@ mod tests { let score1 = { let fen = String::from("r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3"); let board = Board::from_FEN(fen); - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); score @@ -762,7 +753,7 @@ mod tests { let score2 = { let fen = String::from("r1bqkbnr/pppp1ppp/2n5/4p3/4P3/7N/PPPP1PPP/RNBQKB1R w KQkq - 2 3"); let board = Board::from_FEN(fen); - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); score @@ -776,7 +767,7 @@ mod tests { let score1 = { let fen = String::from("r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 1"); let board = Board::from_FEN(fen); - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); score @@ -786,7 +777,7 @@ mod tests { let fen = String::from("r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 1 "); let mut board = Board::from_FEN(fen); board.ply += 1; // TODO: remove me when FEN parsing includes side to move - let score = board.evaluate(None); + let score = board.evaluate(); board.print(); println!("Score {}", score); score diff --git a/src/board/mod.rs b/src/board/mod.rs index fd0ff25..3f37d62 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -269,7 +269,14 @@ impl Board { PieceType::Pawn => { for source in serialize_bitboard(*piece) { let ep_bitboard = match self.ep_target { - Some(square) => square.to_bitboard(), + Some(square) => { + let rank = square.rank(); + if (rank == 2 && color == Color::Black) || (rank == 5 && color == Color::White) { + square.to_bitboard() + } else { + 0 + } + } None => 0, }; for target in serialize_bitboard(self.attacks.pawn[color as usize][source as usize] & capture_targets) { @@ -431,6 +438,7 @@ impl Board { } /// Count pseudo-legal moves without actually generating them + /// Also exclude all moves that put a piece under attack of a pawn - so called safe mobility pub fn mobility(&self, color: Color) -> f32 { let mut mobility = 0.; let opponent_occupancy = self.color_occupancy(color.flip()); @@ -453,7 +461,14 @@ impl Board { PieceType::Pawn => { for source in serialize_bitboard(*piece) { let ep_bitboard = match self.ep_target { - Some(square) => square.to_bitboard(), + Some(square) => { + let rank = square.rank(); + if (rank == 2 && color == Color::Black) || (rank == 5 && color == Color::White) { + square.to_bitboard() + } else { + 0 + } + } None => 0, }; mobility += pop_count(self.attacks.pawn[color as usize][source as usize] & (opponent_occupancy | ep_bitboard)) as f32; -- cgit v1.2.3