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