Skip to content

engine: costs paid by sacrificing a chosen permanent, or by discarding #721

Description

@ninthworld

Parent: #706. One of the exclusion families blocking the 104 M19 cards the catalog does not yet define.

Exclusion (crates/sage-engine/data/exclusions.json): Costs paid by sacrificing a permanent the player chooses, or by discarding — an activation cost may sacrifice its own source and remove its own counters, but a cost that requires picking another permanent or a card has no way to carry the choice.

This is the largest single M19 blocker: 13 of the 104 missing cards need it, and five of them need nothing else.

M19 cards blocked (13)

Complete once this lands — every other piece already exists:

# Card Cost shape
86 Blood Divination additional cast cost: sacrifice a creature
91 Demon of Catastrophes additional cast cost: sacrifice a creature
115 Ravenous Harpy activation: sacrifice another creature
136 Dismissive Pyromancer activation: discard a card
144 Goblin Trashmaster activation: sacrifice a Goblin

Blocked here and elsewhere too:

# Card Cost shape Also needs
4 Ajani's Last Stand sacrifice this as an optional cost optional non-mana costs; a discarded-from-hand trigger
69 Sai, Master Thopterist activation: sacrifice two artifacts a cast trigger filtered to artifact spells
99 Graveyard Marshal activation: exile a chosen card from a graveyard
134 Dark-Dweller Oracle activation: sacrifice a creature playing a card from exile
163 Thud additional cast cost: sacrifice a creature an amount read off the sacrificed creature
201 Scapeshift sacrifice any number of lands a search sized by the number sacrificed
213 Brawl-Bash Ogre optional sacrifice on an attack trigger optional non-mana costs
214 Chromium, the Mutable activation: discard a card loses-all-abilities

Scope

  1. Let a cost carry a choice made at announcement. Action::ActivateAbility and the cast action already carry targets: Vec<Target> in the parameterized form ADR 0004 describes; a chosen sacrifice or discard is not a target and needs its own slot on the action rather than being smuggled into that list.
  2. Widen additional_cost beyond discard: a sacrifice with a permanent filter (creature, a subtype).
  3. Widen Cost with the same, for activated abilities.
  4. Advertise the candidates the way target_requirements advertises target slots, so the client keeps choosing from a server-computed list and computes no legality itself.
  5. Costs are paid as the spell goes on the stack (CR 601.2h): an unpayable cost means the action is never offered, and the sacrifice is a real death every dies-watcher sees, exactly as sacrifice_this already is.

This is a protocol change. docs/protocol.md, sage-protocol, and the TypeScript mirror move in the same PR.

Acceptance criteria

  • The five cards above are authored in crates/sage-engine/data/catalog/, printed in data/sets/M19.json, and covered by tests driving the real apply_action.
  • An unpayable cost withholds the action; a paid one is paid before resolution and cannot be countered away.
  • Generated rules text (crates/sage-server/src/rules_text) states the cost.
  • The exclusion narrows to what still cannot be written; make compat regenerated and committed.
  • docs/card-schema.md and docs/protocol.md updated. No rules logic added to the client.
  • make verify green.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions