aboutsummaryrefslogtreecommitdiff
path: root/src/grossmeister/evaluation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/grossmeister/evaluation.rs')
-rw-r--r--src/grossmeister/evaluation.rs44
1 files changed, 12 insertions, 32 deletions
diff --git a/src/grossmeister/evaluation.rs b/src/grossmeister/evaluation.rs
index b78c49a..6fc4149 100644
--- a/src/grossmeister/evaluation.rs
+++ b/src/grossmeister/evaluation.rs
@@ -1,3 +1,5 @@
+use std::f32::INFINITY;
+
use crate::{board::{piece::Piece, color::Color, CastlingSide}, bitboard::{Bitboard, BitboardFns}, square::Square};
use super::Grossmeister;
@@ -117,34 +119,6 @@ impl Grossmeister {
}
}
- pub fn is_dead_position(&self) -> bool {
- let non_minor_exists = [
- Piece::Pawn,
- Piece::PawnBlack,
- Piece::Rook,
- Piece::RookBlack,
- Piece::Queen,
- Piece::QueenBlack
- ].iter().any(|&piece| {
- self.board.piece_sets[piece as usize].pop_count() > 0
- });
-
- if non_minor_exists {
- return false;
- }
-
- let minor_pieces = [
- Piece::Knight,
- Piece::KnightBlack,
- Piece::Bishop,
- Piece::BishopBlack
- ].iter().fold(0, |acc, &piece| {
- acc + self.board.piece_sets[piece as usize].pop_count()
- });
-
- minor_pieces <= 1
- }
-
/// Return number of pawns above the king (+left/right)
pub fn pawn_shield(&self, color: Color) -> f32 {
let behind_pawns = match color {
@@ -236,12 +210,16 @@ impl Grossmeister {
/// Evaluate a position relative to the current player
pub fn evaluate(&self) -> f32 {
- if self.is_dead_position() {
- return 0.0
- }
let color = self.board.color();
let opponent_color = color.flip();
+ let winnable = self.board.is_theoretically_winnable(color);
+ let loseable = self.board.is_theoretically_winnable(opponent_color);
+
+ if !winnable && !loseable {
+ return 0.0
+ }
+
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);
@@ -265,7 +243,9 @@ impl Grossmeister {
let phase = self.phase();
let tapered_eval = (middlegame_eval * phase as f32 + endgame_eval * (240 - phase) as f32) / 240.;
- material_advantage + tapered_eval
+ (material_advantage + tapered_eval)
+ .min(if winnable { INFINITY } else { 0.0 }) // Can not score > 0 if not winnable
+ .max(if loseable { -INFINITY } else { 0.0 }) // Can not score < 0 if not loseable
}
/// Count pseudo-legal moves without actually generating them