diff --git a/config/common.yaml b/config/common.yaml index 2c6526f..b3d763b 100644 --- a/config/common.yaml +++ b/config/common.yaml @@ -12,3 +12,4 @@ config: - common/slides.yaml - common/sound_system.yaml - common/switches.yaml +- common/variables.yaml diff --git a/config/common/variables.yaml b/config/common/variables.yaml index 363edfe..bd334a9 100644 --- a/config/common/variables.yaml +++ b/config/common/variables.yaml @@ -1,8 +1,17 @@ #config_version=6 +# NOTE: this is only for machine-wide variables. Put +# player-specific variables in modes - -variable_player: - game_started: - green_flags_hit: - action: set - int: 0 +player_vars: + level_green_flag: + initial_value: 0 + # 2 is full, + # 1 is half + # 0 is empty + level_fuel: + # player begins game with empty tank + initial_value: 0 + level_oil: + initial_value: 2 + level_tires: + initial_value: 2 diff --git a/docs/RULES.md b/docs/RULES.md index c007677..ef333ae 100644 --- a/docs/RULES.md +++ b/docs/RULES.md @@ -1,14 +1,22 @@ Grand Prix ’86 RULES ==================== +Music Possibilities: + +- "The Distance" by Cake (attract mode) +- "Highway to the Danger Zone" by Kenny Loggins +- "Mach 5" by The Presidents of the United States of America +- "Shake your Groove Thing" by Peaches & Herb +- "302 Cubic Inch V8 Powered Blues" by Zeke +- "The Beautiful People" by Marilyn Manson (Chimebox) + Modes ----- -### Base (Pace Lap) +### Base (Pit Row) Racers, on your mark... -- Music: "The Distance" - Top left gate is closed. - Standard scoring described here @@ -16,10 +24,9 @@ Racers, on your mark... The race begins! -- Music: "Flirting with Disaster" -- Activated when the required number of qualifiers are hit +- Activated when fuel, oil, and tires reach max level - Top left gate is open allowing a counter-clockwise orbit -- Bottom-most 3 inserts on South-East chain track orbits +- Bottom-most 3 inserts on South-East chain tracks current orbit - 3 successful orbits: - Awards a bonus (TBD) - Resets the inserts @@ -67,7 +74,6 @@ Every driver's gotta pit Cole... ### End of Ball Bonus -- Music "The Beautiful People" in time with Chimebox - Pulses chimebox in time with music equal to lit letters, turning them off with each group (throwback) and is followed by "There's no time to discriminate @@ -92,12 +98,10 @@ Every driver's gotta pit Cole... #### Shake your Groove Thing Multiball (2-ball) -- Music "Shake your Groove Thing" - Spinner and Grooveline rollover awards 2x scoring #### Grand Prix Multiball (3-ball) -- Music: "Mach 5" - Primary Multiball - Top-hole keeps ball locked. Autokicker will launch the others. - Add a ball up to 3 times by getting into any hole, exclusive diff --git a/modes/base/config/base.yaml b/modes/base/config/base.yaml index 301f468..33c09de 100644 --- a/modes/base/config/base.yaml +++ b/modes/base/config/base.yaml @@ -24,16 +24,19 @@ variable_player: s_pop2_active: score: 10 s_grooveline_active: - score: 25 + score: 50 * (current_player.level_green_flag + 1) s_qualifier1_active: score: 100 bonus: 10 - s_qualifier3_active: + level_fuel: 2 + s_qualifier2_active: score: 100 bonus: 10 - s_qualifier2_active: + level_oil: 2 + s_qualifier3_active: score: 100 bonus: 10 + level_tires: 2 s_podium_hole_active: score: 500 bonus: 50 @@ -44,7 +47,7 @@ variable_player: score: 100 bonus: 10 s_spinner_active: - score: 10 + score: 10 * (current_player.level_green_flag + 1) bonus: 1 s_grand_advance_active: score: 10 @@ -71,24 +74,23 @@ variable_player: s_outlane2_active: score: 50 - ###################### - # Custom Player Vars # - ###################### - level_green_flag: - initial_value: 0 - # To activate "green_flag" mode, the user's vehicle # must be ready to race: event_player: - # Top up her gas every time (Qualifier1) + # Top up her fuel every time (Qualifier1) s_qualifier1_active: - - green_flag{current_player.level_green_flag==0} + - green_flag{current_player.level_green_flag==0} + # - green_flag_fuel_reset # Change oil after putting some miles on her (Qualifier2) logicblock_seq_green_flag2_complete: - - green_flag{current_player.level_green_flag==1} + - green_flag{current_player.level_green_flag==1} # She's going to need some tires, now (Qualifier3) logicblock_seq_green_flag3_complete: - - green_flag + - green_flag + # s_qualifier2_active: + # # - green_flag_oil_reset + # s_qualifier3_active: + # # - green_flag_tires_reset sequences: seq_green_flag2: diff --git a/modes/green_flag/config/green_flag.yaml b/modes/green_flag/config/green_flag.yaml index b333e1d..a13d404 100644 --- a/modes/green_flag/config/green_flag.yaml +++ b/modes/green_flag/config/green_flag.yaml @@ -4,7 +4,12 @@ mode: start_events: - green_flag stop_events: - - s_disqualifier_active + - pit_required_oil + - pit_required_fuel + - pit_required_tires + - green_flag_wreck + - green_flag_head_gasket + - green_flag_timing_belt restart_on_next_ball: true priority: 100 @@ -13,23 +18,86 @@ light_player: x_loop_gate: color: white +sequences: + seq_lap: + events: + - s_spinner_active + - s_grooveline_active + disable_on_complete: false + +counters: + lap_counter: + count_events: logicblock_seq_lap_complete + starting_count: 0 + count_interval: 1 + # TODO: maybe consider having a ceiling + # where the "race is completed" + #count_complete_value: 100 + +# Every 3 laps, a random event will occur +random_event_player: + player_lap_counter_count{(current_player.lap_counter_count % 3 == 0) and (current_player.lap_counter_count > 0)}: + events: + # TODO: 20% chance good things happen + green_flag_smooth_sailing: 20 + # 74% chance of normal wear and tear + degrade_fuel: 20 + degrade_oil: 20 + degrade_tires: 20 + degrade_all: 14 + # TODO: 5% chance of a multi-car wreck + green_flag_under_red: 5 + # TODO: Tiny chance ball ends immediately + green_flag_bad_luck: 1 + green_flag_bad_luck: + events: + - green_flag_wreck + - green_flag_head_gasket + - green_flag_timing_belt + s_disqualifier_active: + events: + - degrade_fuel + - degrade_oil + - degrade_tires + variable_player: mode_green_flag_started: level_green_flag: action: add int: 1 + # Per docs, "Counters no longer save their + # state in player variables" + logicblock_lap_counter_updated: + lap_counter_count: + int: value + action: set + degrade_fuel: + level_fuel: + action: add + int: -1 + degrade_oil: + level_oil: + action: add + int: -1 + degrade_tires: + level_tires: + action: add + int: -1 + s_qualifier1_active: + level_fuel: 0|block + s_qualifier2_active: + level_oil: 0|block + s_qualifier3_active: + level_tires: 0|block - ########### - # Scoring # - ########### - - s_spinner_active: - score: - int: 20 * (current_player.level_green_flag + 1) - block: true - s_grooveline_active: - score: - int: 500 * (current_player.level_green_flag + 1) - block: true - bonus: - int: 50 * (current_player.level_green_flag + 1) +event_player: + degrade_fuel{current_player.level_fuel == 1}: + - pit_required_fuel + degrade_oil{current_player.level_oil == 1}: + - pit_required_oil + degrade_tires{current_player.level_tires == 1}: + - pit_required_tires + degrade_all: + - pit_required_fuel + - pit_required_oil + - pit_required_tires diff --git a/tests/test_base.py b/tests/test_base.py index 02f3e08..49045e9 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -10,7 +10,8 @@ def test_scoring(self): self.assertEqual(0, self.machine.game.player.score) self.assertIncrement(score, "s_pop1", 10) self.assertIncrement(score, "s_pop2", 10) - self.assertIncrement(score, "s_grooveline", 25) + self.assertIncrement(score, "s_grooveline", 50) + self.assertIncrement(score, "s_qualifier2", 100) self.assertIncrement(score, "s_qualifier3", 100) self.assertIncrement(score, "s_podium_hole", 500) diff --git a/tests/test_green_flag.py b/tests/test_green_flag.py index 974f8ea..0451d61 100644 --- a/tests/test_green_flag.py +++ b/tests/test_green_flag.py @@ -20,55 +20,82 @@ def test_scoring(self): # Green Flag Mode is about the loop # TODO: Count the number of loops: # both continuous and in total - self.assertIncrement(score, "s_spinner", 20 * 2) - self.assertIncrement(score, "s_grooveline", 500 * 2) - # Only the grooveline adds to the bonus - self.assertIncrement("bonus", "s_grooveline", 50 * 2) + self.assertIncrement(score, "s_spinner", 10 * 2) + self.assertIncrement(score, "s_grooveline", 50 * 2) # Other switches score normally per Base Mode self.assertIncrement(score, "s_pop1", 10) self.assertIncrement(score, "s_podium_advance1", 10) self.assertIncrement(score, "s_slingshot2", 10) - - def test_qualification(self): + def test_laps(self): + random_events = [ + "green_flag_smooth_sailing", + "degrade_fuel", + "degrade_oil", + "degrade_tires", + "degrade_all", + "green_flag_under_red", + "green_flag_bad_luck", + ] + # No random event should have occurred, yet + for event in random_events: + self.mock_event(event) + self.assertEqual(0, self._events.get(event, 0)) self.__start_green_flag() - self.assertEqual( - 1, self.machine.game.player.level_green_flag - ) - self.hit_and_release_switch("s_disqualifier") - self.assertModeNotRunning("green_flag") - # Second time around, it requires hitting two - # qualifiers to start the mode - self.__qualify_level_two() + for i in range(3): + self.__complete_lap() + self.assertEqual( + 3, self.machine.game.player.lap_counter_count) - # Third time around, it requires hitting - # all three qualifiers - self.__qualify_final_level() + # Recording 3 laps triggers a single random event + random_events_fired = [] + for e in random_events: + random_events_fired.append(self._events.get(e, 0)) + self.assertEqual(1, sum(random_events_fired)) - # Further attempts function the same way, - # requiring all 3 qualifiers to be hit - self.__qualify_final_level() + # NOTE: we're testing the event here, not the mode + # since the mode could end up stopped - def __start_green_flag(self): + def test_qualification(self): self.start_game() + self.assertModeNotRunning("green_flag") + self.hit_and_release_switch("s_qualifier1") + self.assertEqual( + 2, self.machine.game.player.level_fuel) + self.assertModeRunning("green_flag") + + # player hits the disqualifier which triggers + # the random event "degrade_oil" reducing the + # player's oil level from 2 to 1 + self.machine.events.post("degrade_oil") self.advance_time_and_run(1) + self.assertEqual( + 1, self.machine.game.player.level_oil) self.assertModeRunning("green_flag") - def __qualify_level_two(self): - self.hit_and_release_switch("s_qualifier1") + # player's poor luck continues as they hit the + # disqualifier again, triggering the same event, + # reducing their oil level from 1 to 0 + self.machine.events.post("degrade_oil") + self.advance_time_and_run(1) + self.assertEqual( + 0, self.machine.game.player.level_oil) self.assertModeNotRunning("green_flag") - self.hit_and_release_switch("s_qualifier2") - self.assertModeRunning("green_flag") - self.hit_and_release_switch("s_disqualifier") - def __qualify_final_level(self): + def __start_green_flag(self): + self.start_game() + # Player must "fill up" to start racing + self.assertEqual( + 0, self.machine.game.player.level_fuel) + # Hitting the first qualifier fills up the tank self.hit_and_release_switch("s_qualifier1") - self.assertModeNotRunning("green_flag") - self.hit_and_release_switch("s_qualifier2") - self.assertModeNotRunning("green_flag") - self.hit_and_release_switch("s_qualifier3") + self.advance_time_and_run(1) self.assertModeRunning("green_flag") - self.hit_and_release_switch("s_disqualifier") + + def __complete_lap(self): + self.hit_and_release_switch("s_spinner") + self.hit_and_release_switch("s_grooveline") + self.advance_time_and_run(1)