refact: bot strategy trait
This commit is contained in:
parent
acab0b0593
commit
7848bfcbca
195
bot/src/lib.rs
195
bot/src/lib.rs
|
|
@ -4,81 +4,59 @@ use store::{
|
||||||
CheckerMove, Color, Dice, GameEvent, GameState, Player, PlayerId, PointsRules, Stage, TurnStage,
|
CheckerMove, Color, Dice, GameEvent, GameState, Player, PlayerId, PointsRules, Stage, TurnStage,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub trait BotStrategy {
|
||||||
|
fn get_game(&self) -> &GameState;
|
||||||
|
fn get_mut_game(&mut self) -> &mut GameState;
|
||||||
|
fn calculate_points(&self) -> u8;
|
||||||
|
fn calculate_adv_points(&self) -> u8;
|
||||||
|
fn choose_move(&self) -> (CheckerMove, CheckerMove);
|
||||||
|
fn set_player_id(&mut self, player_id: PlayerId);
|
||||||
|
fn init_players(&mut self) {
|
||||||
|
self.get_mut_game().init_player("p1");
|
||||||
|
self.get_mut_game().init_player("p2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Bot {
|
pub struct DefaultStrategy {
|
||||||
pub game: GameState,
|
pub game: GameState,
|
||||||
pub player_id: PlayerId,
|
pub player_id: PlayerId,
|
||||||
color: Color,
|
pub color: Color,
|
||||||
schools_enabled: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Bot {
|
impl Default for DefaultStrategy {
|
||||||
fn default() -> Bot {
|
fn default() -> Self {
|
||||||
Bot {
|
let game = GameState::default();
|
||||||
game: GameState::default(),
|
let mut strategy = Self {
|
||||||
player_id: 1,
|
|
||||||
color: Color::Black,
|
|
||||||
schools_enabled: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl PlayerEngine for Bot {}
|
|
||||||
|
|
||||||
impl Bot {
|
|
||||||
/// new initialize a bot
|
|
||||||
/// # Examples
|
|
||||||
/// ```let mut bot = Bot::new(Color::Black);
|
|
||||||
/// assert_eq!(bot.game.stage, Stage::PreGame);
|
|
||||||
/// ```
|
|
||||||
pub fn new(color: Color, schools_enabled: bool) -> Self {
|
|
||||||
let mut game = GameState::default();
|
|
||||||
game.init_player("p1");
|
|
||||||
game.init_player("p2");
|
|
||||||
|
|
||||||
let player_id = match color {
|
|
||||||
Color::White => 1,
|
|
||||||
Color::Black => 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
|
||||||
game,
|
game,
|
||||||
player_id,
|
player_id: 2,
|
||||||
color,
|
color: Color::Black,
|
||||||
schools_enabled: false,
|
};
|
||||||
}
|
strategy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefaultStrategy {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BotStrategy for DefaultStrategy {
|
||||||
|
fn get_game(&self) -> &GameState {
|
||||||
|
&self.game
|
||||||
|
}
|
||||||
|
fn get_mut_game(&mut self) -> &mut GameState {
|
||||||
|
&mut self.game
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_event(&mut self, event: &GameEvent) -> Option<GameEvent> {
|
fn set_player_id(&mut self, player_id: PlayerId) {
|
||||||
self.game.consume(event);
|
self.player_id = player_id;
|
||||||
// println!("bot game {:?}", self.game);
|
|
||||||
// println!("bot player_id {:?}", self.player_id);
|
|
||||||
if self.game.active_player_id == self.player_id {
|
|
||||||
return match self.game.turn_stage {
|
|
||||||
TurnStage::MarkAdvPoints => Some(GameEvent::Mark {
|
|
||||||
player_id: self.player_id,
|
|
||||||
points: self.calculate_adv_points(),
|
|
||||||
}),
|
|
||||||
TurnStage::RollDice => Some(GameEvent::Roll {
|
|
||||||
player_id: self.player_id,
|
|
||||||
}),
|
|
||||||
TurnStage::MarkPoints => Some(GameEvent::Mark {
|
|
||||||
player_id: self.player_id,
|
|
||||||
points: self.calculate_points(),
|
|
||||||
}),
|
|
||||||
TurnStage::Move => Some(GameEvent::Move {
|
|
||||||
player_id: self.player_id,
|
|
||||||
moves: self.choose_move(),
|
|
||||||
}),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_points(&self) -> u8 {
|
fn calculate_points(&self) -> u8 {
|
||||||
let dice_roll_count = self
|
let dice_roll_count = self
|
||||||
.game
|
.get_game()
|
||||||
.players
|
.players
|
||||||
.get(&self.player_id)
|
.get(&self.player_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -89,7 +67,7 @@ impl Bot {
|
||||||
|
|
||||||
fn calculate_adv_points(&self) -> u8 {
|
fn calculate_adv_points(&self) -> u8 {
|
||||||
let dice_roll_count = self
|
let dice_roll_count = self
|
||||||
.game
|
.get_game()
|
||||||
.players
|
.players
|
||||||
.get(&self.player_id)
|
.get(&self.player_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -116,29 +94,108 @@ impl Bot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Bot<BotStrategy> {
|
||||||
|
pub player_id: PlayerId,
|
||||||
|
strategy: BotStrategy,
|
||||||
|
color: Color,
|
||||||
|
schools_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Bot<DefaultStrategy> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
player_id: 2,
|
||||||
|
strategy: DefaultStrategy::default(),
|
||||||
|
color: Color::Black,
|
||||||
|
schools_enabled: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<BS> Bot<BS>
|
||||||
|
where
|
||||||
|
BS: BotStrategy,
|
||||||
|
{
|
||||||
|
/// new initialize a bot
|
||||||
|
/// # Examples
|
||||||
|
/// ```let mut bot = Bot::new(Color::Black);
|
||||||
|
/// assert_eq!(bot.game.stage, Stage::PreGame);
|
||||||
|
/// ```
|
||||||
|
pub fn new(mut strategy: BS, color: Color, schools_enabled: bool) -> Self {
|
||||||
|
let game = strategy.get_mut_game();
|
||||||
|
strategy.init_players();
|
||||||
|
let player_id = match color {
|
||||||
|
Color::White => 1,
|
||||||
|
Color::Black => 2,
|
||||||
|
};
|
||||||
|
strategy.set_player_id(player_id);
|
||||||
|
Self {
|
||||||
|
player_id,
|
||||||
|
strategy,
|
||||||
|
color,
|
||||||
|
schools_enabled: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_event(&mut self, event: &GameEvent) -> Option<GameEvent> {
|
||||||
|
let game = self.strategy.get_mut_game();
|
||||||
|
game.consume(event);
|
||||||
|
// println!("bot game {:?}", self.game);
|
||||||
|
// println!("bot player_id {:?}", self.player_id);
|
||||||
|
if game.active_player_id == self.player_id {
|
||||||
|
return match game.turn_stage {
|
||||||
|
TurnStage::MarkAdvPoints => Some(GameEvent::Mark {
|
||||||
|
player_id: self.player_id,
|
||||||
|
points: self.strategy.calculate_adv_points(),
|
||||||
|
}),
|
||||||
|
TurnStage::RollDice => Some(GameEvent::Roll {
|
||||||
|
player_id: self.player_id,
|
||||||
|
}),
|
||||||
|
TurnStage::MarkPoints => Some(GameEvent::Mark {
|
||||||
|
player_id: self.player_id,
|
||||||
|
points: self.strategy.calculate_points(),
|
||||||
|
}),
|
||||||
|
TurnStage::Move => Some(GameEvent::Move {
|
||||||
|
player_id: self.player_id,
|
||||||
|
moves: self.strategy.choose_move(),
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_state(&self) -> &GameState {
|
||||||
|
self.strategy.get_game()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_new() {
|
fn test_new() {
|
||||||
let bot = Bot::new(Color::Black, false);
|
let bot = Bot::new(DefaultStrategy::new(), Color::Black, false);
|
||||||
assert_eq!(bot.game.stage, Stage::PreGame);
|
assert_eq!(bot.get_state().stage, Stage::PreGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_consume() {
|
fn test_consume() {
|
||||||
let mut bot = Bot::new(Color::Black, false);
|
let mut bot = Bot::new(DefaultStrategy::new(), Color::Black, false);
|
||||||
let mut event = bot.handle_event(&GameEvent::BeginGame { goes_first: 2 });
|
let mut event = bot.handle_event(&GameEvent::BeginGame { goes_first: 2 });
|
||||||
assert_eq!(event, Some(GameEvent::Roll { player_id: 2 }));
|
assert_eq!(event, Some(GameEvent::Roll { player_id: 2 }));
|
||||||
|
assert_eq!(bot.get_state().active_player_id, 2);
|
||||||
|
|
||||||
event = bot.handle_event(&GameEvent::BeginGame { goes_first: 1 });
|
event = bot.handle_event(&GameEvent::BeginGame { goes_first: 1 });
|
||||||
assert_eq!(event, None);
|
assert_eq!(event, None);
|
||||||
|
|
||||||
|
assert_eq!(bot.get_state().active_player_id, 1);
|
||||||
bot.handle_event(&GameEvent::RollResult {
|
bot.handle_event(&GameEvent::RollResult {
|
||||||
player_id: 2,
|
player_id: 1,
|
||||||
dice: Dice { values: (2, 3) },
|
dice: Dice { values: (2, 3) },
|
||||||
});
|
});
|
||||||
assert_eq!(bot.game.turn_stage, TurnStage::Move);
|
assert_eq!(bot.get_state().turn_stage, TurnStage::Move);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::game_runner::Game;
|
use crate::game_runner::Game;
|
||||||
|
use bot::BotStrategy;
|
||||||
use store::{CheckerMove, GameEvent, GameState, PointsRules, Stage, TurnStage};
|
use store::{CheckerMove, GameEvent, GameState, PointsRules, Stage, TurnStage};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,26 @@
|
||||||
use bot::Bot;
|
use bot::{Bot, BotStrategy, DefaultStrategy};
|
||||||
use store::{CheckerMove, DiceRoller, GameEvent, GameState, PlayerId, TurnStage};
|
use store::{CheckerMove, DiceRoller, GameEvent, GameState, PlayerId, TurnStage};
|
||||||
|
|
||||||
// Application Game
|
// Application Game
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug)]
|
||||||
pub struct Game {
|
pub struct Game {
|
||||||
pub state: GameState,
|
pub state: GameState,
|
||||||
pub dice_roller: DiceRoller,
|
pub dice_roller: DiceRoller,
|
||||||
pub first_move: Option<CheckerMove>,
|
pub first_move: Option<CheckerMove>,
|
||||||
pub player_id: Option<PlayerId>,
|
pub player_id: Option<PlayerId>,
|
||||||
bot: Bot,
|
bot: Bot<DefaultStrategy>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Game {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
state: GameState::default(),
|
||||||
|
dice_roller: DiceRoller::default(),
|
||||||
|
first_move: None,
|
||||||
|
player_id: None,
|
||||||
|
bot: Bot::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
|
|
@ -20,7 +32,8 @@ impl Game {
|
||||||
// bot
|
// bot
|
||||||
let bot_id: PlayerId = state.init_player("bot").unwrap();
|
let bot_id: PlayerId = state.init_player("bot").unwrap();
|
||||||
let bot_color = state.player_color_by_id(&bot_id).unwrap();
|
let bot_color = state.player_color_by_id(&bot_id).unwrap();
|
||||||
let bot: Bot = Bot::new(bot_color, schools_enabled);
|
let bot_strategy = DefaultStrategy::default();
|
||||||
|
let bot: Bot<DefaultStrategy> = Bot::new(bot_strategy, bot_color, schools_enabled);
|
||||||
|
|
||||||
let mut game = Self {
|
let mut game = Self {
|
||||||
state,
|
state,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue