Skip to content

Commit 2884054

Browse files
committed
Merge branch 'dev' into 0.80.x
# Conflicts: # mpf/modes/bonus/code/bonus.py # mpf/tests/test_Bonus.py
2 parents ba32634 + 7a96651 commit 2884054

File tree

11 files changed

+120
-44
lines changed

11 files changed

+120
-44
lines changed

mpf/config_spec.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ fast_exp_board:
668668
led_ports: list|subconfig(fast_led_port)|None
669669
led_fade_time: single|ms|0
670670
led_hz: single|float|30
671+
ignore_led_errors: single|bool|false
671672
fast_breakout:
672673
port: single|enum(1,2,3)|
673674
model: single|str|

mpf/modes/bonus/code/bonus.py

+9-10
Original file line numberDiff line numberDiff line change
@@ -95,29 +95,28 @@ def _bonus_next_item(self):
9595
# following names are reserved for end-of-bonus behavior.
9696
assert entry not in ["subtotal", "multiplier", "total"], "Bonus entry cannot be reserved word '%s'" % entry
9797

98-
# Calling player.vars.get() instead of player.get() bypasses the
99-
# auto-fill zero and will throw if there is no player variable.
100-
# The fallback value of 1 is used for bonus entries that don't use
101-
# a player score, which are multiplied by one to get the bonus.
102-
hits = self.player.vars.get(entry['player_score_entry'], 1)
98+
# If a player_score_entry is provided, use player getattr to get a
99+
# fallback value of zero if the variable is not set. Otherwise
100+
# use 1 as the multiplier for non-player-score bonuses.
101+
hits = self.player[entry['player_score_entry']] if entry['player_score_entry'] else 1
103102
score = entry['score'].evaluate([]) * hits
104103

105104
if (not score and entry['skip_if_zero']) or (score < 0 and entry['skip_if_negative']):
106-
self.debug_log("Skipping bonus entry '%s' because its value is 0",
107-
entry['entry'])
105+
self.info_log("Skipping bonus entry '%s' because its value is 0",
106+
entry['entry'])
108107
self._bonus_next_item()
109108
return
110109

111110
# pylint: disable=superfluous-parens
112111
if self.settings["rounding_value"] and (r := (score % self.settings["rounding_value"])):
113-
self.debug_log("rounding bonus score %s remainder of %s", score, r)
112+
self.info_log("rounding bonus score %s remainder of %s", score, r)
114113
if self.settings["rounding_direction"] == "down":
115114
score -= r
116115
else:
117116
score += self.settings["rounding_value"] - r
118117

119-
self.debug_log("Bonus Entry '%s': score: %s player_score_entry: %s=%s",
120-
entry['entry'], score, entry['player_score_entry'], hits)
118+
self.info_log("Bonus Entry '%s': score: %s player_score_entry: %s=%s",
119+
entry['entry'], score, entry['player_score_entry'], hits)
121120

