126 lines
2.6 KiB
Rust
126 lines
2.6 KiB
Rust
// Eryn Wells <eryn@erynwells.me>
|
|
|
|
use std::{
|
|
fmt,
|
|
ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign},
|
|
};
|
|
|
|
pub(crate) type Value = i32;
|
|
|
|
/// A score for a position in centipawns.
|
|
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
|
pub struct Score(Value);
|
|
|
|
impl Score {
|
|
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);
|
|
|
|
pub(crate) const CENTIPAWNS_PER_POINT: f32 = 100.0;
|
|
|
|
#[must_use]
|
|
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 {
|
|
type Output = Self;
|
|
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
Score(self.0 + rhs.0)
|
|
}
|
|
}
|
|
|
|
impl AddAssign for Score {
|
|
fn add_assign(&mut self, rhs: Self) {
|
|
self.0 += rhs.0;
|
|
}
|
|
}
|
|
|
|
impl Sub for Score {
|
|
type Output = Self;
|
|
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
Score(self.0 - rhs.0)
|
|
}
|
|
}
|
|
|
|
impl SubAssign for Score {
|
|
fn sub_assign(&mut self, rhs: Self) {
|
|
self.0 -= rhs.0;
|
|
}
|
|
}
|
|
|
|
impl Mul<Value> for Score {
|
|
type Output = Self;
|
|
|
|
fn mul(self, rhs: Value) -> Self::Output {
|
|
Score(self.0 * rhs)
|
|
}
|
|
}
|
|
|
|
impl Mul<Score> for Value {
|
|
type Output = Score;
|
|
|
|
fn mul(self, rhs: Score) -> Self::Output {
|
|
Score(self * rhs.0)
|
|
}
|
|
}
|
|
|
|
impl Neg for Score {
|
|
type Output = Self;
|
|
|
|
fn neg(self) -> Self::Output {
|
|
Score(-self.0)
|
|
}
|
|
}
|
|
|
|
impl From<Value> for Score {
|
|
fn from(value: Value) -> Self {
|
|
Score(value)
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Score {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
let value = self.0;
|
|
if *self == Self::MAX {
|
|
write!(f, "INF")
|
|
} else if *self == Self::MIN {
|
|
write!(f, "-INF")
|
|
} else {
|
|
write!(f, "{value}cp")
|
|
}
|
|
}
|
|
}
|