Skip to content

feat(parser): reach graveyard cards with the chosen-creature-type static (Ashes of the Fallen)#5864

Open
minion1227 wants to merge 1 commit into
phase-rs:mainfrom
minion1227:minion_ashes
Open

feat(parser): reach graveyard cards with the chosen-creature-type static (Ashes of the Fallen)#5864
minion1227 wants to merge 1 commit into
phase-rs:mainfrom
minion1227:minion_ashes

Conversation

@minion1227

Copy link
Copy Markdown
Contributor

Closes #5863

Summary

"Each creature card in your graveyard has the chosen creature type in addition to its other types." (Ashes of the Fallen) strict-failed — zero statics, so the card did nothing after its ETB choice. The battlefield sibling (Arcane Adaptation) parses fine, so this was purely a zone-scope gap.

parse_arcane_adaptation_chosen_type_static dispatches on ChosenCreatureTypeStaticScope, whose subject matcher had fixed arms only for creatures you control are / each creature you control is / vehicle creatures you control are. The graveyard subject — which also reads "has" rather than "are" — had no arm, so the line fell through unparsed.

Files changed

  • crates/engine/src/parser/oracle_static/type_change.rs
  • crates/engine/src/parser/oracle_static/tests.rs

CR references

  • CR 400.1 — zones; the grant reaches cards in the controller's graveyard, not battlefield permanents.
  • CR 205.1b — "in addition to its other types" retention (additive, no subtype wipe).
  • CR 607.2d — the chosen-value link between the ETB choice and the grant.
  • CR 613.1d — Layer 4, type-changing effects.

Implementation method (required)

Method: not-applicable — authored directly against the oracle-parser skill. Pure parser change; no card-data regeneration required (AST-shape fix).

Track

Developer

LLM

Model: claude-opus-4-8
Thinking: high

Verification

  • Required checks ran clean, or the exact CI-owned alternative is stated below.
  • Verification below is for the current committed head (a08d0c992).
  • Final review below is clean for the current committed head.
  • Both anchors cite existing analogous code at the same seam.

Results on head a08d0c992:

  • cargo test -p engine --lib parser::ok. 8188 passed; 0 failed (2 new; all snapshot tests unaffected).
  • cargo clippy -p engine --all-targets --features proptest -- -D warningsFinished, 0 warnings (exit 0).
  • cargo fmt --all — clean.

Parse diff (Ashes of the Fallen)

Before:

statics = []          // card does nothing after the ETB choice

After:

affected = {Creature, controller: You, InAnyZone[Graveyard]}
mods     = [AddChosenSubtype { kind: CreatureType }]

Anchored on

  • crates/engine/src/parser/oracle_static/type_change.rs (parse_arcane_adaptation_chosen_type_static + ChosenCreatureTypeStaticScope) — the existing scope axis this extends. Same creature subject, same additive AddChosenSubtype{CreatureType}, same additive/SET application split; only the zone differs, so it becomes a fourth scope arm rather than a parallel handler.
  • crates/engine/src/parser/oracle_static/shared.rs (parse_hand_cards_have_derived_cost_keyword) — the established zone-fold precedent: a card-in-a-zone static carries its scope as FilterProp::InAnyZone { zones: [Hand] } on the same typed filter. This reuses that fold verbatim with [Graveyard].

Final review

Self-review against the review-impl lenses. No new engine primitive: AddChosenSubtype, FilterProp::InAnyZone, and the additive/SET split are pre-existing and already runtime-wired, so this is a parser-recognition change only. The new arm matches the full literal subject+verb ("each creature card in your graveyard has"), so it cannot claim any other line, and it binds "its" as the retention pronoun to match the card's "in addition to its other types" (the pronoun feeds the shared additive-suffix check). The graveyard scope is grouped with the other creature-card subjects in the SET/replace arm for semantic correctness; no SET printing exists today (Ashes is additive), so that arm is unreachable in practice and documented as such. Battlefield forms are byte-for-byte unchanged — regression-tested that Arcane Adaptation gains no zone restriction (arcane_adaptation_stays_unzoned_after_graveyard_arm), plus 8188 parser tests incl. snapshots unaffected.

Claimed parse impact

  • Ashes of the Fallen

The CI coverage-parse-diff sticky enumerates the full affected set for the current head.

Validation Failures

None.

CI Failures

None.

…tic (Ashes of the Fallen)

"Each creature card in your graveyard has the chosen creature type in
addition to its other types." (Ashes of the Fallen) strict-failed — the
line produced zero statics, so the card did nothing after its ETB choice.

This is the ZONE-axis sibling of Arcane Adaptation: the same creature
subject and the same additive AddChosenSubtype{CreatureType} grant, one
axis different — the cards live in the controller's graveyard rather than
on the battlefield. So it extends the existing scope axis
(ChosenCreatureTypeStaticScope) that parse_arcane_adaptation_chosen_type_
static already dispatches on, and the new scope's target_filter carries the
restriction with the identical FilterProp::InAnyZone fold that
parse_hand_cards_have_derived_cost_keyword applies for its hand-scoped
grant. The subject arm reads "has" (a single card) rather than "are", and
binds "its" as the retention pronoun.

