diff --git a/src/main.rs b/src/main.rs index 1b6a0f2..311825c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,12 +39,26 @@ fn main() { let program = args[0].clone(); let mut opts = Options::new(); - opts.optopt("l", "loglevel", "Log level, one of 'trace', 'debug', 'info', 'warn', and 'error'", "LOGLEVEL"); - opts.optopt("n", "ntrials", "Number of games to simulate", "NTRIALS"); - opts.optopt("t", "nthreads", "Number of threads to use for simulation", "NTHREADS"); - opts.optopt("s", "seed", "Seed for PRNG", "SEED"); - opts.optopt("p", "nplayers", "Number of players", "NPLAYERS"); - opts.optflag("h", "help", "Print this help menu"); + opts.optopt("l", "loglevel", + "Log level, one of 'trace', 'debug', 'info', 'warn', and 'error'", + "LOGLEVEL"); + opts.optopt("n", "ntrials", + "Number of games to simulate", + "NTRIALS"); + opts.optopt("t", "nthreads", + "Number of threads to use for simulation", + "NTHREADS"); + opts.optopt("s", "seed", + "Seed for PRNG", + "SEED"); + opts.optopt("p", "nplayers", + "Number of players", + "NPLAYERS"); + opts.optopt("g", "strategy", + "Which strategy to use. One of 'random' and 'cheat'", + "STRATEGY"); + opts.optflag("h", "help", + "Print this help menu"); let matches = match opts.parse(&args[1..]) { Ok(m) => { m } Err(f) => { @@ -92,7 +106,7 @@ fn main() { _ => { panic!("There should be 2 to 5 players, not {}", n_players); } }; - let opts = game::GameOptions { + let game_opts = game::GameOptions { num_players: n_players, hand_size: hand_size, num_hints: 8, @@ -101,11 +115,22 @@ fn main() { allow_empty_hints: false, }; - // TODO: make this configurable - // let strategy_config = strategies::examples::RandomStrategyConfig { - // hint_probability: 0.4, - // play_probability: 0.2, - // }; - let strategy_config = strategies::cheating::CheatingStrategyConfig::new(); - simulator::simulate(&opts, &strategy_config, seed, n, n_threads); + let strategy_str : &str = &matches.opt_str("g").unwrap_or("cheat".to_string()); + let strategy_config : Box = match strategy_str { + "random" => { + Box::new(strategies::examples::RandomStrategyConfig { + hint_probability: 0.4, + play_probability: 0.2, + }) as Box + }, + "cheat" => { + Box::new(strategies::cheating::CheatingStrategyConfig::new()) + as Box + }, + _ => { + print_usage(&program, opts); + panic!("Unexpected strategy argument {}", strategy_str); + }, + }; + simulator::simulate(&game_opts, strategy_config, seed, n, n_threads); } diff --git a/src/simulator.rs b/src/simulator.rs index 2697907..7477eab 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -1,9 +1,10 @@ use rand::{self, Rng}; -use game::*; use std::collections::HashMap; use std::fmt; use crossbeam; +use game::*; + // Traits to implement for any valid Hanabi strategy // Represents the strategy of a given player @@ -118,9 +119,9 @@ impl fmt::Display for Histogram { } } -pub fn simulate( +pub fn simulate( opts: &GameOptions, - strat_config: &T, + strat_config: Box, first_seed_opt: Option, n_trials: u32, n_threads: u32, @@ -128,6 +129,7 @@ pub fn simulate( let first_seed = first_seed_opt.unwrap_or(rand::thread_rng().next_u32()); + let strat_config_ref = &strat_config; crossbeam::scope(|scope| { let mut join_handles = Vec::new(); for i in 0..n_threads { @@ -146,7 +148,7 @@ pub fn simulate( i, seed-start, histogram.average() ); } - let score = simulate_once(&opts, strat_config.initialize(&opts), Some(seed)); + let score = simulate_once(&opts, strat_config_ref.initialize(&opts), Some(seed)); histogram.insert(score); if score != 25 { non_perfect_seeds.push((score, seed)); } }