diff --git a/src/game.rs b/src/game.rs index a68be96..13ccb3c 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,4 +1,4 @@ -use rand::{self, Rng}; +use rand::{self, Rng, SeedableRng}; use std::collections::HashMap; use std::fmt; @@ -49,10 +49,6 @@ impl fmt::Display for Card { pub type Cards = Vec; pub type CardsInfo = Vec; -fn shuffle(vec: &mut Vec) { - rand::thread_rng().shuffle(&mut vec[..]); -} - #[derive(Debug)] pub struct Firework { pub color: Color, @@ -293,7 +289,7 @@ impl PlayerState { } } -fn new_deck() -> Cards { +fn new_deck(seed: u32) -> Cards { let mut deck: Cards = Cards::new(); for color in COLORS.iter() { @@ -304,7 +300,9 @@ fn new_deck() -> Cards { } } }; - shuffle(&mut deck); + + rand::ChaChaRng::from_seed(&[seed]).shuffle(&mut deck[..]); + trace!("Created deck: {:?}", deck); deck } @@ -334,14 +332,14 @@ pub struct BoardState { pub deckless_turns_remaining: u32, } impl BoardState { - pub fn new(opts: &GameOptions) -> BoardState { + pub fn new(opts: &GameOptions, seed: u32) -> BoardState { let mut fireworks : HashMap = HashMap::new(); for color in COLORS.iter() { fireworks.insert(color, Firework::new(color)); } BoardState { - deck: new_deck(), + deck: new_deck(seed), fireworks: fireworks, discard: Discard::new(), num_players: opts.num_players, @@ -528,8 +526,8 @@ impl fmt::Display for GameState { pub type Score = u32; impl GameState { - pub fn new(opts: &GameOptions) -> GameState { - let mut board = BoardState::new(opts); + pub fn new(opts: &GameOptions, seed: u32) -> GameState { + let mut board = BoardState::new(opts, seed); let mut player_states : HashMap = HashMap::new(); for i in 0..opts.num_players { diff --git a/src/main.rs b/src/main.rs index e845b7d..621203f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,8 +28,8 @@ impl log::Log for SimpleLogger { fn main() { log::set_logger(|max_log_level| { - //max_log_level.set(log::LogLevelFilter::Trace); - max_log_level.set(log::LogLevelFilter::Info); + max_log_level.set(log::LogLevelFilter::Trace); + // max_log_level.set(log::LogLevelFilter::Info); Box::new(SimpleLogger) }).unwrap(); @@ -42,15 +42,6 @@ fn main() { let n = 1000; // simulator::simulate(&opts, &strategies::examples::AlwaysDiscard, n); // simulator::simulate_symmetric(&opts, strategies::examples::AlwaysPlayConfig, n); - // simulator::simulate( - // &opts, - // &vec![ - // Box::new(strategies::examples::AlwaysPlayConfig), - // Box::new(strategies::examples::AlwaysPlayConfig), - // Box::new(strategies::examples::AlwaysPlayConfig), - // Box::new(strategies::examples::AlwaysPlayConfig), - // ], - // n); // simulator::simulate_symmetric( // &opts, // strategies::examples::RandomStrategyConfig { @@ -59,9 +50,13 @@ fn main() { // }, // n // ); - simulator::simulate_symmetric( - &opts, + // simulator::simulate_symmetric( + // &opts, + // strategies::cheating::CheatingStrategyConfig::new(), + // n + // ); + simulator::simulate_symmetric_once( + &opts, Some(993), strategies::cheating::CheatingStrategyConfig::new(), - n ); } diff --git a/src/simulator.rs b/src/simulator.rs index a669813..93442c4 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -1,3 +1,4 @@ +use rand::{self, Rng}; use game::*; use std::collections::HashMap; @@ -11,8 +12,19 @@ pub trait StrategyConfig { fn initialize(&self, Player, &GameStateView) -> Box; } -pub fn simulate_once<'a>(opts: &GameOptions, strat_configs: &Vec>) -> Score { - let mut game = GameState::new(opts); +pub fn simulate_once<'a>( + opts: &GameOptions, + seed_opt: Option, + strat_configs: &Vec> + ) -> Score { + + let seed = if let Some(seed) = seed_opt { + seed + } else { + rand::thread_rng().next_u32() + }; + + let mut game = GameState::new(opts, seed); assert_eq!(opts.num_players, (strat_configs.len() as u32)); @@ -54,9 +66,12 @@ pub fn simulate_once<'a>(opts: &GameOptions, strat_configs: &Vec(opts: &GameOptions, strat_configs: &Vec>, n_trials: u32) -> f32 { let mut total_score = 0; - for _ in 0..n_trials { - let score = simulate_once(&opts, strat_configs); + for seed in 0..n_trials { + let score = simulate_once(&opts, Some(seed), strat_configs); debug!("Scored: {:?}", score); + if score != 25 { + info!("Seed with non-perfect score: {:?}", seed); + } total_score += score; } let average: f32 = (total_score as f32) / (n_trials as f32); @@ -64,6 +79,19 @@ pub fn simulate<'a>(opts: &GameOptions, strat_configs: &Vec( + opts: &GameOptions, + seed_opt: Option, + strat_config: S + ) -> Score { + + let mut strat_configs = Vec::new(); + for _ in 0..opts.num_players { + strat_configs.push(Box::new(strat_config.clone()) as Box); + } + simulate_once(opts, seed_opt, &strat_configs) +} + pub fn simulate_symmetric<'a, S: StrategyConfig + Clone + 'a>(opts: &GameOptions, strat_config: S, n_trials: u32) -> f32 { let mut strat_configs = Vec::new(); for _ in 0..opts.num_players {