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,647 @@
1
+ # Keyword abilities
2
+
3
+ <!-- Generated by `rake docs` from the primitive registry. Do not edit. -->
4
+
5
+ ## abilities_cant_be_activated
6
+
7
+ Its activated abilities, mana abilities included, can't be activated ("Activated abilities of artifacts can't be activated" is a static handing it out).
8
+
9
+ Rules: CR 602.5, CR 605.3a, CR 101.2
10
+
11
+ ```json
12
+ {
13
+ "keywords": [
14
+ "abilities cant be activated"
15
+ ]
16
+ }
17
+ ```
18
+
19
+ ## assigns_damage_by_toughness
20
+
21
+ If this creature's toughness is greater than its power, it assigns combat damage equal to its toughness rather than its power.
22
+
23
+ Rules: CR 510.1a
24
+
25
+ ```json
26
+ {
27
+ "keywords": [
28
+ "assigns damage by toughness"
29
+ ]
30
+ }
31
+ ```
32
+
33
+ ## attacks_despite_defender
34
+
35
+ Defender doesn't stop this creature from attacking.
36
+
37
+ Rules: CR 702.3b, CR 508.1c
38
+
39
+ ```json
40
+ {
41
+ "keywords": [
42
+ "attacks despite defender"
43
+ ]
44
+ }
45
+ ```
46
+
47
+ ## attacks_each_combat
48
+
49
+ Requirement: this creature attacks each combat if able. Declaring attackers can't finish while it could still attack.
50
+
51
+ Rules: CR 508.1d
52
+
53
+ ```json
54
+ {
55
+ "keywords": [
56
+ "attacks each combat"
57
+ ]
58
+ }
59
+ ```
60
+
61
+ ## cant_attack
62
+
63
+ Restriction: this creature can't attack.
64
+
65
+ Rules: CR 508.1c
66
+
67
+ ```json
68
+ {
69
+ "keywords": [
70
+ "cant attack"
71
+ ]
72
+ }
73
+ ```
74
+
75
+ ## cant_attack_alone
76
+
77
+ Restriction: this creature can't attack unless another creature attacks too. It is offered as an attacker only while another creature attacks or could still be declared, and declaring attackers can't finish while it attacks alone.
78
+
79
+ Rules: CR 506.5, CR 508.1c
80
+
81
+ ```json
82
+ {
83
+ "keywords": [
84
+ "cant attack alone"
85
+ ]
86
+ }
87
+ ```
88
+
89
+ ## cant_be_beamed_up
90
+
91
+ This creature can't be returned to its owner's hand to pay a beam me up cost.
92
+
93
+ Rules: CR 702.196b
94
+
95
+ ```json
96
+ {
97
+ "keywords": [
98
+ "cant_be_beamed_up"
99
+ ]
100
+ }
101
+ ```
102
+
103
+ ## cant_be_blocked
104
+
105
+ Restriction: this creature can't be blocked.
106
+
107
+ Rules: CR 509.1b
108
+
109
+ ```json
110
+ {
111
+ "keywords": [
112
+ "cant be blocked"
113
+ ]
114
+ }
115
+ ```
116
+
117
+ ## cant_be_countered
118
+
119
+ This spell can't be countered: counter effects leave it on the stack.
120
+
121
+ Rules: CR 701.6a, CR 101.2
122
+
123
+ ```json
124
+ {
125
+ "keywords": [
126
+ "cant be countered"
127
+ ]
128
+ }
129
+ ```
130
+
131
+ ## cant_block
132
+
133
+ Restriction: this creature can't block.
134
+
135
+ Rules: CR 509.1b
136
+
137
+ ```json
138
+ {
139
+ "keywords": [
140
+ "cant block"
141
+ ]
142
+ }
143
+ ```
144
+
145
+ ## cascade
146
+
147
+ When you cast this spell, exile cards from the top of your library until you exile a nonland card with lesser mana value. You may cast it without paying its mana cost. Then the exiled cards not cast go on the bottom of your library in a random order.
148
+
149
+ Rules: CR 702.85a, CR 702.85c, CR 608.2g
150
+
151
+ ```json
152
+ {
153
+ "keywords": [
154
+ "cascade"
155
+ ]
156
+ }
157
+ ```
158
+
159
+ ## changeling
160
+
161
+ This object is every creature type (a characteristic-defining ability that works in all zones).
162
+
163
+ Rules: CR 702.73a, CR 604.3, CR 205.3m, CR 113.6a
164
+
165
+ ```json
166
+ {
167
+ "keywords": [
168
+ "changeling"
169
+ ]
170
+ }
171
+ ```
172
+
173
+ ## convoke
174
+
175
+ Convoke: while paying this spell's total cost you may tap untapped creatures you control, each paying for {1} or one mana of one of its colors (pay_cost option `{type: "convoke", object: id}`). It isn't an alternative or additional cost.
176
+
177
+ Rules: CR 702.51a, CR 702.51b, CR 702.51c, CR 702.51d
178
+
179
+ ```json
180
+ {
181
+ "keywords": [
182
+ "convoke"
183
+ ]
184
+ }
185
+ ```
186
+
187
+ ## deathtouch
188
+
189
+ Any damage it deals to a creature is enough to destroy it; 1 damage counts as lethal when assigning combat damage.
190
+
191
+ Rules: CR 702.2b, CR 702.2c, CR 704.5h
192
+
193
+ ```json
194
+ {
195
+ "keywords": [
196
+ "deathtouch"
197
+ ]
198
+ }
199
+ ```
200
+
201
+ ## decayed
202
+
203
+ This creature can't block. When it attacks, sacrifice it at end of combat.
204
+
205
+ Rules: CR 702.147a, CR 122.1b
206
+
207
+ ```json
208
+ {
209
+ "keywords": [
210
+ "decayed"
211
+ ]
212
+ }
213
+ ```
214
+
215
+ ## defender
216
+
217
+ Can't attack.
218
+
219
+ Rules: CR 702.3b
220
+
221
+ ```json
222
+ {
223
+ "keywords": [
224
+ "defender"
225
+ ]
226
+ }
227
+ ```
228
+
229
+ ## doesnt_untap
230
+
231
+ This permanent doesn't untap during its controller's untap step.
232
+
233
+ Rules: CR 502.3
234
+
235
+ ```json
236
+ {
237
+ "keywords": [
238
+ "doesnt untap"
239
+ ]
240
+ }
241
+ ```
242
+
243
+ ## double_strike
244
+
245
+ Deals combat damage in both the first-strike and the regular combat damage step.
246
+
247
+ Rules: CR 702.4b, CR 510.4
248
+
249
+ ```json
250
+ {
251
+ "keywords": [
252
+ "double strike"
253
+ ]
254
+ }
255
+ ```
256
+
257
+ ## extort
258
+
259
+ Whenever you cast a spell, you may pay {W/B}. If you do, each opponent loses 1 life and you gain life equal to the total life lost this way.
260
+
261
+ Rules: CR 702.101a, CR 702.101b, CR 118.12
262
+
263
+ ```json
264
+ {
265
+ "keywords": [
266
+ "extort"
267
+ ]
268
+ }
269
+ ```
270
+
271
+ ## first_strike
272
+
273
+ Deals combat damage in a first combat damage step, before creatures without first strike.
274
+
275
+ Rules: CR 702.7b, CR 510.4
276
+
277
+ ```json
278
+ {
279
+ "keywords": [
280
+ "first strike"
281
+ ]
282
+ }
283
+ ```
284
+
285
+ ## flash
286
+
287
+ You may cast this spell any time you could cast an instant.
288
+
289
+ Rules: CR 702.8a
290
+
291
+ ```json
292
+ {
293
+ "keywords": [
294
+ "flash"
295
+ ]
296
+ }
297
+ ```
298
+
299
+ ## flying
300
+
301
+ Can't be blocked except by creatures with flying or reach.
302
+
303
+ Rules: CR 702.9b
304
+
305
+ ```json
306
+ {
307
+ "keywords": [
308
+ "flying"
309
+ ]
310
+ }
311
+ ```
312
+
313
+ ## haste
314
+
315
+ This creature can attack and use {T} abilities even if it hasn't been under your control continuously since your most recent turn began.
316
+
317
+ Rules: CR 702.10a, CR 302.6
318
+
319
+ ```json
320
+ {
321
+ "keywords": [
322
+ "haste"
323
+ ]
324
+ }
325
+ ```
326
+
327
+ ## hexproof
328
+
329
+ Can't be the target of spells or abilities your opponents control.
330
+
331
+ Rules: CR 702.11b
332
+
333
+ ```json
334
+ {
335
+ "keywords": [
336
+ "hexproof"
337
+ ]
338
+ }
339
+ ```
340
+
341
+ ## improvise
342
+
343
+ Improvise: while paying this spell's total cost you may tap untapped artifacts you control, each paying for {1} of its generic part (pay_cost option `{type: "improvise", object: id}`). It isn't an alternative or additional cost.
344
+
345
+ Rules: CR 702.126a, CR 702.126b, CR 702.126c
346
+
347
+ ```json
348
+ {
349
+ "keywords": [
350
+ "improvise"
351
+ ]
352
+ }
353
+ ```
354
+
355
+ ## increment
356
+
357
+ Whenever you cast a spell, if this is a creature and the mana spent to cast that spell is greater than its power or its toughness, put a +1/+1 counter on it.
358
+
359
+ Rules: CR 702.191a, CR 702.191b, CR 603.4
360
+
361
+ ```json
362
+ {
363
+ "keywords": [
364
+ "increment"
365
+ ]
366
+ }
367
+ ```
368
+
369
+ ## indestructible
370
+
371
+ Can't be destroyed: lethal damage, deathtouch and "destroy" effects don't put it into the graveyard.
372
+
373
+ Rules: CR 702.12b
374
+
375
+ ```json
376
+ {
377
+ "keywords": [
378
+ "indestructible"
379
+ ]
380
+ }
381
+ ```
382
+
383
+ ## job_select
384
+
385
+ When this Equipment enters, create a 1/1 colorless Hero creature token, then attach this Equipment to it.
386
+
387
+ Rules: CR 702.182a
388
+
389
+ ```json
390
+ {
391
+ "keywords": [
392
+ "job_select"
393
+ ]
394
+ }
395
+ ```
396
+
397
+ ## keeps_damage
398
+
399
+ Damage isn't removed from this permanent during cleanup steps (remove_damage still removes it).
400
+
401
+ Rules: CR 514.2, CR 120.6
402
+
403
+ ```json
404
+ {
405
+ "keywords": [
406
+ "keeps damage"
407
+ ]
408
+ }
409
+ ```
410
+
411
+ ## lifelink
412
+
413
+ Damage dealt by this source also causes its controller to gain that much life.
414
+
415
+ Rules: CR 702.15b
416
+
417
+ ```json
418
+ {
419
+ "keywords": [
420
+ "lifelink"
421
+ ]
422
+ }
423
+ ```
424
+
425
+ ## menace
426
+
427
+ Can't be blocked except by two or more creatures.
428
+
429
+ Rules: CR 702.111b
430
+
431
+ ```json
432
+ {
433
+ "keywords": [
434
+ "menace"
435
+ ]
436
+ }
437
+ ```
438
+
439
+ ## must_be_blocked
440
+
441
+ Requirement: this attacking creature must be blocked if able. Declaring blockers can't finish while it is unblocked and a creature that could block it blocks nothing.
442
+
443
+ Rules: CR 509.1c
444
+
445
+ ```json
446
+ {
447
+ "keywords": [
448
+ "must be blocked"
449
+ ]
450
+ }
451
+ ```
452
+
453
+ ## paradigm
454
+
455
+ As this instant or sorcery finishes resolving: if it's the first time a spell you control with its name has resolved this game, at the beginning of each of your precombat main phases for the rest of the game you create a copy of the card in exile and may cast it without paying its mana cost. Then the spell is exiled.
456
+
457
+ Rules: CR 702.192a, CR 707.12, CR 603.7, CR 608.2g
458
+
459
+ ```json
460
+ {
461
+ "keywords": [
462
+ "paradigm"
463
+ ]
464
+ }
465
+ ```
466
+
467
+ ## phasing
468
+
469
+ During each of its controller's untap steps, before they untap, it phases out if it's phased in (and phases in if it phased out under their control).
470
+
471
+ Rules: CR 702.26a, CR 702.26p, CR 502.1
472
+
473
+ ```json
474
+ {
475
+ "keywords": [
476
+ "phasing"
477
+ ]
478
+ }
479
+ ```
480
+
481
+ ## prowess
482
+
483
+ Whenever you cast a noncreature spell, this creature gets +1/+1 until end of turn.
484
+
485
+ Rules: CR 702.108a
486
+
487
+ ```json
488
+ {
489
+ "keywords": [
490
+ "prowess"
491
+ ]
492
+ }
493
+ ```
494
+
495
+ ## reach
496
+
497
+ Can block creatures with flying.
498
+
499
+ Rules: CR 702.17b
500
+
501
+ ```json
502
+ {
503
+ "keywords": [
504
+ "reach"
505
+ ]
506
+ }
507
+ ```
508
+
509
+ ## riot
510
+
511
+ As this permanent enters, its controller chooses an additional +1/+1 counter or haste (an enter_choice: `{type: "option", option: "counter" | "haste"}`).
512
+
513
+ Rules: CR 702.136a, CR 614.12
514
+
515
+ ```json
516
+ {
517
+ "keywords": [
518
+ "riot"
519
+ ]
520
+ }
521
+ ```
522
+
523
+ ## start_your_engines
524
+
525
+ If you control this permanent and have no speed, your speed becomes 1. Once you have speed, it increases by 1 (to at most 4) once on each of your turns when one or more opponents lose life. Pair with `max_speed` abilities and the `speed` amount.
526
+
527
+ Rules: CR 702.179a, CR 702.179b, CR 702.179c, CR 702.179d, CR 704.3
528
+
529
+ ```json
530
+ {
531
+ "keywords": [
532
+ "start_your_engines"
533
+ ]
534
+ }
535
+ ```
536
+
537
+ ## station
538
+
539
+ An activated ability: tap another untapped creature you control to put charge counters equal to its power on this permanent. Sorcery speed. Pair with `station_symbol` abilities for what the counters unlock.
540
+
541
+ Rules: CR 702.184a, CR 722.4
542
+
543
+ ```json
544
+ {
545
+ "keywords": [
546
+ "station"
547
+ ]
548
+ }
549
+ ```
550
+
551
+ ## storied
552
+
553
+ While you control this permanent, once you control three or more permanents that are artifacts, Sagas and/or legendary, you have an enduring story for the rest of the game (condition `{"designation": "enduring_story"}`).
554
+
555
+ Rules: CR 702.195a, CR 702.195b, CR 702.195c
556
+
557
+ ```json
558
+ {
559
+ "keywords": [
560
+ "storied"
561
+ ]
562
+ }
563
+ ```
564
+
565
+ ## storm
566
+
567
+ When you cast this spell, copy it for each other spell cast before it this turn; you may choose new targets for the copies.
568
+
569
+ Rules: CR 702.40a, CR 702.40b, CR 707.10
570
+
571
+ ```json
572
+ {
573
+ "keywords": [
574
+ "storm"
575
+ ]
576
+ }
577
+ ```
578
+
579
+ ## sunburst
580
+
581
+ As this permanent enters from the stack as a resolving spell, it gets a +1/+1 counter (a creature) or a charge counter (otherwise) for each color of mana spent to cast it.
582
+
583
+ Rules: CR 702.44a, CR 702.44b
584
+
585
+ ```json
586
+ {
587
+ "keywords": [
588
+ "sunburst"
589
+ ]
590
+ }
591
+ ```
592
+
593
+ ## suspend
594
+
595
+ This card has suspend: while it's exiled with time counters, its owner removes one at the beginning of each of their upkeeps; when the last is removed they may play it without paying its mana cost (a creature spell gains haste). "Suspend N—cost" is the ability `suspend`.
596
+
597
+ Rules: CR 702.62a, CR 702.62b
598
+
599
+ ```json
600
+ {
601
+ "keywords": [
602
+ "suspend"
603
+ ]
604
+ }
605
+ ```
606
+
607
+ ## trample
608
+
609
+ Excess combat damage beyond lethal damage to its blockers can be assigned to the player or planeswalker it's attacking.
610
+
611
+ Rules: CR 702.19b, CR 702.19e
612
+
613
+ ```json
614
+ {
615
+ "keywords": [
616
+ "trample"
617
+ ]
618
+ }
619
+ ```
620
+
621
+ ## vigilance
622
+
623
+ Attacking doesn't cause this creature to tap.
624
+
625
+ Rules: CR 702.20b
626
+
627
+ ```json
628
+ {
629
+ "keywords": [
630
+ "vigilance"
631
+ ]
632
+ }
633
+ ```
634
+
635
+ ## wither
636
+
637
+ Damage this source deals to creatures is dealt as that many -1/-1 counters instead of marked damage, put by its controller.
638
+
639
+ Rules: CR 702.80a, CR 702.80c, CR 702.80d, CR 120.3d
640
+
641
+ ```json
642
+ {
643
+ "keywords": [
644
+ "wither"
645
+ ]
646
+ }
647
+ ```