enjine 0.1.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.
Files changed (269) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +28 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +201 -0
  5. data/SUPPORTED.md +387 -0
  6. data/docs/ARCHITECTURE.md +141 -0
  7. data/docs/DESIGN.md +139 -0
  8. data/docs/MECHANICS_COVERAGE.md +670 -0
  9. data/docs/guides/adding-a-mechanic.md +60 -0
  10. data/docs/guides/api.md +614 -0
  11. data/docs/guides/card-data-format.md +1472 -0
  12. data/docs/guides/deck-builder.md +157 -0
  13. data/docs/plans/standard.md +371 -0
  14. data/docs/reference/abilities.md +1680 -0
  15. data/docs/reference/costs.md +339 -0
  16. data/docs/reference/counters.md +121 -0
  17. data/docs/reference/decisions.md +102 -0
  18. data/docs/reference/effects.md +2340 -0
  19. data/docs/reference/filters.md +172 -0
  20. data/docs/reference/keywords.md +647 -0
  21. data/docs/reference/subtypes.md +169 -0
  22. data/docs/reference/supertypes.md +31 -0
  23. data/docs/reference/triggers.md +797 -0
  24. data/docs/reference/types.md +216 -0
  25. data/exe/enjine +7 -0
  26. data/lib/enjine/actions/activate_mana_ability.rb +24 -0
  27. data/lib/enjine/actions/cast.rb +57 -0
  28. data/lib/enjine/actions/pass.rb +18 -0
  29. data/lib/enjine/actions/play_land.rb +52 -0
  30. data/lib/enjine/actions/special_action.rb +37 -0
  31. data/lib/enjine/actions.rb +20 -0
  32. data/lib/enjine/agents/busy.rb +27 -0
  33. data/lib/enjine/agents/random.rb +28 -0
  34. data/lib/enjine/card_definition.rb +433 -0
  35. data/lib/enjine/card_faces.rb +116 -0
  36. data/lib/enjine/catalog.rb +56 -0
  37. data/lib/enjine/characteristics.rb +39 -0
  38. data/lib/enjine/cli/text.rb +295 -0
  39. data/lib/enjine/cli.rb +312 -0
  40. data/lib/enjine/decisions/bottom.rb +29 -0
  41. data/lib/enjine/decisions/casting.rb +188 -0
  42. data/lib/enjine/decisions/combat.rb +75 -0
  43. data/lib/enjine/decisions/discard.rb +29 -0
  44. data/lib/enjine/decisions/effect_choice.rb +21 -0
  45. data/lib/enjine/decisions/enter_choice.rb +26 -0
  46. data/lib/enjine/decisions/legend_rule.rb +21 -0
  47. data/lib/enjine/decisions/mulligan.rb +26 -0
  48. data/lib/enjine/decisions/order_triggers.rb +21 -0
  49. data/lib/enjine/decisions/play_or_draw.rb +19 -0
  50. data/lib/enjine/decisions/priority.rb +22 -0
  51. data/lib/enjine/decisions/untap_choice.rb +35 -0
  52. data/lib/enjine/decisions.rb +22 -0
  53. data/lib/enjine/deck.rb +151 -0
  54. data/lib/enjine/deck_builder.rb +454 -0
  55. data/lib/enjine/docs.rb +90 -0
  56. data/lib/enjine/engine/ability_layers.rb +118 -0
  57. data/lib/enjine/engine/attachments.rb +86 -0
  58. data/lib/enjine/engine/casting/alt_casting.rb +254 -0
  59. data/lib/enjine/engine/casting/cast_choices.rb +292 -0
  60. data/lib/enjine/engine/casting/casting.rb +326 -0
  61. data/lib/enjine/engine/casting/cost_options.rb +99 -0
  62. data/lib/enjine/engine/casting/costs.rb +117 -0
  63. data/lib/enjine/engine/casting/payment.rb +353 -0
  64. data/lib/enjine/engine/casting/permissions.rb +412 -0
  65. data/lib/enjine/engine/casting/target_counts.rb +113 -0
  66. data/lib/enjine/engine/casting/waterbend.rb +90 -0
  67. data/lib/enjine/engine/characteristics.rb +379 -0
  68. data/lib/enjine/engine/class_levels.rb +25 -0
  69. data/lib/enjine/engine/combat.rb +315 -0
  70. data/lib/enjine/engine/copies.rb +208 -0
  71. data/lib/enjine/engine/damage.rb +196 -0
  72. data/lib/enjine/engine/designations.rb +46 -0
  73. data/lib/enjine/engine/emblems.rb +37 -0
  74. data/lib/enjine/engine/entering.rb +156 -0
  75. data/lib/enjine/engine/face_down.rb +30 -0
  76. data/lib/enjine/engine/faces.rb +222 -0
  77. data/lib/enjine/engine/follow_ups.rb +27 -0
  78. data/lib/enjine/engine/mana_sources.rb +230 -0
  79. data/lib/enjine/engine/phasing.rb +74 -0
  80. data/lib/enjine/engine/pregame.rb +95 -0
  81. data/lib/enjine/engine/priority.rb +47 -0
  82. data/lib/enjine/engine/resolution.rb +168 -0
  83. data/lib/enjine/engine/rules.rb +287 -0
  84. data/lib/enjine/engine/sagas.rb +41 -0
  85. data/lib/enjine/engine/speed.rb +104 -0
  86. data/lib/enjine/engine/spell_grants.rb +46 -0
  87. data/lib/enjine/engine/state_based_actions.rb +157 -0
  88. data/lib/enjine/engine/triggers.rb +364 -0
  89. data/lib/enjine/engine/turn_history.rb +240 -0
  90. data/lib/enjine/engine/turn_structure.rb +224 -0
  91. data/lib/enjine/engine/zones.rb +278 -0
  92. data/lib/enjine/engine.rb +55 -0
  93. data/lib/enjine/errors.rb +62 -0
  94. data/lib/enjine/events.rb +161 -0
  95. data/lib/enjine/frames.rb +84 -0
  96. data/lib/enjine/fuzz.rb +112 -0
  97. data/lib/enjine/game.rb +204 -0
  98. data/lib/enjine/history.rb +26 -0
  99. data/lib/enjine/mana.rb +142 -0
  100. data/lib/enjine/mechanics/abilities/additional_triggers.rb +86 -0
  101. data/lib/enjine/mechanics/abilities/chosen_values.rb +213 -0
  102. data/lib/enjine/mechanics/abilities/cost_changes.rb +154 -0
  103. data/lib/enjine/mechanics/abilities/damage_replacements.rb +569 -0
  104. data/lib/enjine/mechanics/abilities/double_counters.rb +71 -0
  105. data/lib/enjine/mechanics/abilities/entering_choices.rb +91 -0
  106. data/lib/enjine/mechanics/abilities/entering_copy.rb +69 -0
  107. data/lib/enjine/mechanics/abilities/enters_tapped.rb +159 -0
  108. data/lib/enjine/mechanics/abilities/enters_with_counters.rb +116 -0
  109. data/lib/enjine/mechanics/abilities/mana_ability.rb +209 -0
  110. data/lib/enjine/mechanics/abilities/play_permissions.rb +527 -0
  111. data/lib/enjine/mechanics/abilities/player_rules.rb +169 -0
  112. data/lib/enjine/mechanics/abilities/replacement_effects.rb +368 -0
  113. data/lib/enjine/mechanics/abilities/restrictions.rb +144 -0
  114. data/lib/enjine/mechanics/abilities/spell_keywords.rb +55 -0
  115. data/lib/enjine/mechanics/abilities/stack_abilities.rb +542 -0
  116. data/lib/enjine/mechanics/abilities/static.rb +365 -0
  117. data/lib/enjine/mechanics/abilities/tapping_power.rb +71 -0
  118. data/lib/enjine/mechanics/abilities/turn_rules.rb +49 -0
  119. data/lib/enjine/mechanics/card_spec.rb +177 -0
  120. data/lib/enjine/mechanics/copy_except.rb +73 -0
  121. data/lib/enjine/mechanics/costs/base.rb +115 -0
  122. data/lib/enjine/mechanics/costs/behold.rb +76 -0
  123. data/lib/enjine/mechanics/costs/discard.rb +65 -0
  124. data/lib/enjine/mechanics/costs/exert.rb +29 -0
  125. data/lib/enjine/mechanics/costs/exile_cards.rb +39 -0
  126. data/lib/enjine/mechanics/costs/from_graveyard.rb +45 -0
  127. data/lib/enjine/mechanics/costs/get_counters.rb +39 -0
  128. data/lib/enjine/mechanics/costs/mana.rb +37 -0
  129. data/lib/enjine/mechanics/costs/one_of.rb +49 -0
  130. data/lib/enjine/mechanics/costs/pay_life.rb +50 -0
  131. data/lib/enjine/mechanics/costs/remove_counters.rb +51 -0
  132. data/lib/enjine/mechanics/costs/sacrifice.rb +59 -0
  133. data/lib/enjine/mechanics/costs/tap.rb +56 -0
  134. data/lib/enjine/mechanics/costs/waterbend.rb +29 -0
  135. data/lib/enjine/mechanics/counters/kinds.rb +190 -0
  136. data/lib/enjine/mechanics/effects/add_subtypes.rb +30 -0
  137. data/lib/enjine/mechanics/effects/airbend.rb +41 -0
  138. data/lib/enjine/mechanics/effects/amass.rb +124 -0
  139. data/lib/enjine/mechanics/effects/assimilate.rb +72 -0
  140. data/lib/enjine/mechanics/effects/base.rb +148 -0
  141. data/lib/enjine/mechanics/effects/become.rb +182 -0
  142. data/lib/enjine/mechanics/effects/behold.rb +48 -0
  143. data/lib/enjine/mechanics/effects/blight.rb +94 -0
  144. data/lib/enjine/mechanics/effects/choose_cards.rb +168 -0
  145. data/lib/enjine/mechanics/effects/copy.rb +370 -0
  146. data/lib/enjine/mechanics/effects/counter_spell.rb +21 -0
  147. data/lib/enjine/mechanics/effects/counters.rb +161 -0
  148. data/lib/enjine/mechanics/effects/damage.rb +72 -0
  149. data/lib/enjine/mechanics/effects/delayed_triggers.rb +112 -0
  150. data/lib/enjine/mechanics/effects/destroy.rb +22 -0
  151. data/lib/enjine/mechanics/effects/discard.rb +86 -0
  152. data/lib/enjine/mechanics/effects/draw.rb +16 -0
  153. data/lib/enjine/mechanics/effects/earthbend.rb +70 -0
  154. data/lib/enjine/mechanics/effects/emblem.rb +52 -0
  155. data/lib/enjine/mechanics/effects/endure.rb +63 -0
  156. data/lib/enjine/mechanics/effects/exile.rb +49 -0
  157. data/lib/enjine/mechanics/effects/extra_turn.rb +122 -0
  158. data/lib/enjine/mechanics/effects/faces.rb +115 -0
  159. data/lib/enjine/mechanics/effects/fight.rb +76 -0
  160. data/lib/enjine/mechanics/effects/flip_coins.rb +97 -0
  161. data/lib/enjine/mechanics/effects/gain_control.rb +94 -0
  162. data/lib/enjine/mechanics/effects/game_end.rb +42 -0
  163. data/lib/enjine/mechanics/effects/library.rb +327 -0
  164. data/lib/enjine/mechanics/effects/life.rb +83 -0
  165. data/lib/enjine/mechanics/effects/look_at_hand.rb +17 -0
  166. data/lib/enjine/mechanics/effects/loot.rb +118 -0
  167. data/lib/enjine/mechanics/effects/mana.rb +96 -0
  168. data/lib/enjine/mechanics/effects/may.rb +82 -0
  169. data/lib/enjine/mechanics/effects/meld.rb +77 -0
  170. data/lib/enjine/mechanics/effects/mill.rb +22 -0
  171. data/lib/enjine/mechanics/effects/pay.rb +231 -0
  172. data/lib/enjine/mechanics/effects/phasing.rb +51 -0
  173. data/lib/enjine/mechanics/effects/proliferate.rb +72 -0
  174. data/lib/enjine/mechanics/effects/pump.rb +60 -0
  175. data/lib/enjine/mechanics/effects/put_in_library.rb +98 -0
  176. data/lib/enjine/mechanics/effects/return_choice.rb +29 -0
  177. data/lib/enjine/mechanics/effects/return_to_battlefield.rb +80 -0
  178. data/lib/enjine/mechanics/effects/return_to_hand.rb +20 -0
  179. data/lib/enjine/mechanics/effects/roll_dice.rb +45 -0
  180. data/lib/enjine/mechanics/effects/sacrifice.rb +118 -0
  181. data/lib/enjine/mechanics/effects/scry_and_surveil.rb +74 -0
  182. data/lib/enjine/mechanics/effects/search.rb +156 -0
  183. data/lib/enjine/mechanics/effects/tap_untap.rb +23 -0
  184. data/lib/enjine/mechanics/effects/tokens.rb +76 -0
  185. data/lib/enjine/mechanics/filters/any_target.rb +15 -0
  186. data/lib/enjine/mechanics/filters/base.rb +386 -0
  187. data/lib/enjine/mechanics/filters/graveyard.rb +23 -0
  188. data/lib/enjine/mechanics/filters/one_of.rb +55 -0
  189. data/lib/enjine/mechanics/filters/permanents.rb +52 -0
  190. data/lib/enjine/mechanics/filters/players.rb +20 -0
  191. data/lib/enjine/mechanics/filters/stack.rb +97 -0
  192. data/lib/enjine/mechanics/follow_up.rb +46 -0
  193. data/lib/enjine/mechanics/keywords/alternative_costs.rb +361 -0
  194. data/lib/enjine/mechanics/keywords/beam_me_up.rb +78 -0
  195. data/lib/enjine/mechanics/keywords/changeling.rb +58 -0
  196. data/lib/enjine/mechanics/keywords/convoke.rb +77 -0
  197. data/lib/enjine/mechanics/keywords/crew.rb +155 -0
  198. data/lib/enjine/mechanics/keywords/cycling.rb +58 -0
  199. data/lib/enjine/mechanics/keywords/decayed.rb +25 -0
  200. data/lib/enjine/mechanics/keywords/devour.rb +61 -0
  201. data/lib/enjine/mechanics/keywords/evergreen.rb +54 -0
  202. data/lib/enjine/mechanics/keywords/extort.rb +26 -0
  203. data/lib/enjine/mechanics/keywords/flags.rb +46 -0
  204. data/lib/enjine/mechanics/keywords/foretell.rb +45 -0
  205. data/lib/enjine/mechanics/keywords/gift.rb +50 -0
  206. data/lib/enjine/mechanics/keywords/hideaway.rb +28 -0
  207. data/lib/enjine/mechanics/keywords/increment.rb +31 -0
  208. data/lib/enjine/mechanics/keywords/job_select.rb +29 -0
  209. data/lib/enjine/mechanics/keywords/kicker.rb +92 -0
  210. data/lib/enjine/mechanics/keywords/mobilize_and_firebending.rb +84 -0
  211. data/lib/enjine/mechanics/keywords/paradigm.rb +91 -0
  212. data/lib/enjine/mechanics/keywords/power_up.rb +48 -0
  213. data/lib/enjine/mechanics/keywords/protection.rb +111 -0
  214. data/lib/enjine/mechanics/keywords/prowess.rb +30 -0
  215. data/lib/enjine/mechanics/keywords/riot.rb +35 -0
  216. data/lib/enjine/mechanics/keywords/saddle.rb +115 -0
  217. data/lib/enjine/mechanics/keywords/speed.rb +89 -0
  218. data/lib/enjine/mechanics/keywords/station.rb +163 -0
  219. data/lib/enjine/mechanics/keywords/storied.rb +41 -0
  220. data/lib/enjine/mechanics/keywords/storm_and_cascade.rb +86 -0
  221. data/lib/enjine/mechanics/keywords/sunburst.rb +29 -0
  222. data/lib/enjine/mechanics/keywords/suspend.rb +191 -0
  223. data/lib/enjine/mechanics/keywords/teamwork.rb +45 -0
  224. data/lib/enjine/mechanics/keywords/ward.rb +67 -0
  225. data/lib/enjine/mechanics/linked.rb +67 -0
  226. data/lib/enjine/mechanics/mana_spent.rb +99 -0
  227. data/lib/enjine/mechanics/selector.rb +207 -0
  228. data/lib/enjine/mechanics/subtypes/auras_and_equipment.rb +176 -0
  229. data/lib/enjine/mechanics/subtypes/basic_land_types.rb +36 -0
  230. data/lib/enjine/mechanics/subtypes/class_levels.rb +102 -0
  231. data/lib/enjine/mechanics/subtypes/saga.rb +89 -0
  232. data/lib/enjine/mechanics/supertypes/basic.rb +17 -0
  233. data/lib/enjine/mechanics/supertypes/legendary.rb +18 -0
  234. data/lib/enjine/mechanics/triggers/ability_triggers.rb +51 -0
  235. data/lib/enjine/mechanics/triggers/any_of.rb +43 -0
  236. data/lib/enjine/mechanics/triggers/base.rb +228 -0
  237. data/lib/enjine/mechanics/triggers/casting.rb +219 -0
  238. data/lib/enjine/mechanics/triggers/combat.rb +123 -0
  239. data/lib/enjine/mechanics/triggers/damage.rb +130 -0
  240. data/lib/enjine/mechanics/triggers/dilemma.rb +37 -0
  241. data/lib/enjine/mechanics/triggers/draw_and_discard.rb +85 -0
  242. data/lib/enjine/mechanics/triggers/keyword_actions.rb +55 -0
  243. data/lib/enjine/mechanics/triggers/life.rb +35 -0
  244. data/lib/enjine/mechanics/triggers/steps.rb +39 -0
  245. data/lib/enjine/mechanics/triggers/tap_and_counters.rb +111 -0
  246. data/lib/enjine/mechanics/triggers/zone_changes.rb +249 -0
  247. data/lib/enjine/mechanics/types/kindred.rb +30 -0
  248. data/lib/enjine/mechanics/types/land.rb +24 -0
  249. data/lib/enjine/mechanics/types/permanent_types.rb +67 -0
  250. data/lib/enjine/mechanics/types/spell_types.rb +38 -0
  251. data/lib/enjine/mechanics/values.rb +675 -0
  252. data/lib/enjine/mechanics.rb +74 -0
  253. data/lib/enjine/player.rb +30 -0
  254. data/lib/enjine/primitive.rb +61 -0
  255. data/lib/enjine/replacements.rb +191 -0
  256. data/lib/enjine/rng.rb +57 -0
  257. data/lib/enjine/rules_monitor.rb +404 -0
  258. data/lib/enjine/setup.rb +45 -0
  259. data/lib/enjine/snapshot/player_checks.rb +86 -0
  260. data/lib/enjine/snapshot/turn_checks.rb +91 -0
  261. data/lib/enjine/snapshot.rb +307 -0
  262. data/lib/enjine/state.rb +173 -0
  263. data/lib/enjine/steps.rb +117 -0
  264. data/lib/enjine/tokens.rb +25 -0
  265. data/lib/enjine/verify.rb +233 -0
  266. data/lib/enjine/version.rb +7 -0
  267. data/lib/enjine/view.rb +162 -0
  268. data/lib/enjine.rb +46 -0
  269. metadata +315 -0
