aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2023-08-22 19:36:36 +0300
committereug-vs <eugene@eug-vs.xyz>2023-08-22 19:39:33 +0300
commitb5aecc2b3461582e2a23e57043751bac40c062dc (patch)
tree9875774b92fec9dc3b934967bd27a8fb16deffa7
parentbc88b60cc909f63d1d1389a220c4a43477f2dd7c (diff)
downloadchessnost-b5aecc2b3461582e2a23e57043751bac40c062dc.tar.gz
feat: add piece-square tables
-rw-r--r--src/grossmeister/evaluation.rs71
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.;