Skip to content

[Card Bug] Mutational Advantage prevents damage to all permanents, not just your countered ones #6682

Description

@mike-theDude

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:

  1. "any target"Any
  2. "target creature" / "target permanent"parse_target(...)
  3. the "to you and [<type>] permanents you control" compound
  4. "to you" / "to its controller"Controller
  5. 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

  1. Control one or more permanents with counters on them; opponent controls a creature with no counters.
  2. Cast Mutational Advantage.
  3. Deal damage to an opponent's creature (combat or a burn spell).
  4. Observed: the damage is prevented. Expected: the damage is dealt normally — only your own countered permanents are shielded.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions