Skip to content

Commit d38f024

Browse files
sp00ktoberclaude
andcommitted
feat(studio): a slot's signal is the rule's board index, and a rule that plays nothing matches a slot that plays nothing
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
1 parent fe189f6 commit d38f024

3 files changed

Lines changed: 54 additions & 4 deletions

File tree

‎apps/studio/src/mhfu_studio/monster/rule_game.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
READING = "reading the game…"
3535
DOT = "·"
3636
NO_SIGNAL = -1
37-
"""`Slot.signal` of a rule no signal fires: a manifest of this schema has none."""
37+
"""`Slot.signal` of a rule no signal fires."""
3838

3939

4040
class Read(NamedTuple):
@@ -75,7 +75,7 @@ def match(brain: Brain, m: Manifest) -> dict[int, int] | str:
7575
s = slots.get(k)
7676
same = s is not None and (
7777
s.on == kind(rule.on)
78-
and s.signal == NO_SIGNAL
78+
and s.signal == (NO_SIGNAL if rule.signal is None else rule.signal)
7979
and s.plays == bool(rule.play)
8080
and s.min_frames == rule.min_frames
8181
and s.cooldown == rule.cooldown

‎apps/studio/tests/monster/test_rule_game.py‎

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,32 @@ def brain(m: Manifest, fired: list[int], ticks: int = 100) -> Brain:
6464
CFG,
6565
ticks,
6666
tuple(
67-
Slot(k, rg.kind(r.on), -1, True, r.min_frames, r.cooldown, n, UNLIMITED, 0)
67+
Slot(
68+
k,
69+
rg.kind(r.on),
70+
-1 if r.signal is None else r.signal,
71+
bool(r.play),
72+
r.min_frames,
73+
r.cooldown,
74+
n,
75+
UNLIMITED,
76+
0,
77+
)
6878
for k, (r, n) in enumerate(zip(model.compile(m), fired, strict=True))
6979
),
7080
)
7181

7282

83+
@pytest.fixture
84+
def ms(m: Manifest) -> Manifest:
85+
"""`m` and a rule on the signal roar and a rule on a tail cut that only counts."""
86+
b = m.behaviour
87+
b.blocks["b5"] = Block("on_signal", (260.0, 480.0), {"name": "roar"}, play=["howl"])
88+
b.blocks["b6"] = Block("on_tail_cut", (260.0, 640.0), next=["b7"])
89+
b.blocks["b7"] = Block("counter_add", (460.0, 640.0), {"counter": "cuts", "by": 1})
90+
return m
91+
92+
7393
# ---- match ----------------------------------------------------------------------------------- #
7494

7595

@@ -105,6 +125,26 @@ def test_fewer_slots_than_rules_is_another_build_and_more_are_not_looked_at(m: M
105125
assert rg.match(replace(good, slots=(*good.slots, extra)), m) == {1: 1, 2: 2, 3: 3}
106126

107127

128+
def test_a_signal_rule_and_a_rule_that_plays_nothing_match_what_the_slots_say(
129+
ms: Manifest,
130+
) -> None:
131+
rules = model.compile(ms)
132+
sig = next(k for k, r in enumerate(rules) if r.signal is not None)
133+
idle = next(k for k, r in enumerate(rules) if not r.play)
134+
good = brain(ms, list(range(10, 10 + len(rules))))
135+
assert good.slots[sig].signal == model.signals(ms)["roar"] and not good.slots[idle].plays
136+
assert rg.match(good, ms) == {k + 1: 10 + k for k in range(len(rules))}
137+
for k, field, value in (
138+
(sig, "signal", model.signals(ms)["roar"] + 1),
139+
(sig, "signal", -1),
140+
(idle, "plays", True),
141+
(0, "signal", 0),
142+
):
143+
slots = list(good.slots)
144+
slots[k] = replace(slots[k], **{field: value})
145+
assert rg.match(replace(good, slots=tuple(slots)), ms) == rg.OTHER_BUILD, (k, field)
146+
147+
108148
def test_a_changed_manifest_no_longer_matches(m: Manifest) -> None:
109149
good = brain(m, [1, 2, 3])
110150
m.behaviour.blocks["b4"].params["frames"] = 31

‎apps/studio/tests/monster/ui/test_marks.py‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,17 @@ def __call__(
6363
) -> rg.Read:
6464
self.calls.append(cfg)
6565
slots = tuple(
66-
Slot(k, rg.kind(r.on), -1, True, r.min_frames, r.cooldown, n, UNLIMITED, 0)
66+
Slot(
67+
k,
68+
rg.kind(r.on),
69+
-1 if r.signal is None else r.signal,
70+
bool(r.play),
71+
r.min_frames,
72+
r.cooldown,
73+
n,
74+
UNLIMITED,
75+
0,
76+
)
6777
for k, (r, n) in enumerate(zip(self.rules, self.fired, strict=True))
6878
)
6979
return rg.Read(CFG, Brain(CFG, self.ticks, slots))

0 commit comments

Comments
 (0)