feat(parser): grant Replicate at a self-mana-cost (Hatchery Sliver #5323)#5459
Conversation
…ase-rs#5323) Hatchery Sliver — "Each Sliver spell you cast has replicate. The replicate cost is equal to its mana cost." — strict-failed (Unimplemented static_structure): the whole line was dropped, so it granted no replicate. phase-rs#5436 added the table-driven alt-cost-keyword grant recognizer (`parse_granted_self_cost_keyword`) for Blitz (Henzie "Toolbox" Torre) but excluded Replicate, noting it "needs separate runtime work (granted replicate is card-build-synthesized)". That note is now outdated — the runtime for dynamically-granted Replicate already exists: - `effective_replicate_additional_cost_instances` reads granted Replicate via `effective_spell_keyword_instances` (includes CastWithKeyword grants), surfacing it as a repeatable additional cost (CR 702.56a); and - the `dynamically_granted_replicate` seam in `game/triggers.rs` synthesizes the per-instance copy trigger for CastWithKeyword-granted Replicate. So this reduces to one table entry: add `("replicate", Keyword::Replicate)` to `parse_granted_self_cost_keyword`, mirroring Blitz. Hatchery now lowers to `CastWithKeyword { Replicate(SelfManaCost) }` over a Sliver-spell filter, with zero engine changes. Tests: - parser: Hatchery lowers to CastWithKeyword { Replicate(SelfManaCost) } with a Sliver subtype filter (mirrors the granted-Blitz test). - runtime: `dynamically_granted_replicate_enqueues_copy_trigger` proves the granted Replicate fires its CopySpell trigger end-to-end via the existing seam (this seam previously had no dedicated test). CR 702.56a + CR 611.2f + CR 601.2f. Closes phase-rs#5323 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request extends the static keyword grant parser to support the 'replicate' keyword (e.g., for Hatchery Sliver) alongside 'blitz', mapping it to Keyword::Replicate(ManaCost::SelfManaCost). A comprehensive unit test has been added to verify correct parsing and targeting. No review comments were provided, and the implementation is clean and idiomatic, so I have no feedback to provide.
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.
Parse changes introduced by this PR · 3 card(s), 4 signature(s) (baseline: main
|
matthewevans
left a comment
There was a problem hiding this comment.
Maintainer review: approved. Parser change extends the existing self-cost keyword grant seam; parse-diff matches the claimed Hatchery Sliver / Djinn Illuminatus / Ian Chesterton coverage; runtime granted-Replicate cost and trigger paths are already covered.
|
Thank you @shin-core! Nice work! Swing by the Discord if you're ever up to it :) |
Summary
Fixes #5323. Hatchery Sliver — "Each Sliver spell you cast has replicate. The replicate cost is equal to its mana cost." — strict-failed (
Unimplementedstatic_structure); the whole line was dropped, so it granted no replicate.#5436 added the table-driven alt-cost-keyword grant recognizer (
parse_granted_self_cost_keyword) for Blitz (Henzie "Toolbox" Torre) but excluded Replicate, noting it "needs separate runtime work (granted replicate is card-build-synthesized)."That note is now outdated — the runtime for dynamically-granted Replicate already exists on
main:effective_replicate_additional_cost_instancesreads granted Replicate viaeffective_spell_keyword_instances(which includesCastWithKeywordgrants), surfacing it as a repeatable additional cost (CR 702.56a); anddynamically_granted_replicateseam ingame/triggers.rssynthesizes the per-instance copy trigger forCastWithKeyword-granted Replicate.So this reduces to one table entry — add
("replicate", Keyword::Replicate)toparse_granted_self_cost_keyword, mirroring Blitz. Hatchery now lowers toCastWithKeyword { Replicate(SelfManaCost) }over a Sliver-spell filter, with zero engine changes.Tests
static_grant_replicate_hatchery_sliver): Hatchery lowers toCastWithKeyword { Replicate(SelfManaCost) }with a Sliver subtype filter +ControllerRef::You(mirrors the granted-Blitz test).dynamically_granted_replicate_enqueues_copy_trigger): a granted-Replicate Sliver spell (no printed Replicate, one paid instance) fires itsCopySpelltrigger via the existing seam — empirically proving the grant functions end-to-end. This seam previously had no dedicated test, so this also closes a coverage gap.Verification
cargo check -p engine— cleancargo clippy -p engine— cleanCR 702.56a (Replicate) + CR 611.2f (cast-time keyword snapshot) + CR 601.2f (self-referential granted cost).
🤖 Generated with Claude Code