use std::path::Path; use std::sync::Mutex; use rayon::prelude::*; use time::PreciseTime; use steam_powered_wyrm::game; use steam_powered_wyrm::json; use steam_powered_wyrm::strategy::{choose_move_with_normalized_perf, ScoreConfig}; fn main() { let initial_state = game::GameBoard::new( json::read_state_from_json_file(&Path::new(&format!("./tests/example-state.json"))) .unwrap(), ); let depth = 100; let configs = ScoreConfigTrials { max_health_weight: vec![0., 1.], total_health_weight: vec![0., 1.], points_weight: vec![0., 1.], victory_weight: vec![3000.], snowball_weight: vec![0., 100.], bomb_weight: vec![0., 100.], explore_exploit_weight: vec![1., 10.], } .reify(); eprintln!("{} configs being tested", configs.len()); let victories = Mutex::new(vec![0; configs.len()]); for i in 0..configs.len() { eprintln!("Progress: {} of {}", i, configs.len()); (i + 1..configs.len()) .collect::>() .par_iter() .for_each(|j| { let start_time = PreciseTime::now(); let mut state = initial_state.clone(); while state.outcome == game::SimulationOutcome::Continue { let commands = [ choose_move_with_normalized_perf(&state, &configs[i], 0, depth), choose_move_with_normalized_perf(&state, &configs[*j], 1, depth), ]; state.simulate(commands); } eprintln!( "Runtime: {}ms", start_time.to(PreciseTime::now()).num_milliseconds() ); match state.outcome { game::SimulationOutcome::PlayerWon(0) => victories.lock().unwrap()[i] += 1, game::SimulationOutcome::PlayerWon(1) => victories.lock().unwrap()[*j] += 1, _ => {} }; }); } println!("victories, max_health_weight, total_health_weight, points_weight, victory_weight, snowball_weight, bomb_weight, explore_exploit_weight"); victories .lock() .map(|victories| { for (config, victories) in configs.into_iter().zip(victories.iter()) { println!( "{}, {}, {}, {}, {}, {}, {}, {}", victories, config.max_health_weight, config.total_health_weight, config.points_weight, config.victory_weight, config.snowball_weight, config.bomb_weight, config.explore_exploit_weight ); } }) .unwrap(); } pub struct ScoreConfigTrials { pub max_health_weight: Vec, pub total_health_weight: Vec, pub points_weight: Vec, pub victory_weight: Vec, pub snowball_weight: Vec, pub bomb_weight: Vec, pub explore_exploit_weight: Vec, } impl ScoreConfigTrials { fn reify(self) -> Vec { let mut result = Vec::new(); for max_health_weight in &self.max_health_weight { for total_health_weight in &self.total_health_weight { for points_weight in &self.points_weight { for victory_weight in &self.victory_weight { for snowball_weight in &self.snowball_weight { for bomb_weight in &self.bomb_weight { for explore_exploit_weight in &self.explore_exploit_weight { result.push(ScoreConfig { max_health_weight: *max_health_weight, total_health_weight: *total_health_weight, points_weight: *points_weight, victory_weight: *victory_weight, snowball_weight: *snowball_weight, bomb_weight: *bomb_weight, explore_exploit_weight: *explore_exploit_weight, }); } } } } } } } result } }