othello_agent/simulate/
game.rs1use crate::{
2 agent::rule_based::RuleAgent,
3 agent::traits::Agent,
4 gameplay::{ constants::INITIAL_BOARD, types::IBoard, utils::board_by_playing_piece_at_index },
5};
6
7use super::history::{ GameHistoryStore, GameHistory };
8
9pub struct OthelloSimulator {
10 agent0: RuleAgent,
11 agent1: RuleAgent,
12 board: IBoard,
13 history_store: GameHistoryStore,
14}
15
16impl OthelloSimulator {
17 pub fn new() -> Self {
18 OthelloSimulator {
19 agent0: RuleAgent::new(0),
20 agent1: RuleAgent::new(1),
21 board: INITIAL_BOARD,
22 history_store: GameHistoryStore::new(),
23 }
24 }
25 pub fn play_game(&mut self) {
26 let mut current_player = 0;
27 let mut current_board: IBoard = self.board;
28 let mut num_skips: u8 = 0;
29 let mut game_history = GameHistory::new();
30 loop {
31 println!("Player {}'s turn", current_player);
32 if num_skips == 2 {
34 game_history.add_board(current_board, true);
36 break;
37 } else {
38 game_history.add_board(current_board, false);
40 }
41 let agent = if current_player == 0 { &self.agent0 } else { &self.agent1 };
43 let move_position = agent.get_move(current_board);
45 if move_position.is_none() {
47 println!("Player {} has no move", current_player);
48 current_player = 1 - current_player;
49 num_skips += 1;
50 continue;
51 }
52 let new_board: Option<IBoard> = board_by_playing_piece_at_index(
54 current_board,
55 move_position.unwrap(),
56 current_player
57 );
58 if new_board.is_none() {
59 panic!("Invalid move suggested by agent");
60 }
61 current_board = new_board.unwrap();
63 current_player = 1 - current_player;
64 num_skips = 0;
65 }
66 self.history_store.add_game(game_history);
68 }
69
70 pub fn play_games(&mut self, num_games: u32) {
71 for _ in 0..num_games {
72 self.play_game();
73 }
74 }
75
76 pub fn print_summary(&self) {
77 self.history_store.print_summary();
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use crate::{
84 simulate::{ game::OthelloSimulator, history::GameHistory },
85 gameplay::constants::DEFAULT_BOARD_WIDTH,
86 };
87
88 #[test]
89 fn test_play_game() {
90 let mut simulator = OthelloSimulator::new();
91 simulator.play_game();
92 simulator.print_summary();
94 assert_eq!(simulator.history_store.total_games, 1);
95 let last_game: Option<&GameHistory> = simulator.history_store.last_game();
97 assert_eq!(last_game.is_some(), true);
98 assert_eq!(last_game.unwrap().total_moves > 0, true);
100 assert_eq!(
102 last_game.unwrap().agent0_score > 0 || last_game.unwrap().agent1_score > 0,
103 true
104 );
105 assert_eq!(
107 last_game.unwrap().agent0_score + last_game.unwrap().agent1_score,
108 (DEFAULT_BOARD_WIDTH as i16) * (DEFAULT_BOARD_WIDTH as i16)
109 );
110 }
111}