Skip to content

fix(engine): an observed activation can say "you" - #833

Open
ninthworld wants to merge 1 commit into
mainfrom
engine/activator-scope-you
Open

fix(engine): an observed activation can say "you"#833
ninthworld wants to merge 1 commit into
mainfrom
engine/activator-scope-you

Conversation

@ninthworld

Copy link
Copy Markdown
Owner

Closes #823. Part of #819.

ActivatorScope had exactly two members:

pub enum ActivatorScope { Any, Opponents }

Sarkhan's Whelp prints Whenever you activate an ability of a Sarkhan planeswalker — so it was authored "activator": "any", and an opponent activating their own Sarkhan fired it.

This is the one item in #819 that is a mechanic finding rather than an authoring one: the vocabulary offered no correct answer, so no amount of care in the JSON would have got it right. A missing member of a closed scope doesn't leave a card unwritable; it leaves it writable and wrong.

Two rules-text bugs came out with it

Adding the scope and asserting the Whelp's generated text produced:

Whenever you activates a nonmana ability of a planeswalker, …

against the expected

Whenever you activate a nonmana ability of a Sarkhan planeswalker, …
  • "you activates" — the verb was hard-coded. activator_subject returns the subject and its verb now, because English doesn't let them travel apart, and a fourth scope added later can't reintroduce the disagreement.
  • source_subtype was never rendered. The Whelp read as watching every planeswalker on the table — a different card from the one the engine was enforcing. Pre-existing; this test is what exposed it.

Tests

issue_823_the_whelp_watches_its_own_controllers_sarkhan_and_not_an_opponents puts the same walker on each side of the table and activates one each, so "the scope is enforced" is distinguishable from "nothing fired for some other reason". Falsified by reverting the card to "activator": "any":

---- issue_823_the_whelp_watches_its_own_controllers_sarkhan_and_not_an_opponents ----
panicked: the card says `whenever you activate`, and that was not you

Plus a rules-text assertion for the corrected sentence.

exclusions.json: no change, and why

The acceptance criterion asked that it "no longer assert the activator filter is complete." Re-reading the entry, it doesn't:

Abilities that trigger on a loyalty ability specifically — an observed activation is filtered by who activated it and by the source's card type and printed subtype … but nothing asks whether the ability activated was a loyalty ability rather than any other (CR 606.1)

That's a description, not a completeness claim, and its actual blocker — the loyalty filter, #776 item 7 — is untouched here and stays true. No entry names this scope, so nothing is dropped or narrowed. Flagging rather than making a cosmetic edit to a file #791 is removing.

One thing I noticed and left alone: that entry's example ("a walker's mana ability would satisfy the same watcher") contradicts the first exclusion entry, since a mana ability never reaches the stack and a loyalty ability is never a mana ability (CR 605.1a). Out of scope here; worth a line in #776 or #791.

Docs

docs/card-schema.md — the ability_activated section listed two filters and two scopes; it now lists three of each, including source_subtype, which was undocumented.

make verify green. make compat shows no drift.

🤖 Generated with Claude Code

`ActivatorScope` had `Any` and `Opponents` and no way to say the third thing a
card prints. Sarkhan's Whelp says `whenever **you** activate an ability of a
Sarkhan planeswalker`, was authored `any` because there was nothing else to
author, and fired on an opponent's own Sarkhan (#819, #823).

A missing member of a closed scope does not leave a card unwritable — it leaves
it writable and wrong, which is the worse failure, and the reason this is a
mechanic finding rather than an authoring one: no amount of care in the JSON
would have got it right.

Two rules-text bugs surfaced with it, both on the same card:

The verb was hard-coded as "activates", so the new scope read "whenever you
activates". The subject and its verb travel together now, because English does
not let them travel apart.

`source_subtype` was never rendered at all, so the Whelp read as watching every
planeswalker on the table — a different card from the one the engine was
enforcing. The subtype sits in front of the type noun the way a card prints it.

`exclusions.json` needed no change: no entry names this scope, and the
neighbouring loyalty entry's blocker (nothing asks whether the activated ability
was a *loyalty* ability, #776 item 7) is untouched by this and stays true.

Closes #823. Part of #819.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

engine: an observed activation cannot say "you"

1 participant