Skip to content

feat(parser): compound player+object hexproof/shroud static — generalise You-and-X grants (CR 702.11 / CR 702.18 / CR 611.3a) #5366

Description

@claytonlin1110

Summary

Generalize parse_compound_subject_keyword_static (currently Protection-only + hard-coded object subjects) into the full player + object compound keyword-grant class — the structural sibling of Serra's Emissary / #5219-style compound continuous statics.

Today the handler only claims:

  • object subjects: creatures you control / other creatures you control / permanents you control
  • player half: StaticMode::PlayerProtection only

Every other player+object grant falls through to a single incorrect Continuous that Ors the player filter with objects (empty typed + You), which layers interpret as granting the keyword to every permanent you control — including the wrong self-scope. That is the live Sigarda bug (Discord / #5322).

Class (not a card)

You and <object-subject> have <player-applicable keyword> where the keyword has a player-scope StaticMode:

Keyword Object half Player half
Protection from Q Continuous + AddKeyword(Protection(Q)) PlayerProtection(Q)
Hexproof Continuous + AddKeyword(Hexproof) StaticMode::Hexproof
Shroud Continuous + AddKeyword(Shroud) StaticMode::Shroud

Object subjects must reuse parse_rule_static_subject_filter (subtype scopes, this creature / ~, other Heroes you control, etc.) — not a hard-coded alt of three phrases.

Gated forms of the same class:

  • Leading turn window: During your turn, you and this creature have hexproof. (Gruul Spellbreaker)
  • Inverted / trailing condition: As long as <cond>, you and other Heroes you control have hexproof. (Captain America, Super-Soldier)

Anchored on

  • crates/engine/src/parser/oracle_static/evasion.rs parse_compound_subject_keyword_static — existing Protection splitter (Serra's Emissary)
  • crates/engine/src/parser/oracle_static/grammar.rs lower_rule_static Hexproof/Shroud player-scope arms + static_you_have_hexproof / static_you_have_shroud
  • Dispatch site: shared.rs parse_static_line_multi_dispatch (immediately before single-return fallback)

Same structural shape as #5219: dedicated compound handler before the incomplete single-subject sibling, reuse existing predicate/modification builders, Or/split scopes so one StaticDefinition is not forced to carry both player and object affected sets.

Example Oracle (Scryfall-verified)

  • Sigarda, Heron's Grace: You and Humans you control have hexproof.
  • I Am Untouchable: You and permanents you control have hexproof.
  • Gruul Spellbreaker: During your turn, you and this creature have hexproof.
  • Captain America, Super-Soldier: As long as Captain America has a shield counter on him, you and other Heroes you control have hexproof.
  • Regression: Serra's Emissary Protection compound must keep splitting unchanged

Out of scope

Instant/sorcery until-EOT grants (Dawn's Truce, Lazotep Plating, Veil of Summer) — effect pipeline, not continuous statics.

Related

Acceptance

  • Sigarda-class lines emit exactly two defs: object Continuous{AddKeyword(Hexproof)} with Human/controller filter, and player StaticMode::Hexproof on controller-You
  • Wrong empty-typed Or / self-hexproof misparse is gone
  • Protection compound regressions still pass
  • Gate A (check-parser-combinators.sh) + oracle_static tests green

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions