1 use crate::{AlertHandler, Scenario, Sim, SimOptions}; 2 use abstutil::CmdArgs; 3 use map_model::{Map, MapEdits}; 4 use rand::SeedableRng; 5 use rand_xorshift::XorShiftRng; 6 7 const RNG_SEED: u8 = 42; 8 9 #[derive(Clone)] 10 pub struct SimFlags { 11 pub load: String, 12 pub rng_seed: u8, 13 pub opts: SimOptions, 14 } 15 16 impl SimFlags { from_args(args: &mut CmdArgs) -> SimFlags17 pub fn from_args(args: &mut CmdArgs) -> SimFlags { 18 let rng_seed = args 19 .optional_parse("--rng_seed", |s| s.parse()) 20 .unwrap_or(RNG_SEED); 21 22 SimFlags { 23 load: args 24 .optional_free() 25 .unwrap_or_else(|| abstutil::path_map("montlake")), 26 rng_seed, 27 opts: SimOptions { 28 run_name: args 29 .optional("--run_name") 30 .unwrap_or_else(|| "unnamed".to_string()), 31 use_freeform_policy_everywhere: args.enabled("--freeform_policy"), 32 dont_block_the_box: !args.enabled("--disable_block_the_box"), 33 recalc_lanechanging: !args.enabled("--disable_recalc_lc"), 34 break_turn_conflict_cycles: !args.enabled("--disable_break_turn_conflict_cycles"), 35 handle_uber_turns: !args.enabled("--disable_handle_uber_turns"), 36 enable_pandemic_model: if args.enabled("--pandemic") { 37 Some(XorShiftRng::from_seed([rng_seed; 16])) 38 } else { 39 None 40 }, 41 alerts: args 42 .optional("--alerts") 43 .map(|x| match x.as_ref() { 44 "print" => AlertHandler::Print, 45 "block" => AlertHandler::Block, 46 "silence" => AlertHandler::Silence, 47 _ => panic!("Bad --alerts={}. Must be print|block|silence", x), 48 }) 49 .unwrap_or(AlertHandler::Print), 50 pathfinding_upfront: args.enabled("--pathfinding_upfront"), 51 }, 52 } 53 } 54 55 // TODO rename seattle_test for_test(run_name: &str) -> SimFlags56 pub fn for_test(run_name: &str) -> SimFlags { 57 SimFlags::synthetic_test("montlake", run_name) 58 } 59 synthetic_test(map: &str, run_name: &str) -> SimFlags60 pub fn synthetic_test(map: &str, run_name: &str) -> SimFlags { 61 SimFlags { 62 load: abstutil::path_map(map), 63 rng_seed: RNG_SEED, 64 opts: SimOptions::new(run_name), 65 } 66 } 67 make_rng(&self) -> XorShiftRng68 pub fn make_rng(&self) -> XorShiftRng { 69 XorShiftRng::from_seed([self.rng_seed; 16]) 70 } 71 72 // Convenience method to setup everything. load(&self, timer: &mut abstutil::Timer) -> (Map, Sim, XorShiftRng)73 pub fn load(&self, timer: &mut abstutil::Timer) -> (Map, Sim, XorShiftRng) { 74 let mut rng = self.make_rng(); 75 76 let mut opts = self.opts.clone(); 77 78 if self.load.starts_with(&abstutil::path("player/saves/")) { 79 timer.note(format!("Resuming from {}", self.load)); 80 81 let mut sim: Sim = abstutil::read_binary(self.load.clone(), timer); 82 83 let mut map = Map::new(abstutil::path_map(&sim.map_name), timer); 84 if sim.edits_name != "untitled edits" { 85 map.must_apply_edits( 86 MapEdits::load( 87 &map, 88 abstutil::path_edits(map.get_name(), &sim.edits_name), 89 timer, 90 ) 91 .unwrap(), 92 timer, 93 ); 94 map.recalculate_pathfinding_after_edits(timer); 95 } 96 sim.restore_paths(&map, timer); 97 98 (map, sim, rng) 99 } else if self.load.starts_with(&abstutil::path("system/scenarios/")) { 100 timer.note(format!( 101 "Seeding the simulation from scenario {}", 102 self.load 103 )); 104 105 let scenario: Scenario = abstutil::read_binary(self.load.clone(), timer); 106 107 let map = Map::new(abstutil::path_map(&scenario.map_name), timer); 108 109 if opts.run_name == "unnamed" { 110 opts.run_name = scenario.scenario_name.clone(); 111 } 112 let mut sim = Sim::new(&map, opts, timer); 113 scenario.instantiate(&mut sim, &map, &mut rng, timer); 114 115 (map, sim, rng) 116 } else if self.load.starts_with(&abstutil::path_all_raw_maps()) 117 || self.load.starts_with(&abstutil::path_all_synthetic_maps()) 118 || self.load.starts_with(&abstutil::path_all_maps()) 119 { 120 timer.note(format!("Loading map {}", self.load)); 121 122 let map = Map::new(self.load.clone(), timer); 123 124 timer.start("create sim"); 125 let sim = Sim::new(&map, opts, timer); 126 timer.stop("create sim"); 127 128 (map, sim, rng) 129 } else { 130 panic!("Don't know how to load {}", self.load); 131 } 132 } 133 } 134