Summary
The engine already has the building blocks for granting a keyword ability whose cost is the recipient's own mana cost — ManaCost::SelfManaCost plus ContinuousModification::AddKeyword — used today for one-shot single-target grants like Snapcaster Mage's flashback trigger. It also has a continuous, filter-scoped variant of that same grant for a handful of graveyard keywords (GraveyardGrantedKeywordKind in parser/oracle_static/keyword_grant.rs + oracle.rs's parse_graveyard_keyword_continuation), covering Flashback/Escape/Mayhem/Scavenge/Encore.
That continuous-grant class stops short of real, tournament-legal cards in three ways:
- No cost-delta support.
ManaCost::SelfManaCost only represents "equal to its mana cost" — there's no way to express "equal to its mana cost reduced by {2}", which several real cards need.
- Graveyard-only. The combinator hard-requires the affected filter to be the controller's graveyard (
target_filter_is_your_graveyard). Hand-zone grants (Foretell) aren't recognized at all.
- Missing keywords. Embalm isn't in
GraveyardGrantedKeywordKind even though the runtime resolver (resolve_self_cost_graveyard_activated_keyword) already handles it.
There's also a latent runtime gap: foretell_cost/can_foretell_card (game/casting.rs) read obj.keywords directly instead of going through the off-zone-aware effective_off_zone_keyword path that graveyard keywords already use — so even a correctly-parsed continuous Foretell grant on a hand card would silently never be castable.
Real cards affected (verified against data/mtgjson/AtomicCards.json)
| Card |
Legality |
Zone |
Keyword |
Cost formula |
| Varolz, the Scar-Striped |
Commander/Legacy/Modern/Pioneer/Vintage |
Graveyard |
Scavenge |
mana cost |
| Young Deathclaws |
Commander/Legacy/Vintage |
Graveyard |
Scavenge |
mana cost |
| Wire Surgeons |
Commander/Legacy/Vintage |
Graveyard |
Encore |
mana cost |
| Return the Past |
Commander/Legacy/Vintage |
Graveyard |
Flashback |
mana cost (during your turn only) |
| Bohn, Beguiling Balladeer |
Commander/Legacy/Vintage |
Hand |
Foretell |
mana cost reduced by {2} |
| Dream Devourer |
Modern/Pioneer/Commander/Standard-legal formats |
Hand |
Foretell |
mana cost reduced by {2} |
| Naktamun (Plane) |
Planechase |
Graveyard |
Embalm |
mana cost |
| The Cave of Skulls (Plane) |
Planechase |
Graveyard |
Scavenge |
mana cost |
| Singing Towers of Darillium (Plane) |
Planechase |
Hand |
Foretell |
mana cost reduced by {2} |
Varolz and Dream Devourer are real constructed/Commander staples — this isn't an edge-case cluster.
Proposed fix (building-block, not per-card)
- Add
ManaCost::SelfManaCostAdjusted { delta: i32 } alongside the existing SelfManaCost/SelfManaValue markers (CR 601.2f: generic mana adjusted, floored at {0}), resolved at the single existing choke point resolve_keyword_mana_cost (game/keywords.rs).
- Extend
GraveyardGrantedKeywordKind with Embalm (CR 702.128a) — the runtime resolver already supports it, this is a pure parser gap.
- Add a hand-zone counterpart for Foretell (CR 702.143a/d), reusing the already-generic
FilterProp::WithoutKeywordKind for the "without foretell" exclusion clause that's already a first-class filter predicate.
- Extend the shared cost-suffix combinator to recognize "reduced by {N}" / "minus {N}" (CR 601.2f cost reduction).
- Fix
foretell_cost/can_foretell_card to resolve through effective_off_zone_keyword instead of reading obj.keywords directly, so continuously-granted Foretell on a hand card is actually castable.
- Add a genuine runtime test proving a filter-scoped (not
SpecificObject) continuous grant activates correctly in both hand and graveyard zones — today only single-target grants are tested end-to-end.
This is scoped to keep each card's mechanic within its own CR section (Scavenge/Encore/Flashback/Embalm are all CR 702.x graveyard-cast activated abilities; Foretell is CR 702.143 hand-zone) — no cross-section unification.
Fossilize (Sue, Everlasting Dinosaur) and Madness (Falkenrath Gorger's "isn't on the battlefield" multi-zone filter) are deliberately out of scope: Fossilize has no Comprehensive Rules entry to annotate against, and Falkenrath Gorger's zone scope is broader than hand+graveyard.
Summary
The engine already has the building blocks for granting a keyword ability whose cost is the recipient's own mana cost —
ManaCost::SelfManaCostplusContinuousModification::AddKeyword— used today for one-shot single-target grants like Snapcaster Mage's flashback trigger. It also has a continuous, filter-scoped variant of that same grant for a handful of graveyard keywords (GraveyardGrantedKeywordKindinparser/oracle_static/keyword_grant.rs+oracle.rs'sparse_graveyard_keyword_continuation), covering Flashback/Escape/Mayhem/Scavenge/Encore.That continuous-grant class stops short of real, tournament-legal cards in three ways:
ManaCost::SelfManaCostonly represents "equal to its mana cost" — there's no way to express "equal to its mana cost reduced by {2}", which several real cards need.target_filter_is_your_graveyard). Hand-zone grants (Foretell) aren't recognized at all.GraveyardGrantedKeywordKindeven though the runtime resolver (resolve_self_cost_graveyard_activated_keyword) already handles it.There's also a latent runtime gap:
foretell_cost/can_foretell_card(game/casting.rs) readobj.keywordsdirectly instead of going through the off-zone-awareeffective_off_zone_keywordpath that graveyard keywords already use — so even a correctly-parsed continuous Foretell grant on a hand card would silently never be castable.Real cards affected (verified against
data/mtgjson/AtomicCards.json)Varolz and Dream Devourer are real constructed/Commander staples — this isn't an edge-case cluster.
Proposed fix (building-block, not per-card)
ManaCost::SelfManaCostAdjusted { delta: i32 }alongside the existingSelfManaCost/SelfManaValuemarkers (CR 601.2f: generic mana adjusted, floored at{0}), resolved at the single existing choke pointresolve_keyword_mana_cost(game/keywords.rs).GraveyardGrantedKeywordKindwithEmbalm(CR 702.128a) — the runtime resolver already supports it, this is a pure parser gap.FilterProp::WithoutKeywordKindfor the "without foretell" exclusion clause that's already a first-class filter predicate.foretell_cost/can_foretell_cardto resolve througheffective_off_zone_keywordinstead of readingobj.keywordsdirectly, so continuously-granted Foretell on a hand card is actually castable.SpecificObject) continuous grant activates correctly in both hand and graveyard zones — today only single-target grants are tested end-to-end.This is scoped to keep each card's mechanic within its own CR section (Scavenge/Encore/Flashback/Embalm are all CR 702.x graveyard-cast activated abilities; Foretell is CR 702.143 hand-zone) — no cross-section unification.
Fossilize (Sue, Everlasting Dinosaur) and Madness (Falkenrath Gorger's "isn't on the battlefield" multi-zone filter) are deliberately out of scope: Fossilize has no Comprehensive Rules entry to annotate against, and Falkenrath Gorger's zone scope is broader than hand+graveyard.