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
- 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.
- Widen
additional_cost beyond discard: a sacrifice with a permanent filter (creature, a subtype).
- Widen
Cost with the same, for activated abilities.
- 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.
- 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
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:
Blocked here and elsewhere too:
Scope
Action::ActivateAbilityand the cast action already carrytargets: 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.additional_costbeyonddiscard: a sacrifice with a permanent filter (creature, a subtype).Costwith the same, for activated abilities.target_requirementsadvertises target slots, so the client keeps choosing from a server-computed list and computes no legality itself.sacrifice_thisalready is.This is a protocol change.
docs/protocol.md,sage-protocol, and the TypeScript mirror move in the same PR.Acceptance criteria
crates/sage-engine/data/catalog/, printed indata/sets/M19.json, and covered by tests driving the realapply_action.crates/sage-server/src/rules_text) states the cost.make compatregenerated and committed.docs/card-schema.mdanddocs/protocol.mdupdated. No rules logic added to the client.make verifygreen.