122121
self.bonus_score += score
123122
self.machine.events.post("bonus_entry", entry=entry['entry'],

mpf/platforms/fast/communicators/net_neuron.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def update_switches_from_hw_data(self):
293293
This will silently sync the switch.hw_state. If the logical state changes,
294294
it will process it like any switch change.
295295
"""
296-
for switch in self.machine.switches:
296+
for switch in self.machine.switches.values():
297297
hw_state = self.platform.hw_switch_data[switch.hw_switch.number]
298298

299299
if hw_state != switch.hw_state:

mpf/platforms/fast/fast_exp_board.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import asyncio
44
from base64 import b16decode
5+
from binascii import Error as binasciiError
56
from importlib import import_module
67

78
from packaging import version
@@ -176,11 +177,12 @@ def update_leds(self):
176177

177178
try:
178179
self.communicator.send_bytes(b16decode(f'{msg_header}{msg}'), log_msg)
179-
except Exception as e:
180+
except binasciiError as e:
180181
self.log.error(
181182
f"Error decoding the following message for board {breakout_address} : {msg_header}{msg}")
182-
self.log.debug("Attempted update that caused this error: %s", dirty_leds)
183-
raise e
183+
self.log.info("Attempted update that caused this error: %s", dirty_leds)
184+
if not self.config['ignore_led_errors']:
185+
raise e
184186

185187
def set_led_fade(self, rate: int) -> None:
186188
"""Set LED fade rate in ms."""

mpf/platforms/virtual.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,16 @@ async def get_hw_switch_states(self):
105105

106106
if 'virtual_platform_start_active_switches' in self.machine.config:
107107
initial_active_switches = []
108-
for switch in Util.string_to_list(self.machine.config['virtual_platform_start_active_switches']):
109-
if switch not in self.machine.switches:
110-
if " " in switch:
108+
for switch_name in Util.string_to_list(self.machine.config['virtual_platform_start_active_switches']):
109+
if switch_name not in self.machine.switches.keys():
110+
if " " in switch_name:
111111
self.raise_config_error("MPF no longer supports lists separated by space in "
112112
"virtual_platform_start_active_switches. Please separate "
113-
"switches by comma: {}.".format(switch), 1)
113+
"switches by comma: {}.".format(switch_name), 1)
114114
else:
115115
self.raise_config_error("Switch {} used in virtual_platform_start_active_switches was not "
116-
"found in switches section.".format(switch), 1)
117-
initial_active_switches.append(self.machine.switches[switch].hw_switch.number)
116+
"found in switches section.".format(switch_name), 1)
117+
initial_active_switches.append(self.machine.switches[switch_name].hw_switch.number)
118118

119119
for k in self.hw_switches:
120120
if k in initial_active_switches:

mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ mode_settings:
1212
score: 5000
1313
player_score_entry: modes
1414
reset_player_score_entry: False
15+
- entry: bonus_undefined_var
16+
score: 5000
17+
skip_if_zero: false
18+
player_score_entry: undefined_var
19+
- entry: bonus_static
20+
score: 2000

mpf/tests/machine_files/shots/config/test_shot_groups.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ switches:
1212
number:
1313
switch_4:
1414
number:
15+
switch_5:
16+
number:
17+
switch_6:
18+
number:
1519
s_rotate_l:
1620
number:
1721
s_rotate_r:

mpf/tests/machine_files/shots/modes/base2/config/base2.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ shots:
2020
light: tag1
2121
shot_4:
2222
switch: switch_1
23+
shot_5:
24+
switch: switch_5
25+
shot_6:
26+
switch: switch_6
2327
led_1:
2428
switch: switch_1
2529
show_tokens:

mpf/tests/machine_files/shots/modes/mode1/config/mode1.yaml

+18-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ shots:
2424
mode1_shot_3:
2525
switch: switch_3
2626
profile: mode1_shot_3
27+
mode1_shot_5:
28+
switch: switch_5
29+
profile: mode1_shot_5
30+
mode1_shot_6:
31+
switch: switch_6
32+
profile: mode1_shot_6
2733

2834
shot_profiles:
2935
mode1_shot_2:
@@ -32,10 +38,21 @@ shot_profiles:
3238
- name: mode1_one
3339
- name: mode1_two
3440
- name: mode1_three
35-
mode1_shot_3:
41+
mode1_shot_3: # Test block: True
3642
show: rainbow2
3743
block: True
3844
states:
3945
- name: mode1_one
4046
- name: mode1_two
4147
- name: mode1_three
48+
mode1_shot_5: # Test block: False
49+
show: rainbow2
50+
block: False
51+
states:
52+
- name: mode1_one
53+
- name: mode1_two
54+
mode1_shot_6: # Test block default
55+
show: rainbow2
56+
states:
57+
- name: mode1_one
58+
- name: mode1_two

mpf/tests/test_Bonus.py

+36-8
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,23 @@ def testBonus(self):
7878
self.assertEqual(10000, self._last_event_kwargs["bonus_entry"]["score"])
7979
self.assertEqual(2, self._last_event_kwargs["bonus_entry"]["hits"])
8080
self.advance_time_and_run(2)
81+
self.assertEqual("bonus_undefined_var", self._last_event_kwargs["bonus_entry"]["entry"])
82+
self.assertEqual(0, self._last_event_kwargs["bonus_entry"]["score"])
83+
self.assertEqual(0, self._last_event_kwargs["bonus_entry"]["hits"])
84+
self.advance_time_and_run(2)
85+
self.assertEqual("bonus_static", self._last_event_kwargs["bonus_entry"]["entry"])
86+
self.assertEqual(2000, self._last_event_kwargs["bonus_entry"]["score"])
87+
self.assertEqual(1, self._last_event_kwargs["bonus_entry"]["hits"])
88+
self.advance_time_and_run(2)
8189
self.assertEqual("subtotal", self._last_event_kwargs["bonus_entry"]["entry"])
82-
self.assertEqual(13000, self._last_event_kwargs["bonus_entry"]["score"])
90+
self.assertEqual(15000, self._last_event_kwargs["bonus_entry"]["score"])
8391
self.advance_time_and_run(2)
8492
self.assertEqual("multiplier", self._last_event_kwargs["bonus_entry"]["entry"])
8593
self.assertEqual(5, self._last_event_kwargs["bonus_entry"]["score"])
8694
self.advance_time_and_run(2)
8795
self.assertEqual("total", self._last_event_kwargs["bonus_entry"]["entry"])
88-
self.assertEqual(65000, self._last_event_kwargs["bonus_entry"]["score"])
89-
self.assertEqual(66337, self.machine.game.player.score)
96+
self.assertEqual(75000, self._last_event_kwargs["bonus_entry"]["score"])
97+
self.assertEqual(76337, self.machine.game.player.score)
9098

9199
# check resets
92100
self.assertEqual(0, self.machine.game.player.ramps)
@@ -110,15 +118,23 @@ def testBonus(self):
110118
self.assertEqual(10000, self._last_event_kwargs["bonus_entry"]["score"])
111119
self.assertEqual(2, self._last_event_kwargs["bonus_entry"]["hits"])
112120
self.advance_time_and_run(2)
121+
self.assertEqual("bonus_undefined_var", self._last_event_kwargs["bonus_entry"]["entry"])
122+
self.assertEqual(0, self._last_event_kwargs["bonus_entry"]["score"])
123+
self.assertEqual(0, self._last_event_kwargs["bonus_entry"]["hits"])
124+
self.advance_time_and_run(2)
125+
self.assertEqual("bonus_static", self._last_event_kwargs["bonus_entry"]["entry"])
126+
self.assertEqual(2000, self._last_event_kwargs["bonus_entry"]["score"])
127+
self.assertEqual(1, self._last_event_kwargs["bonus_entry"]["hits"])
128+
self.advance_time_and_run(2)
113129
self.assertEqual("subtotal", self._last_event_kwargs["bonus_entry"]["entry"])
114-
self.assertEqual(10000, self._last_event_kwargs["bonus_entry"]["score"])
130+
self.assertEqual(12000, self._last_event_kwargs["bonus_entry"]["score"])
115131
self.advance_time_and_run(2)
116132
self.assertEqual("multiplier", self._last_event_kwargs["bonus_entry"]["entry"])
117133
self.assertEqual(5, self._last_event_kwargs["bonus_entry"]["score"])
118134
self.advance_time_and_run(2)
119135
self.assertEqual("total", self._last_event_kwargs["bonus_entry"]["entry"])
120-
self.assertEqual(50000, self._last_event_kwargs["bonus_entry"]["score"])
121-
self.assertEqual(116337, self.machine.game.player.score)
136+
self.assertEqual(60000, self._last_event_kwargs["bonus_entry"]["score"])
137+
self.assertEqual(136337, self.machine.game.player.score)
122138

123139
# multiplier should stay the same
124140
self.assertEqual(0, self.machine.game.player.ramps)
@@ -149,6 +165,10 @@ def testBonus(self):
149165
self.post_event('flipper_cancel', .1)
150166
self.assertEqual("bonus_modes", self._last_event_kwargs["bonus_entry"]["entry"])
151167

168+
self.advance_time_and_run(.5)
169+
self.assertEqual("bonus_undefined_var", self._last_event_kwargs["bonus_entry"]["entry"])
170+
self.advance_time_and_run(.5)
171+
self.assertEqual("bonus_static", self._last_event_kwargs["bonus_entry"]["entry"])
152172
self.advance_time_and_run(.5)
153173
self.assertEqual("subtotal", self._last_event_kwargs["bonus_entry"]["entry"])
154174

@@ -179,9 +199,17 @@ def testBonus(self):
179199
self.assertEqual(10000, self._last_event_kwargs["bonus_entry"]["score"])
180200
self.assertEqual(2, self._last_event_kwargs["bonus_entry"]["hits"])
181201
self.advance_time_and_run(2)
202+
self.assertEqual("bonus_undefined_var", self._last_event_kwargs["bonus_entry"]["entry"])
203+
self.assertEqual(0, self._last_event_kwargs["bonus_entry"]["score"])
204+
self.assertEqual(0, self._last_event_kwargs["bonus_entry"]["hits"])
205+
self.advance_time_and_run(2)
206+
self.assertEqual("bonus_static", self._last_event_kwargs["bonus_entry"]["entry"])
207+
self.assertEqual(2000, self._last_event_kwargs["bonus_entry"]["score"])
208+
self.assertEqual(1, self._last_event_kwargs["bonus_entry"]["hits"])
209+
self.advance_time_and_run(2)
182210
self.assertEqual("total", self._last_event_kwargs["bonus_entry"]["entry"])
183-
self.assertEqual(11000, self._last_event_kwargs["bonus_entry"]["score"])
184-
self.assertEqual(149337, self.machine.game.player.score)
211+
self.assertEqual(13000, self._last_event_kwargs["bonus_entry"]["score"])
212+
self.assertEqual(175337, self.machine.game.player.score)
185213

186214

187215
@test_config_directory("tests/machine_files/bonus_no_keep_multiplier/")

mpf/tests/test_Shots.py

+30-15
Original file line numberDiff line numberDiff line change
@@ -29,36 +29,51 @@ def stop_game(self):
2929
self.advance_time_and_run()
3030
self.assertIsNone(self.machine.game)
3131

32-
def test_block(self):
32+
def block_test(self, switch, shot, should_block):
33+
high_priority_shot = "mode1_" + shot
3334
self.mock_event("playfield_active")
34-
self.hit_and_release_switch("switch_3")
35+
self.hit_and_release_switch(switch)
3536
self.advance_time_and_run(.1)
3637
self.assertEventCalled("playfield_active")
3738

3839
self.start_game()
39-
self.assertEqual("unlit", self.machine.shots["shot_3"].state_name)
40+
self.assertEqual("unlit", self.machine.shots[shot].state_name)
4041

41-
self.hit_and_release_switch("switch_3")
42+
self.hit_and_release_switch(switch)
4243
self.advance_time_and_run(.1)
43-
self.assertTrue(self.machine.shots["shot_3"].enabled)
44-
self.assertEqual("lit", self.machine.shots["shot_3"].state_name)
44+
self.assertFalse(self.machine.shots[high_priority_shot].enabled)
45+
self.assertTrue(self.machine.shots[shot].enabled)
46+
self.assertEqual("lit", self.machine.shots[shot].state_name)
4547

46-
self.machine.shots["shot_3"].reset()
47-
self.assertEqual("unlit", self.machine.shots["shot_3"].state_name)
48+
self.machine.shots[shot].reset()
49+
self.assertEqual("unlit", self.machine.shots[shot].state_name)
4850

4951
# Start the mode and make sure those shots load
5052
self.start_mode("mode1")
5153

52-
self.assertTrue(self.machine.shots["shot_3"].enabled)
53-
self.assertTrue(self.machine.shots["mode1_shot_3"].enabled)
54-
self.assertEqual("unlit", self.machine.shots["shot_3"].state_name)
55-
self.assertEqual("mode1_one", self.machine.shots["mode1_shot_3"].state_name)
54+
self.assertTrue(self.machine.shots[shot].enabled)
55+
self.assertTrue(self.machine.shots[high_priority_shot].enabled)
56+
self.assertEqual("unlit", self.machine.shots[shot].state_name)
57+
self.assertEqual("mode1_one", self.machine.shots[high_priority_shot].state_name)
5658

57-
self.hit_and_release_switch("switch_3")
59+
self.hit_and_release_switch(switch)
5860
self.advance_time_and_run(.1)
5961

60-
self.assertEqual("unlit", self.machine.shots["shot_3"].state_name)
61-
self.assertEqual("mode1_two", self.machine.shots["mode1_shot_3"].state_name)
62+
if should_block:
63+
self.assertEqual("unlit", self.machine.shots[shot].state_name)
64+
else:
65+
self.assertEqual("lit", self.machine.shots[shot].state_name)
66+
67+
self.assertEqual("mode1_two", self.machine.shots[high_priority_shot].state_name)
68+
69+
def test_block_true(self):
70+
self.block_test("switch_3", "shot_3", True)
71+
72+
def test_block_false(self):
73+
self.block_test("switch_5", "shot_5", False)
74+
75+
def test_block_default(self): #Default behaves as false
76+
self.block_test("switch_6", "shot_6", False)
6277

6378
def test_loading_shots(self):
6479
# Make sure machine-wide shots load & mode-specific shots do not

0 commit comments

Comments
 (0)