diff --git a/Cargo.lock b/Cargo.lock index c6f2ddd..2a51773 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,7 @@ name = "rust_hanabi" version = "0.1.0" dependencies = [ + "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -10,6 +11,14 @@ name = "libc" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "log" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.3.14" diff --git a/Cargo.toml b/Cargo.toml index 9ccba86..b51f826 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,4 @@ authors = ["Jeff Wu "] [dependencies] rand = "*" +log = "*" diff --git a/src/game.rs b/src/game.rs index e9d3011..9d5c47e 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,3 +1,4 @@ + use rand::{self, Rng}; use std::collections::HashSet; use std::collections::HashMap; @@ -140,7 +141,7 @@ pub struct GameState { pub type Score = u32; impl GameState { - pub fn new(opts: GameOptions) -> GameState { + pub fn new(opts: &GameOptions) -> GameState { let mut deck = GameState::make_deck(); let mut player_states : HashMap = HashMap::new(); @@ -193,7 +194,7 @@ impl GameState { } }; deck.shuffle(); - println!("Created deck: {:?}", deck); + info!("Created deck: {:?}", deck); deck } @@ -210,7 +211,8 @@ impl GameState { pub fn score(&self) -> Score { let mut score = 0; for (_, firework) in &self.board.fireworks { - score += firework.size(); + // subtract one to account for the 0 we pushed + score += firework.size() - 1; } score as u32 } @@ -246,8 +248,8 @@ impl GameState { } } - fn process_choice(&mut self, choice: TurnChoice) { - match choice { + pub fn process_choice(&mut self, choice: &TurnChoice) { + match *choice { TurnChoice::Hint => { assert!(self.board.hints_remaining > 0); self.board.hints_remaining -= 1; @@ -263,6 +265,12 @@ impl GameState { } TurnChoice::Play(index) => { let card = self.take_from_hand(index); + + debug!( + "Here! Playing card at {}, which is {:?}", + index, card + ); + let mut firework_made = false; { @@ -279,6 +287,10 @@ impl GameState { } else { self.board.discard.place(card); self.board.lives_remaining -= 1; + debug!( + "Removing a life! Lives remaining: {}", + self.board.lives_remaining + ); } } diff --git a/src/main.rs b/src/main.rs index 3f90019..055bd07 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,35 @@ extern crate rand; +#[macro_use] +extern crate log; mod game; mod strategies; + +struct SimpleLogger; +impl log::Log for SimpleLogger { + fn enabled(&self, metadata: &log::LogMetadata) -> bool { + metadata.level() <= log::LogLevel::Debug + } + + fn log(&self, record: &log::LogRecord) { + if self.enabled(record.metadata()) { + println!("{} - {}", record.level(), record.args()); + } + } +} + fn main() { + log::set_logger(|max_log_level| { + max_log_level.set(log::LogLevelFilter::Info); + Box::new(SimpleLogger) + }); + let opts = game::GameOptions { num_players: 4, hand_size: 4, num_hints: 8, num_lives: 3, }; - strategies::simulate(opts, strategies::AlwaysPlay); + strategies::simulate(&opts, &strategies::AlwaysPlay, 100); } diff --git a/src/strategies.rs b/src/strategies.rs index 407ed5a..455d76a 100644 --- a/src/strategies.rs +++ b/src/strategies.rs @@ -10,7 +10,7 @@ pub trait Strategy { fn update(&mut Self::InternalState, &Turn, &GameStateView); } -pub fn simulate(opts: GameOptions, strategy: S) -> Score { +pub fn simulate_once(opts: &GameOptions, strategy: &S) -> Score { let mut game = GameState::new(opts); let mut internal_states : HashMap = HashMap::new(); @@ -27,7 +27,10 @@ pub fn simulate(opts: GameOptions, strategy: S) -> Score { let ref mut internal_state = internal_states.get_mut(&player).unwrap(); S::decide(internal_state, &player, &game.get_view(player)) }; - println!("Player {:?} decided to {:?}", player, choice); + + game.process_choice(&choice); + + info!("Player {:?} decided to {:?}", player, choice); let turn = Turn { player: &player, choice: &choice, @@ -40,11 +43,23 @@ pub fn simulate(opts: GameOptions, strategy: S) -> Score { } // TODO: do some stuff - println!("State: {:?}", game); + info!("State: {:?}", game); } game.score() } +pub fn simulate(opts: &GameOptions, strategy: &S, n_trials: u32) -> f32 { + let mut total_score = 0; + for _ in 0..n_trials { + let score = simulate_once(&opts, strategy); + info!("Scored: {:?}", score); + total_score += score; + } + let average: f32 = (total_score as f32) / (n_trials as f32); + info!("Average score: {:?}", average); + average +} + pub struct AlwaysPlay; impl Strategy for AlwaysPlay { type InternalState = ();