feat: bot random strategy

This commit is contained in:
Henri Bourcereau 2025-08-08 16:24:12 +02:00
parent b02ce8d185
commit bf820ecc4e
10 changed files with 106 additions and 27 deletions

View file

@ -1,11 +1,12 @@
pub mod dqn;
pub mod strategy;
use log::{error, info};
use log::{debug, error};
use store::{CheckerMove, Color, GameEvent, GameState, PlayerId, PointsRules, Stage, TurnStage};
pub use strategy::default::DefaultStrategy;
pub use strategy::dqn::DqnStrategy;
pub use strategy::erroneous_moves::ErroneousStrategy;
pub use strategy::random::RandomStrategy;
pub use strategy::stable_baselines3::StableBaselines3Strategy;
pub trait BotStrategy: std::fmt::Debug {
@ -64,7 +65,7 @@ impl Bot {
}
pub fn handle_event(&mut self, event: &GameEvent) -> Option<GameEvent> {
info!(">>>> {:?} BOT handle", self.color);
debug!(">>>> {:?} BOT handle", self.color);
let game = self.strategy.get_mut_game();
let internal_event = if self.color == Color::Black {
&event.get_mirror()
@ -76,7 +77,7 @@ impl Bot {
let turn_stage = game.turn_stage;
game.consume(internal_event);
if game.stage == Stage::Ended {
info!("<<<< end {:?} BOT handle", self.color);
debug!("<<<< end {:?} BOT handle", self.color);
return None;
}
let active_player_id = if self.color == Color::Black {
@ -91,7 +92,7 @@ impl Bot {
if active_player_id == self.player_id {
let player_points = game.who_plays().map(|p| (p.points, p.holes));
if self.color == Color::Black {
info!( " input (internal) evt : {internal_event:?}, points : {init_player_points:?}, stage : {turn_stage:?}");
debug!( " input (internal) evt : {internal_event:?}, points : {init_player_points:?}, stage : {turn_stage:?}");
}
let internal_event = match game.turn_stage {
TurnStage::MarkAdvPoints => Some(GameEvent::Mark {
@ -120,15 +121,15 @@ impl Bot {
_ => None,
};
return if self.color == Color::Black {
info!(" bot (internal) evt : {internal_event:?} ; points : {player_points:?}");
info!("<<<< end {:?} BOT handle", self.color);
debug!(" bot (internal) evt : {internal_event:?} ; points : {player_points:?}");
debug!("<<<< end {:?} BOT handle", self.color);
internal_event.map(|evt| evt.get_mirror())
} else {
info!("<<<< end {:?} BOT handle", self.color);
debug!("<<<< end {:?} BOT handle", self.color);
internal_event
};
}
info!("<<<< end {:?} BOT handle", self.color);
debug!("<<<< end {:?} BOT handle", self.color);
None
}

View file

@ -1,4 +1,5 @@
use crate::{BotStrategy, CheckerMove, Color, GameState, PlayerId};
use log::info;
use std::path::Path;
use store::MoveRules;
@ -31,9 +32,10 @@ impl DqnStrategy {
Self::default()
}
pub fn new_with_model<P: AsRef<Path>>(model_path: P) -> Self {
pub fn new_with_model<P: AsRef<Path> + std::fmt::Debug>(model_path: P) -> Self {
let mut strategy = Self::new();
if let Ok(model) = SimpleNeuralNetwork::load(model_path) {
if let Ok(model) = SimpleNeuralNetwork::load(&model_path) {
info!("Loading model {model_path:?}");
strategy.model = Some(model);
}
strategy

View file

@ -2,4 +2,5 @@ pub mod client;
pub mod default;
pub mod dqn;
pub mod erroneous_moves;
pub mod random;
pub mod stable_baselines3;

View file

@ -0,0 +1,67 @@
use crate::{BotStrategy, CheckerMove, Color, GameState, PlayerId};
use store::MoveRules;
#[derive(Debug)]
pub struct RandomStrategy {
pub game: GameState,
pub player_id: PlayerId,
pub color: Color,
}
impl Default for RandomStrategy {
fn default() -> Self {
let game = GameState::default();
Self {
game,
player_id: 1,
color: Color::White,
}
}
}
impl BotStrategy for RandomStrategy {
fn get_game(&self) -> &GameState {
&self.game
}
fn get_mut_game(&mut self) -> &mut GameState {
&mut self.game
}
fn set_color(&mut self, color: Color) {
self.color = color;
}
fn set_player_id(&mut self, player_id: PlayerId) {
self.player_id = player_id;
}
fn calculate_points(&self) -> u8 {
self.game.dice_points.0
}
fn calculate_adv_points(&self) -> u8 {
self.game.dice_points.1
}
fn choose_go(&self) -> bool {
true
}
fn choose_move(&self) -> (CheckerMove, CheckerMove) {
let rules = MoveRules::new(&self.color, &self.game.board, self.game.dice);
let possible_moves = rules.get_possible_moves_sequences(true, vec![]);
use rand::{seq::SliceRandom, thread_rng};
let mut rng = thread_rng();
let choosen_move = possible_moves
.choose(&mut rng)
.cloned()
.unwrap_or((CheckerMove::default(), CheckerMove::default()));
if self.color == Color::White {
choosen_move
} else {
(choosen_move.0.mirror(), choosen_move.1.mirror())
}
}
}