use std::cmp::PartialOrd;
use std::hash::Hash;
pub enum Evaluation {
Exact(f32),
Heuristic(f32),
}
impl Evaluation {
pub fn val(&self) -> &f32 {
match self {
Self::Exact(t) | Self::Heuristic(t) => t,
}
}
pub fn take(self) -> f32 {
match self {
Self::Exact(t) | Self::Heuristic(t) => t,
}
}
}
pub enum Player {
Maximizing,
Minimizing,
}
impl Player {
pub const fn flip(&self) -> Self {
match self {
Self::Maximizing => Self::Minimizing,
Self::Minimizing => Self::Maximizing,
}
}
pub const fn sign(&self) -> f32 {
match self {
Self::Maximizing => 1.0,
Self::Minimizing => -1.0,
}
}
}
pub trait GameState: Sized + Clone + Hash + Eq {
fn evaluate(&self) -> Evaluation;
fn moves(&self) -> impl IntoIterator<Item = Self>;
fn turn(&self) -> Player;
fn order_moves(&self, moves: Vec<(Self, Option<f32>)>) -> Vec<Self> {
let mut moves: Vec<(f32, Self)> = moves
.into_iter()
.map(|(m, v)| {
let s = self.turn().flip().sign();
(s * v.unwrap_or(m.evaluate().take()), m)
})
.collect();
moves.sort_unstable_by(|(v1, _), (v2, _)| {
v1.partial_cmp(v2).unwrap_or(std::cmp::Ordering::Equal)
});
moves.into_iter().map(|(_, g)| g).collect()
}
fn initial_f(&self) -> f32 {
0.0
}
fn mtdf_window(&self) -> f32 {
1.0
}
fn epsilon(&self) -> f32 {
1e-10
}
fn abdad_defer_depth(&self) -> usize {
3
}
}