diff --git a/minmax-rs/src/lib.rs b/minmax-rs/src/lib.rs index 171377c..cb3d7d0 100644 --- a/minmax-rs/src/lib.rs +++ b/minmax-rs/src/lib.rs @@ -12,13 +12,10 @@ pub mod player; mod state; pub mod tic_tac_toe; -use std::{ - fmt::{Debug, Display}, - ops::Neg, -}; +use std::fmt::Display; pub use self::minmax::PerfectPlayer; -pub use self::state::{Player, State}; +pub use self::state::{Player, Score, State}; pub trait GamePlayer { fn next_move(&mut self, board: &mut G, this_player: Player); @@ -43,6 +40,7 @@ pub trait Game: Display { fn empty() -> Self; + /// Returns an iterator of all possible moves. Should be ordered best to worst. fn possible_moves(&self) -> impl Iterator; fn result(&self) -> State; @@ -81,45 +79,6 @@ pub trait Game: Display { } } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct Score(i32); - -impl Score { - // Due to the nature of two's completement, we can't actually negate this properly, so add 1. - const LOST: Self = Self(i32::MIN + 1); - const TIE: Self = Self(0); - const WON: Self = Self(i32::MAX); - - pub fn new(int: i32) -> Self { - Self(int) - } - - #[allow(unused)] - fn randomize(self) -> Self { - let score = self.0 as f32; - let rand = rand::thread_rng(); - self - } -} - -impl Neg for Score { - type Output = Self; - - fn neg(self) -> Self::Output { - Self(-self.0) - } -} - -impl Debug for Score { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match *self { - Self::WON => f.write_str("WON"), - Self::LOST => f.write_str("LOST"), - Self(other) => Debug::fmt(&other, f), - } - } -} - #[cfg(test)] fn assert_win_ratio, O: GamePlayer>( runs: u64, diff --git a/minmax-rs/src/state.rs b/minmax-rs/src/state.rs index 9daad49..e9e4a01 100644 --- a/minmax-rs/src/state.rs +++ b/minmax-rs/src/state.rs @@ -1,6 +1,6 @@ use std::{ - fmt::Display, - ops::{ControlFlow, Try}, + fmt::{Display, Debug}, + ops::{ControlFlow, Try, Neg}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -96,6 +96,45 @@ impl Try for State { } } +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Score(pub i32); + +impl Score { + // Due to the nature of two's completement, we can't actually negate this properly, so add 1. + pub const LOST: Self = Self(i32::MIN + 1); + pub const TIE: Self = Self(0); + pub const WON: Self = Self(i32::MAX); + + pub fn new(int: i32) -> Self { + Self(int) + } + + #[allow(unused)] + fn randomize(self) -> Self { + let score = self.0 as f32; + let rand = rand::thread_rng(); + self + } +} + +impl Neg for Score { + type Output = Self; + + fn neg(self) -> Self::Output { + Self(-self.0) + } +} + +impl Debug for Score { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + Self::WON => f.write_str("WON"), + Self::LOST => f.write_str("LOST"), + Self(other) => Debug::fmt(&other, f), + } + } +} + #[cfg(test)] mod tests { use std::mem;