No new engine primitive: AddChosenSubtype, InAnyZone and the additive/SET
application split are all pre-existing and already runtime-wired. The
battlefield forms are untouched — regression-tested that Arcane Adaptation
gains no zone restriction.

CR 400.1 (zones) + CR 205.1b (in-addition retention) + CR 607.2d
(chosen-value link) + CR 613.1d (Layer 4).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@minion1227 minion1227 requested a review from matthewevans as a code owner July 15, 2026 14:54

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for graveyard-scoped creature card type-change effects (such as Ashes of the Fallen) by adding the GraveyardCreatureCards variant to ChosenCreatureTypeStaticScope and implementing its target filtering, parsing, and application logic. The review feedback correctly identifies that the comments citing CR 400.1 should instead cite CR 109.2a to accurately reflect the distinction between cards in non-battlefield zones and permanents on the battlefield, in accordance with Rule R6.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +70 to +72
/// CR 400.1 + CR 607.2d: the grant reaches creature CARDS in the controller's
/// graveyard rather than permanents on the battlefield (Ashes of the Fallen).
GraveyardCreatureCards,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

[MED] Incorrect CR citation for zone-based card vs permanent distinction. Evidence: crates/engine/src/parser/oracle_static/type_change.rs:70.
Why it matters: CR 400.1 merely defines what an object is, whereas CR 109.2a specifically explains why an object with a card type in a non-battlefield zone is a card rather than a permanent.
Suggested fix: Change CR 400.1 to CR 109.2a.

Suggested change
/// CR 400.1 + CR 607.2d: the grant reaches creature CARDS in the controller's
/// graveyard rather than permanents on the battlefield (Ashes of the Fallen).
GraveyardCreatureCards,
/// CR 109.2a + CR 607.2d: the grant reaches creature CARDS in the controller's
/// graveyard rather than permanents on the battlefield (Ashes of the Fallen).
GraveyardCreatureCards,
References
  1. Rule R6: Every rules-touching line of engine code must carry a comment of the form CR : . The number must be verified against docs/MagicCompRules.txt before writing. (link)

Comment on lines +93 to +98
// CR 400.1 + CR 607.2d: Ashes of the Fallen grants the chosen type to
// creature CARDS in the controller's graveyard. Same creature subject,
// one axis different — the zone — so the filter carries the restriction
// via the identical `InAnyZone` fold the hand-scoped derived-cost grant
// (`parse_hand_cards_have_derived_cost_keyword`) already applies.
Self::GraveyardCreatureCards => TargetFilter::Typed(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

[MED] Incorrect CR citation for zone-based card vs permanent distinction. Evidence: crates/engine/src/parser/oracle_static/type_change.rs:93.
Why it matters: CR 400.1 merely defines what an object is, whereas CR 109.2a specifically explains why an object with a card type in a non-battlefield zone is a card rather than a permanent.
Suggested fix: Change CR 400.1 to CR 109.2a.

Suggested change
// CR 400.1 + CR 607.2d: Ashes of the Fallen grants the chosen type to
// creature CARDS in the controller's graveyard. Same creature subject,
// one axis different — the zone — so the filter carries the restriction
// via the identical `InAnyZone` fold the hand-scoped derived-cost grant
// (`parse_hand_cards_have_derived_cost_keyword`) already applies.
Self::GraveyardCreatureCards => TargetFilter::Typed(
// CR 109.2a + CR 607.2d: Ashes of the Fallen grants the chosen type to
// creature CARDS in the controller's graveyard. Same creature subject,
// one axis different — the zone — so the filter carries the restriction
// via the identical `InAnyZone` fold the hand-scoped derived-cost grant
// (`parse_hand_cards_have_derived_cost_keyword`) already applies.
Self::GraveyardCreatureCards => TargetFilter::Typed(
References
  1. Rule R6: Every rules-touching line of engine code must carry a comment of the form CR : . The number must be verified against docs/MagicCompRules.txt before writing. (link)

@github-actions

Copy link
Copy Markdown

Parse changes introduced by this PR · 1 card(s), 2 signature(s) (baseline: main c0d7e0f3a5d6)

1 card(s) · static/Continuous · added: Continuous (affects=in graveyard you control creature, mods=add chosen subtype)

Examples: Ashes of the Fallen

1 card(s) · ability/static_structure · removed: static_structure

Examples: Ashes of the Fallen

1 card(s) had Oracle-text changes (errata/reprint) — excluded as non-parser.

@matthewevans matthewevans self-assigned this Jul 16, 2026
@matthewevans matthewevans added the bug Bug fix label Jul 16, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes — correct both type-change CR annotations.

🟡 Finding

[MED] The new annotations cite unrelated CR 607.2d and CR 400.1. Evidence: crates/engine/src/parser/oracle_static/type_change.rs:70,93. Why it matters: the comments claim rule support they do not have. Suggested fix: use the verified relevant citations CR 109.2a + CR 613.1d / CR 205.1b with accurate descriptions.

Recommendation: request-changes.

@matthewevans matthewevans removed their assignment Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

parser: chosen-creature-type static strict-fails when scoped to the graveyard (Ashes of the Fallen)

2 participants