Card(s)
Mutational Advantage (also: Blinding Fog, Defend the Hearth, Energy Arc, and ~40 other prevention cards — same root cause, see below)
Build/version
v0.38.0 (parse re-verified against the live coverage-data.json for this build)
Game mode
AI
Actual behavior
Cast Mutational Advantage. The hexproof/indestructible half worked correctly — only my own permanents with counters on them got the keywords. But the prevention half applied to everything on the battlefield: damage dealt to my opponents' creatures was prevented too, not just damage to my own permanents.
Expected behavior
Per the Oracle text, the prevention should be scoped to the same population as the first sentence — permanents you control that had counters on them when the spell resolved (CR 611.2c: the set is locked in when the continuous effect begins). Opponents' permanents should take damage normally.
Root cause (parser — recipient scope is dropped)
This is a parse defect, not a resolver defect. Oracle text (verified against Scryfall + client/public/card-data.json):
Permanents you control with counters on them gain hexproof and indestructible until end of turn.
Prevent all damage that would be dealt to those permanents this turn.
Proliferate.
The first sentence parses correctly — the affected filter carries both the controller and the counters constraint:
{ "type": "Typed", "type_filters": ["Permanent"], "controller": "You",
"properties": [{ "type": "Counters", "counters": {"type":"Any"}, "comparator": "GE",
"count": {"type":"Fixed","value":1} }] }
The second sentence throws that scope away entirely:
{ "type": "PreventDamage", "amount": "All", "target": { "type": "Any" }, "scope": "AllDamage" }
target: Any is a blanket shield, which is exactly the observed behavior.
The "those permanents" set anaphor never reaches a recipient parser. In parse_prevent_effect
(crates/engine/src/parser/oracle_effect/imperative.rs:5858) the recipient dispatch recognizes only:
"any target" → Any
"target creature" / "target permanent" → parse_target(...)
- the
"to you and [<type>] permanents you control" compound
"to you" / "to its controller" → Controller
- single-object anaphors via
parse_anaphoric_target_ref ("that creature", "it", "the creature"), gated on parent_target_available
…and every other recipient scope falls through to the else arm: TargetFilter::Any.
Two distinct gaps land in that fallback:
- Set anaphors.
parse_target already maps "those permanents" / "those creatures" to a tracked-set filter (crates/engine/src/parser/oracle_target.rs:1066-1067), but the prevent branch never calls it for this shape. And for Mutational Advantage a tracked set alone wouldn't be enough — the antecedent isn't a chosen target, it's the affected filter of the immediately preceding continuous-effect clause in the same chain, so the anaphor needs to bind to that population.
- Mass typed recipients with no anaphor at all.
"dealt to creatures", "dealt to players", "dealt to creatures you control" are not in the dispatch list either, so they also collapse to Any.
Related cards (same fallback, verified from card-data.json)
Every one of these has a scoped recipient in its Oracle text and parses to target: {"type":"Any"}:
| Card |
Oracle recipient |
Parsed recipient |
Wrong how |
| Mutational Advantage |
those permanents (your countered permanents) |
Any |
protects opponents' permanents |
| Blinding Fog |
creatures |
Any |
also prevents damage to players |
| Defend the Hearth |
players |
Any |
also prevents combat damage to creatures |
| Energy Arc |
those creatures (the untapped targets) |
Any |
protects every creature, not the chosen ones |
Broader sweep over card-data.json for prevent (all\|the next) … damage that would be dealt to <recipient> that parses to Any returns ~40 cards, including Avacyn Guardian Angel, Brace for Impact, Commencement of Festivities, Forfend, Maze of Ith, and the whole Gideon cycle. Worth confirming each individually, but the dispatch gap is shared.
Suggested direction
Route the prevent-recipient dispatch through the shared parse_target grammar instead of the hand-rolled scan chain, so mass typed filters and controller qualifiers come through as real TargetFilters rather than Any; then add set-anaphor binding for "those <type>" — for target-derived antecedents to the existing tracked set, and for clause-derived antecedents (Mutational Advantage) to the affected filter of the preceding continuous-effect clause.
Note the Any fallback is silently permissive: a dropped recipient scope makes the shield strictly larger, so these misparses don't surface as "card does nothing" — they surface as opponents' permanents becoming untouchable. A strict-failure marker would be safer than defaulting to Any here.
CR references (verified against docs/MagicCompRules.txt):
- CR 615.1 / 615.1a — prevention effects act as shields around whatever they're affecting
- CR 611.2c — a continuous effect from a resolved spell locks in its affected set when the effect begins
Steps to reproduce
- Control one or more permanents with counters on them; opponent controls a creature with no counters.
- Cast Mutational Advantage.
- Deal damage to an opponent's creature (combat or a burn spell).
- Observed: the damage is prevented. Expected: the damage is dealt normally — only your own countered permanents are shielded.
Card(s)
Mutational Advantage (also: Blinding Fog, Defend the Hearth, Energy Arc, and ~40 other prevention cards — same root cause, see below)
Build/version
v0.38.0 (parse re-verified against the live
coverage-data.jsonfor this build)Game mode
AI
Actual behavior
Cast Mutational Advantage. The hexproof/indestructible half worked correctly — only my own permanents with counters on them got the keywords. But the prevention half applied to everything on the battlefield: damage dealt to my opponents' creatures was prevented too, not just damage to my own permanents.
Expected behavior
Per the Oracle text, the prevention should be scoped to the same population as the first sentence — permanents you control that had counters on them when the spell resolved (CR 611.2c: the set is locked in when the continuous effect begins). Opponents' permanents should take damage normally.
Root cause (parser — recipient scope is dropped)
This is a parse defect, not a resolver defect. Oracle text (verified against Scryfall +
client/public/card-data.json):The first sentence parses correctly — the affected filter carries both the controller and the counters constraint:
{ "type": "Typed", "type_filters": ["Permanent"], "controller": "You", "properties": [{ "type": "Counters", "counters": {"type":"Any"}, "comparator": "GE", "count": {"type":"Fixed","value":1} }] }The second sentence throws that scope away entirely:
{ "type": "PreventDamage", "amount": "All", "target": { "type": "Any" }, "scope": "AllDamage" }target: Anyis a blanket shield, which is exactly the observed behavior.The
"those permanents"set anaphor never reaches a recipient parser. Inparse_prevent_effect(
crates/engine/src/parser/oracle_effect/imperative.rs:5858) the recipient dispatch recognizes only:"any target"→Any"target creature"/"target permanent"→parse_target(...)"to you and [<type>] permanents you control"compound"to you"/"to its controller"→Controllerparse_anaphoric_target_ref("that creature","it","the creature"), gated onparent_target_available…and every other recipient scope falls through to the
elsearm:TargetFilter::Any.Two distinct gaps land in that fallback:
parse_targetalready maps"those permanents"/"those creatures"to a tracked-set filter (crates/engine/src/parser/oracle_target.rs:1066-1067), but the prevent branch never calls it for this shape. And for Mutational Advantage a tracked set alone wouldn't be enough — the antecedent isn't a chosen target, it's the affected filter of the immediately preceding continuous-effect clause in the same chain, so the anaphor needs to bind to that population."dealt to creatures","dealt to players","dealt to creatures you control"are not in the dispatch list either, so they also collapse toAny.Related cards (same fallback, verified from card-data.json)
Every one of these has a scoped recipient in its Oracle text and parses to
target: {"type":"Any"}:those permanents(your countered permanents)AnycreaturesAnyplayersAnythose creatures(the untapped targets)AnyBroader sweep over
card-data.jsonforprevent (all\|the next) … damage that would be dealt to <recipient>that parses toAnyreturns ~40 cards, including Avacyn Guardian Angel, Brace for Impact, Commencement of Festivities, Forfend, Maze of Ith, and the whole Gideon cycle. Worth confirming each individually, but the dispatch gap is shared.Suggested direction
Route the prevent-recipient dispatch through the shared
parse_targetgrammar instead of the hand-rolled scan chain, so mass typed filters and controller qualifiers come through as realTargetFilters rather thanAny; then add set-anaphor binding for"those <type>"— for target-derived antecedents to the existing tracked set, and for clause-derived antecedents (Mutational Advantage) to the affected filter of the preceding continuous-effect clause.Note the
Anyfallback is silently permissive: a dropped recipient scope makes the shield strictly larger, so these misparses don't surface as "card does nothing" — they surface as opponents' permanents becoming untouchable. A strict-failure marker would be safer than defaulting toAnyhere.CR references (verified against
docs/MagicCompRules.txt):Steps to reproduce