From 5b6e7a6f54787fb00b1ff99aed8e6c163291484b Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Thu, 26 Dec 2019 18:53:44 -0600 Subject: [PATCH] jump straight to a challenge from command line for fast development. fixes #31 --- docs/dev.md | 2 ++ game/src/challenges.rs | 17 +++++++++++++---- game/src/game.rs | 11 ++++------- game/src/main.rs | 26 +++++++++++++++++++++++++- game/src/sandbox/gameplay/mod.rs | 2 +- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/docs/dev.md b/docs/dev.md index 6aca6851f1..ae16961d3d 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -36,6 +36,8 @@ One-time setup: map - `cargo run ../data/system/scenarios/caphill/weekday_typical_traffic_from_psrc.bin` starts with a scenario (which is tied to a certain map) + - `cargo run -- --challenge=trafficsig/tut2` starts on a particular challenge. + See the list of aliases by passing in a bad value here. - `cargo run ../data/player/saves/montlake/no_edits_unnamed/00h00m20.3s.bin` restores an exact simulation state. Savestates are found in debug mode (**Control+D**) -- they're probably confusing for the normal player diff --git a/game/src/challenges.rs b/game/src/challenges.rs index 706463d178..3e94bf0018 100644 --- a/game/src/challenges.rs +++ b/game/src/challenges.rs @@ -14,27 +14,30 @@ use std::collections::{BTreeMap, HashSet}; // TODO Also have some kind of screenshot to display for each challenge #[derive(Clone)] -struct Challenge { +pub struct Challenge { title: String, description: Vec, - map_path: String, - gameplay: GameplayMode, + pub map_path: String, + pub alias: String, + pub gameplay: GameplayMode, } impl abstutil::Cloneable for Challenge {} -fn all_challenges() -> BTreeMap> { +pub fn all_challenges() -> BTreeMap> { let mut tree = BTreeMap::new(); tree.insert("Fix all of the traffic signals".to_string(), vec![ Challenge { title: "Tutorial 1".to_string(), description: vec!["Add or remove a dedicated left phase".to_string()], map_path: abstutil::path_synthetic_map("signal_single"), + alias: "trafficsig/tut1".to_string(), gameplay: GameplayMode::FixTrafficSignalsTutorial(0), }, Challenge { title: "Tutorial 2".to_string(), description: vec!["Deal with heavy foot traffic".to_string()], map_path: abstutil::path_synthetic_map("signal_single"), + alias: "trafficsig/tut2".to_string(), gameplay: GameplayMode::FixTrafficSignalsTutorial(1), }, Challenge { @@ -47,6 +50,7 @@ fn all_challenges() -> BTreeMap> { "Objective: Reduce the 50%ile trip time of all drivers by at least 30s".to_string() ], map_path: abstutil::path_map("montlake"), + alias: "trafficsig/main".to_string(), gameplay: GameplayMode::FixTrafficSignals, }, ]); @@ -59,6 +63,7 @@ fn all_challenges() -> BTreeMap> { "Decrease the average waiting time between all of route 48's stops by at least 30s" .to_string()], map_path: abstutil::path_map("montlake"), + alias: "bus48/montlake".to_string(), gameplay: GameplayMode::OptimizeBus("48".to_string()), }, Challenge { @@ -68,6 +73,7 @@ fn all_challenges() -> BTreeMap> { .to_string(), ], map_path: abstutil::path_map("23rd"), + alias: "bus48/23rd".to_string(), gameplay: GameplayMode::OptimizeBus("48".to_string()), }, ], @@ -78,6 +84,7 @@ fn all_challenges() -> BTreeMap> { title: "Gridlock all of the everything".to_string(), description: vec!["Make traffic as BAD as possible!".to_string()], map_path: abstutil::path_map("montlake"), + alias: "gridlock".to_string(), gameplay: GameplayMode::CreateGridlock, }], ); @@ -90,6 +97,7 @@ fn all_challenges() -> BTreeMap> { "Reduce the 50%ile trip times of bikes by at least 1 minute".to_string() ], map_path: abstutil::path_map("montlake"), + alias: "fave/bike".to_string(), gameplay: GameplayMode::FasterTrips(TripMode::Bike), }, Challenge { @@ -98,6 +106,7 @@ fn all_challenges() -> BTreeMap> { "Reduce the 50%ile trip times of drivers by at least 5 minutes".to_string(), ], map_path: abstutil::path_map("montlake"), + alias: "fave/car".to_string(), gameplay: GameplayMode::FasterTrips(TripMode::Drive), }, ], diff --git a/game/src/game.rs b/game/src/game.rs index b9744e941a..9180dab381 100644 --- a/game/src/game.rs +++ b/game/src/game.rs @@ -17,19 +17,16 @@ pub struct Game { } impl Game { - pub fn new(flags: Flags, opts: Options, ctx: &mut EventCtx) -> Game { + pub fn new(flags: Flags, opts: Options, mode: GameplayMode, ctx: &mut EventCtx) -> Game { let title = !opts.dev && !flags.sim_flags.load.contains("data/player/save") - && !flags.sim_flags.load.contains("data/system/scenarios"); + && !flags.sim_flags.load.contains("data/system/scenarios") + && mode == GameplayMode::Freeform; let mut ui = UI::new(flags, opts, ctx, title); let states: Vec> = if title { vec![Box::new(TitleScreen::new(ctx, &ui))] } else { - vec![Box::new(SandboxMode::new( - ctx, - &mut ui, - GameplayMode::Freeform, - ))] + vec![Box::new(SandboxMode::new(ctx, &mut ui, mode))] }; Game { states, ui } } diff --git a/game/src/main.rs b/game/src/main.rs index 2a76398ba5..bbfd768c02 100644 --- a/game/src/main.rs +++ b/game/src/main.rs @@ -52,7 +52,31 @@ fn main() { if let Some(x) = args.optional_parse("--hidpi_factor", |x| x.parse::()) { settings.override_hidpi_factor(x); } + + let mut mode = sandbox::GameplayMode::Freeform; + if let Some(x) = args.optional("--challenge") { + let mut aliases = Vec::new(); + 'OUTER: for (_, stages) in challenges::all_challenges() { + for challenge in stages { + if challenge.alias == x { + mode = challenge.gameplay; + flags.sim_flags.load = challenge.map_path; + break 'OUTER; + } else { + aliases.push(challenge.alias); + } + } + } + if mode == sandbox::GameplayMode::Freeform { + panic!( + "Don't know --challenge={}. Choices: {}", + x, + aliases.join(", ") + ); + } + } + args.done(); - ezgui::run(settings, |ctx| game::Game::new(flags, opts, ctx)); + ezgui::run(settings, |ctx| game::Game::new(flags, opts, mode, ctx)); } diff --git a/game/src/sandbox/gameplay/mod.rs b/game/src/sandbox/gameplay/mod.rs index c3c033fd4f..a248a72418 100644 --- a/game/src/sandbox/gameplay/mod.rs +++ b/game/src/sandbox/gameplay/mod.rs @@ -25,7 +25,7 @@ pub struct GameplayRunner { state: Box, } -#[derive(Clone)] +#[derive(PartialEq, Clone)] pub enum GameplayMode { // TODO Maybe this should be "sandbox" Freeform,