trictrac/client_cli/src/game_runner.rs

109 lines
3.3 KiB
Rust
Raw Normal View History

2025-01-15 17:46:39 +01:00
use bot::{Bot, BotStrategy};
2024-10-16 17:37:38 +02:00
use store::{CheckerMove, DiceRoller, GameEvent, GameState, PlayerId, TurnStage};
// Application Game
2024-11-04 17:37:36 +01:00
#[derive(Debug, Default)]
2024-11-19 17:28:18 +01:00
pub struct GameRunner {
2024-10-16 17:37:38 +02:00
pub state: GameState,
pub dice_roller: DiceRoller,
pub first_move: Option<CheckerMove>,
pub player_id: Option<PlayerId>,
2024-11-19 17:28:18 +01:00
bots: Vec<Bot>,
2024-10-16 17:37:38 +02:00
}
2024-11-19 17:28:18 +01:00
impl GameRunner {
2024-10-16 17:37:38 +02:00
// Constructs a new instance of [`App`].
2024-11-19 17:28:18 +01:00
pub fn new(
schools_enabled: bool,
bot_strategies: Vec<Box<dyn BotStrategy>>,
seed: Option<u64>,
) -> Self {
2024-10-16 17:37:38 +02:00
let mut state = GameState::new(schools_enabled);
// local : player
2025-01-06 20:27:16 +01:00
let player_id: Option<PlayerId> = if bot_strategies.len() > 1 {
None
} else {
state.init_player("myself")
};
2024-11-19 17:28:18 +01:00
// bots
2025-01-03 17:40:08 +01:00
let bots: Vec<Bot> = bot_strategies
2024-11-19 17:28:18 +01:00
.into_iter()
.map(|strategy| {
let bot_id: PlayerId = state.init_player("bot").unwrap();
let bot_color = state.player_color_by_id(&bot_id).unwrap();
Bot::new(strategy, bot_color)
})
.collect();
// let bot_strategy = Box::new(DefaultStrategy::default());
2024-11-04 17:37:36 +01:00
// let bot: Bot = Bot::new(bot_strategy, bot_color, schools_enabled);
2024-11-19 17:28:18 +01:00
// let bot: Bot = Bot::new(bot_strategy, bot_color);
2024-10-16 17:37:38 +02:00
2025-01-03 17:40:08 +01:00
let first_player_id = if bots.len() > 1 {
bots[0].player_id
} else {
player_id.unwrap()
};
2024-10-16 17:37:38 +02:00
let mut game = Self {
state,
dice_roller: DiceRoller::new(seed),
first_move: None,
player_id,
2024-11-19 17:28:18 +01:00
bots,
2024-10-16 17:37:38 +02:00
};
game.handle_event(&GameEvent::BeginGame {
2025-01-03 17:40:08 +01:00
goes_first: first_player_id,
2024-10-16 17:37:38 +02:00
});
game
}
pub fn handle_event(&mut self, event: &GameEvent) -> Option<GameEvent> {
if !self.state.validate(event) {
2025-01-06 20:27:16 +01:00
println!("event not valid : {:?}", event);
2024-10-16 17:37:38 +02:00
return None;
}
// println!("consuming {:?}", event);
self.state.consume(event);
2025-01-03 17:40:08 +01:00
2024-10-16 17:37:38 +02:00
// chain all successive bot actions
2025-01-03 17:40:08 +01:00
if self.bots.is_empty() {
return None;
}
// Collect bot actions to avoid borrow conflicts
let bot_events: Vec<GameEvent> = self
.bots
.iter_mut()
.filter_map(|bot| bot.handle_event(event))
.collect();
2025-01-06 20:27:16 +01:00
// if bot_events.len() > 1 {
// println!(
// "There might be a problem : 2 bots events : {:?}",
// bot_events
// );
// }
2025-01-03 17:40:08 +01:00
let mut next_event = None;
for bot_event in bot_events {
let bot_result_event = self.handle_event(&bot_event);
if let Some(bot_id) = bot_event.player_id() {
next_event = if self.bot_needs_dice_roll(bot_id) {
let dice = self.dice_roller.roll();
self.handle_event(&GameEvent::RollResult {
player_id: bot_id,
dice,
})
} else {
bot_result_event
2025-01-06 20:27:16 +01:00
};
2025-01-03 17:40:08 +01:00
}
2024-10-16 17:37:38 +02:00
}
2025-01-03 17:40:08 +01:00
next_event
2024-10-16 17:37:38 +02:00
}
2025-01-03 17:40:08 +01:00
fn bot_needs_dice_roll(&self, bot_id: PlayerId) -> bool {
self.state.active_player_id == bot_id && self.state.turn_stage == TurnStage::RollWaiting
2024-10-16 17:37:38 +02:00
}
}