From 01b456b4fef8ce4a002f870e5385424614a2a5fb Mon Sep 17 00:00:00 2001 From: Mike White Date: Wed, 15 Sep 2021 20:49:13 -0400 Subject: Added best move function --- ai/src/lib.rs | 20 +++++++++++++++++++- cli/src/eval.rs | 6 +++++- cli/src/main.rs | 24 ++++++++++++++++++++++++ model/src/moves.rs | 14 +++++++++++++- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/ai/src/lib.rs b/ai/src/lib.rs index 405c88d..89fd345 100644 --- a/ai/src/lib.rs +++ b/ai/src/lib.rs @@ -1,4 +1,5 @@ pub use model::{CheckersBitBoard, Move, PieceColor, PossibleMoves}; +use std::mem::MaybeUninit; const KING_WORTH: u32 = 2; @@ -22,7 +23,7 @@ fn eval_position(board: CheckersBitBoard) -> f32 { if dark_eval + light_eval != 0.0 { light_eval / (dark_eval + light_eval) } else { - 0.0 + 0.5 } } @@ -55,3 +56,20 @@ pub fn eval(depth: usize, mut alpha: f32, beta: f32, board: CheckersBitBoard) -> best_eval } } + +pub fn best_move(depth: usize, board: CheckersBitBoard) -> Move { + let mut best_eval = 0.0; + let mut best_move = MaybeUninit::uninit(); + for current_move in PossibleMoves::moves(board) { + let current_eval = eval(depth - 1, best_eval, 1.0, unsafe { + current_move.apply_to(board) + }); + println!("{} {}", current_move, current_eval); + if current_eval > best_eval { + best_eval = current_eval; + best_move = MaybeUninit::new(current_move); + } + } + + unsafe { best_move.assume_init() } +} diff --git a/cli/src/eval.rs b/cli/src/eval.rs index d078c5f..72fa32a 100644 --- a/cli/src/eval.rs +++ b/cli/src/eval.rs @@ -1,4 +1,8 @@ -use ai::CheckersBitBoard; +use ai::{CheckersBitBoard, Move}; pub fn eval(depth: usize) -> f32 { ai::eval(depth, 0.0, 1.0, CheckersBitBoard::starting_position()) } + +pub fn best_move(depth: usize) -> Move { + ai::best_move(depth, CheckersBitBoard::starting_position()) +} diff --git a/cli/src/main.rs b/cli/src/main.rs index a550092..d230398 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -31,6 +31,17 @@ fn main() { .help("The depth to go to"), ), ) + .subcommand( + SubCommand::with_name("best") + .about("Calculate the best move") + .arg( + Arg::with_name("depth") + .required(true) + .short("d") + .takes_value(true) + .help("The depth to go to"), + ), + ) .get_matches(); if let Some(matches) = matches.subcommand_matches("perft") { @@ -59,4 +70,17 @@ fn main() { ) ); } + + if let Some(matches) = matches.subcommand_matches("best") { + println!( + "{}", + eval::best_move( + matches + .value_of("depth") + .unwrap() + .parse() + .expect("Error: not a valid number") + ) + ) + } } diff --git a/model/src/moves.rs b/model/src/moves.rs index 720e11a..f6b1fce 100644 --- a/model/src/moves.rs +++ b/model/src/moves.rs @@ -1,4 +1,5 @@ -use crate::CheckersBitBoard; +use crate::{CheckersBitBoard, SquareCoordinate}; +use std::fmt::{Display, Formatter}; #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum MoveDirection { @@ -122,6 +123,17 @@ impl Move { } } +impl Display for Move { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}-{}", + SquareCoordinate::from_value(self.start as usize), + SquareCoordinate::from_value(self.end_position()) + ) + } +} + #[cfg(test)] mod tests { -- cgit v1.2.3