From 1ae6d5df4887a4b9979be0cab41eeba0a23d913c Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Tue, 24 Jun 2025 20:00:04 -0700 Subject: [PATCH] =?UTF-8?q?[core,=20position]=20Rename=20the=20type=20of?= =?UTF-8?q?=20Score's=20inner=20value=20=E2=86=92=20Value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/colors.rs | 4 +-- core/src/score.rs | 65 ++++++++++++++++++++++++++++++-------- position/src/evaluation.rs | 6 ++-- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/core/src/colors.rs b/core/src/colors.rs index 53e2c1e..e1255b7 100644 --- a/core/src/colors.rs +++ b/core/src/colors.rs @@ -1,6 +1,6 @@ // Eryn Wells -use crate::{Direction, score::ScoreInner}; +use crate::{Direction, score}; use std::fmt; use thiserror::Error; @@ -59,7 +59,7 @@ impl Color { } #[must_use] - pub const fn score_factor(self) -> ScoreInner { + pub const fn score_factor(self) -> score::Value { match self { Color::White => 1, Color::Black => -1, diff --git a/core/src/score.rs b/core/src/score.rs index a7f24cd..2dfd7c9 100644 --- a/core/src/score.rs +++ b/core/src/score.rs @@ -5,22 +5,53 @@ use std::{ ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign}, }; -pub(crate) type ScoreInner = i32; +pub(crate) type Value = i32; /// A score for a position in centipawns. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct Score(ScoreInner); +pub struct Score(Value); impl Score { - #[must_use] - pub const fn zero() -> Self { - Self(0) - } + pub const ZERO: Score = Score(0); + + /// The minimum possible value of a score. Notably, this is *not* the + /// minimum value for the inner integer value so negation works correctly. + /// This property is important during search, which relies on being able to + /// negate "infinity". + /// + /// ## Examples + /// + /// ``` + /// use chessfriend_core::score::Score; + /// assert_eq!(!Score::MIN, Score::MAX); + /// ``` + /// + pub const MIN: Score = Score(Value::MIN + 1); + + /// The maximum possible value of a score. + pub const MAX: Score = Score(Value::MAX); + + const CENTIPAWNS_PER_POINT: f32 = 100.0; #[must_use] - pub const fn new(value: ScoreInner) -> Self { + pub const fn new(value: Value) -> Self { Self(value) } + + /// Returns `true` if this [`Score`] is zero. + /// + /// ## Examples + /// + /// ``` + /// use chessfriend_core::score::Score; + /// assert!(Score::ZERO.is_zero()); + /// assert!(Score::new(0).is_zero()); + /// ``` + /// + #[must_use] + pub const fn is_zero(&self) -> bool { + self.0 == 0 + } } impl Add for Score { @@ -51,15 +82,15 @@ impl SubAssign for Score { } } -impl Mul for Score { - type Output = Score; +impl Mul for Score { + type Output = Self; - fn mul(self, rhs: ScoreInner) -> Self::Output { + fn mul(self, rhs: Value) -> Self::Output { Score(self.0 * rhs) } } -impl Mul for ScoreInner { +impl Mul for Value { type Output = Score; fn mul(self, rhs: Score) -> Self::Output { @@ -67,8 +98,16 @@ impl Mul for ScoreInner { } } -impl From for Score { - fn from(value: ScoreInner) -> Self { +impl Neg for Score { + type Output = Self; + + fn neg(self) -> Self::Output { + Score(-self.0) + } +} + +impl From for Score { + fn from(value: Value) -> Self { Score(value) } } diff --git a/position/src/evaluation.rs b/position/src/evaluation.rs index 883398b..b776777 100644 --- a/position/src/evaluation.rs +++ b/position/src/evaluation.rs @@ -19,10 +19,10 @@ impl Evaluator { fn material_balance(board: &Board, color: Color) -> Score { let other_color = color.other(); - Shape::into_iter().fold(Score::zero(), |acc, shape| { + Shape::into_iter().fold(Score::ZERO, |acc, shape| { let (active_pieces, other_pieces) = ( - board.count_piece(&Piece::new(color, shape)) as i32, - board.count_piece(&Piece::new(other_color, shape)) as i32, + i32::from(board.count_piece(&Piece::new(color, shape))), + i32::from(board.count_piece(&Piece::new(other_color, shape))), ); let factor = shape.score() * (active_pieces - other_pieces);