Document that shadow invis swiftness appears in two places.
[crawl.git] / crawl-ref / source / ability.cc
1 /**
2  * @file
3  * @brief Functions related to special abilities.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "ability.h"
9
10 #include <cctype>
11 #include <cmath>
12 #include <cstdio>
13 #include <cstring>
14 #include <iomanip>
15 #include <sstream>
16
17 #include "abyss.h"
18 #include "acquire.h"
19 #include "areas.h"
20 #include "branch.h"
21 #include "butcher.h"
22 #include "cloud.h"
23 #include "coordit.h"
24 #include "database.h"
25 #include "decks.h"
26 #include "delay.h"
27 #include "describe.h"
28 #include "directn.h"
29 #include "dungeon.h"
30 #include "evoke.h"
31 #include "exercise.h"
32 #include "food.h"
33 #include "godabil.h"
34 #include "godconduct.h"
35 #include "godprayer.h"
36 #include "hints.h"
37 #include "items.h"
38 #include "item_use.h"
39 #include "libutil.h"
40 #include "macro.h"
41 #include "maps.h"
42 #include "menu.h"
43 #include "message.h"
44 #include "misc.h"
45 #include "mon-place.h"
46 #include "mutation.h"
47 #include "notes.h"
48 #include "output.h"
49 #include "player-stats.h"
50 #include "potion.h"
51 #include "prompt.h"
52 #include "religion.h"
53 #include "skills.h"
54 #include "spl-cast.h"
55 #include "spl-clouds.h"
56 #include "spl-damage.h"
57 #include "spl-goditem.h"
58 #include "spl-miscast.h"
59 #include "spl-other.h"
60 #include "spl-selfench.h"
61 #include "spl-summoning.h"
62 #include "spl-transloc.h"
63 #include "stairs.h"
64 #include "state.h"
65 #include "stringutil.h"
66 #include "target.h"
67 #include "terrain.h"
68 #include "tilepick.h"
69 #include "transform.h"
70 #include "traps.h"
71 #include "uncancel.h"
72 #include "unicode.h"
73 #include "zotdef.h"
74
75 enum ability_flag_type
76 {
77     ABFLAG_NONE           = 0x00000000,
78     ABFLAG_BREATH         = 0x00000001, // ability uses DUR_BREATH_WEAPON
79     ABFLAG_DELAY          = 0x00000002, // ability has its own delay
80     ABFLAG_PAIN           = 0x00000004, // ability must hurt player (ie torment)
81     ABFLAG_PIETY          = 0x00000008, // ability has its own piety cost
82     ABFLAG_EXHAUSTION     = 0x00000010, // fails if you.exhausted
83     ABFLAG_INSTANT        = 0x00000020, // doesn't take time to use
84     ABFLAG_PERMANENT_HP   = 0x00000040, // costs permanent HPs
85     ABFLAG_PERMANENT_MP   = 0x00000080, // costs permanent MPs
86     ABFLAG_CONF_OK        = 0x00000100, // can use even if confused
87     ABFLAG_FRUIT          = 0x00000200, // ability requires fruit
88     ABFLAG_VARIABLE_FRUIT = 0x00000400, // ability requires fruit or piety
89                           //0x00000800,
90                           //0x00001000,
91     ABFLAG_NECRO_MISCAST_MINOR = 0x00002000, // severity 2 necro miscast
92                           //0x00004000,
93                           //0x00008000,
94     ABFLAG_LEVEL_DRAIN    = 0x00010000, // drains 2 levels
95     ABFLAG_STAT_DRAIN     = 0x00020000, // stat drain
96     ABFLAG_ZOTDEF         = 0x00040000, // ZotDef ability, w/ appropriate hotkey
97     ABFLAG_SKILL_DRAIN    = 0x00080000, // drains skill levels
98     ABFLAG_GOLD           = 0x00100000, // costs gold
99     ABFLAG_SACRIFICE      = 0x00200000, // sacrifice (Ru)
100 };
101
102 static int  _find_ability_slot(const ability_def& abil);
103 static spret_type _do_ability(const ability_def& abil, bool fail);
104 static void _pay_ability_costs(const ability_def& abil, int zpcost);
105 static int _scale_piety_cost(ability_type abil, int original_cost);
106 static string _zd_mons_description_for_ability(const ability_def &abil);
107 static monster_type _monster_for_ability(const ability_def& abil);
108
109 /**
110  * This all needs to be split into data/util/show files
111  * and the struct mechanism here needs to be rewritten (again)
112  * along with the display routine to piece the strings
113  * together dynamically ... I'm getting to it now {dlb}
114  *
115  * This array corresponds with ::god_gain_power_messages and
116  * ::god_lose_power_messages, which have the same shape.
117  *
118  * It makes more sense to think of them as an array
119  * of structs than two arrays that share common index
120  * values -- well, doesn't it? {dlb}
121  *
122  * @note Declaring this const messes up externs later, so don't do it!
123  */
124 ability_type god_abilities[NUM_GODS][MAX_GOD_ABILITIES] =
125 {
126     // no god
127     { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
128       ABIL_NON_ABILITY },
129     // Zin
130     { ABIL_ZIN_RECITE, ABIL_ZIN_VITALISATION, ABIL_ZIN_IMPRISON,
131       ABIL_NON_ABILITY, ABIL_ZIN_SANCTUARY },
132     // TSO
133     { ABIL_NON_ABILITY, ABIL_TSO_DIVINE_SHIELD, ABIL_NON_ABILITY,
134       ABIL_TSO_CLEANSING_FLAME, ABIL_TSO_SUMMON_DIVINE_WARRIOR },
135     // Kikubaaqudgha
136     { ABIL_KIKU_RECEIVE_CORPSES, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
137       ABIL_NON_ABILITY, ABIL_KIKU_TORMENT },
138     // Yredelemnul
139     { ABIL_YRED_ANIMATE_REMAINS_OR_DEAD, ABIL_YRED_RECALL_UNDEAD_SLAVES,
140       ABIL_NON_ABILITY, ABIL_YRED_DRAIN_LIFE, ABIL_YRED_ENSLAVE_SOUL },
141     // Xom
142     { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
143       ABIL_NON_ABILITY },
144     // Vehumet
145     { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
146       ABIL_NON_ABILITY },
147     // Okawaru
148     { ABIL_OKAWARU_HEROISM, ABIL_NON_ABILITY, ABIL_NON_ABILITY,
149       ABIL_NON_ABILITY, ABIL_OKAWARU_FINESSE },
150     // Makhleb
151     { ABIL_NON_ABILITY, ABIL_MAKHLEB_MINOR_DESTRUCTION,
152       ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB, ABIL_MAKHLEB_MAJOR_DESTRUCTION,
153       ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB },
154     // Sif Muna
155     { ABIL_SIF_MUNA_CHANNEL_ENERGY, ABIL_SIF_MUNA_FORGET_SPELL,
156       ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY },
157     // Trog
158     { ABIL_TROG_BERSERK, ABIL_TROG_REGEN_MR, ABIL_NON_ABILITY,
159       ABIL_TROG_BROTHERS_IN_ARMS, ABIL_NON_ABILITY },
160     // Nemelex
161     { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NEMELEX_TRIPLE_DRAW,
162       ABIL_NEMELEX_DEAL_FOUR, ABIL_NEMELEX_STACK_FIVE },
163     // Elyvilon
164     { ABIL_ELYVILON_LESSER_HEALING, ABIL_ELYVILON_HEAL_OTHER,
165       ABIL_ELYVILON_PURIFICATION, ABIL_ELYVILON_GREATER_HEALING,
166       ABIL_ELYVILON_DIVINE_VIGOUR },
167     // Lugonu
168     { ABIL_LUGONU_ABYSS_EXIT, ABIL_LUGONU_BEND_SPACE, ABIL_LUGONU_BANISH,
169       ABIL_LUGONU_CORRUPT, ABIL_LUGONU_ABYSS_ENTER },
170     // Beogh
171     { ABIL_NON_ABILITY, ABIL_BEOGH_SMITING, ABIL_NON_ABILITY,
172       ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS, ABIL_BEOGH_GIFT_ITEM },
173     // Jiyva
174     { ABIL_JIYVA_CALL_JELLY, ABIL_JIYVA_JELLY_PARALYSE, ABIL_NON_ABILITY,
175       ABIL_JIYVA_SLIMIFY, ABIL_JIYVA_CURE_BAD_MUTATION },
176     // Fedhas
177     { ABIL_FEDHAS_EVOLUTION, ABIL_FEDHAS_SUNLIGHT, ABIL_FEDHAS_PLANT_RING,
178       ABIL_FEDHAS_SPAWN_SPORES, ABIL_FEDHAS_RAIN},
179     // Cheibriados
180     { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_CHEIBRIADOS_DISTORTION,
181       ABIL_CHEIBRIADOS_SLOUCH, ABIL_CHEIBRIADOS_TIME_STEP },
182     // Ashenzari
183     { ABIL_NON_ABILITY, ABIL_ASHENZARI_SCRYING, ABIL_NON_ABILITY,
184       ABIL_NON_ABILITY, ABIL_ASHENZARI_TRANSFER_KNOWLEDGE },
185     // Dithmenos
186     { ABIL_NON_ABILITY, ABIL_DITHMENOS_SHADOW_STEP, ABIL_NON_ABILITY,
187       ABIL_NON_ABILITY, ABIL_DITHMENOS_SHADOW_FORM },
188     // Gozag
189     { ABIL_GOZAG_POTION_PETITION, ABIL_GOZAG_CALL_MERCHANT,
190       ABIL_GOZAG_BRIBE_BRANCH, ABIL_NON_ABILITY, ABIL_NON_ABILITY },
191     // Qazlal
192     { ABIL_NON_ABILITY, ABIL_QAZLAL_UPHEAVAL, ABIL_QAZLAL_ELEMENTAL_FORCE,
193       ABIL_NON_ABILITY, ABIL_QAZLAL_DISASTER_AREA },
194     // Ru
195     { ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_RU_DRAW_OUT_POWER,
196       ABIL_RU_POWER_LEAP, ABIL_RU_APOCALYPSE }
197 };
198
199 // The description screen was way out of date with the actual costs.
200 // This table puts all the information in one place... -- bwr
201 //
202 // The five numerical fields are: MP, HP, food, piety and ZP.
203 // Note:  food_cost  = val + random2avg(val, 2)
204 //        piety_cost = val + random2((val + 1) / 2 + 1);
205 //        hp cost is in per-mil of maxhp (i.e. 20 = 2% of hp, rounded up)
206 static const ability_def Ability_List[] =
207 {
208     // NON_ABILITY should always come first
209     { ABIL_NON_ABILITY, "No ability", 0, 0, 0, 0, 0, ABFLAG_NONE},
210     { ABIL_SPIT_POISON, "Spit Poison", 0, 0, 40, 0, 0, ABFLAG_BREATH},
211
212     { ABIL_BLINK, "Blink", 0, 50, 50, 0, 0, ABFLAG_NONE},
213
214     { ABIL_BREATHE_FIRE, "Breathe Fire", 0, 0, 125, 0, 0, ABFLAG_BREATH},
215     { ABIL_BREATHE_FROST, "Breathe Frost", 0, 0, 125, 0, 0, ABFLAG_BREATH},
216     { ABIL_BREATHE_POISON, "Breathe Poison Gas",
217       0, 0, 125, 0, 0, ABFLAG_BREATH},
218     { ABIL_BREATHE_MEPHITIC, "Breathe Noxious Fumes",
219       0, 0, 125, 0, 0, ABFLAG_BREATH},
220     { ABIL_BREATHE_LIGHTNING, "Breathe Lightning",
221       0, 0, 125, 0, 0, ABFLAG_BREATH},
222     { ABIL_BREATHE_POWER, "Breathe Dispelling Energy", 0, 0, 125, 0, 0, ABFLAG_BREATH},
223     { ABIL_BREATHE_STICKY_FLAME, "Breathe Sticky Flame",
224       0, 0, 125, 0, 0, ABFLAG_BREATH},
225     { ABIL_BREATHE_STEAM, "Breathe Steam", 0, 0, 75, 0, 0, ABFLAG_BREATH},
226     { ABIL_TRAN_BAT, "Bat Form", 2, 0, 0, 0, 0, ABFLAG_NONE},
227
228     { ABIL_SPIT_ACID, "Spit Acid", 0, 0, 125, 0, 0, ABFLAG_BREATH},
229
230     { ABIL_FLY, "Fly", 3, 0, 100, 0, 0, ABFLAG_NONE},
231     { ABIL_STOP_FLYING, "Stop Flying", 0, 0, 0, 0, 0, ABFLAG_NONE},
232     { ABIL_HELLFIRE, "Hellfire", 0, 150, 200, 0, 0, ABFLAG_NONE},
233
234     { ABIL_DELAYED_FIREBALL, "Release Delayed Fireball",
235       0, 0, 0, 0, 0, ABFLAG_INSTANT},
236     { ABIL_STOP_SINGING, "Stop Singing",
237       0, 0, 0, 0, 0, ABFLAG_NONE},
238     { ABIL_MUMMY_RESTORATION, "Self-Restoration",
239       1, 0, 0, 0, 0, ABFLAG_PERMANENT_MP},
240
241     { ABIL_DIG, "Dig", 0, 0, 0, 0, 0, ABFLAG_INSTANT},
242     { ABIL_SHAFT_SELF, "Shaft Self", 0, 0, 250, 0, 0, ABFLAG_DELAY},
243
244     // EVOKE abilities use Evocations and come from items.
245     // Teleportation and Blink can also come from mutations
246     // so we have to distinguish them (see above). The off items
247     // below are labeled EVOKE because they only work now if the
248     // player has an item with the evocable power (not just because
249     // you used a wand, potion, or miscast effect). I didn't see
250     // any reason to label them as "Evoke" in the text, they don't
251     // use or train Evocations (the others do).  -- bwr
252     { ABIL_EVOKE_TELEPORTATION, "Evoke Teleportation",
253       3, 0, 200, 0, 0, ABFLAG_NONE},
254     { ABIL_EVOKE_BLINK, "Evoke Blink", 1, 0, 50, 0, 0, ABFLAG_NONE},
255     { ABIL_RECHARGING, "Device Recharging", 1, 0, 0, 0, 0, ABFLAG_PERMANENT_MP},
256
257     { ABIL_EVOKE_BERSERK, "Evoke Berserk Rage", 0, 0, 0, 0, 0, ABFLAG_NONE},
258
259     { ABIL_EVOKE_TURN_INVISIBLE, "Evoke Invisibility",
260       2, 0, 250, 0, 0, ABFLAG_NONE},
261     { ABIL_EVOKE_TURN_VISIBLE, "Turn Visible", 0, 0, 0, 0, 0, ABFLAG_NONE},
262     { ABIL_EVOKE_FLIGHT, "Evoke Flight", 1, 0, 100, 0, 0, ABFLAG_NONE},
263     { ABIL_EVOKE_FOG, "Evoke Fog", 2, 0, 250, 0, 0, ABFLAG_NONE},
264     { ABIL_EVOKE_TELEPORT_CONTROL, "Evoke Teleport Control", 4, 0, 200, 0, 0, ABFLAG_NONE},
265     { ABIL_EVOKE_TWISTER, "Evoke Twister", 10, 0, 200, 0, 0, ABFLAG_NONE},
266
267     { ABIL_END_TRANSFORMATION, "End Transformation", 0, 0, 0, 0, 0, ABFLAG_NONE},
268
269     // INVOCATIONS:
270     // Zin
271     { ABIL_ZIN_RECITE, "Recite", 0, 0, 0, 0, 0, ABFLAG_BREATH},
272     { ABIL_ZIN_VITALISATION, "Vitalisation", 0, 0, 0, 1, 0, ABFLAG_NONE},
273     { ABIL_ZIN_IMPRISON, "Imprison", 5, 0, 125, 4, 0, ABFLAG_NONE},
274     { ABIL_ZIN_SANCTUARY, "Sanctuary", 7, 0, 150, 15, 0, ABFLAG_NONE},
275     { ABIL_ZIN_CURE_ALL_MUTATIONS, "Cure All Mutations",
276       0, 0, 0, 0, 0, ABFLAG_NONE},
277
278     // The Shining One
279     { ABIL_TSO_DIVINE_SHIELD, "Divine Shield", 3, 0, 50, 2, 0, ABFLAG_NONE},
280     { ABIL_TSO_CLEANSING_FLAME, "Cleansing Flame",
281       5, 0, 100, 2, 0, ABFLAG_NONE},
282     { ABIL_TSO_SUMMON_DIVINE_WARRIOR, "Summon Divine Warrior",
283       8, 0, 150, 5, 0, ABFLAG_NONE},
284
285     // Kikubaaqudgha
286     { ABIL_KIKU_RECEIVE_CORPSES, "Receive Corpses",
287       3, 0, 50, 2, 0, ABFLAG_NONE},
288     { ABIL_KIKU_TORMENT, "Torment", 4, 0, 0, 8, 0, ABFLAG_NONE},
289
290     // Yredelemnul
291     { ABIL_YRED_INJURY_MIRROR, "Injury Mirror", 0, 0, 0, 0, 0, ABFLAG_PIETY},
292     { ABIL_YRED_ANIMATE_REMAINS, "Animate Remains",
293       2, 0, 50, 0, 0, ABFLAG_NONE},
294     { ABIL_YRED_RECALL_UNDEAD_SLAVES, "Recall Undead Slaves",
295       2, 0, 50, 0, 0, ABFLAG_NONE},
296     { ABIL_YRED_ANIMATE_DEAD, "Animate Dead", 2, 0, 50, 0, 0, ABFLAG_NONE},
297     { ABIL_YRED_DRAIN_LIFE, "Drain Life", 6, 0, 200, 2, 0, ABFLAG_NONE},
298     { ABIL_YRED_ENSLAVE_SOUL, "Enslave Soul", 8, 0, 150, 4, 0, ABFLAG_NONE},
299     // Placeholder for Animate Remains or Animate Dead.
300     { ABIL_YRED_ANIMATE_REMAINS_OR_DEAD, "Animate Remains or Dead",
301       2, 0, 100, 0, 0, ABFLAG_NONE},
302
303     // Okawaru
304     { ABIL_OKAWARU_HEROISM, "Heroism", 2, 0, 50, 2, 0, ABFLAG_NONE},
305     { ABIL_OKAWARU_FINESSE, "Finesse", 5, 0, 100, 4, 0, ABFLAG_NONE},
306
307     // Makhleb
308     { ABIL_MAKHLEB_MINOR_DESTRUCTION, "Minor Destruction",
309       0, scaling_cost::fixed(1), 20, 0, 0, ABFLAG_NONE},
310     { ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB, "Lesser Servant of Makhleb",
311       0, scaling_cost::fixed(4), 50, 2, 0, ABFLAG_NONE},
312     { ABIL_MAKHLEB_MAJOR_DESTRUCTION, "Major Destruction",
313       0, scaling_cost::fixed(6), 100, generic_cost::range(0, 1), 0, ABFLAG_NONE},
314     { ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB, "Greater Servant of Makhleb",
315       0, scaling_cost::fixed(10), 100, 5, 0, ABFLAG_NONE},
316
317     // Sif Muna
318     { ABIL_SIF_MUNA_CHANNEL_ENERGY, "Channel Energy",
319       0, 0, 100, 0, 0, ABFLAG_NONE},
320     { ABIL_SIF_MUNA_FORGET_SPELL, "Forget Spell", 5, 0, 0, 8, 0, ABFLAG_NONE},
321
322     // Trog
323     { ABIL_TROG_BURN_SPELLBOOKS, "Burn Spellbooks",
324       0, 0, 10, 0, 0, ABFLAG_NONE},
325     { ABIL_TROG_BERSERK, "Berserk", 0, 0, 200, 0, 0, ABFLAG_NONE},
326     { ABIL_TROG_REGEN_MR, "Trog's Hand",
327       0, 0, 50, generic_cost::range(2, 3), 0, ABFLAG_NONE},
328     { ABIL_TROG_BROTHERS_IN_ARMS, "Brothers in Arms",
329       0, 0, 100, generic_cost::range(5, 6), 0, ABFLAG_NONE},
330
331     // Elyvilon
332     { ABIL_ELYVILON_LIFESAVING, "Divine Protection",
333       0, 0, 0, 0, 0, ABFLAG_NONE},
334     { ABIL_ELYVILON_LESSER_HEALING, "Lesser Healing",
335       1, 0, 100, generic_cost::range(0, 1), 0, ABFLAG_CONF_OK},
336     { ABIL_ELYVILON_HEAL_OTHER, "Heal Other",
337       2, 0, 250, 2, 0, ABFLAG_NONE},
338     { ABIL_ELYVILON_PURIFICATION, "Purification", 3, 0, 300, 3, 0,
339       ABFLAG_CONF_OK},
340     { ABIL_ELYVILON_GREATER_HEALING, "Greater Healing",
341       2, 0, 250, 3, 0, ABFLAG_CONF_OK},
342     { ABIL_ELYVILON_DIVINE_VIGOUR, "Divine Vigour", 0, 0, 600, 6, 0,
343       ABFLAG_CONF_OK},
344
345     // Lugonu
346     { ABIL_LUGONU_ABYSS_EXIT, "Depart the Abyss",
347       1, 0, 150, 10, 0, ABFLAG_NONE},
348     { ABIL_LUGONU_BEND_SPACE, "Bend Space", 1, 0, 50, 0, 0, ABFLAG_PAIN},
349     { ABIL_LUGONU_BANISH, "Banish",
350       4, 0, 200, generic_cost::range(3, 4), 0, ABFLAG_NONE},
351     { ABIL_LUGONU_CORRUPT, "Corrupt",
352       7, scaling_cost::fixed(5), 500, generic_cost::range(10, 14), 0, ABFLAG_NONE},
353     { ABIL_LUGONU_ABYSS_ENTER, "Enter the Abyss",
354       9, 0, 500, generic_cost::fixed(35), 0, ABFLAG_PAIN},
355
356     // Nemelex
357     { ABIL_NEMELEX_TRIPLE_DRAW, "Triple Draw", 2, 0, 100, 2, 0, ABFLAG_NONE},
358     { ABIL_NEMELEX_DEAL_FOUR, "Deal Four", 8, 0, 200, 8, 0, ABFLAG_NONE},
359     { ABIL_NEMELEX_STACK_FIVE, "Stack Five", 5, 0, 250, 10, 0, ABFLAG_NONE},
360
361     // Beogh
362     { ABIL_BEOGH_SMITING, "Smiting",
363       3, 0, 80, generic_cost::fixed(3), 0, ABFLAG_NONE},
364     { ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS, "Recall Orcish Followers",
365       2, 0, 50, 0, 0, ABFLAG_NONE},
366     { ABIL_BEOGH_GIFT_ITEM, "Give Item to Named Follower",
367       0, 0, 0, 0, 0, ABFLAG_NONE},
368
369     // Jiyva
370     { ABIL_JIYVA_CALL_JELLY, "Request Jelly", 2, 0, 20, 1, 0, ABFLAG_NONE},
371     { ABIL_JIYVA_JELLY_PARALYSE, "Jelly Paralyse", 0, 0, 0, 0, 0, ABFLAG_PIETY},
372     { ABIL_JIYVA_SLIMIFY, "Slimify", 4, 0, 100, 8, 0, ABFLAG_NONE},
373     { ABIL_JIYVA_CURE_BAD_MUTATION, "Cure Bad Mutation",
374       8, 0, 200, 15, 0, ABFLAG_NONE},
375
376     // Fedhas
377     { ABIL_FEDHAS_EVOLUTION, "Evolution", 2, 0, 0, 0, 0, ABFLAG_VARIABLE_FRUIT},
378     { ABIL_FEDHAS_SUNLIGHT, "Sunlight", 2, 0, 50, 0, 0, ABFLAG_NONE},
379     { ABIL_FEDHAS_PLANT_RING, "Growth", 2, 0, 0, 0, 0, ABFLAG_FRUIT},
380     { ABIL_FEDHAS_SPAWN_SPORES, "Reproduction", 4, 0, 100, 1, 0, ABFLAG_NONE},
381     { ABIL_FEDHAS_RAIN, "Rain", 4, 0, 150, 4, 0, ABFLAG_NONE},
382
383     // Cheibriados
384     { ABIL_CHEIBRIADOS_TIME_BEND, "Bend Time", 3, 0, 50, 1, 0, ABFLAG_NONE},
385     { ABIL_CHEIBRIADOS_DISTORTION, "Temporal Distortion",
386       4, 0, 200, 3, 0, ABFLAG_INSTANT},
387     { ABIL_CHEIBRIADOS_SLOUCH, "Slouch", 5, 0, 100, 8, 0, ABFLAG_NONE},
388     { ABIL_CHEIBRIADOS_TIME_STEP, "Step From Time",
389       10, 0, 200, 10, 0, ABFLAG_NONE},
390
391     // Ashenzari
392     { ABIL_ASHENZARI_SCRYING, "Scrying",
393       4, 0, 50, generic_cost::range(2, 3), 0, ABFLAG_INSTANT},
394     { ABIL_ASHENZARI_TRANSFER_KNOWLEDGE, "Transfer Knowledge",
395       0, 0, 0, 20, 0, ABFLAG_NONE},
396     { ABIL_ASHENZARI_END_TRANSFER, "End Transfer Knowledge",
397       0, 0, 0, 0, 0, ABFLAG_NONE},
398
399     // Dithmenos
400     { ABIL_DITHMENOS_SHADOW_STEP, "Shadow Step",
401       4, 0, 0, 4, 0, ABFLAG_NONE },
402     { ABIL_DITHMENOS_SHADOW_FORM, "Shadow Form",
403       9, 0, 0, 10, 0, ABFLAG_SKILL_DRAIN },
404
405     // Ru
406     { ABIL_RU_DRAW_OUT_POWER, "Draw Out Power",
407       0, 0, 0, 0, 0, ABFLAG_EXHAUSTION|ABFLAG_SKILL_DRAIN|ABFLAG_CONF_OK },
408     { ABIL_RU_POWER_LEAP, "Power Leap",
409       5, 0, 0, 0, 0, ABFLAG_EXHAUSTION },
410     { ABIL_RU_APOCALYPSE, "Apocalypse",
411       8, 0, 0, 0, 0, ABFLAG_EXHAUSTION|ABFLAG_SKILL_DRAIN },
412
413     { ABIL_RU_SACRIFICE_PURITY, "Sacrifice Purity",
414       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
415     { ABIL_RU_SACRIFICE_WORDS, "Sacrifice Words",
416       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
417     { ABIL_RU_SACRIFICE_DRINK, "Sacrifice Drink",
418       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
419     { ABIL_RU_SACRIFICE_ESSENCE, "Sacrifice Essence",
420       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
421     { ABIL_RU_SACRIFICE_HEALTH, "Sacrifice Health",
422       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
423     { ABIL_RU_SACRIFICE_STEALTH, "Sacrifice Stealth",
424       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
425     { ABIL_RU_SACRIFICE_ARTIFICE, "Sacrifice Artifice",
426       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
427     { ABIL_RU_SACRIFICE_LOVE, "Sacrifice Love",
428       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
429     { ABIL_RU_SACRIFICE_COURAGE, "Sacrifice Courage",
430       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
431     { ABIL_RU_SACRIFICE_ARCANA, "Sacrifice Arcana",
432       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
433     { ABIL_RU_SACRIFICE_NIMBLENESS, "Sacrifice Nimbleness",
434       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
435     { ABIL_RU_SACRIFICE_DURABILITY, "Sacrifice Durability",
436       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
437     { ABIL_RU_SACRIFICE_HAND, "Sacrifice a Hand",
438       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
439     { ABIL_RU_SACRIFICE_EXPERIENCE, "Sacrifice Experience",
440       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
441     { ABIL_RU_SACRIFICE_SKILL, "Sacrifice Skill",
442       0, 0, 0, 0, 0, ABFLAG_SACRIFICE },
443     { ABIL_RU_REJECT_SACRIFICES, "Reject Sacrifices",
444       0, 0, 0, 0, 0, ABFLAG_NONE },
445
446     // Gozag
447     { ABIL_GOZAG_POTION_PETITION, "Potion Petition",
448       0, 0, 0, 0, 0, ABFLAG_GOLD },
449     { ABIL_GOZAG_CALL_MERCHANT, "Call Merchant",
450       0, 0, 0, 0, 0, ABFLAG_GOLD },
451     { ABIL_GOZAG_BRIBE_BRANCH, "Bribe Branch",
452       0, 0, 0, 0, 0, ABFLAG_GOLD },
453
454     // Qazlal
455     { ABIL_QAZLAL_UPHEAVAL, "Upheaval", 4, 0, 0, 3, 0, ABFLAG_NONE },
456     { ABIL_QAZLAL_ELEMENTAL_FORCE, "Elemental Force",
457       6, 0, 0, 6, 0, ABFLAG_NONE },
458     { ABIL_QAZLAL_DISASTER_AREA, "Disaster Area", 7, 0, 0,
459       generic_cost::range(10, 14), 0, ABFLAG_NONE },
460
461     { ABIL_STOP_RECALL, "Stop Recall", 0, 0, 0, 0, 0, ABFLAG_NONE},
462
463     // zot defence abilities
464     { ABIL_MAKE_FUNGUS, "Make mushroom circle", 0, 0, 0, 0, 10, ABFLAG_ZOTDEF},
465     { ABIL_MAKE_PLANT, "Make plant", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
466     { ABIL_MAKE_OKLOB_SAPLING, "Make oklob sapling", 0, 0, 0, 0, 60, ABFLAG_ZOTDEF},
467     { ABIL_MAKE_BURNING_BUSH, "Make burning bush", 0, 0, 0, 0, 200, ABFLAG_ZOTDEF},
468     { ABIL_MAKE_OKLOB_PLANT, "Make oklob plant", 0, 0, 0, 0, 250, ABFLAG_ZOTDEF},
469     { ABIL_MAKE_ICE_STATUE, "Make ice statue", 0, 0, 0, 0, 2000, ABFLAG_ZOTDEF},
470     { ABIL_MAKE_OCS, "Make crystal statue", 0, 0, 0, 0, 2000, ABFLAG_ZOTDEF},
471     { ABIL_MAKE_OBSIDIAN_STATUE, "Make obsidian statue", 0, 0, 0, 0, 3000, ABFLAG_ZOTDEF},
472     { ABIL_MAKE_CURSE_SKULL, "Make curse skull",
473       0, 0, 600, 0, 10000, ABFLAG_ZOTDEF|ABFLAG_NECRO_MISCAST_MINOR},
474     { ABIL_MAKE_TELEPORT, "Zot-teleport", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
475     { ABIL_MAKE_ARROW_TRAP, "Make arrow trap", 0, 0, 0, 0, 30, ABFLAG_ZOTDEF},
476     { ABIL_MAKE_BOLT_TRAP, "Make bolt trap", 0, 0, 0, 0, 300, ABFLAG_ZOTDEF},
477     { ABIL_MAKE_SPEAR_TRAP, "Make spear trap", 0, 0, 0, 0, 50, ABFLAG_ZOTDEF},
478     { ABIL_MAKE_NEEDLE_TRAP, "Make needle trap", 0, 0, 0, 0, 30, ABFLAG_ZOTDEF},
479     { ABIL_MAKE_NET_TRAP, "Make net trap", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
480     { ABIL_MAKE_ALARM_TRAP, "Make alarm trap", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
481     { ABIL_MAKE_BLADE_TRAP, "Make blade trap", 0, 0, 0, 0, 3000, ABFLAG_ZOTDEF},
482     { ABIL_MAKE_OKLOB_CIRCLE, "Make oklob circle", 0, 0, 0, 0, 1000, ABFLAG_ZOTDEF},
483     { ABIL_MAKE_ACQUIRE_GOLD, "Acquire gold",
484       0, 0, 0, 0, 0, ABFLAG_ZOTDEF|ABFLAG_LEVEL_DRAIN},
485     { ABIL_MAKE_ACQUIREMENT, "Acquirement",
486       0, 0, 0, 0, 0, ABFLAG_ZOTDEF|ABFLAG_LEVEL_DRAIN},
487     { ABIL_MAKE_WATER, "Make water", 0, 0, 0, 0, 10, ABFLAG_ZOTDEF},
488     { ABIL_MAKE_LIGHTNING_SPIRE, "Make lightning spire", 0, 0, 0, 0, 100, ABFLAG_ZOTDEF},
489     { ABIL_MAKE_BAZAAR, "Make bazaar",
490       0, 30, 0, 0, 100, ABFLAG_ZOTDEF|ABFLAG_PERMANENT_HP},
491     { ABIL_MAKE_ALTAR, "Make altar", 0, 0, 0, 0, 50, ABFLAG_ZOTDEF},
492     { ABIL_MAKE_GRENADES, "Make grenades", 0, 0, 0, 0, 2, ABFLAG_ZOTDEF},
493     { ABIL_REMOVE_CURSE, "Remove Curse",
494       0, 0, 0, 0, 0, ABFLAG_ZOTDEF|ABFLAG_STAT_DRAIN},
495
496     { ABIL_RENOUNCE_RELIGION, "Renounce Religion", 0, 0, 0, 0, 0, ABFLAG_NONE},
497     { ABIL_CONVERT_TO_BEOGH, "Convert to Beogh", 0, 0, 0, 0, 0, ABFLAG_NONE},
498 };
499
500 const ability_def& get_ability_def(ability_type abil)
501 {
502     for (const ability_def &ab_def : Ability_List)
503         if (ab_def.ability == abil)
504             return ab_def;
505
506     return Ability_List[0];
507 }
508
509 /**
510  * Is there a valid ability with a name matching that given?
511  *
512  * @param key   The name in question. (Not case sensitive.)
513  * @return      true if such an ability exists; false if not.
514  */
515 bool string_matches_ability_name(const string& key)
516 {
517     return ability_by_name(key) != ABIL_NON_ABILITY;
518 }
519
520 /**
521  * Find an ability whose name matches the given key.
522  *
523  * @param name      The name in question. (Not case sensitive.)
524  * @return          The enum of the relevant ability, if there was one; else
525  *                  ABIL_NON_ABILITY.
526  */
527 ability_type ability_by_name(const string &key)
528 {
529     for (const auto &abil : Ability_List)
530     {
531         if (abil.ability == ABIL_NON_ABILITY)
532             continue;
533
534         // don't display zot abilties outside zotdef
535         if ((abil.flags & ABFLAG_ZOTDEF) && !crawl_state.game_is_zotdef())
536             continue;
537
538         const string name = lowercase_string(ability_name(abil.ability));
539         if (name == lowercase_string(key))
540             return abil.ability;
541     }
542
543     return ABIL_NON_ABILITY;
544 }
545
546 string print_abilities()
547 {
548     string text = "\n<w>a:</w> ";
549
550     const vector<talent> talents = your_talents(false);
551
552     if (talents.empty())
553         text += "no special abilities";
554     else
555     {
556         for (unsigned int i = 0; i < talents.size(); ++i)
557         {
558             if (i)
559                 text += ", ";
560             text += ability_name(talents[i].which);
561         }
562     }
563
564     return text;
565 }
566
567 static monster_type _monster_for_ability(const ability_def& abil)
568 {
569     monster_type mtyp = MONS_PROGRAM_BUG;
570     switch (abil.ability)
571     {
572         case ABIL_MAKE_PLANT:         mtyp = MONS_PLANT;         break;
573         case ABIL_MAKE_FUNGUS:        mtyp = MONS_FUNGUS;        break;
574         case ABIL_MAKE_OKLOB_SAPLING: mtyp = MONS_OKLOB_SAPLING; break;
575         case ABIL_MAKE_OKLOB_CIRCLE:
576         case ABIL_MAKE_OKLOB_PLANT:   mtyp = MONS_OKLOB_PLANT;   break;
577         case ABIL_MAKE_BURNING_BUSH:  mtyp = MONS_BURNING_BUSH;  break;
578         case ABIL_MAKE_LIGHTNING_SPIRE:  mtyp = MONS_LIGHTNING_SPIRE;  break;
579         case ABIL_MAKE_ICE_STATUE:    mtyp = MONS_ICE_STATUE;    break;
580         case ABIL_MAKE_OCS:           mtyp = MONS_ORANGE_STATUE; break;
581         case ABIL_MAKE_OBSIDIAN_STATUE: mtyp = MONS_OBSIDIAN_STATUE; break;
582         case ABIL_MAKE_CURSE_SKULL:   mtyp = MONS_CURSE_SKULL;   break;
583         default:
584             mprf("DEBUG: NO RELEVANT MONSTER FOR %d", abil.ability);
585             break;
586     }
587     return mtyp;
588 }
589
590 static string _zd_mons_description_for_ability(const ability_def &abil)
591 {
592     switch (abil.ability)
593     {
594     case ABIL_MAKE_PLANT:
595         return "Tendrils and shoots erupt from the earth and gnarl into the form of a plant.";
596     case ABIL_MAKE_OKLOB_SAPLING:
597         return "A rhizome shoots up through the ground and merges with vitriolic spirits in the atmosphere.";
598     case ABIL_MAKE_OKLOB_PLANT:
599         return "A rhizome shoots up through the ground and merges with vitriolic spirits in the atmosphere.";
600     case ABIL_MAKE_BURNING_BUSH:
601         return "Blackened shoots writhe from the ground and burst into flame!";
602     case ABIL_MAKE_ICE_STATUE:
603         return "Water vapor collects and crystallises into an icy humanoid shape.";
604     case ABIL_MAKE_OCS:
605         return "Quartz juts from the ground and forms a humanoid shape. You smell citrus.";
606     case ABIL_MAKE_OBSIDIAN_STATUE:
607         return "Molten obsidian falls from the ceiling and solidifies into a vaguely humanoid shape.";
608     case ABIL_MAKE_CURSE_SKULL:
609         return "You sculpt a terrible being from the primitive principle of evil.";
610     case ABIL_MAKE_LIGHTNING_SPIRE:
611         return "You mount a charged rod inside a coil.";
612     default:
613         return "";
614     }
615 }
616
617 static int _count_relevant_monsters(const ability_def& abil)
618 {
619     monster_type mtyp = _monster_for_ability(abil);
620     if (mtyp == MONS_PROGRAM_BUG)
621         return 0;
622     return count_monsters(mtyp, true);        // Friendly ones only
623 }
624
625 static trap_type _trap_for_ability(const ability_def& abil)
626 {
627     switch (abil.ability)
628     {
629         case ABIL_MAKE_ARROW_TRAP: return TRAP_ARROW;
630         case ABIL_MAKE_BOLT_TRAP: return TRAP_BOLT;
631         case ABIL_MAKE_SPEAR_TRAP: return TRAP_SPEAR;
632         case ABIL_MAKE_NEEDLE_TRAP: return TRAP_NEEDLE;
633         case ABIL_MAKE_NET_TRAP: return TRAP_NET;
634         case ABIL_MAKE_ALARM_TRAP: return TRAP_ALARM;
635         case ABIL_MAKE_BLADE_TRAP: return TRAP_BLADE;
636         default: return TRAP_UNASSIGNED;
637     }
638 }
639
640 // Scale the zp cost by the number of friendly monsters
641 // of that type. Each successive critter costs 20% more
642 // than the last one, after the first two.
643 static int _zp_cost(const ability_def& abil)
644 {
645     int cost = abil.zp_cost;
646     int scale10 = 0;        // number of times to scale up by 10%
647     int scale20 = 0;        // number of times to scale up by 20%
648     int num;
649     switch (abil.ability)
650     {
651         default:
652             return abil.zp_cost;
653
654         // Monster type 1: reasonably generous
655         case ABIL_MAKE_PLANT:
656         case ABIL_MAKE_FUNGUS:
657         case ABIL_MAKE_OKLOB_SAPLING:
658         case ABIL_MAKE_OKLOB_PLANT:
659         case ABIL_MAKE_OKLOB_CIRCLE:
660         case ABIL_MAKE_BURNING_BUSH:
661         case ABIL_MAKE_LIGHTNING_SPIRE:
662             num = _count_relevant_monsters(abil);
663             // special case for oklob circles
664             if (abil.ability == ABIL_MAKE_OKLOB_CIRCLE)
665                 num /= 3;
666             // ... and for harmless stuff
667             else if (abil.ability == ABIL_MAKE_PLANT
668                      || abil.ability == ABIL_MAKE_FUNGUS)
669             {
670                 num /= 5;
671             }
672             num -= 2;        // first two are base cost
673             num = max(num, 0);
674             scale10 = min(num, 10);       // next 10 at 10% increment
675             scale20 = num - scale10;      // after that at 20% increment
676             break;
677
678         // Monster type 2: less generous
679         case ABIL_MAKE_ICE_STATUE:
680         case ABIL_MAKE_OCS:
681             num = _count_relevant_monsters(abil);
682             num -= 2; // first two are base cost
683             scale20 = max(num, 0);        // after first two, 20% increment
684             break;
685
686         // Monster type 3: least generous
687         case ABIL_MAKE_OBSIDIAN_STATUE:
688         case ABIL_MAKE_CURSE_SKULL:
689             scale20 = _count_relevant_monsters(abil); // scale immediately
690             break;
691
692         // Simple Traps
693         case ABIL_MAKE_ARROW_TRAP:
694         case ABIL_MAKE_BOLT_TRAP:
695         case ABIL_MAKE_SPEAR_TRAP:
696         case ABIL_MAKE_NEEDLE_TRAP:
697         case ABIL_MAKE_NET_TRAP:
698         case ABIL_MAKE_ALARM_TRAP:
699             num = count_traps(_trap_for_ability(abil));
700             scale10 = max(num-5, 0);   // First 5 at base cost
701             break;
702
703         case ABIL_MAKE_BLADE_TRAP:
704             scale10 = count_traps(TRAP_BLADE); // Max of 18-ish at base cost 3000
705             break;
706     }
707
708     float c = cost; // stave off round-off errors
709     for (; scale10 > 0; scale10--)
710         c = c * 1.1;        // +10%
711     for (; scale20 > 0; scale20--)
712         c = c * 1.2;        // +20%
713
714     return c;
715 }
716
717 int get_gold_cost(ability_type ability)
718 {
719     switch (ability)
720     {
721     case ABIL_GOZAG_CALL_MERCHANT:
722         return gozag_price_for_shop(true);
723     case ABIL_GOZAG_POTION_PETITION:
724         return gozag_potion_price();
725     case ABIL_GOZAG_BRIBE_BRANCH:
726         return GOZAG_BRIBE_AMOUNT;
727     default:
728         return 0;
729     }
730 }
731
732 const string make_cost_description(ability_type ability)
733 {
734     const ability_def& abil = get_ability_def(ability);
735     string ret;
736     if (abil.mp_cost)
737     {
738         ret += make_stringf(", %d %sMP", abil.mp_cost,
739             abil.flags & ABFLAG_PERMANENT_MP ? "Permanent " : "");
740     }
741
742     if (abil.hp_cost)
743     {
744         ret += make_stringf(", %d %sHP", abil.hp_cost.cost(you.hp_max),
745             abil.flags & ABFLAG_PERMANENT_HP ? "Permanent " : "");
746     }
747
748     if (abil.zp_cost)
749         ret += make_stringf(", %d ZP", (int)_zp_cost(abil));
750
751     if (abil.food_cost && !you_foodless(true)
752         && (you.undead_state() != US_SEMI_UNDEAD
753             || you.hunger_state > HS_STARVING))
754     {
755         ret += ", Hunger"; // randomised and exact amount hidden from player
756     }
757
758     if (abil.piety_cost || abil.flags & ABFLAG_PIETY)
759         ret += ", Piety"; // randomised and exact amount hidden from player
760
761     if (abil.flags & ABFLAG_BREATH)
762         ret += ", Breath";
763
764     if (abil.flags & ABFLAG_DELAY)
765         ret += ", Delay";
766
767     if (abil.flags & ABFLAG_PAIN)
768         ret += ", Pain";
769
770     if (abil.flags & ABFLAG_EXHAUSTION)
771         ret += ", Exhaustion";
772
773     if (abil.flags & ABFLAG_INSTANT)
774         ret += ", Instant"; // not really a cost, more of a bonus - bwr
775
776     if (abil.flags & ABFLAG_FRUIT)
777         ret += ", Fruit";
778
779     if (abil.flags & ABFLAG_VARIABLE_FRUIT)
780         ret += ", Fruit or Piety";
781
782     if (abil.flags & ABFLAG_LEVEL_DRAIN)
783         ret += ", Level drain";
784
785     if (abil.flags & ABFLAG_STAT_DRAIN)
786         ret += ", Stat drain";
787
788     if (abil.flags & ABFLAG_SKILL_DRAIN)
789         ret += ", Skill drain";
790
791     if (abil.flags & ABFLAG_GOLD)
792     {
793         const int amount = get_gold_cost(ability);
794         if (amount)
795             ret += make_stringf(", %d Gold", amount);
796         else if (ability == ABIL_GOZAG_POTION_PETITION)
797             ret += ", Free";
798         else
799             ret += ", Gold";
800     }
801
802     if (abil.flags & ABFLAG_SACRIFICE)
803     {
804         ret += ", ";
805         const string prefix = "Sacrifice ";
806         ret += string(ability_name(ability)).substr(prefix.size());
807         ret += ru_sac_text(ability);
808     }
809
810     // If we haven't output anything so far, then the effect has no cost
811     if (ret.empty())
812         return "None";
813
814     ret.erase(0, 2);
815     return ret;
816 }
817
818 static string _get_piety_amount_str(int value)
819 {
820     return value > 15 ? "extremely large" :
821            value > 10 ? "large" :
822            value > 5  ? "moderate" :
823                         "small";
824 }
825
826 static const string _detailed_cost_description(ability_type ability)
827 {
828     const ability_def& abil = get_ability_def(ability);
829     ostringstream ret;
830     vector<string> values;
831     string str;
832
833     bool have_cost = false;
834     ret << "This ability costs: ";
835
836     if (abil.mp_cost > 0)
837     {
838         have_cost = true;
839         if (abil.flags & ABFLAG_PERMANENT_MP)
840             ret << "\nMax MP : ";
841         else
842             ret << "\nMP     : ";
843         ret << abil.mp_cost;
844     }
845     if (abil.hp_cost)
846     {
847         have_cost = true;
848         if (abil.flags & ABFLAG_PERMANENT_HP)
849             ret << "\nMax HP : ";
850         else
851             ret << "\nHP     : ";
852         ret << abil.hp_cost.cost(you.hp_max);
853     }
854     if (abil.zp_cost)
855     {
856         have_cost = true;
857         ret << "\nZP     : ";
858         ret << abil.zp_cost;
859     }
860
861     if (abil.food_cost && !you_foodless(true)
862         && (you.undead_state() != US_SEMI_UNDEAD
863             || you.hunger_state > HS_STARVING))
864     {
865         have_cost = true;
866         ret << "\nHunger : ";
867         ret << hunger_cost_string(abil.food_cost + abil.food_cost / 2);
868     }
869
870     if (abil.piety_cost || abil.flags & ABFLAG_PIETY)
871     {
872         have_cost = true;
873         ret << "\nPiety  : ";
874         if (abil.flags & ABFLAG_PIETY)
875             ret << "variable";
876         else
877         {
878             int avgcost = abil.piety_cost.base + abil.piety_cost.add / 2;
879             ret << _get_piety_amount_str(avgcost);
880         }
881     }
882
883     if (abil.flags & ABFLAG_GOLD)
884     {
885         have_cost = true;
886         ret << "\nGold   : ";
887         int gold_amount = get_gold_cost(ability);
888         if (gold_amount)
889             ret << gold_amount;
890         else if (ability == ABIL_GOZAG_POTION_PETITION)
891             ret << "free";
892         else
893             ret << "variable";
894     }
895
896     if (!have_cost)
897         ret << "nothing.";
898
899     if (abil.flags & ABFLAG_BREATH)
900         ret << "\nYou must catch your breath between uses of this ability.";
901
902     if (abil.flags & ABFLAG_DELAY)
903         ret << "\nIt takes some time before being effective.";
904
905     if (abil.flags & ABFLAG_PAIN)
906         ret << "\nUsing this ability will hurt you.";
907
908     if (abil.flags & ABFLAG_EXHAUSTION)
909         ret << "\nIt cannot be used when exhausted.";
910
911     if (abil.flags & ABFLAG_INSTANT)
912         ret << "\nIt is instantaneous.";
913
914     if (abil.flags & ABFLAG_CONF_OK)
915         ret << "\nYou can use it even if confused.";
916
917     if (abil.flags & ABFLAG_LEVEL_DRAIN)
918         ret << "\nIt will lower your experience level by one when used.";
919
920     if (abil.flags & ABFLAG_STAT_DRAIN)
921         ret << "\nIt will temporarily drain your strength, intelligence or dexterity when used.";
922
923     if (abil.flags & ABFLAG_SKILL_DRAIN)
924         ret << "\nIt will temporarily drain your skills when used.";
925
926     return ret.str();
927 }
928
929 static ability_type _fixup_ability(ability_type ability)
930 {
931     switch (ability)
932     {
933     case ABIL_YRED_ANIMATE_REMAINS_OR_DEAD:
934         // Placeholder for Animate Remains or Animate Dead.
935         if (yred_can_animate_dead())
936             return ABIL_YRED_ANIMATE_DEAD;
937         else
938             return ABIL_YRED_ANIMATE_REMAINS;
939
940     case ABIL_YRED_RECALL_UNDEAD_SLAVES:
941     case ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS:
942         if (!you.recall_list.empty())
943             return ABIL_STOP_RECALL;
944         return ability;
945
946     case ABIL_EVOKE_BERSERK:
947     case ABIL_TROG_BERSERK:
948         if (you.is_lifeless_undead(false)
949             || you.species == SP_FORMICID)
950         {
951             return ABIL_NON_ABILITY;
952         }
953         return ability;
954
955     case ABIL_OKAWARU_FINESSE:
956     case ABIL_BLINK:
957     case ABIL_EVOKE_BLINK:
958         if (you.species == SP_FORMICID)
959             return ABIL_NON_ABILITY;
960         else
961             return ability;
962
963     default:
964         return ability;
965     }
966 }
967
968 talent get_talent(ability_type ability, bool check_confused)
969 {
970     ASSERT(ability != ABIL_NON_ABILITY);
971
972     talent result;
973     // Placeholder handling, part 1: The ability we have might be a
974     // placeholder, so convert it into its corresponding ability before
975     // doing anything else, so that we'll handle its flags properly.
976     result.which = _fixup_ability(ability);
977
978     const ability_def &abil = get_ability_def(result.which);
979
980     int failure = 0;
981     bool invoc = false;
982
983     if (check_confused)
984     {
985         if (you.confused() && !testbits(abil.flags, ABFLAG_CONF_OK))
986         {
987             // Initialize these so compilers don't complain.
988             result.is_invocation = 0;
989             result.is_zotdef = 0;
990             result.hotkey = 0;
991             result.fail = 0;
992
993             result.which = ABIL_NON_ABILITY;
994             return result;
995         }
996     }
997
998     // Look through the table to see if there's a preference, else find
999     // a new empty slot for this ability. - bwr
1000     const int index = _find_ability_slot(abil);
1001     if (index != -1)
1002         result.hotkey = index_to_letter(index);
1003     else
1004         result.hotkey = 0;      // means 'find later on'
1005
1006     switch (ability)
1007     {
1008     // begin spell abilities
1009     case ABIL_DELAYED_FIREBALL:
1010     case ABIL_MUMMY_RESTORATION:
1011     case ABIL_STOP_SINGING:
1012         failure = 0;
1013         break;
1014
1015     // begin zot defence abilities
1016     case ABIL_MAKE_FUNGUS:
1017     case ABIL_MAKE_PLANT:
1018     case ABIL_MAKE_OKLOB_PLANT:
1019     case ABIL_MAKE_OKLOB_SAPLING:
1020     case ABIL_MAKE_BURNING_BUSH:
1021     case ABIL_MAKE_ICE_STATUE:
1022     case ABIL_MAKE_OCS:
1023     case ABIL_MAKE_OBSIDIAN_STATUE:
1024     case ABIL_MAKE_CURSE_SKULL:
1025     case ABIL_MAKE_TELEPORT:
1026     case ABIL_MAKE_ARROW_TRAP:
1027     case ABIL_MAKE_BOLT_TRAP:
1028     case ABIL_MAKE_SPEAR_TRAP:
1029     case ABIL_MAKE_NEEDLE_TRAP:
1030     case ABIL_MAKE_NET_TRAP:
1031     case ABIL_MAKE_ALARM_TRAP:
1032     case ABIL_MAKE_BLADE_TRAP:
1033     case ABIL_MAKE_OKLOB_CIRCLE:
1034     case ABIL_MAKE_ACQUIRE_GOLD:
1035     case ABIL_MAKE_ACQUIREMENT:
1036     case ABIL_MAKE_WATER:
1037     case ABIL_MAKE_LIGHTNING_SPIRE:
1038     case ABIL_MAKE_BAZAAR:
1039     case ABIL_MAKE_ALTAR:
1040     case ABIL_MAKE_GRENADES:
1041     case ABIL_REMOVE_CURSE:
1042         failure = 0;
1043         break;
1044
1045     // begin species abilities - some are mutagenic, too {dlb}
1046     case ABIL_SPIT_POISON:
1047         failure = 40
1048                   - 10 * player_mutation_level(MUT_SPIT_POISON)
1049                   - you.experience_level;
1050         break;
1051
1052     case ABIL_BREATHE_FIRE:
1053         failure = ((you.species == SP_RED_DRACONIAN) ? 30 : 50)
1054                         - 10 * player_mutation_level(MUT_BREATHE_FLAMES)
1055                         - you.experience_level;
1056
1057         if (you.form == TRAN_DRAGON)
1058             failure -= 20;
1059         break;
1060     case ABIL_BREATHE_FROST:
1061     case ABIL_BREATHE_POISON:
1062     case ABIL_SPIT_ACID:
1063     case ABIL_BREATHE_LIGHTNING:
1064     case ABIL_BREATHE_POWER:
1065     case ABIL_BREATHE_STICKY_FLAME:
1066     case ABIL_BREATHE_MEPHITIC:
1067         failure = 30 - you.experience_level;
1068
1069         if (you.form == TRAN_DRAGON)
1070             failure -= 20;
1071         break;
1072
1073     case ABIL_BREATHE_STEAM:
1074         failure = 20 - you.experience_level;
1075
1076         if (you.form == TRAN_DRAGON)
1077             failure -= 20;
1078         break;
1079
1080     case ABIL_FLY:
1081         failure = 42 - (3 * you.experience_level);
1082         break;
1083
1084     case ABIL_TRAN_BAT:
1085         failure = 45 - (2 * you.experience_level);
1086         break;
1087
1088     case ABIL_RECHARGING:       // this is for deep dwarves {1KB}
1089         failure = 45 - (2 * you.experience_level);
1090         break;
1091
1092     case ABIL_DIG:
1093     case ABIL_SHAFT_SELF:
1094         failure = 0;
1095         break;
1096         // end species abilities (some mutagenic)
1097
1098         // begin demonic powers {dlb}
1099     case ABIL_HELLFIRE:
1100         failure = 50 - you.experience_level;
1101         break;
1102         // end demonic powers {dlb}
1103
1104     case ABIL_BLINK:
1105         failure = 48 - (12 * player_mutation_level(MUT_BLINK))
1106                   - you.experience_level / 2;
1107         break;
1108
1109         // begin transformation abilities {dlb}
1110     case ABIL_END_TRANSFORMATION:
1111         failure = 0;
1112         break;
1113         // end transformation abilities {dlb}
1114
1115         // begin item abilities - some possibly mutagenic {dlb}
1116     case ABIL_EVOKE_TURN_INVISIBLE:
1117     case ABIL_EVOKE_TELEPORTATION:
1118         failure = 60 - you.skill(SK_EVOCATIONS, 2);
1119         break;
1120
1121     case ABIL_EVOKE_TURN_VISIBLE:
1122     case ABIL_STOP_FLYING:
1123         failure = 0;
1124         break;
1125
1126     case ABIL_EVOKE_FLIGHT:
1127     case ABIL_EVOKE_BLINK:
1128         failure = 40 - you.skill(SK_EVOCATIONS, 2);
1129         break;
1130     case ABIL_EVOKE_BERSERK:
1131     case ABIL_EVOKE_FOG:
1132     case ABIL_EVOKE_TELEPORT_CONTROL:
1133         failure = 50 - you.skill(SK_EVOCATIONS, 2);
1134         break;
1135     case ABIL_EVOKE_TWISTER:
1136         failure = 100 - you.skill(SK_EVOCATIONS, 4);
1137         break;
1138         // end item abilities - some possibly mutagenic {dlb}
1139
1140         // begin invocations {dlb}
1141     // Abilities with no fail rate.
1142     case ABIL_ZIN_CURE_ALL_MUTATIONS:
1143     case ABIL_ELYVILON_LIFESAVING:
1144     case ABIL_TROG_BURN_SPELLBOOKS:
1145     case ABIL_ASHENZARI_TRANSFER_KNOWLEDGE:
1146     case ABIL_ASHENZARI_END_TRANSFER:
1147     case ABIL_ASHENZARI_SCRYING:
1148     case ABIL_BEOGH_GIFT_ITEM:
1149     case ABIL_JIYVA_CALL_JELLY:
1150     case ABIL_JIYVA_CURE_BAD_MUTATION:
1151     case ABIL_JIYVA_JELLY_PARALYSE:
1152     case ABIL_GOZAG_POTION_PETITION:
1153     case ABIL_GOZAG_CALL_MERCHANT:
1154     case ABIL_GOZAG_BRIBE_BRANCH:
1155     case ABIL_RU_DRAW_OUT_POWER:
1156     case ABIL_RU_POWER_LEAP:
1157     case ABIL_RU_APOCALYPSE:
1158     case ABIL_RU_SACRIFICE_PURITY:
1159     case ABIL_RU_SACRIFICE_WORDS:
1160     case ABIL_RU_SACRIFICE_DRINK:
1161     case ABIL_RU_SACRIFICE_ESSENCE:
1162     case ABIL_RU_SACRIFICE_HEALTH:
1163     case ABIL_RU_SACRIFICE_STEALTH:
1164     case ABIL_RU_SACRIFICE_ARTIFICE:
1165     case ABIL_RU_SACRIFICE_LOVE:
1166     case ABIL_RU_SACRIFICE_COURAGE:
1167     case ABIL_RU_SACRIFICE_ARCANA:
1168     case ABIL_RU_SACRIFICE_NIMBLENESS:
1169     case ABIL_RU_SACRIFICE_DURABILITY:
1170     case ABIL_RU_SACRIFICE_HAND:
1171     case ABIL_RU_SACRIFICE_EXPERIENCE:
1172     case ABIL_RU_SACRIFICE_SKILL:
1173     case ABIL_RU_REJECT_SACRIFICES:
1174     case ABIL_STOP_RECALL:
1175         invoc = true;
1176         failure = 0;
1177         break;
1178
1179     case ABIL_YRED_ANIMATE_REMAINS_OR_DEAD: // Placeholder.
1180         invoc = true;
1181         break;
1182
1183     // Trog and Jiyva abilities, only based on piety.
1184     case ABIL_TROG_BERSERK:    // piety >= 30
1185         invoc = true;
1186         failure = 0;
1187         break;
1188
1189     case ABIL_TROG_REGEN_MR:            // piety >= 50
1190         invoc = true;
1191         failure = piety_breakpoint(2) - you.piety; // starts at 25%
1192         break;
1193
1194     case ABIL_TROG_BROTHERS_IN_ARMS:    // piety >= 100
1195         invoc = true;
1196         failure = piety_breakpoint(5) - you.piety; // starts at 60%
1197         break;
1198
1199     case ABIL_JIYVA_SLIMIFY:
1200         invoc = true;
1201         failure = 90 - you.piety / 2;
1202         break;
1203
1204     // Other invocations, based on piety and Invocations skill.
1205     case ABIL_ELYVILON_PURIFICATION:
1206         invoc = true;
1207         failure = 20 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 5);
1208         break;
1209
1210     case ABIL_ZIN_RECITE:
1211     case ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS:
1212     case ABIL_OKAWARU_HEROISM:
1213     case ABIL_ELYVILON_LESSER_HEALING:
1214     case ABIL_LUGONU_ABYSS_EXIT:
1215     case ABIL_FEDHAS_SUNLIGHT:
1216     case ABIL_FEDHAS_EVOLUTION:
1217     case ABIL_DITHMENOS_SHADOW_STEP:
1218         invoc = true;
1219         failure = 30 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 6);
1220         break;
1221
1222     case ABIL_YRED_ANIMATE_REMAINS:
1223     case ABIL_YRED_ANIMATE_DEAD:
1224     case ABIL_YRED_INJURY_MIRROR:
1225     case ABIL_CHEIBRIADOS_TIME_BEND:
1226         invoc = true;
1227         failure = 40 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 4);
1228         break;
1229
1230     case ABIL_ZIN_VITALISATION:
1231     case ABIL_TSO_DIVINE_SHIELD:
1232     case ABIL_BEOGH_SMITING:
1233     case ABIL_SIF_MUNA_FORGET_SPELL:
1234     case ABIL_MAKHLEB_MINOR_DESTRUCTION:
1235     case ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB:
1236     case ABIL_ELYVILON_GREATER_HEALING:
1237     case ABIL_ELYVILON_HEAL_OTHER:
1238     case ABIL_LUGONU_BEND_SPACE:
1239     case ABIL_FEDHAS_PLANT_RING:
1240     case ABIL_QAZLAL_UPHEAVAL:
1241         invoc = true;
1242         failure = 40 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 5);
1243         break;
1244
1245     case ABIL_KIKU_RECEIVE_CORPSES:
1246         invoc = true;
1247         failure = 40 - (you.piety / 20) - you.skill(SK_NECROMANCY, 5);
1248         break;
1249
1250     case ABIL_SIF_MUNA_CHANNEL_ENERGY:
1251         invoc = true;
1252         failure = 40 - you.intel() - you.skill(SK_INVOCATIONS, 1);
1253         break;
1254
1255     case ABIL_YRED_RECALL_UNDEAD_SLAVES:
1256         invoc = true;
1257         failure = 50 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 4);
1258         break;
1259
1260     case ABIL_ZIN_IMPRISON:
1261     case ABIL_LUGONU_BANISH:
1262     case ABIL_CHEIBRIADOS_DISTORTION:
1263     case ABIL_QAZLAL_ELEMENTAL_FORCE:
1264         invoc = true;
1265         failure = 60 - (you.piety / 20) - you.skill(SK_INVOCATIONS, 5);
1266         break;
1267
1268     case ABIL_KIKU_TORMENT:
1269         invoc = true;
1270         failure = 60 - (you.piety / 20) - you.skill(SK_NECROMANCY, 5);
1271         break;
1272
1273     case ABIL_MAKHLEB_MAJOR_DESTRUCTION:
1274     case ABIL_FEDHAS_SPAWN_SPORES:
1275     case ABIL_YRED_DRAIN_LIFE:
1276     case ABIL_CHEIBRIADOS_SLOUCH:
1277     case ABIL_OKAWARU_FINESSE:
1278         invoc = true;
1279         failure = 60 - (you.piety / 25) - you.skill(SK_INVOCATIONS, 4);
1280         break;
1281
1282     case ABIL_TSO_CLEANSING_FLAME:
1283     case ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB:
1284     case ABIL_LUGONU_CORRUPT:
1285     case ABIL_FEDHAS_RAIN:
1286     case ABIL_QAZLAL_DISASTER_AREA:
1287         invoc = true;
1288         failure = 70 - (you.piety / 25) - you.skill(SK_INVOCATIONS, 4);
1289         break;
1290
1291     case ABIL_ZIN_SANCTUARY:
1292     case ABIL_TSO_SUMMON_DIVINE_WARRIOR:
1293     case ABIL_YRED_ENSLAVE_SOUL:
1294     case ABIL_ELYVILON_DIVINE_VIGOUR:
1295     case ABIL_LUGONU_ABYSS_ENTER:
1296     case ABIL_CHEIBRIADOS_TIME_STEP:
1297     case ABIL_DITHMENOS_SHADOW_FORM:
1298         invoc = true;
1299         failure = 80 - (you.piety / 25) - you.skill(SK_INVOCATIONS, 4);
1300         break;
1301
1302     case ABIL_NEMELEX_STACK_FIVE:
1303         invoc = true;
1304         failure = 80 - (you.piety / 25) - you.skill(SK_EVOCATIONS, 4);
1305         break;
1306
1307     case ABIL_NEMELEX_DEAL_FOUR:
1308         invoc = true;
1309         failure = 70 - (you.piety * 2 / 45) - you.skill(SK_EVOCATIONS, 9) / 2;
1310         break;
1311
1312     case ABIL_NEMELEX_TRIPLE_DRAW:
1313         invoc = true;
1314         failure = 60 - (you.piety / 20) - you.skill(SK_EVOCATIONS, 5);
1315         break;
1316
1317     case ABIL_RENOUNCE_RELIGION:
1318     case ABIL_CONVERT_TO_BEOGH:
1319         invoc = true;
1320         failure = 0;
1321         break;
1322
1323         // end invocations {dlb}
1324     default:
1325         failure = -1;
1326         break;
1327     }
1328
1329     if (failure < 0)
1330         failure = 0;
1331
1332     if (failure > 100)
1333         failure = 100;
1334
1335     result.fail = failure;
1336     result.is_invocation = invoc;
1337     result.is_zotdef = abil.flags & ABFLAG_ZOTDEF;
1338
1339     return result;
1340 }
1341
1342 const char* ability_name(ability_type ability)
1343 {
1344     return get_ability_def(ability).name;
1345 }
1346
1347 vector<const char*> get_ability_names()
1348 {
1349     vector<const char*> result;
1350     for (const talent &tal : your_talents(false))
1351         result.push_back(ability_name(tal.which));
1352     return result;
1353 }
1354
1355 // XXX: should this be in describe.cc?
1356 string get_ability_desc(const ability_type ability)
1357 {
1358     const string& name = ability_name(ability);
1359
1360     string lookup = getLongDescription(name + " ability");
1361
1362     if (lookup.empty()) // Nothing found?
1363         lookup = "No description found.\n";
1364
1365     if (god_hates_ability(ability, you.religion))
1366     {
1367         lookup += uppercase_first(god_name(you.religion))
1368                   + " frowns upon the use of this ability.\n";
1369     }
1370
1371     ostringstream res;
1372     res << name << "\n\n" << lookup << "\n"
1373         << _detailed_cost_description(ability);
1374
1375     const string quote = getQuoteString(name + " ability");
1376     if (!quote.empty())
1377         res << "\n\n" << quote;
1378
1379     return res.str();
1380 }
1381
1382 static void _print_talent_description(const talent& tal)
1383 {
1384     clrscr();
1385
1386     print_description(get_ability_desc(tal.which));
1387
1388     getchm();
1389     clrscr();
1390 }
1391
1392 void no_ability_msg()
1393 {
1394     // Give messages if the character cannot use innate talents right now.
1395     // * Vampires can't turn into bats when full of blood.
1396     // * Tengu can't start to fly if already flying.
1397     if (you.species == SP_VAMPIRE && you.experience_level >= 3)
1398     {
1399         ASSERT(you.hunger_state > HS_SATIATED);
1400         mpr("Sorry, you're too full to transform right now.");
1401     }
1402     else if (player_mutation_level(MUT_TENGU_FLIGHT)
1403              || player_mutation_level(MUT_BIG_WINGS))
1404     {
1405         if (you.airborne())
1406             mpr("You're already flying!");
1407     }
1408     else
1409         mpr("Sorry, you're not good enough to have a special ability.");
1410 }
1411
1412 bool activate_ability()
1413 {
1414     if (you.berserk())
1415     {
1416         canned_msg(MSG_TOO_BERSERK);
1417         crawl_state.zero_turns_taken();
1418         return false;
1419     }
1420
1421     vector<talent> talents = your_talents(false);
1422     if (talents.empty())
1423     {
1424         no_ability_msg();
1425         crawl_state.zero_turns_taken();
1426         return false;
1427     }
1428
1429     if (you.confused())
1430     {
1431         talents = your_talents(true);
1432         if (talents.empty())
1433         {
1434             canned_msg(MSG_TOO_CONFUSED);
1435             crawl_state.zero_turns_taken();
1436             return false;
1437         }
1438     }
1439 #ifdef TOUCH_UI
1440     int selected = choose_ability_menu(talents);
1441     if (selected == -1)
1442     {
1443         canned_msg(MSG_OK);
1444         crawl_state.zero_turns_taken();
1445         return false;
1446     }
1447 #else
1448     int selected = -1;
1449     while (selected < 0)
1450     {
1451         msg::streams(MSGCH_PROMPT) << "Use which ability? (? or * to list) "
1452                                    << endl;
1453
1454         const int keyin = get_ch();
1455
1456         if (keyin == '?' || keyin == '*')
1457         {
1458             selected = choose_ability_menu(talents);
1459             if (selected == -1)
1460             {
1461                 canned_msg(MSG_OK);
1462                 crawl_state.zero_turns_taken();
1463                 return false;
1464             }
1465         }
1466         else if (key_is_escape(keyin) || keyin == ' ' || keyin == '\r'
1467                  || keyin == '\n')
1468         {
1469             canned_msg(MSG_OK);
1470             crawl_state.zero_turns_taken();
1471             return false;
1472         }
1473         else if (isaalpha(keyin))
1474         {
1475             // Try to find the hotkey.
1476             for (unsigned int i = 0; i < talents.size(); ++i)
1477             {
1478                 if (talents[i].hotkey == keyin)
1479                 {
1480                     selected = static_cast<int>(i);
1481                     break;
1482                 }
1483             }
1484
1485             // If we can't, cancel out.
1486             if (selected < 0)
1487             {
1488                 mpr("You can't do that.");
1489                 crawl_state.zero_turns_taken();
1490                 return false;
1491             }
1492         }
1493     }
1494 #endif
1495     return activate_talent(talents[selected]);
1496 }
1497
1498 // Check prerequisites for a number of abilities.
1499 // Abort any attempt if these cannot be met, without losing the turn.
1500 // TODO: Many more cases need to be added!
1501 static bool _check_ability_possible(const ability_def& abil,
1502                                     bool hungerCheck = true,
1503                                     bool quiet = false)
1504 {
1505     if (you.berserk())
1506     {
1507         if (!quiet)
1508             canned_msg(MSG_TOO_BERSERK);
1509         return false;
1510     }
1511
1512     if (you.confused() && !testbits(abil.flags, ABFLAG_CONF_OK))
1513     {
1514         if (!quiet)
1515             canned_msg(MSG_TOO_CONFUSED);
1516         return false;
1517     }
1518
1519     if (silenced(you.pos()))
1520     {
1521         talent tal = get_talent(abil.ability, false);
1522         if (tal.is_invocation)
1523         {
1524             if (!quiet)
1525             {
1526                 mprf("You cannot call out to %s while silenced.",
1527                      god_name(you.religion).c_str());
1528             }
1529             return false;
1530         }
1531     }
1532     // Don't insta-starve the player.
1533     // (Losing consciousness possible from 400 downward.)
1534     if (hungerCheck && !you.undead_state())
1535     {
1536         const int expected_hunger = you.hunger - abil.food_cost * 2;
1537         if (!quiet)
1538         {
1539             dprf("hunger: %d, max. food_cost: %d, expected hunger: %d",
1540                  you.hunger, abil.food_cost * 2, expected_hunger);
1541         }
1542         // Safety margin for natural hunger, mutations etc.
1543         if (expected_hunger <= 50)
1544         {
1545             if (!quiet)
1546                 canned_msg(MSG_TOO_HUNGRY);
1547             return false;
1548         }
1549     }
1550
1551     // in case of mp rot ability, check is the player have enough natural MP
1552     // (avoid use of ring/staf of magical power)
1553     if ((abil.flags & ABFLAG_PERMANENT_MP)
1554         && get_real_mp(false) < (int)abil.mp_cost)
1555     {
1556         if (!quiet)
1557             mpr("You don't have enough innate magic capacity to sacrifice.");
1558         return false;
1559     }
1560
1561     switch (abil.ability)
1562     {
1563     case ABIL_ZIN_RECITE:
1564     {
1565         if (!zin_check_able_to_recite(quiet))
1566             return false;
1567
1568         if (zin_check_recite_to_monsters(quiet) != 1)
1569         {
1570             if (!quiet)
1571                 mpr("There's no appreciative audience!");
1572             return false;
1573         }
1574         return true;
1575     }
1576
1577     case ABIL_ZIN_CURE_ALL_MUTATIONS:
1578         return how_mutated();
1579
1580     case ABIL_ZIN_SANCTUARY:
1581         if (env.sanctuary_time)
1582         {
1583             if (!quiet)
1584                 mpr("There's already a sanctuary in place on this level.");
1585             return false;
1586         }
1587         return true;
1588
1589     case ABIL_ELYVILON_PURIFICATION:
1590         if (!you.disease && !you.duration[DUR_POISONING]
1591             && !you.duration[DUR_CONF] && !you.duration[DUR_SLOW]
1592             && !you.petrifying()
1593             && you.strength(false) == you.max_strength()
1594             && you.intel(false) == you.max_intel()
1595             && you.dex(false) == you.max_dex()
1596             && !player_rotted()
1597             && !you.duration[DUR_WEAK])
1598         {
1599             if (!quiet)
1600                 mpr("Nothing ails you!");
1601             return false;
1602         }
1603         return true;
1604
1605     case ABIL_MUMMY_RESTORATION:
1606         if (you.strength(false) == you.max_strength()
1607             && you.intel(false) == you.max_intel()
1608             && you.dex(false) == you.max_dex()
1609             && !player_rotted())
1610         {
1611             if (!quiet)
1612                 mpr("You don't need to restore your stats or health!");
1613             return false;
1614         }
1615         return true;
1616
1617     case ABIL_LUGONU_ABYSS_EXIT:
1618         if (!player_in_branch(BRANCH_ABYSS))
1619         {
1620             if (!quiet)
1621                 mpr("You aren't in the Abyss!");
1622             return false;
1623         }
1624         return true;
1625
1626     case ABIL_LUGONU_CORRUPT:
1627         return !is_level_incorruptible(quiet);
1628
1629     case ABIL_LUGONU_ABYSS_ENTER:
1630         if (player_in_branch(BRANCH_ABYSS) || brdepth[BRANCH_ABYSS] == -1)
1631         {
1632             if (!quiet)
1633                 mpr("You're already here!");
1634             return false;
1635         }
1636         return true;
1637
1638     case ABIL_SIF_MUNA_FORGET_SPELL:
1639         if (you.spell_no == 0)
1640         {
1641             if (!quiet)
1642                 canned_msg(MSG_NO_SPELLS);
1643             return false;
1644         }
1645         return true;
1646
1647     case ABIL_ASHENZARI_TRANSFER_KNOWLEDGE:
1648         if (all_skills_maxed(true))
1649         {
1650             if (!quiet)
1651                 mpr("You have nothing more to learn.");
1652             return false;
1653         }
1654         return true;
1655
1656     case ABIL_OKAWARU_FINESSE:
1657         if (stasis_blocks_effect(false,
1658                                  quiet ? nullptr
1659                                        : "%s makes your neck tingle."))
1660         {
1661             return false;
1662         }
1663         return true;
1664
1665     case ABIL_FEDHAS_EVOLUTION:
1666         return fedhas_check_evolve_flora(quiet);
1667
1668     case ABIL_FEDHAS_SPAWN_SPORES:
1669     {
1670         const int retval = fedhas_check_corpse_spores(quiet);
1671         if (retval <= 0)
1672         {
1673             if (!quiet)
1674             {
1675                 if (retval == 0)
1676                     mpr("No corpses are in range.");
1677                 else
1678                     canned_msg(MSG_OK);
1679             }
1680             return false;
1681         }
1682         return true;
1683     }
1684
1685     case ABIL_SPIT_POISON:
1686     case ABIL_BREATHE_FIRE:
1687     case ABIL_BREATHE_FROST:
1688     case ABIL_BREATHE_POISON:
1689     case ABIL_BREATHE_LIGHTNING:
1690     case ABIL_SPIT_ACID:
1691     case ABIL_BREATHE_POWER:
1692     case ABIL_BREATHE_STICKY_FLAME:
1693     case ABIL_BREATHE_STEAM:
1694     case ABIL_BREATHE_MEPHITIC:
1695         if (you.duration[DUR_BREATH_WEAPON])
1696         {
1697             if (!quiet)
1698                 canned_msg(MSG_CANNOT_DO_YET);
1699             return false;
1700         }
1701         return true;
1702
1703     case ABIL_BLINK:
1704     case ABIL_EVOKE_BLINK:
1705     {
1706         const string no_tele_reason = you.no_tele_reason(false, true);
1707         if (no_tele_reason.empty())
1708             return true;
1709
1710         if (!quiet)
1711              mpr(no_tele_reason);
1712         return false;
1713     }
1714
1715     case ABIL_EVOKE_BERSERK:
1716     case ABIL_TROG_BERSERK:
1717         return you.can_go_berserk(true, false, true)
1718                && (quiet || berserk_check_wielded_weapon());
1719
1720     case ABIL_EVOKE_FOG:
1721         if (env.cgrid(you.pos()) != EMPTY_CLOUD)
1722         {
1723             if (!quiet)
1724                 mpr("It's too cloudy to do that here.");
1725             return false;
1726         }
1727         return true;
1728
1729     case ABIL_GOZAG_POTION_PETITION:
1730         return gozag_setup_potion_petition(quiet);
1731
1732     case ABIL_GOZAG_CALL_MERCHANT:
1733         return gozag_setup_call_merchant(quiet);
1734
1735     case ABIL_GOZAG_BRIBE_BRANCH:
1736         return gozag_check_bribe_branch(quiet);
1737
1738     case ABIL_RU_SACRIFICE_EXPERIENCE:
1739         if (you.experience_level <= RU_SAC_XP_LEVELS)
1740         {
1741             if (!quiet)
1742                 mpr("You don't have enough experience to sacrifice.");
1743             return false;
1744         }
1745         return true;
1746
1747     default:
1748         return true;
1749     }
1750 }
1751
1752 bool check_ability_possible(const ability_type ability, bool hungerCheck,
1753                             bool quiet)
1754 {
1755     return _check_ability_possible(get_ability_def(ability), hungerCheck,
1756                                    quiet);
1757 }
1758
1759 bool activate_talent(const talent& tal)
1760 {
1761     if (you.berserk())
1762     {
1763         canned_msg(MSG_TOO_BERSERK);
1764         crawl_state.zero_turns_taken();
1765         return false;
1766     }
1767
1768     // Doing these would outright kill the player.
1769     // (or, in the case of the stat-zeros, they'd at least be extremely
1770     // dangerous.)
1771     if (tal.which == ABIL_STOP_FLYING)
1772     {
1773         if (is_feat_dangerous(grd(you.pos()), false, true))
1774         {
1775             mpr("Stopping flight right now would be fatal!");
1776             crawl_state.zero_turns_taken();
1777             return false;
1778         }
1779     }
1780     else if (tal.which == ABIL_TRAN_BAT)
1781     {
1782         if (!check_form_stat_safety(TRAN_BAT))
1783         {
1784             crawl_state.zero_turns_taken();
1785             return false;
1786         }
1787     }
1788     else if (tal.which == ABIL_END_TRANSFORMATION)
1789     {
1790         if (feat_dangerous_for_form(TRAN_NONE, env.grid(you.pos())))
1791         {
1792             mprf("Turning back right now would cause you to %s!",
1793                  env.grid(you.pos()) == DNGN_LAVA ? "burn" : "drown");
1794
1795             crawl_state.zero_turns_taken();
1796             return false;
1797         }
1798
1799         if (!check_form_stat_safety(TRAN_NONE))
1800         {
1801             crawl_state.zero_turns_taken();
1802             return false;
1803         }
1804     }
1805
1806     if ((tal.which == ABIL_EVOKE_BERSERK || tal.which == ABIL_TROG_BERSERK)
1807         && !you.can_go_berserk(true))
1808     {
1809         crawl_state.zero_turns_taken();
1810         return false;
1811     }
1812
1813     if ((tal.which == ABIL_EVOKE_FLIGHT || tal.which == ABIL_TRAN_BAT || tal.which == ABIL_FLY)
1814         && !flight_allowed())
1815     {
1816         crawl_state.zero_turns_taken();
1817         return false;
1818     }
1819
1820     // Some abilities don't need a hunger check.
1821     bool hungerCheck = true;
1822     switch (tal.which)
1823     {
1824         case ABIL_RENOUNCE_RELIGION:
1825         case ABIL_CONVERT_TO_BEOGH:
1826         case ABIL_STOP_FLYING:
1827         case ABIL_EVOKE_TURN_VISIBLE:
1828         case ABIL_END_TRANSFORMATION:
1829         case ABIL_DELAYED_FIREBALL:
1830         case ABIL_STOP_SINGING:
1831         case ABIL_MUMMY_RESTORATION:
1832         case ABIL_TRAN_BAT:
1833         case ABIL_ASHENZARI_END_TRANSFER:
1834         case ABIL_ZIN_VITALISATION:
1835         case ABIL_GOZAG_POTION_PETITION:
1836             hungerCheck = false;
1837             break;
1838         default:
1839             break;
1840     }
1841
1842     if (hungerCheck && !you.undead_state() && !you_foodless()
1843         && you.hunger_state == HS_STARVING)
1844     {
1845         canned_msg(MSG_TOO_HUNGRY);
1846         crawl_state.zero_turns_taken();
1847         return false;
1848     }
1849
1850     const ability_def& abil = get_ability_def(tal.which);
1851
1852     // Check that we can afford to pay the costs.
1853     // Note that mutation shenanigans might leave us with negative MP,
1854     // so don't fail in that case if there's no MP cost.
1855     if (abil.mp_cost > 0 && !enough_mp(abil.mp_cost, false, true))
1856     {
1857         crawl_state.zero_turns_taken();
1858         return false;
1859     }
1860
1861     const int hpcost = abil.hp_cost.cost(you.hp_max);
1862     if (hpcost > 0 && !enough_hp(hpcost, false))
1863     {
1864         crawl_state.zero_turns_taken();
1865         return false;
1866     }
1867
1868     const int zpcost = _zp_cost(abil);
1869     if (zpcost)
1870     {
1871         if (!enough_zp(zpcost, false))
1872         {
1873             crawl_state.zero_turns_taken();
1874             return false;
1875         }
1876     }
1877
1878     if (!_check_ability_possible(abil, hungerCheck))
1879     {
1880         crawl_state.zero_turns_taken();
1881         return false;
1882     }
1883
1884     bool fail = random2avg(100, 3) < tal.fail;
1885
1886     const spret_type ability_result = _do_ability(abil, fail);
1887     switch (ability_result)
1888     {
1889         case SPRET_SUCCESS:
1890             ASSERT(!fail);
1891             practise(EX_USED_ABIL, abil.ability);
1892             _pay_ability_costs(abil, zpcost);
1893             count_action(tal.is_invocation ? CACT_INVOKE : CACT_ABIL, abil.ability);
1894             return true;
1895         case SPRET_FAIL:
1896             mpr("You fail to use your ability.");
1897             you.turn_is_over = true;
1898             return false;
1899         case SPRET_ABORT:
1900             crawl_state.zero_turns_taken();
1901             return false;
1902         case SPRET_NONE:
1903         default:
1904             die("Weird ability return type");
1905             return false;
1906     }
1907 }
1908
1909 static int _calc_breath_ability_range(ability_type ability)
1910 {
1911     // Following monster draconian abilities.
1912     switch (ability)
1913     {
1914     case ABIL_BREATHE_FIRE:         return 6;
1915     case ABIL_BREATHE_FROST:        return 6;
1916     case ABIL_BREATHE_MEPHITIC:     return 7;
1917     case ABIL_BREATHE_LIGHTNING:    return 8;
1918     case ABIL_SPIT_ACID:            return 8;
1919     case ABIL_BREATHE_POWER:        return 8;
1920     case ABIL_BREATHE_STICKY_FLAME: return 1;
1921     case ABIL_BREATHE_STEAM:        return 7;
1922     case ABIL_BREATHE_POISON:       return 7;
1923     default:
1924         die("Bad breath type!");
1925         break;
1926     }
1927     return -2;
1928 }
1929
1930 static bool _sticky_flame_can_hit(const actor *act)
1931 {
1932     if (act->is_monster())
1933     {
1934         const monster* mons = act->as_monster();
1935         bolt testbeam;
1936         testbeam.thrower = KILL_YOU;
1937         zappy(ZAP_BREATHE_STICKY_FLAME, 100, testbeam);
1938
1939         return !testbeam.ignores_monster(mons);
1940     }
1941     else
1942         return false;
1943 }
1944
1945 /*
1946  * Use an ability.
1947  *
1948  * @param abil The actual ability used.
1949  * @param fail If true, the ability is doomed to fail, and SPRET_FAIL will
1950  * be returned if the ability is not SPRET_ABORTed.
1951  * @returns Whether the spell succeeded (SPRET_SUCCESS), failed (SPRET_FAIL),
1952  *  or was canceled (SPRET_ABORT). Never returns SPRET_NONE.
1953  */
1954 static spret_type _do_ability(const ability_def& abil, bool fail)
1955 {
1956     int power;
1957     dist abild;
1958     bolt beam;
1959     dist spd;
1960
1961     direction_chooser_args args;
1962     args.restricts = DIR_TARGET;
1963     args.needs_path = false;
1964     args.may_target_monster = false;
1965
1966     // Note: the costs will not be applied until after this switch
1967     // statement... it's assumed that only failures have returned! - bwr
1968     switch (abil.ability)
1969     {
1970     case ABIL_MAKE_FUNGUS:
1971         fail_check();
1972         if (count_allies() > MAX_MONSTERS / 2)
1973         {
1974             mpr("Mushrooms don't grow well in such thickets.");
1975             return SPRET_ABORT;
1976         }
1977         args.top_prompt="Center fungus circle where?";
1978         direction(abild, args);
1979         if (!abild.isValid)
1980         {
1981             if (abild.isCancel)
1982             canned_msg(MSG_OK);
1983             return SPRET_ABORT;
1984         }
1985         for (adjacent_iterator ai(abild.target); ai; ++ai)
1986         {
1987             place_monster(mgen_data(MONS_FUNGUS, BEH_FRIENDLY, &you, 0, 0, *ai,
1988                           you.pet_target), true);
1989         }
1990         break;
1991
1992     // Begin ZotDef allies
1993     case ABIL_MAKE_PLANT:
1994     case ABIL_MAKE_OKLOB_SAPLING:
1995     case ABIL_MAKE_OKLOB_PLANT:
1996     case ABIL_MAKE_BURNING_BUSH:
1997     case ABIL_MAKE_ICE_STATUE:
1998     case ABIL_MAKE_OCS:
1999     case ABIL_MAKE_OBSIDIAN_STATUE:
2000     case ABIL_MAKE_CURSE_SKULL:
2001     case ABIL_MAKE_LIGHTNING_SPIRE:
2002         fail_check();
2003         if (!create_zotdef_ally(_monster_for_ability(abil),
2004             _zd_mons_description_for_ability(abil).c_str()))
2005         {
2006             return SPRET_ABORT;
2007         }
2008         break;
2009     // End ZotDef Allies
2010
2011     case ABIL_MAKE_TELEPORT:
2012         fail_check();
2013         you_teleport_now(true);
2014         break;
2015
2016     // ZotDef traps
2017     case ABIL_MAKE_ARROW_TRAP:
2018     case ABIL_MAKE_BOLT_TRAP:
2019     case ABIL_MAKE_SPEAR_TRAP:
2020     case ABIL_MAKE_NEEDLE_TRAP:
2021     case ABIL_MAKE_NET_TRAP:
2022     case ABIL_MAKE_ALARM_TRAP:
2023     case ABIL_MAKE_BLADE_TRAP:
2024         fail_check();
2025         if (!create_trap(_trap_for_ability(abil)))
2026             return SPRET_ABORT;
2027         break;
2028     // End ZotDef traps
2029
2030     case ABIL_MAKE_OKLOB_CIRCLE:
2031         fail_check();
2032         args.top_prompt = "Center oklob circle where?";
2033         direction(abild, args);
2034         if (!abild.isValid)
2035         {
2036             if (abild.isCancel)
2037             canned_msg(MSG_OK);
2038             return SPRET_ABORT;
2039         }
2040         for (adjacent_iterator ai(abild.target); ai; ++ai)
2041         {
2042             place_monster(mgen_data(MONS_OKLOB_PLANT, BEH_FRIENDLY, &you, 0, 0,
2043                           *ai, you.pet_target), true);
2044         }
2045         break;
2046
2047     case ABIL_MAKE_ACQUIRE_GOLD:
2048         fail_check();
2049         acquirement(OBJ_GOLD, AQ_SCROLL);
2050         break;
2051
2052     case ABIL_MAKE_ACQUIREMENT:
2053         fail_check();
2054         acquirement(OBJ_RANDOM, AQ_SCROLL);
2055         break;
2056
2057     case ABIL_MAKE_WATER:
2058         fail_check();
2059         zotdef_create_pond(you.pos(), 3);
2060         break;
2061
2062     case ABIL_MAKE_BAZAAR:
2063     {
2064         fail_check();
2065         // Early exit: don't clobber important features.
2066         if (feat_is_critical(grd(you.pos())))
2067         {
2068             mpr("The dungeon trembles momentarily.");
2069             return SPRET_ABORT;
2070         }
2071
2072         // Generate a portal to something.
2073         const map_def *mapidx = random_map_for_tag("zotdef_bazaar", false);
2074         if (mapidx && dgn_safe_place_map(mapidx, false, true, you.pos()))
2075             mpr("A mystic portal forms.");
2076         else
2077         {
2078             mpr("A buggy portal flickers into view, then vanishes.");
2079             return SPRET_ABORT;
2080         }
2081
2082         break;
2083     }
2084
2085     case ABIL_MAKE_ALTAR:
2086         fail_check();
2087         if (!zotdef_create_altar())
2088         {
2089             mpr("The dungeon dims for a moment.");
2090             return SPRET_ABORT;
2091         }
2092         break;
2093
2094     case ABIL_MAKE_GRENADES:
2095         fail_check();
2096         if (create_monster(
2097                mgen_data(MONS_GIANT_SPORE, BEH_FRIENDLY, &you, 6, 0,
2098                          you.pos(), you.pet_target,
2099                          0)))
2100         {
2101             mpr("You create a living grenade.");
2102         }
2103         if (create_monster(
2104                mgen_data(MONS_GIANT_SPORE, BEH_FRIENDLY, &you, 6, 0,
2105                          you.pos(), you.pet_target,
2106                          0)))
2107         {
2108             mpr("You create a living grenade.");
2109         }
2110         break;
2111
2112     case ABIL_REMOVE_CURSE:
2113         fail_check();
2114         remove_curse();
2115         lose_stat(STAT_RANDOM, 1, true);
2116         break;
2117
2118     case ABIL_MUMMY_RESTORATION:
2119     {
2120         fail_check();
2121         mpr("You infuse your body with magical energy.");
2122         bool did_restore = restore_stat(STAT_ALL, 0, false);
2123
2124         const int oldhpmax = you.hp_max;
2125         unrot_hp(9999);
2126         if (you.hp_max > oldhpmax)
2127             did_restore = true;
2128
2129         // If nothing happened, don't take one max MP, don't use a turn.
2130         if (!did_restore)
2131         {
2132             canned_msg(MSG_NOTHING_HAPPENS);
2133             return SPRET_ABORT;
2134         }
2135
2136         break;
2137     }
2138
2139     case ABIL_RECHARGING:
2140         fail_check();
2141         if (recharge_wand() <= 0)
2142             return SPRET_ABORT; // fail message is already given
2143         break;
2144
2145     case ABIL_DIG:
2146         fail_check();
2147         if (!you.digging)
2148         {
2149             you.digging = true;
2150             mpr("You extend your mandibles.");
2151         }
2152         else
2153         {
2154             mpr("You are already prepared to dig.");
2155             return SPRET_ABORT;
2156         }
2157         break;
2158
2159     case ABIL_SHAFT_SELF:
2160         fail_check();
2161         if (you.can_do_shaft_ability(false))
2162         {
2163             if (yesno("Are you sure you want to shaft yourself?", true, 'n'))
2164                 start_delay(DELAY_SHAFT_SELF, 1);
2165             else
2166                 return SPRET_ABORT;
2167         }
2168         else
2169             return SPRET_ABORT;
2170         break;
2171
2172     case ABIL_DELAYED_FIREBALL:
2173     {
2174         fail_check();
2175         // Note: Power level of ball calculated at release. - bwr
2176         power = calc_spell_power(SPELL_DELAYED_FIREBALL, true);
2177         beam.range = spell_range(SPELL_FIREBALL, power);
2178
2179         targetter_beam tgt(&you, beam.range, ZAP_FIREBALL, power, 1, 1);
2180
2181         if (!spell_direction(spd, beam, DIR_NONE, TARG_HOSTILE, beam.range,
2182                              true, true, false, nullptr,
2183                              "Aiming: <white>Delayed Fireball</white>",
2184                              false, &tgt))
2185         {
2186             return SPRET_ABORT;
2187         }
2188
2189         if (!zapping(ZAP_FIREBALL, power, beam, true, nullptr, false))
2190             return SPRET_ABORT;
2191
2192         // Only one allowed, since this is instantaneous. - bwr
2193         you.attribute[ATTR_DELAYED_FIREBALL] = 0;
2194         break;
2195     }
2196
2197     case ABIL_SPIT_POISON:      // Spit poison mutation
2198         power = you.experience_level
2199                 + player_mutation_level(MUT_SPIT_POISON) * 5;
2200         beam.range = 6;         // following Venom Bolt
2201
2202         if (!spell_direction(abild, beam)
2203             || !player_tracer(ZAP_SPIT_POISON, power, beam))
2204         {
2205             return SPRET_ABORT;
2206         }
2207         else
2208         {
2209             fail_check();
2210             zapping(ZAP_SPIT_POISON, power, beam);
2211             zin_recite_interrupt();
2212             you.set_duration(DUR_BREATH_WEAPON, 3 + random2(5));
2213         }
2214         break;
2215
2216     case ABIL_EVOKE_TELEPORTATION:    // ring of teleportation
2217         fail_check();
2218         you_teleport();
2219         break;
2220
2221     case ABIL_BREATHE_STICKY_FLAME:
2222     {
2223         targetter_splash hitfunc(&you);
2224         beam.range = 1;
2225         if (!spell_direction(abild, beam,
2226                              DIR_NONE, TARG_HOSTILE, 0, true, true, false,
2227                              nullptr, nullptr, false,
2228                              &hitfunc))
2229         {
2230             return SPRET_ABORT;
2231         }
2232
2233         if (stop_attack_prompt(hitfunc, "spit at", _sticky_flame_can_hit))
2234             return SPRET_ABORT;
2235
2236         fail_check();
2237         zapping(ZAP_BREATHE_STICKY_FLAME, (you.form == TRAN_DRAGON) ?
2238                 2 * you.experience_level : you.experience_level,
2239             beam, false, "You spit a glob of burning liquid.");
2240
2241         zin_recite_interrupt();
2242         you.increase_duration(DUR_BREATH_WEAPON,
2243                       3 + random2(10) + random2(30 - you.experience_level));
2244         break;
2245     }
2246
2247     case ABIL_BREATHE_FIRE:
2248     case ABIL_BREATHE_FROST:
2249     case ABIL_BREATHE_POISON:
2250     case ABIL_SPIT_ACID:
2251     case ABIL_BREATHE_POWER:
2252     case ABIL_BREATHE_STEAM:
2253     case ABIL_BREATHE_MEPHITIC:
2254         beam.range = _calc_breath_ability_range(abil.ability);
2255         if (!spell_direction(abild, beam))
2256             return SPRET_ABORT;
2257
2258         // fallthrough to ABIL_BREATHE_LIGHTNING
2259
2260     case ABIL_BREATHE_LIGHTNING: // not targeted
2261         fail_check();
2262
2263         // TODO: refactor this to use only one call to zapping(), don't
2264         // duplicate its fail_check(), split out breathe_lightning, etc
2265
2266         switch (abil.ability)
2267         {
2268         case ABIL_BREATHE_FIRE:
2269         {
2270             power = you.experience_level
2271                     + player_mutation_level(MUT_BREATHE_FLAMES) * 4;
2272
2273             if (you.form == TRAN_DRAGON)
2274                 power += 12;
2275
2276             string msg = "You breathe a blast of fire";
2277             msg += (power < 15) ? '.' : '!';
2278
2279             if (!zapping(ZAP_BREATHE_FIRE, power, beam, true, msg.c_str()))
2280                 return SPRET_ABORT;
2281             break;
2282         }
2283
2284         case ABIL_BREATHE_FROST:
2285             if (!zapping(ZAP_BREATHE_FROST,
2286                  (you.form == TRAN_DRAGON) ?
2287                      2 * you.experience_level : you.experience_level,
2288                  beam, true,
2289                          "You exhale a wave of freezing cold."))
2290             {
2291                 return SPRET_ABORT;
2292             }
2293             break;
2294
2295         case ABIL_BREATHE_POISON:
2296             if (!zapping(ZAP_BREATHE_POISON, you.experience_level, beam, true,
2297                          "You exhale a blast of poison gas."))
2298             {
2299                 return SPRET_ABORT;
2300             }
2301             break;
2302
2303         case ABIL_BREATHE_LIGHTNING:
2304             mpr("You breathe a wild blast of lightning!");
2305             black_drac_breath();
2306             break;
2307
2308         case ABIL_SPIT_ACID:
2309             if (!zapping(ZAP_BREATHE_ACID,
2310                 (you.form == TRAN_DRAGON) ?
2311                     2 * you.experience_level : you.experience_level,
2312                 beam, true, "You spit a glob of acid."))
2313             {
2314                 return SPRET_ABORT;
2315             }
2316             break;
2317
2318         case ABIL_BREATHE_POWER:
2319             if (!zapping(ZAP_BREATHE_POWER,
2320                 (you.form == TRAN_DRAGON) ?
2321                     2 * you.experience_level : you.experience_level,
2322                 beam, true,
2323                          "You spit a bolt of dispelling energy."))
2324             {
2325                 return SPRET_ABORT;
2326             }
2327             break;
2328
2329         case ABIL_BREATHE_STICKY_FLAME:
2330             if (!zapping(ZAP_BREATHE_STICKY_FLAME,
2331                 (you.form == TRAN_DRAGON) ?
2332                     2 * you.experience_level : you.experience_level,
2333                 beam, true,
2334                          "You spit a glob of burning liquid."))
2335             {
2336                 return SPRET_ABORT;
2337             }
2338             break;
2339
2340         case ABIL_BREATHE_STEAM:
2341             if (!zapping(ZAP_BREATHE_STEAM,
2342                 (you.form == TRAN_DRAGON) ?
2343                     2 * you.experience_level : you.experience_level,
2344                 beam, true,
2345                          "You exhale a blast of scalding steam."))
2346             {
2347                 return SPRET_ABORT;
2348             }
2349             break;
2350
2351         case ABIL_BREATHE_MEPHITIC:
2352             if (!zapping(ZAP_BREATHE_MEPHITIC,
2353                 (you.form == TRAN_DRAGON) ?
2354                     2 * you.experience_level : you.experience_level,
2355                 beam, true,
2356                          "You exhale a blast of noxious fumes."))
2357             {
2358                 return SPRET_ABORT;
2359             }
2360             break;
2361
2362         default:
2363             break;
2364         }
2365
2366         zin_recite_interrupt();
2367         you.increase_duration(DUR_BREATH_WEAPON,
2368                       3 + random2(10) + random2(30 - you.experience_level));
2369
2370         if (abil.ability == ABIL_BREATHE_STEAM
2371             || abil.ability == ABIL_SPIT_ACID)
2372         {
2373             you.duration[DUR_BREATH_WEAPON] /= 2;
2374         }
2375
2376         break;
2377
2378     case ABIL_EVOKE_BLINK:      // randarts
2379     case ABIL_BLINK:            // mutation
2380         return cast_blink(true, fail);
2381         break;
2382
2383     case ABIL_EVOKE_BERSERK:    // amulet of rage, randarts
2384         fail_check();
2385         you.go_berserk(true);
2386         break;
2387
2388     // Fly (tengu/drac) - permanent at high XL
2389     case ABIL_FLY:
2390         fail_check();
2391         if (you.racial_permanent_flight())
2392         {
2393             you.attribute[ATTR_PERM_FLIGHT] = 1;
2394             float_player();
2395             if (you.species == SP_TENGU)
2396                 mpr("You feel very comfortable in the air.");
2397         }
2398         else
2399             cast_fly(you.experience_level * 4);
2400         break;
2401
2402     // DEMONIC POWERS:
2403     case ABIL_HELLFIRE:
2404         fail_check();
2405         if (your_spells(SPELL_HELLFIRE,
2406                         you.experience_level * 10, false) == SPRET_ABORT)
2407         {
2408             return SPRET_ABORT;
2409         }
2410         break;
2411
2412     case ABIL_EVOKE_TURN_INVISIBLE:     // ring, cloaks, randarts
2413         fail_check();
2414         potionlike_effect(POT_INVISIBILITY, you.skill(SK_EVOCATIONS, 2) + 5);
2415         contaminate_player(1000 + random2(2000), true);
2416         break;
2417
2418     case ABIL_EVOKE_TURN_VISIBLE:
2419         fail_check();
2420         ASSERT(!you.attribute[ATTR_INVIS_UNCANCELLABLE]);
2421         mpr("You feel less transparent.");
2422         you.duration[DUR_INVIS] = 1;
2423         break;
2424
2425     case ABIL_EVOKE_FLIGHT:             // ring, boots, randarts
2426         fail_check();
2427         ASSERT(!get_form()->forbids_flight());
2428         if (you.wearing_ego(EQ_ALL_ARMOUR, SPARM_FLYING))
2429         {
2430             bool standing = !you.airborne();
2431             you.attribute[ATTR_PERM_FLIGHT] = 1;
2432             if (standing)
2433                 float_player();
2434             else
2435                 mpr("You feel more buoyant.");
2436         }
2437         else
2438             fly_player(you.skill(SK_EVOCATIONS, 2) + 30);
2439         break;
2440     case ABIL_EVOKE_FOG:     // cloak of the Thief
2441         fail_check();
2442         mpr("With a swish of your cloak, you release a cloud of fog.");
2443         big_cloud(random_smoke_type(), &you, you.pos(), 50, 8 + random2(8));
2444         break;
2445
2446     case ABIL_EVOKE_TELEPORT_CONTROL:
2447         fail_check();
2448         cast_teleport_control(30 + you.skill(SK_EVOCATIONS, 2), false);
2449         break;
2450
2451     case ABIL_EVOKE_TWISTER:
2452         fail_check();
2453         summon_twister(2);
2454         break;
2455
2456     case ABIL_STOP_SINGING:
2457         fail_check();
2458         you.duration[DUR_SONG_OF_SLAYING] = 0;
2459         mpr("You stop singing.");
2460         break;
2461
2462     case ABIL_STOP_FLYING:
2463         fail_check();
2464         you.duration[DUR_FLIGHT] = 0;
2465         you.attribute[ATTR_PERM_FLIGHT] = 0;
2466         land_player();
2467         break;
2468
2469     case ABIL_END_TRANSFORMATION:
2470         fail_check();
2471         you.time_taken = div_rand_round(you.time_taken * 3, 2);
2472         untransform();
2473         break;
2474
2475     // INVOCATIONS:
2476     case ABIL_ZIN_RECITE:
2477     {
2478         fail_check();
2479         if (zin_check_recite_to_monsters() == 1)
2480         {
2481             you.attribute[ATTR_RECITE_TYPE] = (recite_type) random2(NUM_RECITE_TYPES); // This is just flavor
2482             you.attribute[ATTR_RECITE_SEED] = random2(2187); // 3^7
2483             you.attribute[ATTR_RECITE_HP]   = you.hp;
2484             you.duration[DUR_RECITE] = 3 * BASELINE_DELAY;
2485             mprf("You clear your throat and prepare to recite.");
2486         }
2487         else
2488         {
2489             canned_msg(MSG_OK);
2490             return SPRET_ABORT;
2491         }
2492         break;
2493     }
2494     case ABIL_ZIN_VITALISATION:
2495         fail_check();
2496         zin_recite_interrupt();
2497         zin_vitalisation();
2498         break;
2499
2500     case ABIL_ZIN_IMPRISON:
2501     {
2502         beam.range = LOS_RADIUS;
2503         if (!spell_direction(spd, beam, DIR_TARGET, TARG_HOSTILE, 0, false))
2504             return SPRET_ABORT;
2505
2506         if (beam.target == you.pos())
2507         {
2508             mpr("You cannot imprison yourself!");
2509             return SPRET_ABORT;
2510         }
2511
2512         monster* mons = monster_at(beam.target);
2513
2514         if (mons == nullptr || !you.can_see(mons))
2515         {
2516             mpr("There is no monster there to imprison!");
2517             return SPRET_ABORT;
2518         }
2519
2520         if (mons_is_firewood(mons) || mons_is_conjured(mons->type))
2521         {
2522             mpr("You cannot imprison that!");
2523             return SPRET_ABORT;
2524         }
2525
2526         if (mons->friendly() || mons->good_neutral())
2527         {
2528             mpr("You cannot imprison a law-abiding creature!");
2529             return SPRET_ABORT;
2530         }
2531
2532         fail_check();
2533
2534         zin_recite_interrupt();
2535         power = 3 + (roll_dice(5, you.skill(SK_INVOCATIONS, 5) + 12) / 26);
2536
2537         if (!cast_imprison(power, mons, -GOD_ZIN))
2538             return SPRET_ABORT;
2539         break;
2540     }
2541
2542     case ABIL_ZIN_SANCTUARY:
2543         fail_check();
2544         zin_recite_interrupt();
2545         if (!zin_sanctuary())
2546             return SPRET_ABORT;
2547         break;
2548
2549     case ABIL_ZIN_CURE_ALL_MUTATIONS:
2550         fail_check();
2551         zin_recite_interrupt();
2552         zin_remove_all_mutations();
2553         break;
2554
2555     case ABIL_TSO_DIVINE_SHIELD:
2556         fail_check();
2557         tso_divine_shield();
2558         break;
2559
2560     case ABIL_TSO_CLEANSING_FLAME:
2561         fail_check();
2562         cleansing_flame(10 + you.skill_rdiv(SK_INVOCATIONS, 7, 6),
2563                         CLEANSING_FLAME_INVOCATION, you.pos(), &you);
2564         break;
2565
2566     case ABIL_TSO_SUMMON_DIVINE_WARRIOR:
2567         fail_check();
2568         summon_holy_warrior(you.skill(SK_INVOCATIONS, 4), false);
2569         break;
2570
2571     case ABIL_KIKU_RECEIVE_CORPSES:
2572         fail_check();
2573         kiku_receive_corpses(you.skill(SK_NECROMANCY, 4));
2574         break;
2575
2576     case ABIL_KIKU_TORMENT:
2577         fail_check();
2578         if (!kiku_take_corpse())
2579         {
2580             mpr("There are no corpses to sacrifice!");
2581             return SPRET_ABORT;
2582         }
2583         simple_god_message(" torments the living!");
2584         torment(&you, TORMENT_KIKUBAAQUDGHA, you.pos());
2585         break;
2586
2587     case ABIL_YRED_INJURY_MIRROR:
2588         fail_check();
2589         if (yred_injury_mirror())
2590             mpr("Another wave of unholy energy enters you.");
2591         else
2592         {
2593             mprf("You offer yourself to %s, and fill with unholy energy.",
2594                  god_name(you.religion).c_str());
2595         }
2596         you.duration[DUR_MIRROR_DAMAGE] = 9 * BASELINE_DELAY
2597                      + random2avg(you.piety * BASELINE_DELAY, 2) / 10;
2598         break;
2599
2600     case ABIL_YRED_ANIMATE_REMAINS:
2601     case ABIL_YRED_ANIMATE_DEAD:
2602         fail_check();
2603         if (!yred_animate_remains_or_dead())
2604             return SPRET_ABORT;
2605         break;
2606
2607     case ABIL_YRED_RECALL_UNDEAD_SLAVES:
2608         fail_check();
2609         start_recall(RECALL_YRED);
2610         break;
2611
2612     case ABIL_YRED_DRAIN_LIFE:
2613         fail_check();
2614         cast_los_attack_spell(SPELL_DRAIN_LIFE, you.skill_rdiv(SK_INVOCATIONS),
2615                               &you, true);
2616         break;
2617
2618     case ABIL_YRED_ENSLAVE_SOUL:
2619     {
2620         god_acting gdact;
2621         power = you.skill(SK_INVOCATIONS, 4);
2622         beam.range = LOS_RADIUS;
2623
2624         if (!spell_direction(spd, beam))
2625             return SPRET_ABORT;
2626
2627         if (beam.target == you.pos())
2628         {
2629             mpr("Your soul already belongs to Yredelemnul.");
2630             return SPRET_ABORT;
2631         }
2632
2633         monster* mons = monster_at(beam.target);
2634         if (mons == nullptr || !you.can_see(mons)
2635             || !ench_flavour_affects_monster(BEAM_ENSLAVE_SOUL, mons))
2636         {
2637             mpr("You see nothing there you can enslave the soul of!");
2638             return SPRET_ABORT;
2639         }
2640
2641         // The monster can be no more than lightly wounded/damaged.
2642         if (mons_get_damage_level(mons) > MDAM_LIGHTLY_DAMAGED)
2643         {
2644             simple_monster_message(mons, "'s soul is too badly injured.");
2645             return SPRET_ABORT;
2646         }
2647         fail_check();
2648
2649         return zapping(ZAP_ENSLAVE_SOUL, power, beam, false, nullptr, fail);
2650     }
2651
2652     case ABIL_SIF_MUNA_CHANNEL_ENERGY:
2653         fail_check();
2654         mpr("You channel some magical energy.");
2655
2656         inc_mp(1 + random2(you.skill_rdiv(SK_INVOCATIONS, 1, 4) + 2));
2657         break;
2658
2659     case ABIL_OKAWARU_HEROISM:
2660         fail_check();
2661         mprf(MSGCH_DURATION, you.duration[DUR_HEROISM]
2662              ? "You feel more confident with your borrowed prowess."
2663              : "You gain the combat prowess of a mighty hero.");
2664
2665         you.increase_duration(DUR_HEROISM,
2666             35 + random2(you.skill(SK_INVOCATIONS, 8)), 80);
2667         you.redraw_evasion      = true;
2668         you.redraw_armour_class = true;
2669         break;
2670
2671     case ABIL_OKAWARU_FINESSE:
2672         fail_check();
2673         if (stasis_blocks_effect(true, "%s emits a piercing whistle.",
2674                                  20, "%s makes your neck tingle."))
2675         {
2676             // Identify the amulet and spend costs - finesse will be aborted
2677             // for free with an identified amulet.
2678             break;
2679         }
2680
2681         if (you.duration[DUR_FINESSE])
2682         {
2683             // "Your [hand(s)] get{s} new energy."
2684             mprf(MSGCH_DURATION, "%s",
2685                  you.hands_act("get", "new energy.").c_str());
2686         }
2687         else
2688             mprf(MSGCH_DURATION, "You can now deal lightning-fast blows.");
2689
2690         you.increase_duration(DUR_FINESSE,
2691             40 + random2(you.skill(SK_INVOCATIONS, 8)), 80);
2692
2693         did_god_conduct(DID_HASTY, 8); // Currently irrelevant.
2694         break;
2695
2696     case ABIL_MAKHLEB_MINOR_DESTRUCTION:
2697         beam.range = 8;
2698
2699         if (!spell_direction(spd, beam))
2700             return SPRET_ABORT;
2701
2702         power = you.skill(SK_INVOCATIONS, 1)
2703                 + random2(1 + you.skill(SK_INVOCATIONS, 1))
2704                 + random2(1 + you.skill(SK_INVOCATIONS, 1));
2705
2706         // Since the actual beam is random, check with BEAM_MMISSILE and the
2707         // highest range possible.
2708         if (!player_tracer(ZAP_DEBUGGING_RAY, power, beam, 8))
2709             return SPRET_ABORT;
2710
2711         fail_check();
2712
2713         switch (random2(5))
2714         {
2715         case 0: zapping(ZAP_THROW_FLAME, power, beam); break;
2716         case 1: zapping(ZAP_PAIN,  power, beam); break;
2717         case 2: zapping(ZAP_STONE_ARROW, power, beam); break;
2718         case 3: zapping(ZAP_SHOCK, power, beam); break;
2719         case 4: zapping(ZAP_BREATHE_ACID, power/2, beam); break;
2720         }
2721         break;
2722
2723     case ABIL_MAKHLEB_LESSER_SERVANT_OF_MAKHLEB:
2724         fail_check();
2725         summon_demon_type(random_choose(MONS_HELLWING, MONS_NEQOXEC,
2726                           MONS_ORANGE_DEMON, MONS_SMOKE_DEMON, MONS_YNOXINUL),
2727                           20 + you.skill(SK_INVOCATIONS, 3), GOD_MAKHLEB);
2728         break;
2729
2730     case ABIL_MAKHLEB_MAJOR_DESTRUCTION:
2731         beam.range = 6;
2732
2733         if (!spell_direction(spd, beam))
2734             return SPRET_ABORT;
2735
2736         power = you.skill(SK_INVOCATIONS, 3)
2737                 + random2(1 + you.skill(SK_INVOCATIONS, 1))
2738                 + random2(1 + you.skill(SK_INVOCATIONS, 1));
2739
2740         // Since the actual beam is random, check with BEAM_MMISSILE and the
2741         // highest range possible.
2742         if (!player_tracer(ZAP_DEBUGGING_RAY, power, beam, 8))
2743             return SPRET_ABORT;
2744
2745         fail_check();
2746
2747         {
2748             zap_type ztype =
2749                 random_choose(ZAP_BOLT_OF_FIRE,
2750                               ZAP_FIREBALL,
2751                               ZAP_LIGHTNING_BOLT,
2752                               ZAP_STICKY_FLAME,
2753                               ZAP_IRON_SHOT,
2754                               ZAP_BOLT_OF_DRAINING,
2755                               ZAP_ORB_OF_ELECTRICITY);
2756             zapping(ztype, power, beam);
2757         }
2758         break;
2759
2760     case ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB:
2761         fail_check();
2762         summon_demon_type(random_choose(MONS_EXECUTIONER, MONS_GREEN_DEATH,
2763                           MONS_BLIZZARD_DEMON, MONS_BALRUG, MONS_CACODEMON),
2764                           20 + you.skill(SK_INVOCATIONS, 3), GOD_MAKHLEB);
2765         break;
2766
2767     case ABIL_TROG_BURN_SPELLBOOKS:
2768         fail_check();
2769         if (!trog_burn_spellbooks())
2770             return SPRET_ABORT;
2771         break;
2772
2773     case ABIL_TROG_BERSERK:
2774         fail_check();
2775         // Trog abilities don't use or train invocations.
2776         you.go_berserk(true);
2777         break;
2778
2779     case ABIL_TROG_REGEN_MR:
2780         fail_check();
2781         // Trog abilities don't use or train invocations.
2782         trog_do_trogs_hand(you.piety / 2);
2783         break;
2784
2785     case ABIL_TROG_BROTHERS_IN_ARMS:
2786         fail_check();
2787         // Trog abilities don't use or train invocations.
2788         summon_berserker(you.piety +
2789                          random2(you.piety/4) - random2(you.piety/4),
2790                          &you);
2791         break;
2792
2793     case ABIL_SIF_MUNA_FORGET_SPELL:
2794         fail_check();
2795         if (cast_selective_amnesia() <= 0)
2796             return SPRET_ABORT;
2797         break;
2798
2799     case ABIL_ELYVILON_LIFESAVING:
2800         fail_check();
2801         if (you.duration[DUR_LIFESAVING])
2802             mpr("You renew your call for help.");
2803         else
2804         {
2805             mprf("You beseech %s to protect your life.",
2806                  god_name(you.religion).c_str());
2807         }
2808         // Might be a decrease, this is intentional (like Yred).
2809         you.duration[DUR_LIFESAVING] = 9 * BASELINE_DELAY
2810                      + random2avg(you.piety * BASELINE_DELAY, 2) / 10;
2811         break;
2812
2813     case ABIL_ELYVILON_LESSER_HEALING:
2814     {
2815         fail_check();
2816         int pow = 3 + (you.skill_rdiv(SK_INVOCATIONS, 1, 6));
2817 #if TAG_MAJOR_VERSION == 34
2818         if (you.species == SP_DJINNI)
2819             pow /= 2;
2820 #endif
2821         if (cast_healing(pow,
2822                          3 + (int) ceil(you.skill(SK_INVOCATIONS, 1) / 6.0),
2823                          true, you.pos(), false, TARG_NUM_MODES)
2824                          == SPRET_ABORT)
2825         {
2826             return SPRET_ABORT;
2827         }
2828         break;
2829     }
2830
2831     case ABIL_ELYVILON_PURIFICATION:
2832         fail_check();
2833         elyvilon_purification();
2834         break;
2835
2836     case ABIL_ELYVILON_GREATER_HEALING:
2837     case ABIL_ELYVILON_HEAL_OTHER:
2838     {
2839         fail_check();
2840         const bool self = (abil.ability == ABIL_ELYVILON_GREATER_HEALING);
2841
2842         int pow = 10 + (you.skill_rdiv(SK_INVOCATIONS, 1, 3));
2843 #if TAG_MAJOR_VERSION == 34
2844         if (self && you.species == SP_DJINNI)
2845             pow /= 2;
2846 #endif
2847         if (cast_healing(pow,
2848                          10 + (int) ceil(you.skill(SK_INVOCATIONS, 1) / 3.0),
2849                          true, self ? you.pos() : coord_def(0, 0), !self,
2850                          self ? TARG_NUM_MODES : TARG_INJURED_FRIEND)
2851                          == SPRET_ABORT)
2852         {
2853             return SPRET_ABORT;
2854         }
2855         break;
2856     }
2857
2858     case ABIL_ELYVILON_DIVINE_VIGOUR:
2859         fail_check();
2860         if (!elyvilon_divine_vigour())
2861             return SPRET_ABORT;
2862         break;
2863
2864     case ABIL_LUGONU_ABYSS_EXIT:
2865         fail_check();
2866         down_stairs(DNGN_EXIT_ABYSS);
2867         break;
2868
2869     case ABIL_LUGONU_BEND_SPACE:
2870         fail_check();
2871         lugonu_bend_space();
2872         break;
2873
2874     case ABIL_LUGONU_BANISH:
2875     {
2876         beam.range = LOS_RADIUS;
2877         const int pow = 16 + you.skill(SK_INVOCATIONS, 8);
2878
2879         if (!spell_direction(spd, beam, DIR_NONE, TARG_HOSTILE, 0,
2880                              true, true, false, nullptr, nullptr, false, nullptr,
2881                              bind(desc_success_chance, placeholders::_1,
2882                                   zap_ench_power(ZAP_BANISHMENT, pow))))
2883         {
2884             return SPRET_ABORT;
2885         }
2886
2887         if (beam.target == you.pos())
2888         {
2889             mpr("You cannot banish yourself!");
2890             return SPRET_ABORT;
2891         }
2892
2893         return zapping(ZAP_BANISHMENT, pow, beam, true, nullptr, fail);
2894     }
2895
2896     case ABIL_LUGONU_CORRUPT:
2897         fail_check();
2898         if (!lugonu_corrupt_level(300 + you.skill(SK_INVOCATIONS, 15)))
2899             return SPRET_ABORT;
2900         break;
2901
2902     case ABIL_LUGONU_ABYSS_ENTER:
2903     {
2904         fail_check();
2905         // Deflate HP.
2906         dec_hp(random2avg(you.hp, 2), false);
2907
2908         // Deflate MP.
2909         if (you.magic_points)
2910             dec_mp(random2avg(you.magic_points, 2));
2911
2912         bool note_status = notes_are_active();
2913         activate_notes(false);  // This banishment shouldn't be noted.
2914         banished();
2915         activate_notes(note_status);
2916         break;
2917     }
2918
2919     case ABIL_NEMELEX_TRIPLE_DRAW:
2920         fail_check();
2921         if (!deck_triple_draw())
2922             return SPRET_ABORT;
2923         break;
2924
2925     case ABIL_NEMELEX_DEAL_FOUR:
2926         fail_check();
2927         if (!deck_deal())
2928             return SPRET_ABORT;
2929         break;
2930
2931     case ABIL_NEMELEX_STACK_FIVE:
2932         fail_check();
2933         if (!deck_stack())
2934             return SPRET_ABORT;
2935         break;
2936
2937     case ABIL_BEOGH_SMITING:
2938         fail_check();
2939         if (your_spells(SPELL_SMITING, 12 + skill_bump(SK_INVOCATIONS, 6),
2940                         false) == SPRET_ABORT)
2941         {
2942             return SPRET_ABORT;
2943         }
2944         break;
2945
2946     case ABIL_BEOGH_GIFT_ITEM:
2947         if (!beogh_gift_item())
2948             return SPRET_ABORT;
2949         break;
2950
2951     case ABIL_BEOGH_RECALL_ORCISH_FOLLOWERS:
2952         fail_check();
2953         start_recall(RECALL_BEOGH);
2954         break;
2955
2956     case ABIL_STOP_RECALL:
2957         fail_check();
2958         mpr("You stop recalling your allies.");
2959         end_recall();
2960         break;
2961
2962     case ABIL_FEDHAS_SUNLIGHT:
2963         return fedhas_sunlight(fail);
2964
2965     case ABIL_FEDHAS_PLANT_RING:
2966         fail_check();
2967         if (!fedhas_plant_ring_from_fruit())
2968             return SPRET_ABORT;
2969         break;
2970
2971     case ABIL_FEDHAS_RAIN:
2972         fail_check();
2973         if (!fedhas_rain(you.pos()))
2974         {
2975             canned_msg(MSG_NOTHING_HAPPENS);
2976             return SPRET_ABORT;
2977         }
2978         break;
2979
2980     case ABIL_FEDHAS_SPAWN_SPORES:
2981         fail_check();
2982         ASSERT(fedhas_corpse_spores() > 0);
2983         break;
2984
2985     case ABIL_FEDHAS_EVOLUTION:
2986         fail_check();
2987         fedhas_evolve_flora();
2988         break;
2989
2990     case ABIL_TRAN_BAT:
2991         fail_check();
2992         if (!transform(100, TRAN_BAT))
2993         {
2994             crawl_state.zero_turns_taken();
2995             return SPRET_ABORT;
2996         }
2997         break;
2998
2999     case ABIL_JIYVA_CALL_JELLY:
3000     {
3001         fail_check();
3002         mgen_data mg(MONS_JELLY, BEH_STRICT_NEUTRAL, 0, 0, 0, you.pos(),
3003                      MHITNOT, 0, GOD_JIYVA);
3004
3005         mg.non_actor_summoner = "Jiyva";
3006
3007         if (!create_monster(mg))
3008             return SPRET_ABORT;
3009         break;
3010     }
3011
3012     case ABIL_JIYVA_JELLY_PARALYSE:
3013         fail_check();
3014         jiyva_paralyse_jellies();
3015         break;
3016
3017     case ABIL_JIYVA_SLIMIFY:
3018     {
3019         fail_check();
3020         const item_def* const weapon = you.weapon();
3021         const string msg = (weapon) ? weapon->name(DESC_YOUR)
3022                                     : ("your " + you.hand_name(true));
3023         mprf(MSGCH_DURATION, "A thick mucus forms on %s.", msg.c_str());
3024         you.increase_duration(DUR_SLIMIFY,
3025                               random2avg(you.piety / 4, 2) + 3, 100);
3026         break;
3027     }
3028
3029     case ABIL_JIYVA_CURE_BAD_MUTATION:
3030         fail_check();
3031         jiyva_remove_bad_mutation();
3032         break;
3033
3034     case ABIL_CHEIBRIADOS_TIME_STEP:
3035         fail_check();
3036         cheibriados_time_step(you.skill(SK_INVOCATIONS, 10) * you.piety / 100);
3037         break;
3038
3039     case ABIL_CHEIBRIADOS_TIME_BEND:
3040         fail_check();
3041         cheibriados_time_bend(16 + you.skill(SK_INVOCATIONS, 8));
3042         break;
3043
3044     case ABIL_CHEIBRIADOS_DISTORTION:
3045         fail_check();
3046         cheibriados_temporal_distortion();
3047         break;
3048
3049     case ABIL_CHEIBRIADOS_SLOUCH:
3050         fail_check();
3051         if (!cheibriados_slouch(0))
3052         {
3053             canned_msg(MSG_OK);
3054             return SPRET_ABORT;
3055         }
3056         break;
3057
3058     case ABIL_ASHENZARI_SCRYING:
3059         fail_check();
3060         if (you.duration[DUR_SCRYING])
3061             mpr("You extend your astral sight.");
3062         else
3063             mpr("You gain astral sight.");
3064         you.duration[DUR_SCRYING] = 100 + random2avg(you.piety * 2, 2);
3065         you.xray_vision = true;
3066         break;
3067
3068     case ABIL_ASHENZARI_TRANSFER_KNOWLEDGE:
3069         fail_check();
3070         if (!ashenzari_transfer_knowledge())
3071         {
3072             canned_msg(MSG_OK);
3073             return SPRET_ABORT;
3074         }
3075         break;
3076
3077     case ABIL_ASHENZARI_END_TRANSFER:
3078         fail_check();
3079         ashenzari_end_transfer();
3080         break;
3081
3082     case ABIL_DITHMENOS_SHADOW_STEP:
3083         fail_check();
3084         if (!dithmenos_shadow_step())
3085         {
3086             canned_msg(MSG_OK);
3087             return SPRET_ABORT;
3088         }
3089         break;
3090
3091     case ABIL_DITHMENOS_SHADOW_FORM:
3092         fail_check();
3093         if (!transform(you.skill(SK_INVOCATIONS, 2), TRAN_SHADOW))
3094         {
3095             crawl_state.zero_turns_taken();
3096             return SPRET_ABORT;
3097         }
3098         break;
3099
3100     case ABIL_GOZAG_POTION_PETITION:
3101         fail_check();
3102         run_uncancel(UNC_POTION_PETITION, 0);
3103         break;
3104
3105     case ABIL_GOZAG_CALL_MERCHANT:
3106         fail_check();
3107         run_uncancel(UNC_CALL_MERCHANT, 0);
3108         break;
3109
3110     case ABIL_GOZAG_BRIBE_BRANCH:
3111         fail_check();
3112         if (!gozag_bribe_branch())
3113             return SPRET_ABORT;
3114         break;
3115
3116     case ABIL_QAZLAL_UPHEAVAL:
3117         return qazlal_upheaval(coord_def(), false, fail);
3118
3119     case ABIL_QAZLAL_ELEMENTAL_FORCE:
3120         fail_check();
3121         qazlal_elemental_force();
3122         break;
3123
3124     case ABIL_QAZLAL_DISASTER_AREA:
3125         fail_check();
3126         if (!qazlal_disaster_area())
3127             return SPRET_ABORT;
3128         break;
3129
3130     case ABIL_RU_SACRIFICE_PURITY:
3131     case ABIL_RU_SACRIFICE_WORDS:
3132     case ABIL_RU_SACRIFICE_DRINK:
3133     case ABIL_RU_SACRIFICE_ESSENCE:
3134     case ABIL_RU_SACRIFICE_HEALTH:
3135     case ABIL_RU_SACRIFICE_STEALTH:
3136     case ABIL_RU_SACRIFICE_ARTIFICE:
3137     case ABIL_RU_SACRIFICE_LOVE:
3138     case ABIL_RU_SACRIFICE_COURAGE:
3139     case ABIL_RU_SACRIFICE_ARCANA:
3140     case ABIL_RU_SACRIFICE_NIMBLENESS:
3141     case ABIL_RU_SACRIFICE_DURABILITY:
3142     case ABIL_RU_SACRIFICE_HAND:
3143     case ABIL_RU_SACRIFICE_EXPERIENCE:
3144     case ABIL_RU_SACRIFICE_SKILL:
3145         fail_check();
3146         if (!ru_do_sacrifice(abil.ability))
3147             return SPRET_ABORT;
3148         break;
3149
3150     case ABIL_RU_REJECT_SACRIFICES:
3151         fail_check();
3152         if (!ru_reject_sacrifices())
3153             return SPRET_ABORT;
3154         break;
3155
3156     case ABIL_RU_DRAW_OUT_POWER:
3157         fail_check();
3158         if (you.duration[DUR_EXHAUSTED])
3159         {
3160             mpr("You're too exhausted to draw out your power.");
3161             return SPRET_ABORT;
3162         }
3163         if (you.hp == you.hp_max && you.magic_points == you.max_magic_points
3164             && !you.duration[DUR_CONF]
3165             && !you.duration[DUR_SLOW]
3166             && !you.attribute[ATTR_HELD]
3167             && !you.petrifying()
3168             && !you.is_constricted())
3169         {
3170             mpr("You have no need to draw out power.");
3171             return SPRET_ABORT;
3172         }
3173         ru_draw_out_power();
3174         you.increase_duration(DUR_EXHAUSTED, 12 + random2(5));
3175         break;
3176
3177     case ABIL_RU_POWER_LEAP:
3178         fail_check();
3179         if (you.duration[DUR_EXHAUSTED])
3180         {
3181             mpr("You're too exhausted to power leap.");
3182             return SPRET_ABORT;
3183         }
3184         if (!ru_power_leap())
3185         {
3186             canned_msg(MSG_OK);
3187             return SPRET_ABORT;
3188         }
3189         you.increase_duration(DUR_EXHAUSTED, 18 + random2(8));
3190         break;
3191
3192     case ABIL_RU_APOCALYPSE:
3193         fail_check();
3194         if (you.duration[DUR_EXHAUSTED])
3195         {
3196             mpr("You're too exhausted to unleash your apocalyptic power.");
3197             return SPRET_ABORT;
3198         }
3199         if (!ru_apocalypse())
3200             return SPRET_ABORT;
3201         you.increase_duration(DUR_EXHAUSTED, 30 + random2(20));
3202         break;
3203
3204     case ABIL_RENOUNCE_RELIGION:
3205         fail_check();
3206         if (yesno("Really renounce your faith, foregoing its fabulous benefits?",
3207                   false, 'n')
3208             && yesno("Are you sure you won't change your mind later?",
3209                      false, 'n'))
3210         {
3211             excommunication();
3212         }
3213         else
3214         {
3215             canned_msg(MSG_OK);
3216             return SPRET_ABORT;
3217         }
3218         break;
3219
3220     case ABIL_CONVERT_TO_BEOGH:
3221         fail_check();
3222         god_pitch(GOD_BEOGH);
3223         if (you_worship(GOD_BEOGH))
3224         {
3225             spare_beogh_convert();
3226             break;
3227         }
3228         return SPRET_ABORT;
3229
3230     case ABIL_NON_ABILITY:
3231         fail_check();
3232         mpr("Sorry, you can't do that.");
3233         break;
3234
3235     default:
3236         die("invalid ability");
3237     }
3238
3239     return SPRET_SUCCESS;
3240 }
3241
3242 // [ds] Increase piety cost for god abilities that are particularly
3243 // overpowered in Sprint. Yes, this is a hack. No, I don't care.
3244 static int _scale_piety_cost(ability_type abil, int original_cost)
3245 {
3246     // Abilities that have aroused our ire earn 2.5x their classic
3247     // Crawl piety cost.
3248     return (crawl_state.game_is_sprint()
3249             && (abil == ABIL_TROG_BROTHERS_IN_ARMS
3250                 || abil == ABIL_MAKHLEB_GREATER_SERVANT_OF_MAKHLEB))
3251            ? div_rand_round(original_cost * 5, 2)
3252            : original_cost;
3253 }
3254
3255 // We pass in ability ZP cost as it may have changed during the exercise
3256 // of the ability (if the cost is scaled, for example)
3257 static void _pay_ability_costs(const ability_def& abil, int zpcost)
3258 {
3259     if (abil.flags & ABFLAG_INSTANT)
3260     {
3261         you.turn_is_over = false;
3262         you.elapsed_time_at_last_input = you.elapsed_time;
3263         update_turn_count();
3264     }
3265     else
3266         you.turn_is_over = true;
3267
3268     const int food_cost  = abil.food_cost + random2avg(abil.food_cost, 2);
3269     const int piety_cost =
3270         _scale_piety_cost(abil.ability, abil.piety_cost.cost());
3271     const int hp_cost    = abil.hp_cost.cost(you.hp_max);
3272
3273     dprf("Cost: mp=%d; hp=%d; food=%d; piety=%d",
3274          abil.mp_cost, hp_cost, food_cost, piety_cost);
3275
3276     if (abil.mp_cost)
3277     {
3278         dec_mp(abil.mp_cost);
3279         if (abil.flags & ABFLAG_PERMANENT_MP)
3280             rot_mp(1);
3281     }
3282
3283     if (abil.hp_cost)
3284     {
3285         dec_hp(hp_cost, false);
3286         if (abil.flags & ABFLAG_PERMANENT_HP)
3287             rot_hp(hp_cost);
3288     }
3289
3290     if (zpcost)
3291     {
3292         you.zot_points -= zpcost;
3293         you.redraw_experience = true;
3294     }
3295
3296     if (abil.flags & ABFLAG_NECRO_MISCAST_MINOR)
3297     {
3298         MiscastEffect(&you, nullptr, ABIL_MISCAST, SPTYP_NECROMANCY, 5, 90,
3299                       "power out of control");
3300     }
3301     if (abil.flags & ABFLAG_LEVEL_DRAIN)
3302         adjust_level(-1);
3303
3304     if (food_cost)
3305         make_hungry(food_cost, false, true);
3306
3307     if (piety_cost)
3308         lose_piety(piety_cost);
3309 }
3310
3311 int choose_ability_menu(const vector<talent>& talents)
3312 {
3313 #ifdef USE_TILE_LOCAL
3314     const bool text_only = false;
3315 #else
3316     const bool text_only = true;
3317 #endif
3318
3319     ToggleableMenu abil_menu(MF_SINGLESELECT | MF_ANYPRINTABLE
3320                              | MF_TOGGLE_ACTION | MF_ALWAYS_SHOW_MORE,
3321                              text_only);
3322
3323     abil_menu.set_highlighter(nullptr);
3324 #ifdef USE_TILE_LOCAL
3325     {
3326         // Hack like the one in spl-cast.cc:list_spells() to align the title.
3327         ToggleableMenuEntry* me =
3328             new ToggleableMenuEntry("  Ability - do what?                 "
3329                                     "Cost                          Failure",
3330                                     "  Ability - describe what?           "
3331                                     "Cost                          Failure",
3332                                     MEL_ITEM);
3333         me->colour = BLUE;
3334         abil_menu.add_entry(me);
3335     }
3336 #else
3337     abil_menu.set_title(
3338         new ToggleableMenuEntry("  Ability - do what?                 "
3339                                 "Cost                          Failure",
3340                                 "  Ability - describe what?           "
3341                                 "Cost                          Failure",
3342                                 MEL_TITLE));
3343 #endif
3344     abil_menu.set_tag("ability");
3345     abil_menu.add_toggle_key('!');
3346     abil_menu.add_toggle_key('?');
3347     abil_menu.menu_action = Menu::ACT_EXECUTE;
3348
3349     if (crawl_state.game_is_hints())
3350     {
3351         // XXX: This could be buggy if you manage to pick up lots and
3352         // lots of abilities during hints mode.
3353         abil_menu.set_more(hints_abilities_info());
3354     }
3355     else
3356     {
3357         abil_menu.set_more(formatted_string::parse_string(
3358                            "Press '<w>!</w>' or '<w>?</w>' to toggle "
3359                            "between ability selection and description."));
3360     }
3361
3362     int numbers[52];
3363     for (int i = 0; i < 52; ++i)
3364         numbers[i] = i;
3365
3366     bool found_invocations = false;
3367     bool found_zotdef = false;
3368
3369     // First add all non-invocation, non-zotdef abilities.
3370     for (unsigned int i = 0; i < talents.size(); ++i)
3371     {
3372         if (talents[i].is_invocation)
3373             found_invocations = true;
3374         else if (talents[i].is_zotdef)
3375             found_zotdef = true;
3376         else
3377         {
3378             ToggleableMenuEntry* me =
3379                 new ToggleableMenuEntry(describe_talent(talents[i]),
3380                                         describe_talent(talents[i]),
3381                                         MEL_ITEM, 1, talents[i].hotkey);
3382             me->data = &numbers[i];
3383 #ifdef USE_TILE
3384             me->add_tile(tile_def(tileidx_ability(talents[i].which), TEX_GUI));
3385 #endif
3386             // Only check this here, since your god can't hate its own abilities
3387             if (god_hates_ability(talents[i].which, you.religion))
3388                 me->colour = COL_FORBIDDEN;
3389             abil_menu.add_entry(me);
3390         }
3391     }
3392
3393     if (found_zotdef)
3394     {
3395 #ifdef USE_TILE_LOCAL
3396         ToggleableMenuEntry* subtitle =
3397             new ToggleableMenuEntry("    Zot Defence -",
3398                                     "    Zot Defence -", MEL_ITEM);
3399         subtitle->colour = BLUE;
3400         abil_menu.add_entry(subtitle);
3401 #else
3402         abil_menu.add_entry(
3403             new ToggleableMenuEntry("    Zot Defence - ",
3404                                     "    Zot Defence - ", MEL_SUBTITLE));
3405 #endif
3406         for (unsigned int i = 0; i < talents.size(); ++i)
3407         {
3408             if (talents[i].is_zotdef)
3409             {
3410                 ToggleableMenuEntry* me =
3411                     new ToggleableMenuEntry(describe_talent(talents[i]),
3412                                             describe_talent(talents[i]),
3413                                             MEL_ITEM, 1, talents[i].hotkey);
3414                 me->data = &numbers[i];
3415 #ifdef USE_TILE
3416                 me->add_tile(tile_def(tileidx_ability(talents[i].which),
3417                                       TEX_GUI));
3418 #endif
3419                 abil_menu.add_entry(me);
3420             }
3421         }
3422     }
3423
3424     if (found_invocations)
3425     {
3426 #ifdef USE_TILE_LOCAL
3427         ToggleableMenuEntry* subtitle =
3428             new ToggleableMenuEntry("    Invocations - ",
3429                                     "    Invocations - ", MEL_ITEM);
3430         subtitle->colour = BLUE;
3431         abil_menu.add_entry(subtitle);
3432 #else
3433         abil_menu.add_entry(
3434             new ToggleableMenuEntry("    Invocations - ",
3435                                     "    Invocations - ", MEL_SUBTITLE));
3436 #endif
3437         for (unsigned int i = 0; i < talents.size(); ++i)
3438         {
3439             if (talents[i].is_invocation)
3440             {
3441                 ToggleableMenuEntry* me =
3442                     new ToggleableMenuEntry(describe_talent(talents[i]),
3443                                             describe_talent(talents[i]),
3444                                             MEL_ITEM, 1, talents[i].hotkey);
3445                 me->data = &numbers[i];
3446 #ifdef USE_TILE
3447                 me->add_tile(tile_def(tileidx_ability(talents[i].which),
3448                                       TEX_GUI));
3449 #endif
3450                 abil_menu.add_entry(me);
3451             }
3452         }
3453     }
3454
3455     while (true)
3456     {
3457         vector<MenuEntry*> sel = abil_menu.show(false);
3458         if (!crawl_state.doing_prev_cmd_again)
3459             redraw_screen();
3460         if (sel.empty())
3461             return -1;
3462
3463         ASSERT(sel.size() == 1);
3464         ASSERT(sel[0]->hotkeys.size() == 1);
3465         int selected = *(static_cast<int*>(sel[0]->data));
3466
3467         if (abil_menu.menu_action == Menu::ACT_EXAMINE)
3468             _print_talent_description(talents[selected]);
3469         else
3470             return *(static_cast<int*>(sel[0]->data));
3471     }
3472 }
3473
3474 string describe_talent(const talent& tal)
3475 {
3476     ASSERT(tal.which != ABIL_NON_ABILITY);
3477
3478     const string failure = failure_rate_to_string(tal.fail);
3479
3480     ostringstream desc;
3481     desc << left
3482          << chop_string(ability_name(tal.which), 32)
3483          << chop_string(make_cost_description(tal.which), 30)
3484          << chop_string(failure, 7);
3485     return desc.str();
3486 }
3487
3488 static void _add_talent(vector<talent>& vec, const ability_type ability,
3489                         bool check_confused)
3490 {
3491     const talent t = get_talent(ability, check_confused);
3492     if (t.which != ABIL_NON_ABILITY)
3493         vec.push_back(t);
3494 }
3495
3496 /**
3497  * Return all relevant talents that the player has.
3498  *
3499  * Currently the only abilities that are affected by include_unusable are god
3500  * abilities (affect by e.g. penance or silence).
3501  * @param check_confused If true, abilities that don't work when confused will
3502  *                       be excluded.
3503  * @param include_unusable If true, abilities that are currently unusable will
3504  *                         be excluded.
3505  * @return  A vector of talent structs.
3506  */
3507 vector<talent> your_talents(bool check_confused, bool include_unusable)
3508 {
3509     vector<talent> talents;
3510
3511     // zot defence abilities; must also be updated in player.cc when these levels are changed
3512     if (crawl_state.game_is_zotdef())
3513     {
3514         if (you.experience_level >= 2)
3515             _add_talent(talents, ABIL_MAKE_OKLOB_SAPLING, check_confused);
3516         if (you.experience_level >= 3)
3517             _add_talent(talents, ABIL_MAKE_ARROW_TRAP, check_confused);
3518         if (you.experience_level >= 4)
3519             _add_talent(talents, ABIL_MAKE_PLANT, check_confused);
3520         if (you.experience_level >= 4)
3521             _add_talent(talents, ABIL_REMOVE_CURSE, check_confused);
3522         if (you.experience_level >= 5)
3523             _add_talent(talents, ABIL_MAKE_BURNING_BUSH, check_confused);
3524         if (you.experience_level >= 6)
3525             _add_talent(talents, ABIL_MAKE_ALTAR, check_confused);
3526         if (you.experience_level >= 6)
3527             _add_talent(talents, ABIL_MAKE_GRENADE