diff options
author | eug-vs <eugene@eug-vs.xyz> | 2023-01-27 18:06:12 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2023-01-27 18:06:12 +0300 |
commit | 68536a7c80a5c8ce3af0969e7840198f85b3aa78 (patch) | |
tree | cf496e52ce80ab18bea9869190c76e7c91fd620f /src/board/engine.rs | |
parent | fb142238613f0a2e0a581807d41089ac63793694 (diff) | |
download | chessnost-68536a7c80a5c8ce3af0969e7840198f85b3aa78.tar.gz |
feat: calculate pawn structure penalty
Diffstat (limited to 'src/board/engine.rs')
-rw-r--r-- | src/board/engine.rs | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/src/board/engine.rs b/src/board/engine.rs index 18fb731..2ff3aed 100644 --- a/src/board/engine.rs +++ b/src/board/engine.rs @@ -3,6 +3,8 @@ use crate::{bitboard::pop_count, board::*}; use super::ttable::{NodeType, TranspositionTableItem}; +static A_FILE: Bitboard = 0x0101010101010101; + #[derive(Debug, Default, PartialEq)] pub struct PerftResult { leaf_nodes: u64, @@ -116,6 +118,42 @@ impl Board { eval } + /// Returns sum of the doubled, blocked and isolated pawns + /// The greater result is, the worse is the pawn structure + pub fn pawn_structure_penalty(&self, color: Color) -> f32 { + let mut result = 0.0; + + let pawns = match color { + Color::White => self.pieces[PieceType::Pawn as usize], + Color::Black => self.pieces[PieceType::PawnBlack as usize], + }; + + for file in 0..8 { + let file_mask = A_FILE << file; + let pawns_on_file = pop_count(pawns & file_mask) as f32; + + // Doubled pawns (-1 because one pawn on a file is ok) + result += (pawns_on_file - 1.).max(0.0); + + // Isolated pawns (no pawns on neighbor files) + if [ + A_FILE << (file - 1).max(0), // File to the left (if any) + A_FILE << (file + 1).min(7), // File to the right (if any) + ].iter().all(|file| file & pawns == 0) { + result += pawns_on_file; + } + } + + // Blocked pawns + let blocked_mask = match color { + Color::White => self.occupancy >> 8, + Color::Black => self.occupancy << 8, + }; + result += pop_count(pawns & blocked_mask) as f32; + + result + } + /// Evaluate a position relative to the current player pub fn evaluate(&self, precomputed_mobility: Option<f32>) -> f32 { let opponent_mobility = self.mobility(self.color().flip()); @@ -127,7 +165,9 @@ impl Board { let material_advantage = self.material_advantage(); - material_advantage + 0.1 * mobility_advantage + let pawn_structure_penalty = self.pawn_structure_penalty(self.color()) - self.pawn_structure_penalty(self.color().flip()); + + material_advantage + 0.1 * mobility_advantage - 0.5 * pawn_structure_penalty } /// Evaluate move for move ordering, prioritizing efficient captures |