Skip to content

Commit

Permalink
feat: improve green flag qualification logic
Browse files Browse the repository at this point in the history
  • Loading branch information
unRARed committed Dec 4, 2024
1 parent d2d319c commit 29adb2d
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 76 deletions.
1 change: 1 addition & 0 deletions config/common.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ config:
- common/slides.yaml
- common/sound_system.yaml
- common/switches.yaml
- common/variables.yaml
21 changes: 15 additions & 6 deletions config/common/variables.yaml
Original file line number Diff line number Diff line change
@@ -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
20 changes: 12 additions & 8 deletions docs/RULES.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
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

### Green-flag 1/4

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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
30 changes: 16 additions & 14 deletions modes/base/config/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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:
Expand Down
98 changes: 83 additions & 15 deletions modes/green_flag/config/green_flag.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
3 changes: 2 additions & 1 deletion tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
91 changes: 59 additions & 32 deletions tests/test_green_flag.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit 29adb2d

Please sign in to comment.