@@ -0,0 +1,339 @@
1
+ # Costs
2
+
3
+ <!-- Generated by `rake docs` from the primitive registry. Do not edit. -->
4
+
5
+ ## behold
6
+
7
+ Behold `count` (default 1) objects matching the card spec `card`: each a card revealed from your hand or a permanent you control, chosen while casting or activating. `exile: true` also exiles them as it becomes cast; they are then "exiled with" it (selector `exiled_with`).
8
+
9
+ Rules: CR 701.4a, CR 701.4b, CR 601.2h, CR 602.2b, CR 118.3, CR 607.2a
10
+
11
+ | Parameter | Description |
12
+ | --- | --- |
13
+ | `card` | card spec (required), e.g. {"subtypes": ["goblin"]} |
14
+ | `count` | integer (default 1) |
15
+ | `exile` | true: exile what was beheld |
16
+
17
+ ```json
18
+ {
19
+ "behold": {
20
+ "card": {
21
+ "subtypes": [
22
+ "goblin"
23
+ ]
24
+ },
25
+ "exile": true
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## blight
31
+
32
+ Blight `amount`: put that many -1/-1 counters on a creature you control, chosen while casting or activating and put on it as it becomes cast.
33
+
34
+ Rules: CR 701.68a, CR 701.68b, CR 601.2h, CR 602.2b, CR 118.3
35
+
36
+ | Parameter | Description |
37
+ | --- | --- |
38
+ | `amount` | integer >= 1 |
39
+
40
+ ```json
41
+ {
42
+ "blight": {
43
+ "amount": 1
44
+ }
45
+ }
46
+ ```
47
+
48
+ ## bottom_self_from_graveyard
49
+
50
+ Put this card from your graveyard on the bottom of your library. An ability with this cost is activated from your graveyard.
51
+
52
+ Rules: CR 401.1, CR 113.6m, CR 602.2b, CR 118.3
53
+
54
+ ```json
55
+ "bottom_self_from_graveyard"
56
+ ```
57
+
58
+ ## discard
59
+
60
+ Discard `count` cards (default 1) from your hand, never this card, matching the card spec `card` if given: chosen while casting or activating and discarded as the spell or ability becomes cast. `random: true` discards them at random instead.
61
+
62
+ Rules: CR 701.9a, CR 701.9b, CR 601.2h, CR 602.2b, CR 118.3
63
+
64
+ | Parameter | Description |
65
+ | --- | --- |
66
+ | `count` | integer (default 1), or "X": the X announced |
67
+ | `card` | card spec, e.g. {"types": ["land"]} |
68
+ | `random` | true: at random (CR 701.9b) |
69
+
70
+ ```json
71
+ {
72
+ "discard": {
73
+ "count": 1
74
+ }
75
+ }
76
+ ```
77
+
78
+ ## discard_self
79
+
80
+ Discard the card the ability belongs to (it goes from your hand to your graveyard). An ability with this cost is activated from your hand.
81
+
82
+ Rules: CR 701.9a, CR 602.2b, CR 113.6m, CR 118.3
83
+
84
+ ```json
85
+ "discard_self"
86
+ ```
87
+
88
+ ## exert
89
+
90
+ Exert this permanent: it doesn't untap during your next untap step.
91
+
92
+ Rules: CR 701.43a, CR 701.43b, CR 701.43c
93
+
94
+ ```json
95
+ "exert"
96
+ ```
97
+
98
+ ## exile_from_graveyard
99
+
100
+ 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.
101
+
102
+ Rules: CR 406.1, CR 601.2h, CR 602.2b, CR 118.3
103
+
104
+ | Parameter | Description |
105
+ | --- | --- |
106
+ | `count` | integer (default 1), or "X": the X announced |
107
+ | `card` | card spec, e.g. {"types": ["creature"]} |
108
+
109
+ ```json
110
+ {
111
+ "exile_from_graveyard": {
112
+ "count": 2
113
+ }
114
+ }
115
+ ```
116
+
117
+ ## exile_from_hand
118
+
119
+ 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.
120
+
121
+ Rules: CR 406.1, CR 601.2h, CR 602.2b, CR 118.3
122
+
123
+ | Parameter | Description |
124
+ | --- | --- |
125
+ | `count` | integer (default 1), or "X": the X announced |
126
+ | `card` | card spec, e.g. {"types": ["creature"]} |
127
+
128
+ ```json
129
+ {
130
+ "exile_from_hand": {
131
+ "count": 1
132
+ }
133
+ }
134
+ ```
135
+
136
+ ## exile_self_from_graveyard
137
+
138
+ Exile this card from your graveyard. An ability with this cost is activated from your graveyard.
139
+
140
+ Rules: CR 406.1, CR 113.6m, CR 602.2b, CR 118.3
141
+
142
+ ```json
143
+ "exile_self_from_graveyard"
144
+ ```
145
+
146
+ ## get_counters
147
+
148
+ You get `amount` counters of the kind `counter` (e.g. poison). It can always be paid.
149
+
150
+ Rules: CR 118.1, CR 122.1, CR 704.5c
151
+
152
+ | Parameter | Description |
153
+ | --- | --- |
154
+ | `counter` | player counter kind, e.g. "poison" |
155
+ | `amount` | integer >= 1 |
156
+
157
+ ```json
158
+ {
159
+ "get_counters": {
160
+ "counter": "poison",
161
+ "amount": 5
162
+ }
163
+ }
164
+ ```
165
+
166
+ ## mana
167
+
168
+ Pay mana as part of an activation. Paid during the activation by spending mana from your pool, tapping sources one at a time.
169
+
170
+ Rules: CR 601.2g, CR 601.2h, CR 602.2b
171
+
172
+ | Parameter | Description |
173
+ | --- | --- |
174
+ | `(value)` | mana cost string, e.g. "{1}{R}" |
175
+
176
+ ```json
177
+ {
178
+ "mana": "{1}{R}"
179
+ }
180
+ ```
181
+
182
+ ## one_of
183
+
184
+ Pay one of the listed costs (two or more), chosen as the spell or ability is cast or activated (the `choose_cost_option` decision) or, for `pay` and ward, as it is paid. A cost that can't be paid can't be chosen.
185
+
186
+ Rules: CR 118.3, CR 601.2b, CR 601.2f, CR 602.2b, CR 118.12
187
+
188
+ | Parameter | Description |
189
+ | --- | --- |
190
+ | `(list)` | two or more costs |
191
+
192
+ ```json
193
+ {
194
+ "one_of": [
195
+ {
196
+ "behold": {
197
+ "card": {
198
+ "subtypes": [
199
+ "goblin"
200
+ ]
201
+ }
202
+ }
203
+ },
204
+ {
205
+ "mana": "{2}"
206
+ }
207
+ ]
208
+ }
209
+ ```
210
+
211
+ ## pay_life
212
+
213
+ 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.
214
+
215
+ Rules: CR 119.4, CR 119.4b, CR 118.3b, CR 601.2b, CR 107.3a
216
+
217
+ | Parameter | Description |
218
+ | --- | --- |
219
+ | `(value)` | integer >= 1, or "X" |
220
+
221
+ ```json
222
+ {
223
+ "pay_life": 2
224
+ }
225
+ ```
226
+
227
+ ## remove_counters
228
+
229
+ 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.
230
+
231
+ Rules: CR 602.2b, CR 601.2h, CR 118.3, CR 122.1
232
+
233
+ | Parameter | Description |
234
+ | --- | --- |
235
+ | `count` | integer |
236
+ | `filter` | filter (default creature) |
237
+ | `counter` | counter name (optional) |
238
+
239
+ ```json
240
+ {
241
+ "remove_counters": {
242
+ "count": 3
243
+ }
244
+ }
245
+ ```
246
+
247
+ ## sacrifice
248
+
249
+ Sacrifice the permanent the ability belongs to (it goes to its owner's graveyard).
250
+
251
+ Rules: CR 701.21a, CR 602.2b, CR 118.3
252
+
253
+ ```json
254
+ "sacrifice"
255
+ ```
256
+
257
+ ## sacrifice_permanent
258
+
259
+ 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`).
260
+
261
+ Rules: CR 701.21a, CR 601.2h, CR 602.2b, CR 118.3, CR 608.2h
262
+
263
+ | Parameter | Description |
264
+ | --- | --- |
265
+ | `filter` | filter (default permanent) |
266
+ | `count` | integer (default 1) |
267
+ | `other` | true: not the source itself |
268
+
269
+ ```json
270
+ {
271
+ "sacrifice_permanent": {
272
+ "filter": "creature",
273
+ "other": true
274
+ }
275
+ }
276
+ ```
277
+
278
+ ## tap
279
+
280
+ {T} — tap the permanent the ability belongs to. Requires it to be untapped.
281
+
282
+ Rules: CR 107.5, CR 602.5a
283
+
284
+ ```json
285
+ "tap"
286
+ ```
287
+
288
+ ## tap_another_creature
289
+
290
+ Tap another untapped creature you control, chosen while activating. A creature that came under your control this turn can be tapped this way.
291
+
292
+ Rules: CR 702.184a, CR 601.2h, CR 602.2b, CR 302.6
293
+
294
+ ```json
295
+ "tap_another_creature"
296
+ ```
297
+
298
+ ## tap_permanents
299
+
300
+ 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.
301
+
302
+ Rules: CR 601.2h, CR 602.2b, CR 302.6, CR 118.3
303
+
304
+ | Parameter | Description |
305
+ | --- | --- |
306
+ | `count` | integer (default 1) |
307
+ | `filter` | filter (default creature) |
308
+ | `other` | true: not the source itself |
309
+
310
+ ```json
311
+ {
312
+ "tap_permanents": {
313
+ "count": 3,
314
+ "filter": {
315
+ "creature": {
316
+ "types": [
317
+ "artifact"
318
+ ]
319
+ }
320
+ }
321
+ }
322
+ }
323
+ ```
324
+
325
+ ## waterbend
326
+
327
+ Waterbend [cost]: pay this mana cost; for each generic mana in it you may instead tap an untapped artifact or creature you control (pay_cost option `{type: "waterbend", object: id}`). Only the waterbend cost's own generic mana can be paid this way.
328
+
329
+ Rules: CR 701.67a, CR 701.67b, CR 701.67c
330
+
331
+ | Parameter | Description |
332
+ | --- | --- |
333
+ | `(value)` | mana cost string, e.g. "{3}" or "{X}" |
334
+
335
+ ```json
336
+ {
337
+ "waterbend": "{3}"
338
+ }
339
+ ```
@@ -0,0 +1,121 @@
1
+ # Counters with rules
2
+
3
+ <!-- Generated by `rake docs` from the primitive registry. Do not edit. -->
4
+
5
+ ## +1/+1
6
+
7
+ Adds 1 to power and toughness (layer 7c). Any +X/+Y or -X/-Y counter works the same way. If a permanent has both +1/+1 and -1/-1 counters, N of each are removed as a state-based action (N = the smaller count).
8
+
9
+ Rules: CR 122.1a, CR 122.3, CR 613.4c, CR 704.5q
10
+
11
+ ```json
12
+ {
13
+ "add_counters": {
14
+ "counter": "+1/+1",
15
+ "amount": 1,
16
+ "to": "self"
17
+ }
18
+ }
19
+ ```
20
+
21
+ ## -1/-1
22
+
23
+ Subtracts 1 from power and toughness (layer 7c).
24
+
25
+ Rules: CR 122.1a, CR 122.3, CR 613.4c, CR 704.5q
26
+
27
+ ```json
28
+ {
29
+ "add_counters": {
30
+ "counter": "-1/-1",
31
+ "amount": 1,
32
+ "to": {
33
+ "target": 0
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ ## finality
40
+
41
+ If the permanent would be put into a graveyard from the battlefield, it is exiled instead.
42
+
43
+ Rules: CR 122.1h, CR 614.1a
44
+
45
+ ```json
46
+ {
47
+ "enters_with_counters": {
48
+ "counters": {
49
+ "finality": 1
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ## keyword
56
+
57
+ A counter named after a keyword (flying, first_strike, double_strike, deathtouch, decayed, haste, hexproof, indestructible, lifelink, menace, reach, trample, vigilance) gives the permanent that keyword (layer 6). Write the keyword itself as the counter name.
58
+
59
+ Rules: CR 122.1b, CR 613.1f
60
+
61
+ ```json
62
+ {
63
+ "add_counters": {
64
+ "counter": "hexproof",
65
+ "amount": 1,
66
+ "to": "self"
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## loyalty
72
+
73
+ A planeswalker's loyalty; at 0 it is put into its owner's graveyard.
74
+
75
+ Rules: CR 122.1e, CR 306.5b, CR 704.5i
76
+
77
+ ```json
78
+ {
79
+ "add_counters": {
80
+ "counter": "loyalty",
81
+ "amount": 1,
82
+ "to": "self"
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## shield
88
+
89
+ If the permanent would be destroyed by an effect, instead remove a shield counter. If damage would be dealt to it, prevent it and remove a shield counter (simultaneous damage, such as combat damage, removes only one).
90
+
91
+ Rules: CR 122.1c, CR 614.1a, CR 615.1a, CR 701.8b
92
+
93
+ ```json
94
+ {
95
+ "add_counters": {
96
+ "counter": "shield",
97
+ "amount": 1,
98
+ "to": {
99
+ "target": 0
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ ## stun
106
+
107
+ If the permanent would become untapped (untap step or an effect), instead one stun counter is removed from it.
108
+
109
+ Rules: CR 122.1d, CR 502.3, CR 701.26b
110
+
111
+ ```json
112
+ {
113
+ "add_counters": {
114
+ "counter": "stun",
115
+ "amount": 1,
116
+ "to": {
117
+ "target": 0
118
+ }
119
+ }
120
+ }
121
+ ```
@@ -0,0 +1,102 @@
1
+ # Decisions
2
+
3
+ <!-- Generated by `rake docs` from the primitive registry. Do not edit. -->
4
+
5
+ `game.pending_decision` returns the decision below; submit one of its `options`.
6
+
7
+ ## assign_damage
8
+
9
+ Assign one point of combat damage of `attacker`: `{type: "assign", object: blocker_id}`. `remaining` points are left.
10
+
11
+ ## bottom
12
+
13
+ Right after a mulligan, put one card from the new hand on the bottom of the library: `{type: "bottom", object: id}`, once per mulligan taken so far, before declaring again. Hidden from the opponent (CR 103.5).
14
+
15
+ ## choose_cost
16
+
17
+ While casting/activating: `{type: "cost", object: id}` picks the permanent (or card) a cost uses (the creature to tap for station, the creature to sacrifice, the creature beamed up, ...); `{type: "done"}` stops choosing for a cost of any number of permanents once enough are chosen (crew: total power N or more); `{type: "cancel"}` rewinds. `cost` describes the cost.
18
+
19
+ ## choose_cost_option
20
+
21
+ While casting/activating with a choice between costs (cost `one_of`): `{type: "cost_option", option: i}` (0-based, in the order of `costs`) for one that could be paid; `{type: "cancel"}` rewinds.
22
+
23
+ ## choose_kicker
24
+
25
+ While casting a spell with kicker: `{type: "kick"}` pays the kicker cost too, `{type: "no_kick"}` doesn't; `{type: "cancel"}` rewinds. `cost` describes the kicker cost.
26
+
27
+ ## choose_mode
28
+
29
+ Choose a mode of a modal ("choose one") spell or ability: `{type: "mode", mode: index}` (0-based, in printed order); `{type: "done"}` once enough are chosen when more are allowed; `{type: "cancel"}` rewinds a cast. `choose` modes in total (at least `min`).
30
+
31
+ ## choose_target
32
+
33
+ While casting/activating: `{type: "target", target: ref}` for the next target (ref is an object id or "player:<name>"); `{type: "done"}` chooses no more for an "up to" target; `{type: "cancel"}` rewinds the whole cast.
34
+
35
+ ## choose_target_count
36
+
37
+ While casting/activating: `{type: "count", count: n}` announces how many targets (from `min` to `max`, at most as many as there are legal ones) target ##`index` + 1 will have; `{type: "cancel"}` rewinds.
38
+
39
+ ## choose_x
40
+
41
+ While casting/activating a spell or ability with {X} in its cost: `{type: "x", value: n}` announces X (0 up to `max`, the most the available mana could pay for); `{type: "cancel"}` rewinds.
42
+
43
+ ## declare_attackers
44
+
45
+ Declare one attacker: `{type: "attack", object: id, target: ref}` (the defending player or one of their planeswalkers), or `{type: "done"}` (withheld while a creature that attacks each combat if able could still attack, CR 508.1d, or while a creature that can't attack alone attacks alone, CR 506.5; then `{type: "withdraw", object: id}` undoes an attack).
46
+
47
+ ## declare_blockers
48
+
49
+ Declare one blocker: `{type: "block", object: id, attacker: id}`, `{type: "done"}` (only when the blocks are legal), or `{type: "unblock", object: id}` to fix an illegal menace block or free a creature for an attacker that must be blocked if able (CR 509.1c).
50
+
51
+ ## discard
52
+
53
+ Cleanup step: discard one card, `{type: "discard", object: id}`, until the hand has 7 cards. `count` is how many remain (CR 514.1).
54
+
55
+ ## distribute
56
+
57
+ While casting: `{type: "assign", target: ref}` gives one more of the divided amount to that target (each target already has one); `{type: "cancel"}` rewinds. `left` is what remains to divide.
58
+
59
+ ## effect_choice
60
+
61
+ A choice made while an effect resolves (scry, surveil, discard...): submit one of the `choices` exactly as listed; `prompt` describes it.
62
+
63
+ ## enter_choice
64
+
65
+ Before `object` enters: `{type: "pay_life", life: n}` (only with enough life) or `{type: "enter_tapped"}` (CR 614.12, 119.4), or `{type: "behold", object: id}` (CR 701.4a); `{type: "number", number: n}` for "choose a number"; `{type: "name", name: "..."}` for "choose a card name" (CR 201.4); `{type: "color", color: "R"}`, `{type: "creature_type", creature_type: "elf"}`, `{type: "card_type", card_type: "artifact"}`, `{type: "basic_land_type", basic_land_type: "forest"}` or `{type: "option", option: "word"}` for the other "choose a ..." abilities (CR 607.2d); devour picks permanents to sacrifice one at a time, `{type: "devour", object: id}` (`chosen` lists them), then `{type: "done"}` (CR 702.82a). With `effect: true` the permanent is being put onto the battlefield by a resolving effect (a token about to be created has `card`); with several entering at once, each is asked in turn before any enters (CR 614.12a-b).
66
+
67
+ ## legend_rule
68
+
69
+ Keep one of your legendary permanents named `name`: `{type: "keep", object: id}`; the others go to the graveyard (CR 704.5j).
70
+
71
+ ## mulligan
72
+
73
+ Keep the hand (`{type: "keep"}`) or take a London mulligan (`{type: "mulligan"}`). Players declare in turn order; mulligans then happen simultaneously (CR 103.5).
74
+
75
+ ## order_triggers
76
+
77
+ Put one of your pending triggered abilities on the stack next: `{type: "trigger", trigger: id}` (CR 603.3b). The last one put on the stack resolves first.
78
+
79
+ ## pay_cost
80
+
81
+ While casting/activating or paying a cost: `{type: "pay_mana", mana: "R"}` spends one mana from the pool (`restricted: i`: restricted mana, CR 106.6; `from: i`: the pool mana an artifact made that pool_sources[i] names), `{type: "activate_mana", object: id, ability: ref}` (plus `mana: "{G}{G}"` when the mana is chosen) taps a source, `{type: "cancel"}` rewinds (or declines a payment asked for while resolving). Cancel isn't offered once a mana ability with a cost other than {T} (a Treasure) has been activated. `{type: "convoke", object: id}` taps a creature to pay for {1} or one mana of its color (a spell with convoke); `{type: "improvise", object: id}` taps an artifact to pay for {1} (a spell with improvise); `{type: "waterbend", object: id}` taps an artifact or creature to pay {1} of a waterbend cost. `remaining` shows what is left to pay.
82
+
83
+ ## play_or_draw
84
+
85
+ The die-roll winner chooses `{type: "play"}` or `{type: "draw"}` (CR 103.1).
86
+
87
+ ## priority
88
+
89
+ The player holding priority takes an action or passes. Options come from the priority actions below (CR 117).
90
+
91
+ ## untap_choice
92
+
93
+ Untap step: `{type: "untap", object: id}` or `{type: "keep_tapped", object: id}` for a permanent you may choose not to untap (CR 502.3).
94
+
95
+ ## Priority actions
96
+
97
+ - `activate` — `{type: "activate", object: id, ability: ref}` — start activating an ability (CR 602.2), including planeswalker loyalty abilities (CR 606) and abilities of cards in your hand (cycling, CR 702.29).
98
+ - `activate_mana` — `{type: "activate_mana", object: id, ability: ref}` — activate a mana ability; it resolves immediately (CR 605.3). `mana: "{G}{G}"` names the mana when it is chosen as the ability is activated.
99
+ - `cast` — `{type: "cast", object: id}` — start casting a card from your hand (CR 601.2). `{type: "cast", object: id, via: method}` casts a card from another zone (graveyard, exile, the top of your library) by the permission or alternative cost `via` names, e.g. beam me up (CR 601.3, 702.196). A card outside the game is named `"outside:<card id>"` (CR 400.11b). `{type: "cast", object: id, face: 1}` casts another face of a card in your hand: a modal double-faced card's back face, an Adventure or an Omen (CR 712.8b, 716.3, 721.3). Offered only when timing allows, targets exist and enough mana is available.
100
+ - `pass` — `{type: "pass"}` — pass priority. When all players pass in succession with an empty stack, the step ends (CR 117.4).
101
+ - `play_land` — `{type: "play_land", object: id}` — special action: your main phase, empty stack, one land per turn plus additional land plays (CR 305.1, 305.2). With `via`: a land from another zone that an effect lets you play. With `face: 1`: a modal double-faced card played with its land back face up (CR 712.9).
102
+ - `special_action` — `{type: "special_action", object: id, ability: ref}` — a special action of a card in your hand: foretell (during your turn, pay {2} and exile it face down, CR 116.2h) or suspend (when you could begin to cast it, pay its suspend cost and exile it with time counters, CR 116.2f).