2024-03-24 18:37:35 +01:00
|
|
|
mod bot;
|
|
|
|
|
|
2024-05-20 19:04:46 +02:00
|
|
|
use store::{
|
|
|
|
|
CheckerMove, Color, Dice, GameEvent, GameState, Player, PlayerId, PointsRules, Stage, TurnStage,
|
|
|
|
|
};
|
2024-03-24 18:37:35 +01:00
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct Bot {
|
|
|
|
|
pub game: GameState,
|
2024-03-27 21:10:15 +01:00
|
|
|
pub player_id: PlayerId,
|
2024-03-24 18:37:35 +01:00
|
|
|
color: Color,
|
2024-09-22 16:11:42 +02:00
|
|
|
schools_enabled: bool,
|
2024-03-24 18:37:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for Bot {
|
|
|
|
|
fn default() -> Bot {
|
|
|
|
|
Bot {
|
|
|
|
|
game: GameState::default(),
|
|
|
|
|
player_id: 1,
|
|
|
|
|
color: Color::Black,
|
2024-09-22 16:11:42 +02:00
|
|
|
schools_enabled: false,
|
2024-03-24 18:37:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
/// ```
|
2024-09-22 16:11:42 +02:00
|
|
|
pub fn new(color: Color, schools_enabled: bool) -> Self {
|
2024-03-24 18:37:35 +01:00
|
|
|
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,
|
|
|
|
|
player_id,
|
|
|
|
|
color,
|
2024-09-22 16:11:42 +02:00
|
|
|
schools_enabled: false,
|
2024-03-24 18:37:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-30 16:10:53 +01:00
|
|
|
pub fn handle_event(&mut self, event: &GameEvent) -> Option<GameEvent> {
|
2024-03-24 18:37:35 +01:00
|
|
|
self.game.consume(event);
|
2024-03-29 21:04:58 +01:00
|
|
|
// println!("bot game {:?}", self.game);
|
|
|
|
|
// println!("bot player_id {:?}", self.player_id);
|
2024-03-24 18:37:35 +01:00
|
|
|
if self.game.active_player_id == self.player_id {
|
|
|
|
|
return match self.game.turn_stage {
|
2024-09-20 20:39:18 +02:00
|
|
|
TurnStage::MarkAdvPoints => Some(GameEvent::Mark {
|
|
|
|
|
player_id: self.player_id,
|
|
|
|
|
points: self.calculate_adv_points(),
|
|
|
|
|
}),
|
2024-03-24 18:37:35 +01:00
|
|
|
TurnStage::RollDice => Some(GameEvent::Roll {
|
|
|
|
|
player_id: self.player_id,
|
|
|
|
|
}),
|
|
|
|
|
TurnStage::MarkPoints => Some(GameEvent::Mark {
|
|
|
|
|
player_id: self.player_id,
|
2024-05-20 19:04:46 +02:00
|
|
|
points: self.calculate_points(),
|
2024-03-24 18:37:35 +01:00
|
|
|
}),
|
|
|
|
|
TurnStage::Move => Some(GameEvent::Move {
|
|
|
|
|
player_id: self.player_id,
|
|
|
|
|
moves: self.choose_move(),
|
|
|
|
|
}),
|
2024-03-27 21:10:15 +01:00
|
|
|
_ => None,
|
2024-03-24 18:37:35 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-20 19:04:46 +02:00
|
|
|
fn calculate_points(&self) -> u8 {
|
2024-09-23 17:53:21 +02:00
|
|
|
let dice_roll_count = self
|
|
|
|
|
.game
|
|
|
|
|
.players
|
|
|
|
|
.get(&self.player_id)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.dice_roll_count;
|
2024-09-20 20:39:18 +02:00
|
|
|
let points_rules = PointsRules::new(&Color::White, &self.game.board, self.game.dice);
|
2024-09-23 17:53:21 +02:00
|
|
|
points_rules.get_points(dice_roll_count).0
|
2024-09-20 20:39:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn calculate_adv_points(&self) -> u8 {
|
2024-09-23 17:53:21 +02:00
|
|
|
let dice_roll_count = self
|
|
|
|
|
.game
|
|
|
|
|
.players
|
|
|
|
|
.get(&self.player_id)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.dice_roll_count;
|
2024-09-20 20:39:18 +02:00
|
|
|
let points_rules = PointsRules::new(&Color::White, &self.game.board, self.game.dice);
|
2024-09-23 17:53:21 +02:00
|
|
|
points_rules.get_points(dice_roll_count).0
|
2024-05-20 19:04:46 +02:00
|
|
|
}
|
|
|
|
|
|
2024-03-24 18:37:35 +01:00
|
|
|
fn choose_move(&self) -> (CheckerMove, CheckerMove) {
|
|
|
|
|
let (dice1, dice2) = match self.color {
|
2024-03-26 21:07:47 +01:00
|
|
|
Color::White => (self.game.dice.values.0 as i8, self.game.dice.values.1 as i8),
|
|
|
|
|
Color::Black => (
|
|
|
|
|
0 - self.game.dice.values.0 as i8,
|
|
|
|
|
0 - self.game.dice.values.1 as i8,
|
|
|
|
|
),
|
2024-03-24 18:37:35 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let fields = self.game.board.get_color_fields(self.color);
|
|
|
|
|
let first_field = fields.first().unwrap();
|
|
|
|
|
(
|
2024-03-26 21:07:47 +01:00
|
|
|
CheckerMove::new(first_field.0, (first_field.0 as i8 + dice1) as usize).unwrap(),
|
|
|
|
|
CheckerMove::new(first_field.0, (first_field.0 as i8 + dice2) as usize).unwrap(),
|
2024-03-24 18:37:35 +01:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_new() {
|
2024-09-22 16:11:42 +02:00
|
|
|
let bot = Bot::new(Color::Black, false);
|
2024-03-24 18:37:35 +01:00
|
|
|
assert_eq!(bot.game.stage, Stage::PreGame);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_consume() {
|
2024-09-22 16:11:42 +02:00
|
|
|
let mut bot = Bot::new(Color::Black, false);
|
2024-03-30 16:10:53 +01:00
|
|
|
let mut event = bot.handle_event(&GameEvent::BeginGame { goes_first: 2 });
|
2024-03-24 18:37:35 +01:00
|
|
|
assert_eq!(event, Some(GameEvent::Roll { player_id: 2 }));
|
|
|
|
|
|
2024-03-30 16:10:53 +01:00
|
|
|
event = bot.handle_event(&GameEvent::BeginGame { goes_first: 1 });
|
2024-03-24 18:37:35 +01:00
|
|
|
assert_eq!(event, None);
|
|
|
|
|
|
2024-03-30 16:10:53 +01:00
|
|
|
bot.handle_event(&GameEvent::RollResult {
|
2024-03-24 18:37:35 +01:00
|
|
|
player_id: 2,
|
|
|
|
|
dice: Dice { values: (2, 3) },
|
|
|
|
|
});
|
2024-09-22 16:11:42 +02:00
|
|
|
assert_eq!(bot.game.turn_stage, TurnStage::Move);
|
2024-03-24 18:37:35 +01:00
|
|
|
}
|
|
|
|
|
}
|