From f4ac92ff894982d85dddee439f93ce6bd05cb578 Mon Sep 17 00:00:00 2001 From: Pavel Lutskov Date: Wed, 5 Mar 2025 21:40:20 +0100 Subject: [PATCH] Implement basic move evaluation It ain't much but it's honest work --- rs/src/board.rs | 2 ++ rs/src/engine.rs | 64 ++++++++++++++++++++++++++++++++++++++++++------ rs/src/ui.rs | 4 +-- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/rs/src/board.rs b/rs/src/board.rs index 8cf5b8b..3099cdb 100644 --- a/rs/src/board.rs +++ b/rs/src/board.rs @@ -264,6 +264,7 @@ impl PieceType { } } +#[derive(Clone)] pub struct Piece { pub color: Color, pub piece_type: PieceType, @@ -292,6 +293,7 @@ impl Piece { } } +#[derive(Clone)] pub struct Board { state: HashMap, } diff --git a/rs/src/engine.rs b/rs/src/engine.rs index 42e3482..6203a1b 100644 --- a/rs/src/engine.rs +++ b/rs/src/engine.rs @@ -1,5 +1,19 @@ use crate::board; -use rand::seq::IteratorRandom; +use crate::rand::Rng; + +impl board::PieceType { + fn value(&self) -> f32 { + match self { + board::PieceType::Pawn => 1.0, + board::PieceType::Knight => 3.0, + } + } +} + +pub struct Move_ { + pub source: board::Position, + pub target: board::Position, +} pub struct Engine { board: board::Board, @@ -43,16 +57,38 @@ impl Engine { self.board.relocate(source, target) } } - pub fn choose_move( + pub fn evaluate_position(&self, board: &board::Board) -> f32 { + board + .iter() + .map(|(_, piece)| match piece.color { + board::Color::White => 1.0, + board::Color::Black => -1.0, + } * piece.piece_type.value()) + .sum() + } + pub fn evaluate_move( &self, color: &board::Color, - ) -> Option<(board::Position, board::Position)> { - self.board + move_: &Move_, + ) -> Result { + let mut board = self.board.clone(); + board.relocate(&move_.source, move_.target.clone())?; + Ok(match color { + board::Color::White => 1.0, + board::Color::Black => -1.0, + } * self.evaluate_position(&board)) + } + pub fn choose_move(&self, color: &board::Color) -> Option { + let all_moves = self + .board .iter() .filter_map(|(source, piece)| { if &piece.color == color { if let Ok(targets) = self.get_legal_moves(source) { - Some(targets.map(|target| (source.clone(), target))) + Some(targets.map(|target| Move_ { + source: source.clone(), + target, + })) } else { None } @@ -60,7 +96,21 @@ impl Engine { None } }) - .flatten() - .choose(&mut rand::thread_rng()) + .flatten(); + let mut rng = rand::thread_rng(); + Some( + all_moves + .map(|move_| { + ( + self.evaluate_move(color, &move_).unwrap() + + rng.gen::() * 0.1, + move_, + ) + }) + .max_by(|(score1, _), (score2, _)| { + score1.partial_cmp(score2).unwrap() + })? + .1, + ) } } diff --git a/rs/src/ui.rs b/rs/src/ui.rs index b05867e..d54d257 100644 --- a/rs/src/ui.rs +++ b/rs/src/ui.rs @@ -258,8 +258,8 @@ impl Ui { format!("Couldn't parse color code {}", color_char) })?, ) { - Some((source, target)) => { - Ok(format!("{},{}", source, target)) + Some(move_) => { + Ok(format!("{},{}", move_.source, move_.target)) } None => { Err(format!("No move possible for {}", color_char))