diff options
author | eug-vs <eugene@eug-vs.xyz> | 2023-08-22 19:36:36 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2023-08-22 19:39:33 +0300 |
commit | b5aecc2b3461582e2a23e57043751bac40c062dc (patch) | |
tree | 9875774b92fec9dc3b934967bd27a8fb16deffa7 | |
parent | bc88b60cc909f63d1d1389a220c4a43477f2dd7c (diff) | |
download | chessnost-b5aecc2b3461582e2a23e57043751bac40c062dc.tar.gz |
feat: add piece-square tables
-rw-r--r-- | src/grossmeister/evaluation.rs | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/src/grossmeister/evaluation.rs b/src/grossmeister/evaluation.rs index d55d9c6..b7060ba 100644 --- a/src/grossmeister/evaluation.rs +++ b/src/grossmeister/evaluation.rs @@ -16,15 +16,15 @@ const PAWN_BONUS: [f32; 64] = [ 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 ]; -const PAWN_PASSER_BONUS: [f32; 64] = [ +const PAWN_BONUS_ENDGAME: [f32; 64] = [ // A B C D E F G H 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, - 1.50, 1.50, 1.50, 1.50, 1.50, 1.50, 1.50, 1.50, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.70, 0.70, 0.70, 0.70, 0.70, 0.70, 0.70, 0.70, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50, 0.50, - 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, + 0.30, 0.30, 0.30, 0.30, 0.30, 0.30, 0.30, 0.30, + 0.10, 0.10, 0.10, 0.10, 0.10, 0.10, 0.10, 0.10, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, ]; @@ -162,27 +162,6 @@ impl Grossmeister { (behind_pawns & (king | king.west_one() | king.east_one())).pop_count() as f32 } - pub fn evaluate_endgame(&self) -> f32 { - let color = self.board.color(); - let opponent_color = color.flip(); - - let mobility_advantage = self.mobility(color) - self.mobility(opponent_color); - let pawn_shield_advantage = self.pawn_shield(color) - self.pawn_shield(opponent_color); - - mobility_advantage * 0.03 + pawn_shield_advantage * 0.20 - } - - - pub fn evaluate_middlegame(&self) -> f32 { - let color = self.board.color(); - let opponent_color = color.flip(); - - let mobility_advantage = self.mobility(color) - self.mobility(opponent_color); - let pawn_shield_advantage = self.pawn_shield(color) - self.pawn_shield(opponent_color); - - mobility_advantage * 0.05 + pawn_shield_advantage * 0.15 - } - // Returns a value in [0, 240] representing how // much material is left in the game // Note: not related to actual material counting @@ -209,6 +188,37 @@ impl Grossmeister { }) } + /// Compute total bonus for well-positioned pieces + /// according to Piece-Square Tables + pub fn pst_bonus(&self, color: Color, is_endgame: bool) -> f32 { + self.board.pieces_by_color(color).iter().enumerate().fold(0., |total, (piece_index, bitboard)| { + let pst = match Piece::from(piece_index).without_color() { + Piece::Pawn => if is_endgame { + PAWN_BONUS_ENDGAME + } else { + PAWN_BONUS + } + Piece::Knight => KNIGHT_BONUS, + Piece::Bishop => BISHOP_BONUS, + Piece::Rook => ROOK_BONUS, + Piece::Queen => QUEEN_BONUS, + Piece::King => if is_endgame { + KING_BONUS_ENGAME + } else { + KING_BONUS + } + _ => panic!("Unreachable") + }; + total + bitboard.serialize().iter().fold(0., |acc, &square| { + let pst_index = match color { + Color::White => square.mirror(), + Color::Black => square, + } as usize; + acc + pst[pst_index] + }) + }) + } + /// Evaluate a position relative to the current player pub fn evaluate(&self) -> f32 { if self.is_dead_position() { @@ -218,9 +228,18 @@ impl Grossmeister { let opponent_color = color.flip(); let material_advantage = self.material(color) - self.material(opponent_color); + let mobility_advantage = self.mobility(color) - self.mobility(opponent_color); + let pawn_shield_advantage = self.pawn_shield(color) - self.pawn_shield(opponent_color); + + let middlegame_eval = + mobility_advantage * 0.05 + + pawn_shield_advantage * 0.15 + + (self.pst_bonus(color, false) - self.pst_bonus(opponent_color, false)); - let middlegame_eval = self.evaluate_middlegame(); - let endgame_eval = self.evaluate_endgame(); + let endgame_eval = + mobility_advantage * 0.03 + + pawn_shield_advantage * 0.20 + + (self.pst_bonus(color, true) - self.pst_bonus(opponent_color, true)); let phase = self.phase(); let tapered_eval = (middlegame_eval * phase as f32 + endgame_eval * (240 - phase) as f32) / 240.; |