enjine 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -1
- data/SUPPORTED.md +12 -9
- data/docs/MECHANICS_COVERAGE.md +1 -1
- data/docs/guides/card-data-format.md +23 -4
- data/docs/plans/dsl-gaps.md +606 -0
- data/docs/plans/standard.md +3 -0
- data/docs/reference/abilities.md +33 -7
- data/docs/reference/costs.md +11 -1
- data/docs/reference/decisions.md +1 -1
- data/docs/reference/effects.md +30 -9
- data/docs/reference/triggers.md +3 -2
- data/lib/enjine/actions/special_action.rb +4 -2
- data/lib/enjine/engine/casting/alt_casting.rb +18 -2
- data/lib/enjine/engine/casting/casting.rb +3 -3
- data/lib/enjine/engine/casting/costs.rb +5 -1
- data/lib/enjine/engine/casting/permissions.rb +1 -1
- data/lib/enjine/engine/characteristics.rb +0 -13
- data/lib/enjine/engine/defined_power_toughness.rb +30 -0
- data/lib/enjine/engine/mana_sources.rb +8 -1
- data/lib/enjine/engine/resolution.rb +1 -0
- data/lib/enjine/engine/triggers.rb +1 -0
- data/lib/enjine/engine/turn_history.rb +25 -1
- data/lib/enjine/engine/zones.rb +16 -6
- data/lib/enjine/mechanics/abilities/additional_triggers.rb +23 -11
- data/lib/enjine/mechanics/abilities/cost_changes.rb +20 -7
- data/lib/enjine/mechanics/abilities/mana_ability.rb +21 -6
- data/lib/enjine/mechanics/abilities/stack_abilities.rb +13 -9
- data/lib/enjine/mechanics/abilities/static.rb +13 -7
- data/lib/enjine/mechanics/costs/sacrifice.rb +28 -2
- data/lib/enjine/mechanics/effects/become.rb +8 -4
- data/lib/enjine/mechanics/effects/choose_cards.rb +9 -7
- data/lib/enjine/mechanics/effects/delayed_triggers.rb +2 -1
- data/lib/enjine/mechanics/effects/search.rb +15 -8
- data/lib/enjine/mechanics/keywords/plot.rb +79 -0
- data/lib/enjine/mechanics/triggers/casting.rb +8 -6
- data/lib/enjine/mechanics/values.rb +82 -14
- data/lib/enjine/version.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 942c6815c091c8bdab9888b68b9b0e612baa78b548342488c863dc1e830a2bf5
|
|
4
|
+
data.tar.gz: 1a03106084654c2ab19cb708526552857230066e0fc0cf0c2fd860a10cbbb992
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d99c29a1802d4f66b4256d6708d2cc70fb3f8570cb48edf0422faef7b522bf204e959b7247faeadba4ebfd2d5c6b51422510e78ee0c3a24a5bd678bba919b6c9
|
|
7
|
+
data.tar.gz: 9757f33c16fc536bc441401c44194592c4ee3875a4db61765128f55d25b906aef61511fefb377272e5d4dcad9edcab9212b13e33a0be17a821674072651b809e
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,34 @@ change the public API; the stable surface is described in
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.2.0] - 2026-11-12
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Amounts `card_types` (how many card types among cards: delirium, "*" power),
|
|
15
|
+
`greatest_mana_value` and `library_size` ("half their library, rounded up").
|
|
16
|
+
- Amount `sacrificed` (`power`, `toughness` or `mana_value` of the permanents sacrificed to pay the cost).
|
|
17
|
+
- `choose_cards` `put: discard`: the owner discards the cards chosen from their hand ("you choose a
|
|
18
|
+
nonland card from it; that player discards that card").
|
|
19
|
+
- `mana` abilities take `limit: "once_each_turn"`.
|
|
20
|
+
- `cost_modifier` `spells` takes `subtypes` and `colors` ("Dragon spells", "red spells").
|
|
21
|
+
- `grant` and `become` take `duration: "until_your_next_turn"`.
|
|
22
|
+
- Cost `exile_self` ("Exile this enchantment: …").
|
|
23
|
+
- `additional_triggers` takes `of`, a filter of the permanent whose ability triggers; `cause` is optional.
|
|
24
|
+
- Plot (CR 702.170): ability `plot` (a special action from the hand) and effect `plot` ("it becomes
|
|
25
|
+
plotted"); a plotted card is cast from exile for free on a later turn with `via: "plotted"`.
|
|
26
|
+
- Statics can grant loyalty abilities; loyalty abilities take `cost: "-X"`; `activates_ability` takes
|
|
27
|
+
`loyalty: true`.
|
|
28
|
+
- `search_library` `put: graveyard`, and `put: library_top` ("then shuffle and put that card on top").
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
- Power, toughness and mana value of a permanent that left the battlefield while the spell or ability
|
|
32
|
+
resolves are read as it last existed (CR 608.2h): a destroyed target, or `{"result": n}` of a sacrifice.
|
|
33
|
+
They read 0 or the card's printed values before. A reflexive trigger ("when you do") reads them too.
|
|
34
|
+
- `search_library` works out computed bounds in `for` ("mana value equal to 1 plus …"); such a search
|
|
35
|
+
found nothing before.
|
|
36
|
+
- A characteristic-defining power/toughness that counts cards in graveyards no longer recurses forever
|
|
37
|
+
while its own card is in a graveyard.
|
|
38
|
+
|
|
11
39
|
## [0.1.0] - 2026-11-11
|
|
12
40
|
|
|
13
41
|
### Added
|
|
@@ -24,5 +52,6 @@ change the public API; the stable surface is described in
|
|
|
24
52
|
- `enjine` CLI: hot-seat and random play, `--validate`, `--verify`,
|
|
25
53
|
`--random-deck`, save and load.
|
|
26
54
|
|
|
27
|
-
[Unreleased]: https://github.com/thisiscetin/enjine/compare/v0.
|
|
55
|
+
[Unreleased]: https://github.com/thisiscetin/enjine/compare/v0.2.0...HEAD
|
|
56
|
+
[0.2.0]: https://github.com/thisiscetin/enjine/compare/v0.1.0...v0.2.0
|
|
28
57
|
[0.1.0]: https://github.com/thisiscetin/enjine/releases/tag/v0.1.0
|
data/SUPPORTED.md
CHANGED
|
@@ -95,7 +95,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
95
95
|
| [`activated`](docs/reference/abilities.md#activated) | 602.1, 602.2, 602.5b, 602.5d, 702.177a, 702.193a, 702.193b, 702.142a | An activated ability: announce it, choose targets, pay its costs, then it goes on the stack. `timing: "sorcery"` restricts it to sorcery speed, `"your_turn"` to your turns; `limit: "once_each_turn"` to one activation per turn, `"once"` to one activation for as long as the object exists; `only_if` to when a condition holds. `zone` ("exile", "graveyard" or "hand") makes it function only while its card is in that zone ("activate only if this card is exiled"). `exhaust: true` makes it an exhaust ability: it can be activated only once (CR 702.177a). `power_up: true` makes it a power-up ability: activate only once, and if the permanent entered this turn its cost is reduced by the permanent's mana cost (CR 702.193). `boast: true`: activate only if this creature attacked this turn and only once each turn (CR 702.142a). |
|
|
96
96
|
| [`additional_cost`](docs/reference/abilities.md#additional_cost) | 601.2b, 601.2f, 601.2h, 118.8, 118.8b | As an additional cost to cast this spell, pay `cost` too (mana and/or chosen costs such as `sacrifice_permanent`). The spell can't be cast without it. `optional: true`: you may pay it (announced with the `choose_kicker` decision); the condition `{"cast_with": "additional_cost"}` then holds (the spell isn't kicked). |
|
|
97
97
|
| [`additional_land_plays`](docs/reference/abilities.md#additional_land_plays) | 305.2, 305.2a, 305.2b, 604.1 | Its controller may play an additional land on each of their turns. Each instance adds one land play (CR 305.2); lands put onto the battlefield by effects don't count. |
|
|
98
|
-
| [`additional_triggers`](docs/reference/abilities.md#additional_triggers) | 603.2d, 119.9 | While this permanent is on the battlefield, a triggered ability of a permanent its controller controls
|
|
98
|
+
| [`additional_triggers`](docs/reference/abilities.md#additional_triggers) | 603.2d, 119.9, 607.2d | While this permanent is on the battlefield, a triggered ability of a permanent its controller controls triggers an additional time if it triggers because of `cause` (you_gain_life: its controller gaining life) and/or its permanent matches `of` (a filter: "triggered abilities of Allies you control", {"creature": {"other": true, "subtypes": "chosen"}}). At least one of them. |
|
|
99
99
|
| [`beam_me_up`](docs/reference/abilities.md#beam_me_up) | 702.196a, 702.196b, 118.9, 601.2b, 601.2f, 601.2h | You may cast this instant or sorcery card from your graveyard for `cost` plus returning a creature you control to its owner's hand, instead of its mana cost. If you do, it's exiled whenever it would leave the stack. Offered as a cast option with `via: "beam:<ref>"`. |
|
|
100
100
|
| [`can_block_only`](docs/reference/abilities.md#can_block_only) | 509.1b, 509.1a | This creature can block only attacking creatures matching `filter` (checked as blockers are declared, with their current characteristics; controller-relative filter keys are seen from this creature's controller). |
|
|
101
101
|
| [`cant_be_blocked_by`](docs/reference/abilities.md#cant_be_blocked_by) | 509.1b, 509.1a | This creature can't be blocked by creatures matching `filter` (checked as blockers are declared, with their current characteristics). |
|
|
@@ -111,7 +111,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
111
111
|
| [`choose_number`](docs/reference/abilities.md#choose_number) | 614.12, 614.12a, 607.2 | As this permanent enters, its controller chooses a number from `min` to `max`; abilities of it that say "the chosen number" use it. |
|
|
112
112
|
| [`choose_option`](docs/reference/abilities.md#choose_option) | 614.12, 607.2f, 614.12b | As this permanent enters, its controller chooses one of the `options` (words with no rules meaning); a condition {"chosen": word} is true when that word was chosen. |
|
|
113
113
|
| [`class_level`](docs/reference/abilities.md#class_level) | 717.2a, 717.2b, 717.2d, 717.3, 602.5d | A class level bar: `cost` (a mana cost string or a list of costs): this permanent's level becomes `level`; activate only if its level is `level` - 1, as a sorcery. While its level is `level` or greater it has `keywords` and `abilities`. A permanent without a level is level 1. |
|
|
114
|
-
| [`cost_modifier`](docs/reference/abilities.md#cost_modifier) | 601.2f, 118.7a, 604.1, 601.2a | While on the battlefield: spells cast by `caster` (you, opponent or any; default you) whose card types match `spells` ({"any_of": [types], "not": [types]}, default all spells) cost `reduce` less or `increase` more generic mana. `from` / `not_from`: only spells cast from (not from) that zone (hand | graveyard | exile | library | outside). |
|
|
114
|
+
| [`cost_modifier`](docs/reference/abilities.md#cost_modifier) | 601.2f, 118.7a, 604.1, 601.2a | While on the battlefield: spells cast by `caster` (you, opponent or any; default you) whose card types match `spells` ({"any_of": [types], "not": [types]}, default all spells; `subtypes` and `colors` narrow it: "Dragon spells", "red spells") cost `reduce` less or `increase` more generic mana. `from` / `not_from`: only spells cast from (not from) that zone (hand | graveyard | exile | library | outside). |
|
|
115
115
|
| [`cost_reduction`](docs/reference/abilities.md#cost_reduction) | 601.2f, 118.7a, 702.41a | This spell costs `amount` generic mana less to cast, if the optional `if` condition holds when its total cost is determined (after targets are chosen). `amount` may be computed, e.g. {"count": {"each": "artifact", "controller": "you"}} for affinity for artifacts (CR 702.41a). It can't reduce colored mana or go below {0}. |
|
|
116
116
|
| [`crew`](docs/reference/abilities.md#crew) | 702.122a, 702.122b, 702.122e, 301.7, 301.7a, 301.7b, 208.3, 302.6 | Crew N: tap any number of other untapped creatures you control with total power N or more (chosen one at a time; `done` once the total is enough): this permanent becomes an artifact creature until end of turn. A Vehicle has its printed power and toughness only while it's a creature. |
|
|
117
117
|
| [`cycling`](docs/reference/abilities.md#cycling) | 702.29a, 702.29b, 702.29e, 702.29f, 113.6m, 602.2a | Cycling: pay `cost` and discard this card from your hand to draw a card. With `for` it is typecycling: instead search your library for a card matching `for`, reveal it, put it into your hand, then shuffle. |
|
|
@@ -147,13 +147,14 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
147
147
|
| [`kicker`](docs/reference/abilities.md#kicker) | 702.33a, 702.33d, 702.33g, 601.2b, 601.2f, 601.2h | Kicker: as you cast this spell you may also pay `cost` (mana and/or chosen costs such as `sacrifice_permanent`). The spell is then kicked: `{"kicked": true}` conditions hold and its `kicked_targets` are used. |
|
|
148
148
|
| [`look_at_top`](docs/reference/abilities.md#look_at_top) | 401.5, 604.1 | While this permanent is on the battlefield, its controller sees the top card of their library (the `library_top` of their view). |
|
|
149
149
|
| [`loyalty`](docs/reference/abilities.md#loyalty) | 606.3, 606.4, 606.5, 602.2b | A loyalty ability. Its cost adds (positive) or removes (negative) loyalty counters and is paid on activation. Sorcery speed, and only one loyalty ability per planeswalker per turn. |
|
|
150
|
-
| [`mana`](docs/reference/abilities.md#mana) | 605.1a, 605.3a, 605.3b, 106.1a, 106.4, 106.6, 607.2d, 602.5b | An activated mana ability: pay the cost, add the mana to your mana pool immediately. It does not use the stack and can be activated whenever you have priority. `produce`: the fixed mana (`amount` times). Or `color`: `amount` mana (default 1) of one color you choose as you activate it (`"any_one"`) or in any combination of colors (`"any"`); `colors` limits the choice. `"chosen"`: of the color chosen as this entered (choose_color). `spend_only` restricts how the mana can be spent. `only_if`: "Activate only if ...". |
|
|
150
|
+
| [`mana`](docs/reference/abilities.md#mana) | 605.1a, 605.3a, 605.3b, 106.1a, 106.4, 106.6, 607.2d, 602.5b | An activated mana ability: pay the cost, add the mana to your mana pool immediately. It does not use the stack and can be activated whenever you have priority. `produce`: the fixed mana (`amount` times). Or `color`: `amount` mana (default 1) of one color you choose as you activate it (`"any_one"`) or in any combination of colors (`"any"`); `colors` limits the choice. `"chosen"`: of the color chosen as this entered (choose_color). `spend_only` restricts how the mana can be spent. `only_if`: "Activate only if ...". `limit: "once_each_turn"`: "Activate only once each turn." |
|
|
151
151
|
| [`max_speed`](docs/reference/abilities.md#max_speed) | 702.178a, 702.178b, 702.179e, 113.6c | While your speed is 4 (max speed), this object has `keywords` and `abilities` (any kind: activated, triggered, static, mana; an ability with a graveyard cost works from your graveyard). |
|
|
152
152
|
| [`may_not_untap`](docs/reference/abilities.md#may_not_untap) | 502.3, 604.1 | Its controller may choose not to untap it during their untap step (decision `untap_choice`, asked only while it's tapped). |
|
|
153
153
|
| [`mayhem`](docs/reference/abilities.md#mayhem) | 702.187a, 702.187b, 702.187c, 118.9, 601.2b, 601.2f, 601.2h, 305.1 | Mayhem: as long as you discarded this card this turn, you may cast it from your graveyard by paying `cost` rather than its mana cost. Without `cost` (`"mayhem"`), you may play it from your graveyard (a land too) if you discarded it this turn. Cast option `via: "alt:<ref>"`. |
|
|
154
154
|
| [`mobilize`](docs/reference/abilities.md#mobilize) | 702.181a, 508.4 | Mobilize `amount`: whenever this creature attacks, create that many 1/1 red Warrior creature tokens tapped and attacking; sacrifice them at the beginning of the next end step. |
|
|
155
155
|
| [`play_from`](docs/reference/abilities.md#play_from) | 601.3, 113.6e, 113.6f, 305.1, 401.5, 122.1, 614.12, 400.11a, 400.11b, 108.3 | With `cards: "self"` (default): its owner may cast this card from `zone` (the ability functions there). With a card spec: while this permanent is on the battlefield, its controller may play their own matching cards from `zone`, or from any of `zones` ("outside": cards they own outside the game, the deck's `outside` list, CR 400.11a). `play`: "cast" (spells only, default) or "play" (lands too, using a land play). `once_each_turn`: once during each of your turns, one use shared by all its zones. `enters_with`: a permanent spell cast this way enters with these counters. Timing and costs are the usual ones. |
|
|
156
156
|
| [`player_rule`](docs/reference/abilities.md#player_rule) | 702.11c, 115.4, 508.1c, 402.2, 514.1, 615.1, 615.1a, 704.5a, 104.3b, 701.21a, 614.17b, 101.2, 601.3, 701.6a, 119.7, 602.5, 615.12, 702.16b, 702.16e, 702.16k, 604.1, 604.2, 611.3a | While this permanent is on the battlefield (and its `if` condition holds), `rule` applies to the players in `affects` (you | opponents | each; default you). Rules: hexproof, cant_attack, no_max_hand_size, prevent_all_damage, cant_lose_for_life, cant_sacrifice, cant_cast, cant_cast_except_from_hand, spells_cant_be_countered, abilities_cant_be_countered, cant_gain_life, cant_activate, damage_cant_be_prevented, combat_damage_cant_be_prevented, protection_from_opponents. `cant_sacrifice` takes a `filter` of the permanents that can't be sacrificed, `cant_activate` may take a `filter` of the sources whose abilities can't be activated (mana abilities still can), and `cant_cast` and `spells_cant_be_countered` may take a card spec of the `spells`. The damage rules apply to all damage whichever players they name. |
|
|
157
|
+
| [`plot`](docs/reference/abilities.md#plot) | 702.170a, 702.170b, 702.170d, 116.2k | Plot `cost`: during your main phase, while the stack is empty, you may pay `cost` and exile this card from your hand (special action `{type: "special_action"}`). It becomes plotted: on a later turn you may cast it from exile without paying its mana cost, during your main phase while the stack is empty (cast option `via: "plotted"`). |
|
|
157
158
|
| [`prevent_damage`](docs/reference/abilities.md#prevent_damage) | 615.1, 615.1a, 615.5, 615.6 | While this permanent is on the battlefield, all damage from sources in `by` to recipients in `to` (damage scopes as in damage_replacement, both optional; `combat`: combat | noncombat) is prevented. "To and by this creature" is two of them. `then`: effects right after it prevents damage ("prevent that damage and put that many +1/+1 counters on him"), reading {"triggering": "amount"} (the damage prevented), "object" (the source) and "player" (its controller). |
|
|
158
159
|
| [`protection_from`](docs/reference/abilities.md#protection_from) | 702.16a, 702.16b, 702.16c, 702.16d, 702.16e, 702.16f, 702.16g, 702.16h, 702.16i, 702.16j, 702.16k, 704.5m, 704.5n | Protection from the quality (a card spec, "everything", "each_opponent": from each of your opponents, or "its_colors"): damage from sources with the quality is prevented, and this permanent can't be enchanted or equipped by, blocked by or targeted by anything with the quality (Auras and Equipment already attached fall off as a state-based action). |
|
|
159
160
|
| [`saddle`](docs/reference/abilities.md#saddle) | 702.171a, 702.171b, 702.171c | Saddle N: tap any number of other untapped creatures you control with total power N or more (chosen one at a time; `done` once the total is enough): this permanent becomes saddled until end of turn. Activate only as a sorcery. |
|
|
@@ -177,7 +178,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
177
178
|
| Name | Rules | Description |
|
|
178
179
|
| --- | --- | --- |
|
|
179
180
|
| [`ability_triggers`](docs/reference/triggers.md#ability_triggers) | 603.2, 603.3b, 508.1, 707.10 | A triggered ability of the subject triggers. `cause: "attacks"` (required): its trigger event was the subject attacking. {"triggering": "ability"} is that triggered ability while it's on the stack. |
|
|
180
|
-
| [`activates_ability`](docs/reference/triggers.md#activates_ability) | 602.2, 605.1a, 603.2, 201.4, 702.177a, 702.142b | A player (`controller`: you (default) | opponent | any) activates an ability that isn't a mana ability. `source`: optional filter on the source's card; `name: "chosen"`: only a source with the name chosen as this permanent entered. `exhaust: true`: only an exhaust ability ("whenever you activate an exhaust ability", CR 702.177). `boast: true`: only a boast ability ("whenever a creature you control boasts", CR 702.142b). |
|
|
181
|
+
| [`activates_ability`](docs/reference/triggers.md#activates_ability) | 602.2, 605.1a, 603.2, 201.4, 702.177a, 702.142b, 606.1 | A player (`controller`: you (default) | opponent | any) activates an ability that isn't a mana ability. `source`: optional filter on the source's card; `name: "chosen"`: only a source with the name chosen as this permanent entered. `exhaust: true`: only an exhaust ability ("whenever you activate an exhaust ability", CR 702.177). `boast: true`: only a boast ability ("whenever a creature you control boasts", CR 702.142b). `loyalty: true`: only a loyalty ability (CR 606). |
|
|
181
182
|
| [`airbends`](docs/reference/triggers.md#airbends) | 701.65b | A player (`controller`: you (default) | opponent | any) airbends. |
|
|
182
183
|
| [`any_of`](docs/reference/triggers.md#any_of) | 603.2, 603.2c | Triggers when any of the listed trigger conditions is met. |
|
|
183
184
|
| [`attacks`](docs/reference/triggers.md#attacks) | 508.3a, 603.2 | The subject is declared as an attacker. `first_time_this_turn: true`: only the first time that creature attacks this turn (later combats of the turn don't trigger it). |
|
|
@@ -229,6 +230,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
229
230
|
| [`exert`](docs/reference/costs.md#exert) | 701.43a, 701.43b, 701.43c | Exert this permanent: it doesn't untap during your next untap step. |
|
|
230
231
|
| [`exile_from_graveyard`](docs/reference/costs.md#exile_from_graveyard) | 406.1, 601.2h, 602.2b, 118.3 | Exile `count` cards from your graveyard (default 1), never this card, chosen while casting or activating and exiled as the spell or ability becomes cast. `card` (a card spec) restricts which. |
|
|
231
232
|
| [`exile_from_hand`](docs/reference/costs.md#exile_from_hand) | 406.1, 601.2h, 602.2b, 118.3 | Exile `count` cards from your hand (default 1), chosen while casting or activating, exiled as the spell or ability becomes cast. `card` (a card spec) restricts which. |
|
|
233
|
+
| [`exile_self`](docs/reference/costs.md#exile_self) | 406.1, 602.2b, 118.3 | Exile the permanent the ability belongs to ("Exile this enchantment: ..."). |
|
|
232
234
|
| [`exile_self_from_graveyard`](docs/reference/costs.md#exile_self_from_graveyard) | 406.1, 113.6m, 602.2b, 118.3 | Exile this card from your graveyard. An ability with this cost is activated from your graveyard. |
|
|
233
235
|
| [`get_counters`](docs/reference/costs.md#get_counters) | 118.1, 122.1, 704.5c | You get `amount` counters of the kind `counter` (e.g. poison). It can always be paid. |
|
|
234
236
|
| [`mana`](docs/reference/costs.md#mana) | 601.2g, 601.2h, 602.2b | Pay mana as part of an activation. Paid during the activation by spending mana from your pool, tapping sources one at a time. |
|
|
@@ -236,7 +238,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
236
238
|
| [`pay_life`](docs/reference/costs.md#pay_life) | 119.4, 119.4b, 118.3b, 601.2b, 107.3a | Pay that much life (you lose it). Only possible while your life total is at least that much. `"X"` pays the X announced for the spell or ability (at most your life total); it may be a spell's additional cost. |
|
|
237
239
|
| [`remove_counters`](docs/reference/costs.md#remove_counters) | 602.2b, 601.2h, 118.3, 122.1 | Remove `count` counters (of kind `counter`, or any kind) from among permanents you control matching `filter` (default creature), one counter per choice. Removed as it becomes cast. |
|
|
238
240
|
| [`sacrifice`](docs/reference/costs.md#sacrifice) | 701.21a, 602.2b, 118.3 | Sacrifice the permanent the ability belongs to (it goes to its owner's graveyard). |
|
|
239
|
-
| [`sacrifice_permanent`](docs/reference/costs.md#sacrifice_permanent) | 701.21a, 601.2h, 602.2b, 118.3, 608.2h | Sacrifice `count` permanents you control matching `filter` (`other: true`: not the source). Chosen while casting or activating, sacrificed as it becomes cast; the sacrificed permanent's last known types and subtypes are remembered (condition `sacrificed`). |
|
|
241
|
+
| [`sacrifice_permanent`](docs/reference/costs.md#sacrifice_permanent) | 701.21a, 601.2h, 602.2b, 118.3, 608.2h | Sacrifice `count` permanents you control matching `filter` (`other: true`: not the source). Chosen while casting or activating, sacrificed as it becomes cast; the sacrificed permanent's last known types and subtypes are remembered (condition `sacrificed`), and its power, toughness and mana value (amount `sacrificed`). |
|
|
240
242
|
| [`tap`](docs/reference/costs.md#tap) | 107.5, 602.5a | {T} — tap the permanent the ability belongs to. Requires it to be untapped. |
|
|
241
243
|
| [`tap_another_creature`](docs/reference/costs.md#tap_another_creature) | 702.184a, 601.2h, 602.2b, 302.6 | Tap another untapped creature you control, chosen while activating. A creature that came under your control this turn can be tapped this way. |
|
|
242
244
|
| [`tap_permanents`](docs/reference/costs.md#tap_permanents) | 601.2h, 602.2b, 302.6, 118.3 | Tap `count` untapped permanents you control matching `filter` (default: creature), chosen while casting or activating; `other: true` excludes the source. They are tapped as they are chosen; cancelling untaps them. |
|
|
@@ -256,7 +258,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
256
258
|
| [`another_counter`](docs/reference/effects.md#another_counter) | 122.1, 122.6 | For each referenced permanent, the controller chooses a kind of counter already on it (asked only when there are several kinds) and puts one more counter of that kind on it. |
|
|
257
259
|
| [`assimilate`](docs/reference/effects.md#assimilate) | 701.72a, 701.72b, 701.72c, 607.2a, 205.1b, 613.1b, 613.1d, 614.12a | Assimilate each referenced permanent or permanent card: you gain control of it (or put it onto the battlefield under your control) with a +1/+1 counter, and it becomes a Borg artifact creature while it stays on the battlefield. `for`: only cards matching a card spec; `choose: true`: you choose one of them. |
|
|
258
260
|
| [`attach`](docs/reference/effects.md#attach) | 701.3a, 701.3b, 701.3c, 301.5c | Attach this Aura or Equipment (the ability's source), or the `attachment` (e.g. a token an earlier effect created, {"result": n}), to the referenced permanent. Nothing happens if it can't legally be attached to it, if it's already attached to it, or if the attachment has left the battlefield. |
|
|
259
|
-
| [`become`](docs/reference/effects.md#become) | 611.2a, 611.2b, 611.2c, 613.1d, 613.1e, 613.1f, 613.4b, 613.7b, 205.1a, 205.1b, 301.7b, 514.2 | Each referenced permanent becomes what the parameters say, for `duration` (end_of_turn, default; indefinite: as long as it stays on the battlefield; while_source_on_battlefield: for as long as this effect's source remains on the battlefield; while_you_control_source: for as long as you control it): it has the card `types`, `supertypes` and `subtypes` in addition to its other types (layer 4, "becomes an artifact creature"), its creature types are exactly `creature_types` (layer 4), its colors are `colors` (layer 5), with `loses_abilities: true` it loses all the abilities it had (layer 6; abilities granted later, keyword counters put on it later and this effect's own `keywords` and `abilities` stay, CR 613.7), it has the `keywords` and `abilities` (layer 6: triggered, activated, mana, play_from or additional_land_plays abilities) and its base power and toughness are `base_power_toughness` (layer 7b). A permanent that becomes a creature has its printed power and toughness (a Vehicle's), or 0/0. |
|
|
261
|
+
| [`become`](docs/reference/effects.md#become) | 611.2a, 611.2b, 611.2c, 613.1d, 613.1e, 613.1f, 613.4b, 613.7b, 205.1a, 205.1b, 301.7b, 514.2 | Each referenced permanent becomes what the parameters say, for `duration` (end_of_turn, default; until_your_next_turn: until your next turn begins; indefinite: as long as it stays on the battlefield; while_source_on_battlefield: for as long as this effect's source remains on the battlefield; while_you_control_source: for as long as you control it): it has the card `types`, `supertypes` and `subtypes` in addition to its other types (layer 4, "becomes an artifact creature"), its creature types are exactly `creature_types` (layer 4), its colors are `colors` (layer 5), with `loses_abilities: true` it loses all the abilities it had (layer 6; abilities granted later, keyword counters put on it later and this effect's own `keywords` and `abilities` stay, CR 613.7), it has the `keywords` and `abilities` (layer 6: triggered, activated, mana, play_from or additional_land_plays abilities) and its base power and toughness are `base_power_toughness` (layer 7b). A permanent that becomes a creature has its printed power and toughness (a Vehicle's), or 0/0. |
|
|
260
262
|
| [`become_copy`](docs/reference/effects.md#become_copy) | 707.2, 707.4, 613.2a, 613.7, 611.2a, 514.2 | Each referenced permanent becomes a copy of the (first) object `of` refers to, with the `except` modifications, until end of turn (default) or for as long as it stays on the battlefield (`duration: "permanent"`). It keeps its counters, status and other effects; nothing enters or leaves, so no enter or leave abilities trigger. Several copy effects apply in timestamp order. |
|
|
261
263
|
| [`become_saddled`](docs/reference/effects.md#become_saddled) | 702.171a, 702.171b | Each referenced permanent (default: this one) becomes saddled until end of turn (filters: `"saddled": true`). |
|
|
262
264
|
| [`behold`](docs/reference/effects.md#behold) | 701.4a, 701.4b, 118.3 | You behold an object matching the card spec `card`: reveal such a card from your hand or choose such a permanent you control. Under `may`, "yes" is offered only when there is one. |
|
|
@@ -265,7 +267,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
265
267
|
| [`cast`](docs/reference/effects.md#cast) | 608.2g, 707.12, 707.12a, 601.2a, 601.2f | The controller may cast referenced cards (or card copies) now, while this resolves, paying their costs; timing restrictions don't apply. `to`, `for`, `not_types`, `max_mana_value`, `count`, `exile_instead` and `any_mana_type` work as for `cast_free`. |
|
|
266
268
|
| [`cast_free`](docs/reference/effects.md#cast_free) | 608.2g, 118.9, 601.2a, 107.3b, 118.6a, 305.2a, 305.3, 406.3a | The controller may cast referenced cards without paying their mana costs while this resolves. `to` names the cards ({"result": n}), or a player for the cards in their hand (default: your hand). Only cards matching `for`/`not_types` with mana value up to `max_mana_value` (optional amount) that could be cast now (legal targets). `count`: 1 (default) or "any" (any number, one at a time). X is 0 (CR 107.3b). `play: true` ("you may play"): a land among them may be played, on your turn with a land play left (`{type: "play_land"}`). A face-down card is judged face up. |
|
|
267
269
|
| [`choose_card_type`](docs/reference/effects.md#choose_card_type) | 205.2a, 607.2d, 608.2c | The player (`to`, default you) chooses a card type; later effects of this spell or ability read it with "types": "chosen". |
|
|
268
|
-
| [`choose_cards`](docs/reference/effects.md#choose_cards) | 701.20a, 701.20e, 400.7j, 608.2c, 607.2a, 118.12, 701.9b | You choose `count` (default 1; "any": any number) cards matching `for` from `from`: a selector (e.g. {"result": 0}, the cards an earlier effect milled) or a player's zone, {"hand": selector} / {"graveyard": selector}. `optional`: you may choose fewer. Then they are put into `put` (`tapped` onto the battlefield, under your control; exiled cards `link`ed to the source). `look`: you look at the whole zone first; `reveal`: "chosen" reveals what you chose, "all" the whole set. `then` runs if a card was chosen, `otherwise` if none was ("if you can't"). `random: true`: the cards are picked at random (the game's random number generator) instead of chosen. |
|
|
270
|
+
| [`choose_cards`](docs/reference/effects.md#choose_cards) | 701.20a, 701.20e, 400.7j, 608.2c, 607.2a, 118.12, 701.9a, 701.9b | You choose `count` (default 1; "any": any number) cards matching `for` from `from`: a selector (e.g. {"result": 0}, the cards an earlier effect milled) or a player's zone, {"hand": selector} / {"graveyard": selector}. `optional`: you may choose fewer. Then they are put into `put` (`discard`: from a hand, its owner discards them; `tapped` onto the battlefield, under your control; exiled cards `link`ed to the source). `look`: you look at the whole zone first; `reveal`: "chosen" reveals what you chose, "all" the whole set. `then` runs if a card was chosen, `otherwise` if none was ("if you can't"). `random: true`: the cards are picked at random (the game's random number generator) instead of chosen. |
|
|
269
271
|
| [`choose_color`](docs/reference/effects.md#choose_color) | 105.4, 607.2d, 608.2c | The player (`to`, default you) chooses a color; later effects of this spell or ability read it with "colors": "chosen". |
|
|
270
272
|
| [`choose_creature_type`](docs/reference/effects.md#choose_creature_type) | 205.3m, 607.2d, 608.2c | The player (`to`, default you) chooses a creature type; later effects of this spell or ability read it with "subtypes": "chosen". |
|
|
271
273
|
| [`choose_new_targets`](docs/reference/effects.md#choose_new_targets) | 115.7, 115.7d, 115.7e | You may choose new targets for each spell or ability on the stack `of` refers to (e.g. {"triggering": "object"}: "that spell"): for each target, keep it or pick another legal target for that spell. |
|
|
@@ -307,7 +309,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
307
309
|
| [`flip_coins`](docs/reference/effects.md#flip_coins) | 705.1, 705.2, 705.3, 608.2c | You flip `amount` coins (default 1), each coming up heads or tails at random (the game's random number generator). `count`: "wins" (default; you call each flip and win it if the call matches) or "heads" (no one wins or loses). How many were counted is this effect's amount: {"this_way": n} in later effects and conditions. |
|
|
308
310
|
| [`gain_control`](docs/reference/effects.md#gain_control) | 613.1b, 108.4, 506.4, 302.6, 514.2, 611.2b | The player referenced by `gains` (default you) gains control of each referenced permanent: indefinitely (`duration: "permanent"`, default), until end of turn, or for as long as this effect's source remains on the battlefield / tapped / under your control (it does nothing if that is already over). A permanent that changes control leaves combat and is newly under its controller's control (it can't attack or {T} without haste). |
|
|
309
311
|
| [`gain_life`](docs/reference/effects.md#gain_life) | 119.3 | Each referenced player gains `amount` life (default: you). |
|
|
310
|
-
| [`grant`](docs/reference/effects.md#grant) | 611.2a, 611.2c, 613.1f, 514.2 | Each referenced permanent (or spell on the stack) gains the `keywords` until end of turn. |
|
|
312
|
+
| [`grant`](docs/reference/effects.md#grant) | 611.2a, 611.2c, 613.1f, 514.2, 500.1 | Each referenced permanent (or spell on the stack) gains the `keywords` until end of turn (`duration: "until_your_next_turn"`: until its controller's next turn begins). |
|
|
311
313
|
| [`grant_ability`](docs/reference/effects.md#grant_ability) | 113.6b, 611.2a, 613.1f | Each referenced object (a permanent, or a card in any zone, e.g. an exiled card) gains `ability` (any ability entry) for as long as it stays in its zone (default) or until end of turn. `for` (a card spec) keeps only matching objects ("that nonland card"). An activated ability with `zone` works from that zone ("activate only if this card is exiled"). |
|
|
312
314
|
| [`look_at_hand`](docs/reference/effects.md#look_at_hand) | 701.20e | You look at each referenced player's hand (other players don't see the cards). |
|
|
313
315
|
| [`lose_game`](docs/reference/effects.md#lose_game) | 104.3e, 104.4a | Each referenced player (default you) loses the game. |
|
|
@@ -319,6 +321,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
319
321
|
| [`phase_out`](docs/reference/effects.md#phase_out) | 702.26a, 702.26b, 702.26d, 702.26g, 702.26h, 502.1, 506.4 | Each referenced permanent phases out, with the Auras and Equipment attached to it (indirectly). It phases in during the untap step of the player who controlled it as it phased out. Phasing isn't a zone change: no enters or leaves triggers. |
|
|
320
322
|
| [`play_permission`](docs/reference/effects.md#play_permission) | 611.2a, 601.3, 305.1, 400.7, 514.2, 601.2f, 108.3, 406.3b, 609.4b | A player may play (`play: "play"`, default) or cast (`"cast"`) each referenced exiled card matching `for`/`not_types`, paying its costs and following timing rules, for `duration`: end_of_turn (default), end_of_your_next_turn or while_exiled. With `choose: "one_per_owner"` only one chosen card per owner. `to_player`: who may play it, "controller" (default, the effect's controller), "owner" (the card's owner) or a player selector (a face-down card: only someone who may look at it). `cost_increase`: spells cast this way cost that much generic mana more. `any_mana_type: true`: mana of any type can be spent to cast those spells. |
|
|
321
323
|
| [`player_rule`](docs/reference/effects.md#player_rule) | 702.11c, 115.4, 508.1c, 402.2, 514.1, 615.1, 615.1a, 704.5a, 104.3b, 701.21a, 614.17b, 101.2, 601.3, 701.6a, 119.7, 602.5, 615.12, 702.16b, 702.16e, 702.16k, 611.2a, 514.2 | Each referenced player (default you) gets `rule` for the `duration`: end_of_turn (default) or until_your_next_turn (until the controller's next turn begins). Rules: hexproof, cant_attack, no_max_hand_size, prevent_all_damage, cant_lose_for_life, cant_cast, cant_cast_except_from_hand, spells_cant_be_countered, abilities_cant_be_countered, cant_gain_life, cant_activate, damage_cant_be_prevented, combat_damage_cant_be_prevented, protection_from_opponents. |
|
|
324
|
+
| [`plot`](docs/reference/effects.md#plot) | 702.170c, 702.170d, 406.1 | Each referenced card or spell is exiled (if it isn't already) and becomes plotted: its owner may cast it from exile without paying its mana cost during their main phase while the stack is empty, on any later turn (cast option `via: "plotted"`). |
|
|
322
325
|
| [`prepare`](docs/reference/effects.md#prepare) | 723.3a, 723.3c | Each referenced permanent (default: this one) becomes prepared, if it has a prepare spell and isn't prepared already: its controller creates a copy of the prepare spell in exile and may cast that copy while the permanent stays prepared. Casting it unprepares the permanent. |
|
|
323
326
|
| [`prevent_damage`](docs/reference/effects.md#prevent_damage) | 615.1, 615.3, 615.5, 615.7, 615.8, 609.7a, 611.2a, 611.2b, 611.2c | For the `duration` (end_of_turn by default, until_your_next_turn, or while_source_on_battlefield: for as long as this effect's source remains on the battlefield), damage that would be dealt to the referenced players and permanents (`to`, fixed as it resolves) or to those matching `to_each` as the damage is dealt (a damage scope seen from the controller, e.g. {"each": "creature", "controller": "you"}), and/or by the referenced sources (`by`; "chosen_source": a source the controller chooses as it resolves) is prevented (`combat`: combat | noncombat only). With `next`, it is a shield that prevents only the next that much damage; with `next_time: true` it prevents only the next damage event it applies to. `then`: effects right after it prevents damage, reading {"triggering": "amount"} (the damage prevented), "object" (the source) and "player" (its controller). |
|
|
324
327
|
| [`proliferate`](docs/reference/effects.md#proliferate) | 701.34a, 122.1, 122.6 | You choose any number of permanents and/or players that have counters (one at a time, then done); each gets one more counter of each kind already on it. `amount` (default 1): how many times to proliferate. |
|
|
@@ -337,7 +340,7 @@ Rules version: Comprehensive Rules effective 2026-11-06.
|
|
|
337
340
|
| [`sacrifice`](docs/reference/effects.md#sacrifice) | 701.21a | The controller sacrifices each referenced permanent they control (it goes to its owner's graveyard; it isn't destroyed, so indestructible doesn't stop it). |
|
|
338
341
|
| [`sacrifice_choice`](docs/reference/effects.md#sacrifice_choice) | 701.21a, 101.4, 118.3 | Each referenced player (default: you) sacrifices `count` (default 1; "any": any number) permanents they control matching `filter`, chosen by them in turn order starting with the active player; all are sacrificed at once. The `filter`'s `controller` and `other` restrictions are relative to the effect's controller and source. |
|
|
339
342
|
| [`scry`](docs/reference/effects.md#scry) | 701.22a | Look at the top `amount` cards of your library; put any number on the bottom and the rest on top in any order. |
|
|
340
|
-
| [`search_library`](docs/reference/effects.md#search_library) | 701.23a, 701.23b, 701.23d, 701.23e, 701.20a, 701.24a, 701.24b, 118.12, 110.2a | Search your library for up to `count` cards matching `for`, then put them into your hand (or onto the battlefield, tapped if `tapped`, with `counters
|
|
343
|
+
| [`search_library`](docs/reference/effects.md#search_library) | 701.23a, 701.23b, 701.23d, 701.23e, 701.20a, 701.24a, 701.24b, 118.12, 110.2a | Search your library for up to `count` cards matching `for`, then put them into your hand (or onto the battlefield, tapped if `tapped`, with `counters`; or into your graveyard) and shuffle. `put: library_top`: shuffle, then put the found card (one) on top. Computed bounds in `for` are worked out as the effect resolves. With a stated quality you may find fewer (or none); a search for just "a card" must find one if it can. `reveal` shows the found cards to every player. `searcher` names another player who searches their own library (e.g. {"controller_of": {"target": 0}}); `may: true` lets the searcher decline (then nothing is shuffled). `different_names: true`: the cards found must all have different names ("basic land cards with different names"). |
|
|
341
344
|
| [`set_base_power_toughness`](docs/reference/effects.md#set_base_power_toughness) | 613.4b, 611.2a, 611.2b, 611.2c | Each referenced creature's base power and toughness become `power`/`toughness` (layer 7b; counters and pumps still apply), until end of turn or, with `duration: "indefinite"`, for as long as it stays on the battlefield. |
|
|
342
345
|
| [`set_creature_types`](docs/reference/effects.md#set_creature_types) | 205.1a, 613.1d, 611.2c, 514.2 | Until end of turn, each referenced creature's creature types are exactly `types` (its other subtypes, such as artifact types, stay). The affected set is locked in. |
|
|
343
346
|
| [`set_life`](docs/reference/effects.md#set_life) | 119.5, 119.7 | Each referenced player's life total becomes `amount` (default: you): they gain or lose the difference (so "can't gain life" and life-gain triggers apply). |
|
data/docs/MECHANICS_COVERAGE.md
CHANGED
|
@@ -666,5 +666,5 @@ replacement/prevention (614–616), "dies" and leaves-the-battlefield triggers
|
|
|
666
666
|
|
|
667
667
|
- **613 layers.** The layer pass runs in three stages over the whole battlefield (layers 1–4, 5–6, 7), so a later layer sees earlier results: 7a characteristic-defining power/toughness (604.3, card data `"power": <amount>`), 7b setting effects (`set_base_power_toughness`, 613.4b), 7c counters, static bonuses (fixed or computed) and pumps. Layer 4 sets creature types (205.1a: `creature_types` statics, `set_creature_types` until end of turn). Layer 6 adds keywords and granted triggered/mana abilities (613.1f; refs `granted:<card>:<ref>`). Statics may be conditional (`if`, 604.2) and `affects: "self"`. 613.8 is enforced at build time: statics and characteristic-defining amounts can't read power, toughness or combat status.
|
|
668
668
|
- **"This turn" history.** Per-player turn and game logs (spells cast, permanents that entered/died/returned to hand, life gained/lost, dilemmas faced) and per-object "attacked" and "resolved N times" counts, recorded from events in one hook (a cancelled cast never counts, 601.2i).
|
|
669
|
-
- **608.2h last known information.** A source that leaves the battlefield is remembered by its abilities (power, toughness, counters, controller); "its controller" of a destroyed target uses the controller it last had.
|
|
669
|
+
- **608.2h last known information.** A source that leaves the battlefield is remembered by its abilities (power, toughness, mana value, counters, controller); "its controller" of a destroyed target uses the controller it last had, and its power, toughness and mana value are read as it last existed, as are those of a permanent an earlier effect of the same list sacrificed (`{"result": n}`, a token included) and of one sacrificed to pay the cost (`{"sacrificed": ...}`, 601.2h); a reflexive "when you do" trigger reads what its parent moved the same way (603.12).
|
|
670
670
|
- **202.2 / 204 colors.** Cards have colors from their mana cost or an explicit `colors` list (color indicator, token colors, 111.3); filters take `colors`.
|
|
@@ -154,7 +154,7 @@ takes `spend_only` too ("Add {C}{C}. Spend this mana only to cast spells.").
|
|
|
154
154
|
```
|
|
155
155
|
|
|
156
156
|
- `cost`: costs before the colon. `"tap"` is `{T}`; `{ "mana": "{1}{R}" }` is a mana
|
|
157
|
-
cost; `"sacrifice"` sacrifices this permanent; `{ "sacrifice_permanent": { "filter": "creature", "other": true } }`,
|
|
157
|
+
cost; `"sacrifice"` sacrifices this permanent and `"exile_self"` exiles it; `{ "sacrifice_permanent": { "filter": "creature", "other": true } }`,
|
|
158
158
|
`{ "tap_permanents": { "count": 3, "filter": ... } }` and `{ "remove_counters": { "count": 3 } }` are chosen while
|
|
159
159
|
activating; `"exile_self_from_graveyard"` / `"bottom_self_from_graveyard"` make it a graveyard ability. `{Q}` is
|
|
160
160
|
not supported yet. More costs (each also usable in a spell's `additional_cost`):
|
|
@@ -219,8 +219,11 @@ is fixed) and then chooses that many different objects; `{ "target": n }` then m
|
|
|
219
219
|
"effects": [{ "deal_damage": { "amount": 3, "to": { "target": 0 } } }] } }
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
-
`cost` is the signed number: `+1` → `1`, `−2` → `-2`, `0` → `0
|
|
223
|
-
|
|
222
|
+
`cost` is the signed number: `+1` → `1`, `−2` → `-2`, `0` → `0`, or `"-X"` (X is announced as
|
|
223
|
+
it's activated, at most the planeswalker's loyalty; effects read it as `"x"`). Sorcery timing and
|
|
224
|
+
once-per-turn are automatic. A static grants one like any other ability: "Planeswalkers you control
|
|
225
|
+
have '[−2]: …'" is `{ "static": { "affects": { "each": "planeswalker", "controller": "you" },
|
|
226
|
+
"abilities": [{ "loyalty": { "cost": -2, "effects": [ … ] } }] } }`.
|
|
224
227
|
|
|
225
228
|
### 4.4 Target filters
|
|
226
229
|
|
|
@@ -297,6 +300,7 @@ is a flicker ("exile …, then return it to the battlefield under its owner's co
|
|
|
297
300
|
| one of your creatures is targeted by an opponent's spell or ability | `{ "becomes_target": { "subject": { "each": "creature", "controller": "you" }, "by": "opponent" } }` |
|
|
298
301
|
| "Whenever a card leaves your graveyard" / "one or more cards leave" | `{ "leaves_graveyard": {} }` / `{ "leaves_graveyard": { "batched": true } }` |
|
|
299
302
|
| "Whenever an opponent activates an ability" (not mana abilities) | `{ "activates_ability": { "controller": "opponent" } }` |
|
|
303
|
+
| "Whenever an opponent activates a loyalty ability" | `{ "activates_ability": { "controller": "opponent", "loyalty": true } }` |
|
|
300
304
|
| "When you cast this spell" | `{ "cast": { "self": true } }` |
|
|
301
305
|
| you cast a spell that is a creature or a Spacecraft | `{ "cast": { "spell": { "one_of": [{ "spell": { "any_of": ["creature"] } }, { "spell": { "subtypes": ["spacecraft"] } }] } } }` |
|
|
302
306
|
| a number chosen as it enters (0 to 10) / spells whose mana value is that number | ability `{ "choose_number": { "min": 0, "max": 10 } }` / `"cast": { "mana_value": "chosen" }` |
|
|
@@ -311,6 +315,7 @@ is a flicker ("exile …, then return it to the battlefield under its owner's co
|
|
|
311
315
|
| optional A; if it was done, a reflexive trigger B with its own target | `{ "may": { "effects": [A], "then": [{ "reflexive_trigger": { "targets": [...], "effects": [B] } }] } }` |
|
|
312
316
|
| a targeted opponent decides whether A happens; B if not | `{ "may": { "chooser": { "target": 0 }, "effects": [A], "otherwise": [B] } }` |
|
|
313
317
|
| your life gain makes your permanents' triggered abilities trigger one extra time | `{ "additional_triggers": { "cause": "you_gain_life" } }` |
|
|
318
|
+
| "If a triggered ability of an Ally you control triggers, it triggers an additional time" | `{ "additional_triggers": { "of": { "creature": { "subtypes": ["ally"] } } } }` (`"other": true`, `"subtypes": "chosen"` work in the filter; combine with `cause`) |
|
|
314
319
|
| tapped unless its controller has two other lands / a trigger only if it came in untapped | `{ "enters_tapped_unless": { "condition": { "controls": { "each": "land", "controller": "you" }, "at_least": 2 } } }` / `{ "enters": { "untapped": true } }` |
|
|
315
320
|
| returned to the battlefield carrying a +1/+1 counter | `"counters": { "+1/+1": 1 }` on `return_to_battlefield` |
|
|
316
321
|
|
|
@@ -350,6 +355,7 @@ See `docs/reference/effects.md` for the generated list. Currently:
|
|
|
350
355
|
| `deal_damage` | "deals N damage to …" | `{ "deal_damage": { "amount": N, "to": … } }` |
|
|
351
356
|
| `pump` | "gets +X/+Y until end of turn" | `{ "pump": { "power": X, "toughness": Y, "to": … } }` |
|
|
352
357
|
| `pump` | "get -1/-0 until your next turn" | `{ "pump": { "power": -1, "toughness": 0, "duration": "until_your_next_turn", "to": … } }` (ends as your next turn begins, CR 611.2a) |
|
|
358
|
+
| `grant`, `become` | "gain flying until your next turn", "until your next turn, it becomes a land" | `"duration": "until_your_next_turn"` on `grant` or `become` |
|
|
353
359
|
| `add_counters` | "put N +1/+1 counters on …" | `{ "add_counters": { "counter": "+1/+1", "amount": N, "to": … } }` (any counter name: `+1/+1`, `stun`, `shield`, `oil`, a keyword; see `docs/reference/counters.md`) |
|
|
354
360
|
| `gain_life` | "you gain N life" | `{ "gain_life": { "amount": N } }` (`to` defaults to `"you"`) |
|
|
355
361
|
| `lose_life` | "each opponent loses N life" | `{ "lose_life": { "amount": N, "to": "each_opponent" } }` |
|
|
@@ -371,6 +377,7 @@ See `docs/reference/effects.md` for the generated list. Currently:
|
|
|
371
377
|
| "Affinity for artifacts" | `{ "cost_reduction": { "amount": { "count": { "each": "artifact", "controller": "you" } } } }` |
|
|
372
378
|
| "Noncreature spells you cast cost {1} less to cast." | `{ "cost_modifier": { "spells": { "not": ["creature"] }, "reduce": 1 } }` |
|
|
373
379
|
| "Spells your opponents cast cost {1} more to cast." | `{ "cost_modifier": { "caster": "opponent", "increase": 1 } }` |
|
|
380
|
+
| "Dragon spells you cast cost {1} less" / "Red spells you cast cost {1} less" | `{ "cost_modifier": { "spells": { "subtypes": ["dragon"] }, "reduce": 1 } }` / `"spells": { "colors": ["R"] }` (combine with `any_of` / `not`) |
|
|
374
381
|
| "This ability costs {1} less to activate for each land you control." | `"cost_reduction": { "amount": {...} }` inside the `activated` ability |
|
|
375
382
|
|
|
376
383
|
An activated ability without targets that adds mana is a *mana ability* (CR 605.1a):
|
|
@@ -579,6 +586,11 @@ The full lists are in `lib/enjine/mechanics/values.rb` (`Amount`, `Condition`).
|
|
|
579
586
|
| "the number of creature types among …" | `{ "distinct_types": <selector> }` |
|
|
580
587
|
| "the number of counters on it" | `{ "counters": { "of": "self", "kind": "quest" } }` (no `kind`: every counter) |
|
|
581
588
|
| "cards in your graveyard", "greatest power among …" | `{ "graveyard_size": "you" }`, `{ "greatest_power": <selector> }` |
|
|
589
|
+
| "cards in your library", "half their library, rounded up" | `{ "library_size": "you" }`, `{ "divide": [{ "plus": [{ "library_size": <player> }, 1] }, 2] }` |
|
|
590
|
+
| "the greatest mana value among …" | `{ "greatest_mana_value": <selector> }` (0 for none) |
|
|
591
|
+
| "its mana value" / "its power" of a target destroyed earlier in the same effects; "the sacrificed creature's power" after a `sacrifice_choice` | `{ "mana_value": { "target": 0 } }`, `{ "power": { "result": n } }`: read as it last existed on the battlefield (CR 608.2h) |
|
|
592
|
+
| "the sacrificed artifact's mana value" when the sacrifice is a cost | `{ "sacrificed": "mana_value" }` (also `"power"`, `"toughness"`; CR 601.2h) |
|
|
593
|
+
| delirium: "four or more card types among cards in your graveyard" | `{ "amount": { "card_types": { "each": { "graveyard_card": {} }, "controller": "you" } }, "at_least": 4 }` |
|
|
582
594
|
| "life you gained / that player lost this turn" | `{ "life_gained_this_turn": "you" }`, `{ "life_lost_this_turn": "each_opponent" }` |
|
|
583
595
|
| an amount an earlier effect changed (life it made a player lose) | `{ "this_way": n }` (effect n of the same list) |
|
|
584
596
|
| N or more cards drawn by an earlier effect; "if you do" after a mandatory effect | `{ "amount": { "count": { "result": n } }, "at_least": 3 }` |
|
|
@@ -619,6 +631,7 @@ Generic shapes (N, [quality] and [zone] stand for whatever the card says):
|
|
|
619
631
|
| exile the top N; the permanent cards exiled this way enter the battlefield | `exile_top`, then `{ "return_to_battlefield": { "to": { "result": 0 }, "under": "you" } }` |
|
|
620
632
|
| mill N; you may put a [quality] card from among them into your hand | `mill`, then `{ "choose_cards": { "from": { "result": 0 }, "for": spec, "optional": true, "put": "hand" } }` |
|
|
621
633
|
| return a [quality] card from your graveyard to your hand; if you can't, [effect] | `{ "choose_cards": { "from": { "graveyard": "you" }, "for": spec, "put": "hand", "otherwise": [ … ] } }` |
|
|
634
|
+
| target opponent reveals their hand; you choose a [quality] card from it; that player discards that card | `{ "choose_cards": { "from": { "hand": { "target": 0 } }, "for": spec, "reveal": "all", "put": "discard" } }` (a discard: discard triggers see it) |
|
|
622
635
|
| look at a player's hand; you may choose a [quality] card; if you do, [effect] | `{ "choose_cards": { "from": { "hand": { "target": 0 } }, "look": true, "for": spec, "optional": true, "put": "exile", "then": [ … ] } }` |
|
|
623
636
|
| each player sacrifices a [quality] permanent of their choice | `{ "sacrifice_choice": { "filter": filter, "to": { "each": "player" } } }` (`"count": "any"`: any number) |
|
|
624
637
|
| exile a target card in a graveyard; return a target card from your graveyard to your hand | `exile` / `return_to_hand` with a `graveyard_card` target |
|
|
@@ -1186,6 +1199,7 @@ but cards already revealed for a behold or permanents tapped for a cost stay so.
|
|
|
1186
1199
|
| "costs {X} less to cast, where X is the greatest toughness among creatures you control" | `{ "cost_reduction": { "amount": { "greatest_toughness": { "each": "creature", "controller": "you" } } } }` |
|
|
1187
1200
|
| "Spend this mana only to cast a spell from anywhere other than your hand" / "only to cast spells from exile" | `"spend_only": { "not_from": "hand" }` / `{ "from": "exile" }` (also with `spells`) |
|
|
1188
1201
|
| "{T}: Add {G}{G}. Activate only if there is an Elf card in your graveyard." (CR 602.5b) | `{ "mana": { "cost": ["tap"], "produce": "{G}{G}", "only_if": condition } }` |
|
|
1202
|
+
| "{1}: Add {B}, {G}, or {W}. Activate only once each turn." (CR 602.5b) | `{ "mana": { "cost": [{ "mana": "{1}" }], "color": "any_one", "colors": ["W", "B", "G"], "limit": "once_each_turn" } }` |
|
|
1189
1203
|
| "If that spell would be put into a graveyard, exile it instead" (CR 614.1a) | `"exile_instead": true` on `cast_free`, `cast` or `play_permission`; a card spec instead of `true` limits it ("if an instant or sorcery spell cast this way …": `{ "any_of": [{ "types": ["instant"] }, { "types": ["sorcery"] }] }`) |
|
|
1190
1204
|
| "you may cast it, and mana of any type can be spent to cast that spell" (while resolving) | `{ "cast": { "to": { "target": 0 }, "any_mana_type": true } }` |
|
|
1191
1205
|
|
|
@@ -1294,6 +1308,9 @@ grants its abilities.
|
|
|
1294
1308
|
| "you may copy it. If you do, those spells gain wither" | `copy_spell` with `"except": { "keywords": ["wither"] }`, then `{ "grant": { "keywords": ["wither"], "to": { "triggering": "object" } } }` (a spell on the stack can gain keywords) |
|
|
1295
1309
|
| "Instant and sorcery spells you cast from your hand have cascade" | ability `{ "spell_keywords": { "spells": { "spell": { "any_of": ["instant", "sorcery"] } }, "from": "hand", "keywords": ["cascade"] } }` |
|
|
1296
1310
|
| "search your library for up to X basic land cards with different names" | `{ "search_library": { "for": { "supertypes": ["basic"], "types": ["land"] }, "count": "x", "different_names": true } }` |
|
|
1311
|
+
| "search your library for a creature card, put it into your graveyard, then shuffle" | `{ "search_library": { "for": { "types": ["creature"] }, "put": "graveyard" } }` |
|
|
1312
|
+
| "search your library for a card, then shuffle and put that card on top" | `{ "search_library": { "put": "library_top" } }` (one card; add `"reveal": true` if it's revealed) |
|
|
1313
|
+
| "an artifact card with mana value equal to 1 plus the sacrificed artifact's mana value" | `"for": { "types": ["artifact"], "mana_value": { "equal": { "plus": [{ "sacrificed": "mana_value" }, 1] } } }` |
|
|
1297
1314
|
| "The first time you flip one or more coins each turn, those coins come up heads and you win those flips" (CR 705.3) | ability `"first_flips_win"` |
|
|
1298
1315
|
| "Roll a d20" / "roll two six-sided dice" (CR 706) | `{ "roll_dice": { "sides": 20 } }` / `{ "roll_dice": { "amount": 2 } }`; the total is `{ "this_way": n }` (a results table is effects with an `if` on it) |
|
|
1299
1316
|
|
|
@@ -1312,6 +1329,8 @@ grants its abilities.
|
|
|
1312
1329
|
| --- | --- |
|
|
1313
1330
|
| "Paradigm" (CR 702.192a) | `"keywords": ["paradigm"]` on an instant or sorcery: as it finishes resolving it's exiled; the first time a spell you control with its name resolves this game, at the beginning of each of your precombat main phases you create a copy of the card in exile and may cast it without paying its mana cost (an `effect_choice` of `{type: "cast"}` or `"done"`) |
|
|
1314
1331
|
| "Foretell {2}{R}" (CR 702.143a) | ability `{ "foretell": { "cost": "{2}{R}" } }`: during your turn the priority option `{type: "special_action", object: id, ability: ref}` pays {2} and exiles it face down; on a later turn it's cast from exile with `via: "alt:<ref>"`; condition `{ "cast_with": "foretell" }` |
|
|
1332
|
+
| "Plot {1}{R}" (CR 702.170a) | ability `{ "plot": { "cost": "{1}{R}" } }`: in your main phase with an empty stack the priority option `{type: "special_action", object: id, ability: ref}` pays the cost and exiles it face up; on a later turn it's cast from exile without paying its mana cost with `via: "plotted"`, at sorcery timing even for an instant |
|
|
1333
|
+
| "Exile target spell. It becomes plotted." / "it becomes plotted" for an exiled card (CR 702.170c) | effect `{ "plot": { "to": { "target": 0 } } }` (or `{ "result": n }` for a card an earlier effect exiled) |
|
|
1315
1334
|
| "Suspend 3—{2}{W}" (CR 702.62a) | ability `{ "suspend": { "amount": 3, "cost": "{2}{W}" } }`: the special action exiles it with three time counters whenever you could begin to cast it |
|
|
1316
1335
|
| "exile it with four time counters on it. If it doesn't have suspend, it gains suspend" | effect `{ "suspend": { "to": …, "amount": 4 } }` (a spell, a card or a permanent); a card that has suspend from the start is `"keywords": ["suspend"]` |
|
|
1317
1336
|
| suspended cards (CR 702.62b) | automatic: at the beginning of its owner's upkeep a time counter is removed; when the last is removed they may play it without paying its mana cost (`effect_choice` `{type: "cast"}` / `{type: "play_land"}`), and a creature spell cast this way has haste while they control it |
|
|
@@ -1419,7 +1438,7 @@ bundle exec exe/enjine --validate cards.json
|
|
|
1419
1438
|
`cards.json` is a JSON array of card blocks (or a single block). The report:
|
|
1420
1439
|
|
|
1421
1440
|
```json
|
|
1422
|
-
{ "rules_version": "2026-11-06", "engine_version": "0.
|
|
1441
|
+
{ "rules_version": "2026-11-06", "engine_version": "0.2.0",
|
|
1423
1442
|
"valid": [ { "index": 0, "id": "lightning_bolt", "name": "Lightning Bolt", "card": { ...canonical... } } ],
|
|
1424
1443
|
"invalid": [ { "index": 1, "name": "Gale Drifter", "errors": ["keywords[0]: unknown keyword \"flyng\" ..."] } ] }
|
|
1425
1444
|
```
|