use crate::board; 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, } impl Engine { pub fn new() -> Self { let mut board = board::Board::new(); board.reset(); Engine { board, } } pub fn reset(&mut self) { self.board.reset() } pub fn get_state(&self) -> &board::Board { &self.board } pub fn set_state(&mut self, board: board::Board) { self.board = board; } pub fn get_legal_moves( &self, position: &board::Position, ) -> Result + '_, ()> { Ok(self .board .find_moves(position)? .chain(self.board.find_captures(position)?)) } pub fn make_move( &mut self, source: &board::Position, target: board::Position, ) -> Result<(), ()> { if !self.get_legal_moves(source)?.any(|pos| pos == target) { Err(()) } else { // We checked that there is a piece at source in get_legal_moves self.board.relocate(source, target) } } 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, 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| Move_ { source: source.clone(), target, })) } else { None } } else { None } }) .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, ) } }