1 /**
2  * @file
3  * @brief Spell casting and miscast functions.
4 **/
5 
6 #include "AppHdr.h"
7 
8 #include "spl-cast.h"
9 
10 #include <iomanip>
11 #include <sstream>
12 #include <cmath>
13 
14 #include "act-iter.h"
15 #include "areas.h"
16 #include "art-enum.h"
17 #include "beam.h"
18 #include "chardump.h"
19 #include "cloud.h"
20 #include "colour.h"
21 #include "coordit.h"
22 #include "database.h"
23 #include "describe.h"
24 #include "directn.h"
25 #include "english.h"
26 #include "env.h"
27 #include "evoke.h"
28 #include "exercise.h"
29 #include "format.h"
30 #include "god-abil.h"
31 #include "god-conduct.h"
32 #include "god-item.h"
33 #include "god-passive.h" // passive_t::shadow_spells
34 #include "hints.h"
35 #include "items.h"
36 #include "item-prop.h"
37 #include "item-use.h"
38 #include "libutil.h"
39 #include "macro.h"
40 #include "menu.h"
41 #include "message.h"
42 #include "misc.h"
43 #include "mon-behv.h"
44 #include "mon-cast.h"
45 #include "mon-explode.h"
46 #include "mon-place.h"
47 #include "mon-project.h"
48 #include "mon-util.h"
49 #include "mutation.h"
50 #include "options.h"
51 #include "ouch.h"
52 #include "output.h"
53 #include "player.h"
54 #include "player-stats.h"
55 #include "prompt.h"
56 #include "religion.h"
57 #include "shout.h"
58 #include "skills.h"
59 #include "spl-book.h"
60 #include "spl-clouds.h"
61 #include "spl-damage.h"
62 #include "spl-goditem.h"
63 #include "spl-miscast.h"
64 #include "spl-monench.h"
65 #include "spl-other.h"
66 #include "spl-selfench.h"
67 #include "spl-summoning.h"
68 #include "spl-transloc.h"
69 #include "spl-wpnench.h"
70 #include "spl-zap.h"
71 #include "state.h"
72 #include "stepdown.h"
73 #include "stringutil.h"
74 #include "tag-version.h"
75 #include "target.h"
76 #include "teleport.h"
77 #include "terrain.h"
78 #include "tilepick.h"
79 #include "transform.h"
80 #include "unicode.h"
81 #include "unwind.h"
82 #include "view.h"
83 #include "viewchar.h" // stringize_glyph
84 
85 static int _spell_enhancement(spell_type spell);
86 static string _spell_failure_rate_description(spell_type spell);
87 
surge_power(const int enhanced)88 void surge_power(const int enhanced)
89 {
90     if (enhanced)               // one way or the other {dlb}
91     {
92         const string modifier = (enhanced  < -2) ? "extraordinarily" :
93                                 (enhanced == -2) ? "extremely" :
94                                 (enhanced ==  2) ? "strong" :
95                                 (enhanced  >  2) ? "huge"
96                                                  : "";
97         mprf("You feel %s %s",
98              !modifier.length() ? "a"
99                                 : article_a(modifier).c_str(),
100              (enhanced < 0) ? "numb sensation."
101                             : "surge of power!");
102     }
103 }
104 
surge_power_wand(const int mp_cost)105 void surge_power_wand(const int mp_cost)
106 {
107     if (mp_cost)
108     {
109         const bool slight = mp_cost < 3;
110         mprf("You feel a %ssurge of power%s",
111              slight ? "slight " : "",
112              slight ? "."      : "!");
113     }
114 }
115 
_spell_base_description(spell_type spell,bool viewing)116 static string _spell_base_description(spell_type spell, bool viewing)
117 {
118     ostringstream desc;
119 
120     int highlight =  spell_highlight_by_utility(spell, COL_UNKNOWN, !viewing);
121 
122     desc << "<" << colour_to_str(highlight) << ">" << left;
123 
124     // spell name
125     desc << chop_string(spell_title(spell), 30);
126 
127     // spell schools
128     desc << spell_schools_string(spell);
129 
130     const int so_far = strwidth(desc.str()) - (strwidth(colour_to_str(highlight))+2);
131     if (so_far < 60)
132         desc << string(60 - so_far, ' ');
133     desc << "</" << colour_to_str(highlight) <<">";
134 
135     // spell fail rate, level
136     const string failure_rate = spell_failure_rate_string(spell);
137     const int width = strwidth(formatted_string::parse_string(failure_rate).tostring());
138     desc << failure_rate << string(12-width, ' ');
139     desc << spell_difficulty(spell);
140     desc << " ";
141 
142     return desc.str();
143 }
144 
_spell_extra_description(spell_type spell,bool viewing)145 static string _spell_extra_description(spell_type spell, bool viewing)
146 {
147     ostringstream desc;
148 
149     int highlight =  spell_highlight_by_utility(spell, COL_UNKNOWN, !viewing);
150 
151     desc << "<" << colour_to_str(highlight) << ">" << left;
152 
153     // spell name
154     desc << chop_string(spell_title(spell), 30);
155 
156     // spell power, spell range, noise
157     const string rangestring = spell_range_string(spell);
158     const string damagestring = spell_damage_string(spell);
159 
160     desc << chop_string(spell_power_string(spell), 10)
161          << chop_string(damagestring.length() ? damagestring : "N/A", 10)
162          << chop_string(rangestring, 10)
163          << chop_string(spell_noise_string(spell, 10), 14);
164 
165     desc << "</" << colour_to_str(highlight) <<">";
166 
167     return desc.str();
168 }
169 
170 // selector is a boolean function that filters spells according
171 // to certain criteria. Currently used for Tiles to distinguish
172 // spells targeted on player vs. spells targeted on monsters.
list_spells(bool toggle_with_I,bool viewing,bool allow_preselect,const string & title,spell_selector selector)173 int list_spells(bool toggle_with_I, bool viewing, bool allow_preselect,
174                 const string &title, spell_selector selector)
175 {
176     if (toggle_with_I && get_spell_by_letter('I') != SPELL_NO_SPELL)
177         toggle_with_I = false;
178 
179     ToggleableMenu spell_menu(MF_SINGLESELECT | MF_ANYPRINTABLE
180             | MF_NO_WRAP_ROWS | MF_ALWAYS_SHOW_MORE | MF_ALLOW_FORMATTING);
181     string titlestring = make_stringf("%-25.25s", title.c_str());
182     {
183         ToggleableMenuEntry* me =
184             new ToggleableMenuEntry(
185                 titlestring + "         Type                          Failure  Level",
186                 titlestring + "         Power     Damage    Range     Noise ",
187                 MEL_TITLE);
188         spell_menu.set_title(me, true, true);
189     }
190     spell_menu.set_highlighter(nullptr);
191     spell_menu.set_tag("spell");
192     spell_menu.add_toggle_key('!');
193 
194     string more_str = "Press '<w>!</w>' ";
195     if (toggle_with_I)
196     {
197         spell_menu.add_toggle_key('I');
198         more_str += "or '<w>I</w>' ";
199     }
200     if (!viewing)
201         spell_menu.menu_action = Menu::ACT_EXECUTE;
202     more_str += "to toggle spell view.";
203     spell_menu.set_more(formatted_string::parse_string(more_str));
204 
205     // If there's only a single spell in the offered spell list,
206     // taking the selector function into account, preselect that one.
207     bool preselect_first = false;
208     if (allow_preselect)
209     {
210         int count = 0;
211         if (you.spell_no == 1)
212             count = 1;
213         else if (selector)
214         {
215             for (int i = 0; i < 52; ++i)
216             {
217                 const char letter = index_to_letter(i);
218                 const spell_type spell = get_spell_by_letter(letter);
219                 if (!is_valid_spell(spell) || !(*selector)(spell))
220                     continue;
221 
222                 // Break out early if we've got > 1 spells.
223                 if (++count > 1)
224                     break;
225             }
226         }
227         // Preselect the first spell if it's only spell applicable.
228         preselect_first = (count == 1);
229     }
230     // TODO: maybe fill this from the quiver if there's a quivered spell and
231     // no last cast one?
232     if (allow_preselect || preselect_first
233                            && you.last_cast_spell != SPELL_NO_SPELL)
234     {
235         spell_menu.set_flags(spell_menu.get_flags() | MF_PRESELECTED);
236     }
237 
238     for (int i = 0; i < 52; ++i)
239     {
240         const char letter = index_to_letter(i);
241         const spell_type spell = get_spell_by_letter(letter);
242 
243         if (!is_valid_spell(spell))
244             continue;
245 
246         if (selector && !(*selector)(spell))
247             continue;
248 
249         bool preselect = (preselect_first
250                           || allow_preselect && you.last_cast_spell == spell);
251 
252         ToggleableMenuEntry* me =
253             new ToggleableMenuEntry(_spell_base_description(spell, viewing),
254                                     _spell_extra_description(spell, viewing),
255                                     MEL_ITEM, 1, letter, preselect);
256 
257         me->add_tile(tile_def(tileidx_spell(spell)));
258         spell_menu.add_entry(me);
259     }
260 
261     int choice = 0;
262     spell_menu.on_single_selection = [&choice, &spell_menu](const MenuEntry& item)
263     {
264         ASSERT(item.hotkeys.size() == 1);
265         if (spell_menu.menu_action == Menu::ACT_EXAMINE)
266         {
267             describe_spell(get_spell_by_letter(item.hotkeys[0]), nullptr);
268             return true;
269         }
270         else
271         {
272             choice = item.hotkeys[0];
273             return false;
274         }
275     };
276 
277     spell_menu.show();
278     if (!crawl_state.doing_prev_cmd_again)
279     {
280         redraw_screen();
281         update_screen();
282     }
283     return choice;
284 }
285 
_apply_spellcasting_success_boosts(spell_type spell,int chance)286 static int _apply_spellcasting_success_boosts(spell_type spell, int chance)
287 {
288     int fail_reduce = 100;
289 
290     if (have_passive(passive_t::spells_success) && vehumet_supports_spell(spell))
291     {
292         // [dshaligram] Fail rate multiplier used to be .5, scaled
293         // back to 67%.
294         fail_reduce = fail_reduce * 2 / 3;
295     }
296 
297     const int wizardry = player_wizardry(spell);
298 
299     if (wizardry > 0)
300       fail_reduce = fail_reduce * 6 / (7 + wizardry);
301 
302     // Hard cap on fail rate reduction.
303     if (fail_reduce < 50)
304         fail_reduce = 50;
305 
306     return chance * fail_reduce / 100;
307 }
308 
309 /**
310  * Calculate the player's failure rate with the given spell, including all
311  * modifiers. (Armour, mutations, statuses effects, etc.)
312  *
313  * @param spell     The spell in question.
314  * @return          A failure rate. This is *not* a percentage - for a human-
315  *                  readable version, call _get_true_fail_rate().
316  */
raw_spell_fail(spell_type spell)317 int raw_spell_fail(spell_type spell)
318 {
319     int chance = 60;
320 
321     // Don't cap power for failure rate purposes.
322     // scale by 6, which I guess was chosen because it seems to work.
323     // realistic range for spellpower: -6 to -366 (before scale -1 to -61)
324     chance -= calc_spell_power(spell, false, true, false, 6);
325     chance -= (you.intel() * 2); // realistic range: -2 to -70
326 
327     const int armour_shield_penalty = player_armour_shield_spell_penalty();
328     chance += armour_shield_penalty; // range: 0 to 500 in extreme cases.
329                                      // A midlevel melee character in plate
330                                      // might have 40 or 50, and a caster in a
331                                      // robe would usually have 0.
332 
333     static const int difficulty_by_level[] =
334     {
335         0,
336         3,
337         15,
338         35,
339 
340         70,
341         100,
342         150,
343 
344         200,
345         260,
346         340,
347     };
348     const int spell_level = spell_difficulty(spell);
349     ASSERT_RANGE(spell_level, 0, (int) ARRAYSZ(difficulty_by_level));
350     chance += difficulty_by_level[spell_level]; // between 0 and 330
351 
352     // since chance is passed through a 3rd degree polynomial, cap the
353     // value to avoid any overflow issues. We choose 210 by solving for chance2
354     // = 200 in the polynomial -- it gets capped at 100 ultimately, but we
355     // need a bunch of headroom in case some later calculations lower the value
356     // below 100 after this.
357     chance = min(chance, 210);
358 
359     // This polynomial is a smoother approximation of a breakpoint-based
360     // calculation that originates pre-DCSS, mapping `chance` at this point to
361     // values from around 0 to around 45. (see
362     // https://crawl.develz.org/tavern/viewtopic.php?f=8&t=23414 for some of
363     // the history.)  It was calculated by |amethyst (based on one from minmay
364     // in that thread) and converted to integer values using 262144 as a
365     // convenient power of 2 denominator, then converted to its current form
366     // by Horner's rule, and then tweaked slightly.
367     //
368     // The regular (integer) polynomial form before Horner's rule is:
369     //          (x*x*x + 426*x*x + 82670*x + 7245398) / 262144
370     //
371     // https://www.wolframalpha.com/input/?i=graph+of+y%3D(((x+%2B+426)*x+%2B+82670)*x+%2B+7245398)+%2F+262144+and+y%3D100+and+x%3D125.1+with+x+from+-192+to+126.1
372     //
373     // If you think this is weird, you should see what was here before.
374     int chance2 = max((((chance + 426) * chance + 82670) * chance + 7245398)
375                       / 262144, 0);
376 
377     chance2 += get_form()->spellcasting_penalty;
378     if (you.duration[DUR_EXCRUCIATING_WOUNDS])
379         chance2 += 10; // same as spider form
380 
381     chance2 -= 2 * you.get_mutation_level(MUT_SUBDUED_MAGIC);
382     chance2 += 4 * you.get_mutation_level(MUT_WILD_MAGIC);
383     chance2 += 4 * you.get_mutation_level(MUT_ANTI_WIZARDRY);
384 
385     if (you.props.exists(SAP_MAGIC_KEY))
386         chance2 += you.props[SAP_MAGIC_KEY].get_int() * 12;
387 
388     chance2 += you.duration[DUR_VERTIGO] ? 7 : 0;
389 
390     // Apply the effects of Vehumet and items of wizardry.
391     chance2 = _apply_spellcasting_success_boosts(spell, chance2);
392 
393     return min(max(chance2, 0), 100);
394 }
395 
396 /*
397  * Given some spellpower in centis, do a stepdown at around 50 (5000 in centis)
398  * and return a rescaled value.
399  *
400  * @param power the input spellpower in centis.
401  * @param scale a value to scale the result by, between 1 and 1000. Default is
402  *        1, which returns a regular spellpower. 1000 gives you millis, 100
403  *        centis.
404  */
stepdown_spellpower(int power,int scale)405 int stepdown_spellpower(int power, int scale)
406 {
407     // use millis internally
408     ASSERT_RANGE(scale, 1, 1000);
409     const int divisor = 1000 / scale;
410     int result = stepdown_value(power * 10, 50000, 50000, 150000, 200000)
411                     / divisor;
412     return result;
413 }
414 
_skill_power(spell_type spell)415 static int _skill_power(spell_type spell)
416 {
417     int power = 0;
418 
419     const spschools_type disciplines = get_spell_disciplines(spell);
420     const int skillcount = count_bits(disciplines);
421     if (skillcount)
422     {
423         for (const auto bit : spschools_type::range())
424             if (disciplines & bit)
425                 power += you.skill(spell_type2skill(bit), 200);
426         power /= skillcount;
427     }
428 
429     // Innate casters use spellcasting for every spell school.
430     const int splcast_mult = you.has_mutation(MUT_INNATE_CASTER) ? 250 : 50;
431     power += you.skill(SK_SPELLCASTING, splcast_mult);
432     return power;
433 }
434 
435 /*
436  * Calculate spell power.
437  *
438  * @param spell         the spell to check
439  * @param apply_intel   whether to include intelligence in the calculation
440  * @param fail_rate_check is this just a plain failure rate check or should it
441  *                      incorporate situational facts and mutations?
442  * @param cap_power     whether to apply the power cap for the spell (from
443  *                      `spell_power_cap(spell)`)
444  * @param scale         what scale to apply to the result internally?  This
445  *                      function has higher internal resolution than the default
446  *                      argument, so use this rather than dividing. This must be
447  *                      between 1 and 1000.
448  *
449  * @return the resulting spell power.
450  */
calc_spell_power(spell_type spell,bool apply_intel,bool fail_rate_check,bool cap_power,int scale)451 int calc_spell_power(spell_type spell, bool apply_intel, bool fail_rate_check,
452                      bool cap_power, int scale)
453 {
454     int power = _skill_power(spell);
455 
456     if (you.divine_exegesis)
457         power += you.skill(SK_INVOCATIONS, 300);
458 
459     if (fail_rate_check)
460     {
461         // Scale appropriately.
462         // The stepdown performs this step in the else block.
463         power *= scale;
464         power /= 100;
465     }
466     else
467     {
468         if (apply_intel)
469             power = (power * you.intel()) / 10;
470 
471         // [dshaligram] Enhancers don't affect fail rates any more, only spell
472         // power. Note that this does not affect Vehumet's boost in castability.
473         power = apply_enhancement(power, _spell_enhancement(spell));
474 
475         // Wild magic boosts spell power but decreases success rate.
476         power *= (10 + 3 * you.get_mutation_level(MUT_WILD_MAGIC));
477         power /= (10 + 3 * you.get_mutation_level(MUT_SUBDUED_MAGIC));
478 
479         // Augmentation boosts spell power at high HP.
480         power *= 10 + 4 * augmentation_amount();
481         power /= 10;
482 
483         // Each level of horror reduces spellpower by 10%
484         if (you.duration[DUR_HORROR])
485         {
486             power *= 10;
487             power /= 10 + (you.props[HORROR_PENALTY_KEY].get_int() * 3) / 2;
488         }
489 
490         // at this point, `power` is assumed to be basically in centis.
491         // apply a stepdown, and scale.
492         power = stepdown_spellpower(power, scale);
493     }
494 
495     const int cap = spell_power_cap(spell);
496     if (cap > 0 && cap_power)
497         power = min(power, cap * scale);
498 
499     return power;
500 }
501 
_spell_enhancement(spell_type spell)502 static int _spell_enhancement(spell_type spell)
503 {
504     const spschools_type typeflags = get_spell_disciplines(spell);
505     int enhanced = 0;
506 
507     if (typeflags & spschool::conjuration)
508         enhanced += player_spec_conj();
509 
510     if (typeflags & spschool::hexes)
511         enhanced += player_spec_hex();
512 
513     if (typeflags & spschool::summoning)
514         enhanced += player_spec_summ();
515 
516     if (typeflags & spschool::poison)
517         enhanced += player_spec_poison();
518 
519     if (typeflags & spschool::necromancy)
520         enhanced += player_spec_death();
521 
522     if (typeflags & spschool::fire)
523         enhanced += player_spec_fire();
524 
525     if (typeflags & spschool::ice)
526         enhanced += player_spec_cold();
527 
528     if (typeflags & spschool::earth)
529         enhanced += player_spec_earth();
530 
531     if (typeflags & spschool::air)
532         enhanced += player_spec_air();
533 
534     if (you.form == transformation::shadow)
535         enhanced -= 2;
536 
537     enhanced += you.archmagi();
538     enhanced += you.duration[DUR_BRILLIANCE] > 0
539                 || player_equip_unrand(UNRAND_FOLLY);
540 
541     // These are used in an exponential way, so we'll limit them a bit. -- bwr
542     if (enhanced > 3)
543         enhanced = 3;
544     else if (enhanced < -3)
545         enhanced = -3;
546 
547     return enhanced;
548 }
549 
550 /**
551  * Apply the effects of spell enhancers (and de-enhancers) on spellpower.
552  *
553  * @param initial_power     The power of the spell before enhancers are added.
554  * @param enhancer_levels   The number of enhancements levels to apply.
555  * @return                  The power of the spell with enhancers considered.
556  */
apply_enhancement(const int initial_power,const int enhancer_levels)557 int apply_enhancement(const int initial_power, const int enhancer_levels)
558 {
559     int power = initial_power;
560 
561     if (enhancer_levels > 0)
562     {
563         for (int i = 0; i < enhancer_levels; i++)
564         {
565             power *= 15;
566             power /= 10;
567         }
568     }
569     else if (enhancer_levels < 0)
570     {
571         for (int i = enhancer_levels; i < 0; i++)
572             power /= 2;
573     }
574 
575     return power;
576 }
577 
inspect_spells()578 void inspect_spells()
579 {
580     if (!you.spell_no)
581     {
582         canned_msg(MSG_NO_SPELLS);
583         return;
584     }
585 
586     list_spells(true, true);
587 }
588 
589 /**
590  * Can the player cast any spell at all? Checks for things that limit
591  * spellcasting regardless of the specific spell we want to cast.
592  *
593  * @param quiet    If true, don't print a reason why no spell can be cast.
594  * @param exegesis If true, we're considering casting under Divine Exegesis.
595  * @return True if we could cast a spell, false otherwise.
596 */
can_cast_spells(bool quiet,bool exegesis)597 bool can_cast_spells(bool quiet, bool exegesis)
598 {
599     if (!get_form()->can_cast)
600     {
601         if (!quiet)
602             canned_msg(MSG_PRESENT_FORM);
603         return false;
604     }
605 
606     if (you.duration[DUR_WATER_HOLD] && !you.res_water_drowning())
607     {
608         if (!quiet)
609             mpr("You cannot cast spells while unable to breathe!");
610         return false;
611     }
612 
613     if (you.duration[DUR_BRAINLESS])
614     {
615         if (!quiet)
616             mpr("You lack the mental capacity to cast spells.");
617         return false;
618     }
619 
620     // Randart weapons.
621     if (you.no_cast())
622     {
623         if (!quiet)
624             mpr("Something interferes with your magic!");
625         return false;
626     }
627 
628     // Check that we have a spell memorised. Divine Exegesis does not need this
629     // condition, but we can't just check you.divine_exegesis in all cases, as
630     // it may not be set yet. Check a passed parameter instead.
631     if (!exegesis && !you.spell_no)
632     {
633         if (!quiet)
634             canned_msg(MSG_NO_SPELLS);
635         return false;
636     }
637 
638     if (you.berserk())
639     {
640         if (!quiet)
641             canned_msg(MSG_TOO_BERSERK);
642         return false;
643     }
644 
645     if (you.confused())
646     {
647         if (!quiet)
648             mpr("You're too confused to cast spells.");
649         return false;
650     }
651 
652     if (silenced(you.pos()))
653     {
654         if (!quiet)
655             mpr("You cannot cast spells when silenced!");
656         // included in default force_more_message
657         return false;
658     }
659 
660     return true;
661 }
662 
do_cast_spell_cmd(bool force)663 void do_cast_spell_cmd(bool force)
664 {
665     if (!cast_a_spell(!force))
666         flush_input_buffer(FLUSH_ON_FAILURE);
667 }
668 
_handle_wucad_mu(int cost)669 static void _handle_wucad_mu(int cost)
670 {
671     if (!player_equip_unrand(UNRAND_WUCAD_MU))
672         return;
673 
674     if (you.has_mutation(MUT_HP_CASTING))
675         return;
676 
677     if (!x_chance_in_y(you.skill(SK_EVOCATIONS), 54))
678         return;
679 
680     did_god_conduct(DID_WIZARDLY_ITEM, 10);
681 
682     // The chance of backfiring goes down with evo skill and up with cost
683     if (one_chance_in(max(you.skill(SK_EVOCATIONS) - cost, 1)))
684     {
685         mpr(random_choose("Weird images run through your mind.",
686                           "Your head hurts.",
687                           "You feel a strange surge of energy.",
688                           "You feel uncomfortable."));
689         if (coinflip())
690             confuse_player(2 + random2(4));
691         else
692             lose_stat(STAT_INT, 1 + random2avg(5, 2));
693     }
694 
695     mpr("Magical energy flows into your mind!");
696     inc_mp(cost, true);
697 }
698 
699 /**
700  * Let the Majin-Bo congratulate you on casting a spell while using it.
701  *
702  * @param spell     The spell just successfully cast.
703  */
_majin_speak(spell_type spell)704 static void _majin_speak(spell_type spell)
705 {
706     // since this isn't obviously mental communication, let it be silenced
707     if (silenced(you.pos()))
708         return;
709 
710     const int level = spell_difficulty(spell);
711     const bool weak = level <= 4;
712     const string lookup = weak ? "majin-bo cast weak" : "majin-bo cast";
713     const string msg = "A voice whispers, \"" + getSpeakString(lookup) + "\"";
714     mprf(MSGCH_TALK, "%s", msg.c_str());
715 }
716 
_majin_charge_hp()717 static bool _majin_charge_hp()
718 {
719     return player_equip_unrand(UNRAND_MAJIN) && !you.duration[DUR_DEATHS_DOOR];
720 }
721 
722 
723 /**
724  * Cast a spell.
725  *
726  * Handles general preconditions & costs.
727  *
728  * @param check_range   If true, abort if no targets are in range. (z vs Z)
729  * @param spell         The type of spell to be cast.
730  * @return              Whether the spell was successfully cast.
731  **/
cast_a_spell(bool check_range,spell_type spell,dist * _target)732 bool cast_a_spell(bool check_range, spell_type spell, dist *_target)
733 {
734     if (!can_cast_spells(false, you.divine_exegesis))
735     {
736         crawl_state.zero_turns_taken();
737         return false;
738     }
739 
740     if (crawl_state.game_is_hints())
741         Hints.hints_spell_counter++;
742 
743     if (spell == SPELL_NO_SPELL)
744     {
745         int keyin = 0;
746 
747         string luachoice;
748         if (!clua.callfn("c_choose_spell", ">s", &luachoice))
749         {
750             if (!clua.error.empty())
751                 mprf(MSGCH_ERROR, "Lua error: %s", clua.error.c_str());
752         }
753         else if (!luachoice.empty() && isalpha(luachoice[0]))
754         {
755             keyin = luachoice[0];
756             const spell_type spl = get_spell_by_letter(keyin);
757 
758             // Bad entry from lua, defer to the user
759             if (!is_valid_spell(spl))
760                 keyin = 0;
761         }
762 
763         while (true)
764         {
765 #ifdef TOUCH_UI
766             keyin = list_spells(true, false);
767             if (!keyin)
768                 keyin = ESCAPE;
769 
770             if (!crawl_state.doing_prev_cmd_again)
771             {
772                 redraw_screen();
773                 update_screen();
774             }
775 
776             if (isaalpha(keyin) || key_is_escape(keyin))
777                 break;
778             else
779                 clear_messages();
780 
781             keyin = 0;
782 #else
783             if (keyin == 0)
784             {
785                 if (you.spell_no == 1)
786                 {
787                     // Set last_cast_spell to the current only spell.
788                     for (int i = 0; i < 52; ++i)
789                     {
790                         const char letter = index_to_letter(i);
791                         const spell_type spl = get_spell_by_letter(letter);
792 
793                         if (!is_valid_spell(spl))
794                             continue;
795 
796                         you.last_cast_spell = spl;
797                         break;
798                     }
799                 }
800 
801                 // We allow setting last cast spell by Divine Exegesis, but we
802                 // don't allow recasting it with the UI unless we actually have
803                 // the spell memorized.
804                 if (you.last_cast_spell != SPELL_NO_SPELL
805                     && !you.has_spell(you.last_cast_spell))
806                 {
807                     you.last_cast_spell = SPELL_NO_SPELL;
808                 }
809 
810                 if (you.last_cast_spell == SPELL_NO_SPELL
811                     || !Options.enable_recast_spell)
812                 {
813                     mprf(MSGCH_PROMPT, "Cast which spell? (? or * to list) ");
814                 }
815                 else
816                 {
817                     mprf(MSGCH_PROMPT, "Casting: <w>%s</w> <lightgrey>(%s)</lightgrey>",
818                                        spell_title(you.last_cast_spell),
819                                        _spell_failure_rate_description(you.last_cast_spell).c_str());
820                     mprf(MSGCH_PROMPT, "Confirm with . or Enter, or press "
821                                        "? or * to list all spells.");
822                 }
823 
824                 keyin = get_ch();
825             }
826 
827             if (keyin == '?' || keyin == '*')
828             {
829                 keyin = list_spells(true, false);
830                 if (!keyin)
831                     keyin = ESCAPE;
832 
833                 if (!crawl_state.doing_prev_cmd_again)
834                 {
835                     redraw_screen();
836                     update_screen();
837                 }
838 
839                 if (isaalpha(keyin) || key_is_escape(keyin))
840                     break;
841                 else
842                     clear_messages();
843 
844                 keyin = 0;
845             }
846             else
847                 break;
848 #endif
849         }
850 
851         if (key_is_escape(keyin))
852         {
853             canned_msg(MSG_OK);
854             crawl_state.zero_turns_taken();
855             return false;
856         }
857         else if (Options.enable_recast_spell
858                  && (keyin == '.' || keyin == CK_ENTER))
859         {
860             spell = you.last_cast_spell;
861         }
862         else if (!isaalpha(keyin))
863         {
864             mpr("You don't know that spell.");
865             crawl_state.zero_turns_taken();
866             return false;
867         }
868         else
869             spell = get_spell_by_letter(keyin);
870     }
871 
872     if (spell == SPELL_NO_SPELL)
873     {
874         mpr("You don't know that spell.");
875         crawl_state.zero_turns_taken();
876         return false;
877     }
878 
879     // MP, confusion, Ru sacs
880     const auto reason = casting_uselessness_reason(spell, true);
881     if (!reason.empty())
882     {
883         mpr(reason);
884         crawl_state.zero_turns_taken();
885         return false;
886     }
887 
888     if (check_range && spell_no_hostile_in_range(spell))
889     {
890         // Abort if there are no hostiles within range, but flash the range
891         // markers for a short while.
892         mpr("You can't see any susceptible monsters within range! "
893             "(Use <w>Z</w> to cast anyway.)");
894 
895         if ((Options.use_animations & UA_RANGE) && Options.darken_beyond_range)
896         {
897             targeter_smite range(&you, calc_spell_range(spell), 0, 0, true);
898             range_view_annotator show_range(&range);
899             delay(50);
900         }
901         crawl_state.zero_turns_taken();
902         return false;
903     }
904 
905     if (god_punishes_spell(spell, you.religion)
906         && !crawl_state.disables[DIS_CONFIRMATIONS])
907     {
908         // None currently dock just piety, right?
909         if (!yesno(god_loathes_spell(spell, you.religion) ?
910             "Casting this spell will cause instant excommunication! "
911             "Really cast?" :
912             "Casting this spell will place you under penance. Really cast?",
913             true, 'n'))
914         {
915             canned_msg(MSG_OK);
916             crawl_state.zero_turns_taken();
917             return false;
918         }
919     }
920 
921     you.last_cast_spell = spell;
922     // Silently take MP before the spell.
923     const int cost = spell_mana(spell);
924     pay_mp(cost);
925 
926     // Majin Bo HP cost taken at the same time
927     // (but after hp costs from HP casting)
928     const int hp_cost = min(spell_mana(spell), you.hp - 1);
929     if (_majin_charge_hp())
930         pay_hp(hp_cost);
931 
932     const spret cast_result = your_spells(spell, 0, !you.divine_exegesis,
933                                           nullptr, _target);
934     if (cast_result == spret::abort)
935     {
936         crawl_state.zero_turns_taken();
937         // Return the MP since the spell is aborted.
938         refund_mp(cost);
939         if (_majin_charge_hp())
940             refund_hp(hp_cost);
941 
942         redraw_screen();
943         update_screen();
944         return false;
945     }
946 
947     practise_casting(spell, cast_result == spret::success);
948     if (cast_result == spret::success)
949     {
950         _handle_wucad_mu(cost);
951         if (player_equip_unrand(UNRAND_MAJIN) && one_chance_in(500))
952             _majin_speak(spell);
953         did_god_conduct(DID_SPELL_CASTING, 1 + random2(5));
954         count_action(CACT_CAST, spell);
955     }
956 
957     finalize_mp_cost(_majin_charge_hp() ? hp_cost : 0);
958     you.turn_is_over = true;
959     alert_nearby_monsters();
960 
961     return true;
962 }
963 
964 /**
965  * Handles divine response to spellcasting.
966  *
967  * @param spell         The type of spell just cast.
968  */
_spellcasting_god_conduct(spell_type spell)969 static void _spellcasting_god_conduct(spell_type spell)
970 {
971     // If you are casting while a god is acting, then don't do conducts.
972     // (Presumably Xom is forcing you to cast a spell.)
973     if (crawl_state.is_god_acting())
974         return;
975 
976     const int conduct_level = 10 + spell_difficulty(spell);
977 
978     if (is_evil_spell(spell) || you.spellcasting_unholy())
979         did_god_conduct(DID_EVIL, conduct_level);
980 
981     if (is_unclean_spell(spell))
982         did_god_conduct(DID_UNCLEAN, conduct_level);
983 
984     if (is_chaotic_spell(spell))
985         did_god_conduct(DID_CHAOS, conduct_level);
986 
987     // not is_hasty_spell since the other ones handle the conduct themselves.
988     if (spell == SPELL_SWIFTNESS)
989         did_god_conduct(DID_HASTY, conduct_level);
990 
991     if (spell == SPELL_SUBLIMATION_OF_BLOOD)
992         did_god_conduct(DID_CHANNEL, conduct_level);
993 
994     if (god_loathes_spell(spell, you.religion))
995         excommunication();
996 }
997 
998 /**
999  * Handles side effects of successfully casting a spell.
1000  *
1001  * Spell noise, magic 'sap' effects, and god conducts.
1002  *
1003  * @param spell         The type of spell just cast.
1004  * @param god           Which god is casting the spell; NO_GOD if it's you.
1005  * @param fake_spell    true if the spell is evoked or from an innate or divine ability
1006  *                      false if it is a spell being cast normally.
1007  */
_spellcasting_side_effects(spell_type spell,god_type god,bool fake_spell)1008 static void _spellcasting_side_effects(spell_type spell, god_type god,
1009                                        bool fake_spell)
1010 {
1011     _spellcasting_god_conduct(spell);
1012 
1013     if (god == GOD_NO_GOD)
1014     {
1015         // Casting pain costs 1 hp.
1016         // Deep Dwarves' damage reduction always blocks at least 1 hp.
1017         if (spell == SPELL_PAIN
1018             && (you.species != SP_DEEP_DWARF && !you.res_torment()))
1019         {
1020             dec_hp(1, false);
1021         }
1022 
1023         if (you.duration[DUR_SAP_MAGIC]
1024             && you.props[SAP_MAGIC_KEY].get_int() < 3
1025             && !fake_spell && coinflip())
1026         {
1027             mprf(MSGCH_WARN, "Your control over your magic is sapped.");
1028             you.props[SAP_MAGIC_KEY].get_int()++;
1029         }
1030 
1031         // Make some noise if it's actually the player casting.
1032         noisy(spell_noise(spell), you.pos());
1033     }
1034 
1035     alert_nearby_monsters();
1036 
1037 }
1038 
1039 #ifdef WIZARD
_try_monster_cast(spell_type spell,int,dist & spd,bolt & beam)1040 static void _try_monster_cast(spell_type spell, int /*powc*/,
1041                               dist &spd, bolt &beam)
1042 {
1043     if (monster_at(you.pos()))
1044     {
1045         mpr("Couldn't try casting monster spell because you're "
1046             "on top of a monster.");
1047         return;
1048     }
1049 
1050     monster* mon = get_free_monster();
1051     if (!mon)
1052     {
1053         mpr("Couldn't try casting monster spell because there is "
1054             "no empty monster slot.");
1055         return;
1056     }
1057 
1058     mpr("Invalid player spell, attempting to cast it as monster spell.");
1059 
1060     mon->mname      = "Dummy Monster";
1061     mon->type       = MONS_HUMAN;
1062     mon->behaviour  = BEH_SEEK;
1063     mon->attitude   = ATT_FRIENDLY;
1064     mon->flags      = (MF_NO_REWARD | MF_JUST_SUMMONED | MF_SEEN
1065                        | MF_WAS_IN_VIEW | MF_HARD_RESET);
1066     mon->hit_points = you.hp;
1067     mon->set_hit_dice(you.experience_level);
1068     mon->set_position(you.pos());
1069     mon->target     = spd.target;
1070     mon->mid        = MID_PLAYER;
1071 
1072     if (!spd.isTarget)
1073         mon->foe = MHITNOT;
1074     else if (!monster_at(spd.target))
1075     {
1076         if (spd.isMe())
1077             mon->foe = MHITYOU;
1078         else
1079             mon->foe = MHITNOT;
1080     }
1081     else
1082         mon->foe = env.mgrid(spd.target);
1083 
1084     env.mgrid(you.pos()) = mon->mindex();
1085 
1086     mons_cast(mon, beam, spell, MON_SPELL_NO_FLAGS);
1087 
1088     mon->reset();
1089 }
1090 #endif // WIZARD
1091 
1092 static spret _do_cast(spell_type spell, int powc, const dist& spd,
1093                            bolt& beam, god_type god, bool fail);
1094 
1095 /**
1096  * Should this spell be aborted before casting properly starts, either because
1097  * it can't legally be cast in this circumstance, or because the player opts
1098  * to cancel it in response to a prompt?
1099  *
1100  * @param spell         The spell to be checked
1101  * @param fake_spell    true if the spell is evoked or from an innate or divine ability
1102  *                      false if it is a spell being cast normally.
1103  * @return              Whether the spellcasting should be aborted.
1104  */
_spellcasting_aborted(spell_type spell,bool fake_spell)1105 static bool _spellcasting_aborted(spell_type spell, bool fake_spell)
1106 {
1107     string msg;
1108 
1109     // casting-general checks (MP etc) are not carried out here
1110     msg = spell_uselessness_reason(spell, true, true, true);
1111 
1112     if (!msg.empty())
1113     {
1114         mpr(msg);
1115         return true;
1116     }
1117 
1118     vector<text_pattern> &actions = Options.confirm_action;
1119     if (!actions.empty())
1120     {
1121         const char* name = spell_title(spell);
1122         for (const text_pattern &action : actions)
1123         {
1124             if (!action.matches(name))
1125                 continue;
1126 
1127             string prompt = "Really cast " + string(name) + "?";
1128             if (!yesno(prompt.c_str(), false, 'n'))
1129             {
1130                 canned_msg(MSG_OK);
1131                 return true;
1132             }
1133             break;
1134         }
1135     }
1136 
1137     const int severity = fail_severity(spell);
1138     const string failure_rate = spell_failure_rate_string(spell);
1139     if (Options.fail_severity_to_confirm > 0
1140         && Options.fail_severity_to_confirm <= severity
1141         && !crawl_state.disables[DIS_CONFIRMATIONS]
1142         && !fake_spell)
1143     {
1144         if (failure_rate_to_int(raw_spell_fail(spell)) == 100)
1145         {
1146             mprf(MSGCH_WARN, "It is impossible to cast this spell "
1147                     "(100%% risk of failure)!");
1148             return true;
1149         }
1150 
1151         string prompt = make_stringf("The spell is %s to cast "
1152                                      "(%s risk of failure)%s",
1153                                      fail_severity_adjs[severity],
1154                                      failure_rate.c_str(),
1155                                      severity > 1 ? "!" : ".");
1156 
1157         prompt = make_stringf("%s Continue anyway?", prompt.c_str());
1158         if (!yesno(prompt.c_str(), false, 'n'))
1159         {
1160             canned_msg(MSG_OK);
1161             return true;
1162         }
1163     }
1164 
1165     return false;
1166 }
1167 
_find_blink_targets(actor * a)1168 static vector<coord_def> _find_blink_targets(actor *a)
1169 {
1170     vector<coord_def> result;
1171     if (!a)
1172         return result;
1173 
1174     for (radius_iterator ri(a->pos(), LOS_NO_TRANS); ri; ++ri)
1175         if (valid_blink_destination(a, *ri))
1176             result.push_back(*ri);
1177 
1178     return result;
1179 }
1180 // this is a crude approximation used for the convenience UI targeter of
1181 // Dragon's call and Manifold Assault
_simple_find_all_hostiles(actor * a)1182 static vector<coord_def> _simple_find_all_hostiles(actor *a)
1183 {
1184     vector<coord_def> result;
1185     if (!a)
1186         return result;
1187 
1188     for (monster_near_iterator mi(a->pos(), LOS_NO_TRANS); mi; ++mi)
1189         if (!mons_aligned(&you, *mi) && mons_is_threatening(**mi))
1190             result.push_back((*mi)->pos());
1191 
1192     return result;
1193 }
1194 
1195 // a light wrapper on the code used for casting animate skeleton
_find_animatable_skeletons(actor * a)1196 static vector<coord_def> _find_animatable_skeletons(actor *a)
1197 {
1198     vector<coord_def> result;
1199     coord_def s = find_animatable_skeleton(a->pos());
1200     if (in_bounds(s))
1201         result.push_back(s);
1202     return result;
1203 }
1204 
_simple_corpse_check(const coord_def & c)1205 static bool _simple_corpse_check(const coord_def &c)
1206 {
1207     int motions; // ???
1208     return animate_remains(c, CORPSE_BODY, BEH_FRIENDLY, 1, MHITYOU, &you, "",
1209                         GOD_NO_GOD, false, true, true, nullptr, &motions) > 0;
1210 }
1211 
1212 // XX unify with animate dead code for finding corpses
_simple_find_corpses(actor * a)1213 static vector<coord_def> _simple_find_corpses(actor *a)
1214 {
1215     vector<coord_def> result;
1216     if (!a)
1217         return result;
1218 
1219     for (radius_iterator ri(a->pos(), LOS_NO_TRANS); ri; ++ri)
1220         if (_simple_corpse_check(*ri))
1221             result.push_back(*ri);
1222 
1223     return result;
1224 }
1225 
1226 // wrapper around the simulacrum corpse check
_find_simulacrable_corpses(const coord_def & c)1227 static vector<coord_def> _find_simulacrable_corpses(const coord_def &c)
1228 {
1229     vector<coord_def> result;
1230     if (find_simulacrable_corpse(c) >= 0)
1231         result.push_back(c);
1232     return result;
1233 }
1234 
1235 // TODO: refactor into target.cc, move custom classes out of target.h
find_spell_targeter(spell_type spell,int pow,int range)1236 unique_ptr<targeter> find_spell_targeter(spell_type spell, int pow, int range)
1237 {
1238     switch (spell)
1239     {
1240     case SPELL_FIREBALL:
1241         return make_unique<targeter_beam>(&you, range, ZAP_FIREBALL, pow,
1242                                           1, 1);
1243     case SPELL_ICEBLAST:
1244         return make_unique<targeter_beam>(&you, range, ZAP_ICEBLAST, pow,
1245                                           1, 1);
1246     case SPELL_HURL_DAMNATION:
1247         return make_unique<targeter_beam>(&you, range, ZAP_HURL_DAMNATION, pow,
1248                                           1, 1);
1249     case SPELL_MEPHITIC_CLOUD:
1250         return make_unique<targeter_beam>(&you, range, ZAP_MEPHITIC, pow,
1251                                           pow >= 100 ? 1 : 0, 1);
1252     case SPELL_FIRE_STORM:
1253         return make_unique<targeter_smite>(&you, range, 2, pow > 76 ? 3 : 2);
1254     case SPELL_FREEZING_CLOUD:
1255     case SPELL_POISONOUS_CLOUD:
1256     case SPELL_HOLY_BREATH:
1257         return make_unique<targeter_cloud>(&you, range);
1258     case SPELL_THUNDERBOLT:
1259         return make_unique<targeter_thunderbolt>(&you, range,
1260                                             get_thunderbolt_last_aim(&you));
1261     case SPELL_LRD:
1262         return make_unique<targeter_fragment>(&you, pow, range);
1263     case SPELL_FULMINANT_PRISM:
1264         return make_unique<targeter_smite>(&you, range, 0, 2);
1265     case SPELL_GLACIATE:
1266         return make_unique<targeter_cone>(&you, range);
1267     case SPELL_GRAVITAS:
1268         return make_unique<targeter_smite>(&you, range,
1269                                            gravitas_range(pow),
1270                                            gravitas_range(pow),
1271                                            false,
1272                                            [](const coord_def& p) -> bool {
1273                                               return you.pos() != p; });
1274     case SPELL_VIOLENT_UNRAVELLING:
1275         return make_unique<targeter_unravelling>(&you, range, pow);
1276     case SPELL_INFESTATION:
1277         return make_unique<targeter_smite>(&you, range, 2, 2, false,
1278                                            [](const coord_def& p) -> bool {
1279                                               return you.pos() != p; });
1280     case SPELL_PASSWALL:
1281         return make_unique<targeter_passwall>(range);
1282     case SPELL_DIG:
1283         return make_unique<targeter_dig>(range);
1284 
1285     // untargeted spells -- everything beyond here is a static targeter
1286     // TODO ignite poison
1287     case SPELL_HAILSTORM:
1288         return make_unique<targeter_radius>(&you, LOS_NO_TRANS, range, 0, 2);
1289     case SPELL_ISKENDERUNS_MYSTIC_BLAST:
1290         return make_unique<targeter_radius>(&you, LOS_SOLID_SEE, range);
1291     case SPELL_STARBURST:
1292         return make_unique<targeter_starburst>(&you, range, pow);
1293     case SPELL_CORPSE_ROT: // maybe should also highlight affected corpses? # of clouds depends on them
1294     case SPELL_IRRADIATE:
1295     case SPELL_DISCHARGE: // not entirely accurate...maybe should highlight
1296                           // all potentially affected monsters?
1297         return make_unique<targeter_maybe_radius>(&you, LOS_NO_TRANS, 1, 0, 1);
1298     case SPELL_DAZZLING_FLASH:
1299         return make_unique<targeter_maybe_radius>(&you, LOS_SOLID_SEE, range);
1300     case SPELL_CHAIN_LIGHTNING:
1301         return make_unique<targeter_chain_lightning>();
1302     case SPELL_MAXWELLS_COUPLING:
1303         return make_unique<targeter_maxwells_coupling>();
1304     case SPELL_FROZEN_RAMPARTS:
1305         return make_unique<targeter_ramparts>(&you);
1306     case SPELL_DISPERSAL:
1307     case SPELL_DISJUNCTION:
1308         return make_unique<targeter_maybe_radius>(&you, LOS_SOLID_SEE, range);
1309 
1310     // at player's position only but not a selfench; most transmut spells go here:
1311     case SPELL_SPIDER_FORM:
1312     case SPELL_BLADE_HANDS:
1313     case SPELL_STATUE_FORM:
1314     case SPELL_ICE_FORM:
1315     case SPELL_DRAGON_FORM:
1316     case SPELL_STORM_FORM:
1317     case SPELL_NECROMUTATION:
1318     case SPELL_BEASTLY_APPENDAGE:
1319     case SPELL_WEREBLOOD:
1320     case SPELL_SUBLIMATION_OF_BLOOD:
1321     case SPELL_BORGNJORS_REVIVIFICATION:
1322     case SPELL_CONJURE_FLAME:
1323         return make_unique<targeter_radius>(&you, LOS_SOLID_SEE, 0);
1324 
1325     // LOS radius:
1326     case SPELL_OZOCUBUS_REFRIGERATION:
1327     case SPELL_OLGREBS_TOXIC_RADIANCE:
1328         return make_unique<targeter_maybe_radius>(&you, LOS_NO_TRANS);
1329     case SPELL_POLAR_VORTEX:
1330         return make_unique<targeter_radius>(&you, LOS_NO_TRANS, POLAR_VORTEX_RADIUS);
1331     case SPELL_SHATTER:
1332         return make_unique<targeter_shatter>(&you); // special version that affects walls
1333     case SPELL_IGNITE_POISON: // many cases
1334         return make_unique<targeter_ignite_poison>(&you);
1335     case SPELL_CAUSE_FEAR: // for these, we just mark the eligible monsters
1336         return make_unique<targeter_fear>();
1337     case SPELL_INTOXICATE:
1338         return make_unique<targeter_intoxicate>();
1339     case SPELL_ENGLACIATION:
1340         return make_unique<targeter_englaciate>();
1341     case SPELL_DRAIN_LIFE:
1342         return make_unique<targeter_drain_life>();
1343     case SPELL_DISCORD:
1344         return make_unique<targeter_discord>();
1345     case SPELL_IGNITION:
1346         return make_unique<targeter_multifireball>(&you, get_ignition_blast_sources(&you, true));
1347 
1348     // Summons. Most summons have a simple range 2 radius, see find_newmons_square
1349     case SPELL_SUMMON_SMALL_MAMMAL:
1350     case SPELL_CALL_CANINE_FAMILIAR:
1351     case SPELL_ANIMATE_ARMOUR:
1352     case SPELL_SUMMON_ICE_BEAST:
1353     case SPELL_MONSTROUS_MENAGERIE:
1354     case SPELL_SUMMON_HYDRA:
1355     case SPELL_SUMMON_MANA_VIPER:
1356     case SPELL_CONJURE_BALL_LIGHTNING:
1357     case SPELL_SUMMON_GUARDIAN_GOLEM:
1358     case SPELL_CALL_IMP:
1359     case SPELL_SHADOW_CREATURES: // TODO: dbl check packs
1360     case SPELL_SUMMON_HORRIBLE_THINGS:
1361     case SPELL_SPELLFORGED_SERVITOR:
1362     case SPELL_SUMMON_LIGHTNING_SPIRE:
1363         return make_unique<targeter_maybe_radius>(&you, LOS_SOLID_SEE, 2);
1364     case SPELL_FOXFIRE:
1365         return make_unique<targeter_maybe_radius>(&you, LOS_SOLID_SEE, 1);
1366     case SPELL_BATTLESPHERE:
1367         return make_unique<targeter_maybe_radius>(&you, LOS_SOLID_SEE, 3);
1368     // TODO: these two actually have pretty wtf positioning that uses compass
1369     // directions, so this targeter is not entirely accurate.
1370     case SPELL_MALIGN_GATEWAY:
1371     case SPELL_SUMMON_FOREST:
1372         return make_unique<targeter_radius>(&you, LOS_NO_TRANS, LOS_RADIUS, 0, 2);
1373 
1374     case SPELL_ANIMATE_SKELETON:
1375         // this spell seems (?) to pick the first corpse by radius_iterator, so
1376         // just show that one. If this spell were to do something better, e.g.
1377         // randomization, this would need to take a different approach
1378         return make_unique<targeter_multiposition>(&you, _find_animatable_skeletons(&you), AFF_YES);
1379     case SPELL_ANIMATE_DEAD:
1380         return make_unique<targeter_multiposition>(&you, _simple_find_corpses(&you), AFF_YES);
1381     case SPELL_SIMULACRUM:
1382         return make_unique<targeter_multiposition>(&you, _find_simulacrable_corpses(you.pos()), AFF_YES);
1383     case SPELL_BLINK:
1384         return make_unique<targeter_multiposition>(&you, _find_blink_targets(&you));
1385     case SPELL_MANIFOLD_ASSAULT:
1386         return make_unique<targeter_multiposition>(&you, _simple_find_all_hostiles(&you));
1387     case SPELL_DRAGON_CALL: // this is just convenience: you can start the spell with no enemies in sight
1388         return make_unique<targeter_multifireball>(&you, _simple_find_all_hostiles(&you));
1389     case SPELL_NOXIOUS_BOG:
1390         return make_unique<targeter_bog>(&you, pow);
1391 
1392     default:
1393         break;
1394     }
1395 
1396     if (spell_to_zap(spell) != NUM_ZAPS)
1397     {
1398         return make_unique<targeter_beam>(&you, range, spell_to_zap(spell),
1399                                           pow, 0, 0);
1400     }
1401 
1402     // selfench is used mainly for monster AI, so it is a bit over-applied in
1403     // the spell data
1404     if (get_spell_flags(spell) & spflag::selfench
1405         && !spell_typematch(spell, spschool::summoning) // all summoning spells are selfench
1406         && !spell_typematch(spell, spschool::translocation) // blink, passage
1407         && spell != SPELL_PHANTOM_MIRROR) // ??
1408     {
1409         return make_unique<targeter_radius>(&you, LOS_SOLID_SEE, 0);
1410     }
1411 
1412     return nullptr;
1413 }
1414 
spell_has_targeter(spell_type spell)1415 bool spell_has_targeter(spell_type spell)
1416 {
1417     return bool(find_spell_targeter(spell, 1, 1));
1418 }
1419 
1420 // Returns the nth triangular number.
_triangular_number(int n)1421 static int _triangular_number(int n)
1422 {
1423     return n * (n+1) / 2;
1424 }
1425 
1426 // _tetrahedral_number: returns the nth tetrahedral number.
1427 // This is the number of triples of nonnegative integers with sum < n.
_tetrahedral_number(int n)1428 static int _tetrahedral_number(int n)
1429 {
1430     return n * (n+1) * (n+2) / 6;
1431 }
1432 
1433 /**
1434  * Compute success chance for WL-checking spells and abilities.
1435  *
1436  * @param wl The willpower of the target.
1437  * @param powc The enchantment power.
1438  * @param scale The denominator of the result.
1439  * @param round_up Should the resulting chance be rounded up (true) or
1440  *        down (false, the default)?
1441  *
1442  * @return The chance, out of scale, that the enchantment affects the target.
1443  */
hex_success_chance(const int wl,int powc,int scale,bool round_up)1444 int hex_success_chance(const int wl, int powc, int scale, bool round_up)
1445 {
1446     const int pow = ench_power_stepdown(powc);
1447     const int target = wl + 100 - pow;
1448     const int denom = 101 * 100;
1449     const int adjust = round_up ? denom - 1 : 0;
1450 
1451     if (target <= 0)
1452         return scale;
1453     if (target > 200)
1454         return 0;
1455     if (target <= 100)
1456         return (scale * (denom - _triangular_number(target)) + adjust) / denom;
1457     return (scale * _triangular_number(201 - target) + adjust) / denom;
1458 }
1459 
1460 // approximates _test_beam_hit in a deterministic fashion.
_to_hit_pct(const monster_info & mi,int acc,bool pierce)1461 static int _to_hit_pct(const monster_info& mi, int acc, bool pierce)
1462 {
1463     if (acc == AUTOMATIC_HIT)
1464         return 100;
1465 
1466     acc += mi.lighting_modifiers();
1467     if (acc <= 1)
1468         return mi.ev <= 2 ? 100 : 0;
1469 
1470     int hits = 0;
1471     int iters = 0;
1472     const bool rmsl = mi.is(MB_REPEL_MSL);
1473     for (int outer_ev_roll = 0; outer_ev_roll < mi.ev; outer_ev_roll++)
1474     {
1475         for (int inner_ev_roll_a = 0; inner_ev_roll_a < outer_ev_roll; inner_ev_roll_a++)
1476         {
1477             for (int inner_ev_roll_b = 0; inner_ev_roll_b < outer_ev_roll; inner_ev_roll_b++)
1478             {
1479                 const int ev = (inner_ev_roll_a + inner_ev_roll_b) / 2; // not right but close
1480                 for (int rolled_mhit = 0; rolled_mhit < acc; rolled_mhit++)
1481                 {
1482                     int adjusted_mhit = rolled_mhit;
1483                     if (rmsl)
1484                     {
1485                         // this is wrong - we should be re-rolling here.
1486                         if (pierce)
1487                             adjusted_mhit = adjusted_mhit * 3 /4;
1488                         else
1489                             adjusted_mhit /= 2;
1490                     }
1491 
1492                     iters++;
1493                     if (iters >= 1000000)
1494                         return -1; // sanity breakout to not kill servers
1495                     if (adjusted_mhit >= ev)
1496                         hits++;
1497                 }
1498             }
1499         }
1500     }
1501 
1502     if (iters <= 0) // probably low monster ev?
1503         return 100;
1504 
1505     return hits * 100 / iters;
1506 }
1507 
_desc_hit_chance(const monster_info & mi,targeter * hitfunc)1508 static vector<string> _desc_hit_chance(const monster_info& mi, targeter* hitfunc)
1509 {
1510     targeter_beam* beam_hitf = dynamic_cast<targeter_beam*>(hitfunc);
1511     if (!beam_hitf)
1512         return vector<string>{};
1513     const int acc = beam_hitf->beam.hit;
1514     if (!acc)
1515         return vector<string>{};
1516     const int hit_pct = _to_hit_pct(mi, acc, beam_hitf->beam.pierce);
1517     if (hit_pct == -1)
1518         return vector<string>{};
1519     return vector<string>{make_stringf("%d%% to hit", hit_pct)};
1520 }
1521 
_desc_intoxicate_chance(const monster_info & mi,targeter * hitfunc,int pow)1522 static vector<string> _desc_intoxicate_chance(const monster_info& mi,
1523                                               targeter* hitfunc, int pow)
1524 {
1525     if (hitfunc && !hitfunc->affects_monster(mi))
1526         return vector<string>{"not susceptible"};
1527 
1528     int conf_pct = 40 + pow / 3;
1529 
1530     if (get_resist(mi.resists(), MR_RES_POISON) >= 1)
1531         conf_pct =  conf_pct / 3;
1532 
1533     return vector<string>{make_stringf("chance to confuse: %d%%", conf_pct)};
1534 }
1535 
_desc_englaciate_chance(const monster_info & mi,targeter * hitfunc,int pow)1536 static vector<string> _desc_englaciate_chance(const monster_info& mi,
1537                                               targeter* hitfunc, int pow)
1538 {
1539     if (hitfunc && !hitfunc->affects_monster(mi))
1540         return vector<string>{"not susceptible"};
1541 
1542     const int outcomes = pow * pow * pow;
1543     const int target   = 3 * mi.hd - 2;
1544     int fail_pct;
1545 
1546     // Tetrahedral number calculation to find the chance
1547     // 3 d pow < 3 * mi . hd + 1
1548     if (target <= pow)
1549         fail_pct = 100 * _tetrahedral_number(target) / outcomes;
1550     else if (target <= 2 * pow)
1551     {
1552         fail_pct = 100 * (_tetrahedral_number(target)
1553                        - 3 * _tetrahedral_number(target - pow)) / outcomes;
1554     }
1555     else if (target <= 3 * pow)
1556     {
1557         fail_pct = 100 * (outcomes
1558                        - _tetrahedral_number(3 * pow - target)) / outcomes;
1559     }
1560     else
1561         fail_pct = 100;
1562 
1563     return vector<string>{make_stringf("chance to slow: %d%%", 100 - fail_pct)};
1564 }
1565 
_desc_dazzle_chance(const monster_info & mi,int pow)1566 static vector<string> _desc_dazzle_chance(const monster_info& mi, int pow)
1567 {
1568     if (!mons_can_be_dazzled(mi.type))
1569         return vector<string>{"not susceptible"};
1570 
1571     const int numerator = dazzle_chance_numerator(mi.hd);
1572     const int denom = dazzle_chance_denom(pow);
1573     const int dazzle_pct = max(100 * numerator / denom, 0);
1574 
1575     return vector<string>{make_stringf("chance to dazzle: %d%%", dazzle_pct)};
1576 }
1577 
_desc_meph_chance(const monster_info & mi)1578 static vector<string> _desc_meph_chance(const monster_info& mi)
1579 {
1580     if (get_resist(mi.resists(), MR_RES_POISON) >= 1)
1581         return vector<string>{"not susceptible"};
1582 
1583     int pct_chance = 2;
1584     if (mi.hd < MEPH_HD_CAP)
1585         pct_chance = 100 - (100 * mi.hd / MEPH_HD_CAP);
1586     return vector<string>{make_stringf("chance to affect: %d%%", pct_chance)};
1587 }
1588 
_desc_vampiric_draining_valid(const monster_info & mi)1589 static vector<string> _desc_vampiric_draining_valid(const monster_info& mi)
1590 {
1591     if (mi.mb.get(MB_CANT_DRAIN))
1592         return vector<string>{"not susceptible"};
1593 
1594     return vector<string>{};
1595 }
1596 
_desc_dispersal_chance(const monster_info & mi,int pow)1597 static vector<string> _desc_dispersal_chance(const monster_info& mi, int pow)
1598 {
1599     const int wl = mi.willpower();
1600     if (mons_class_is_stationary(mi.type))
1601         return vector<string>{"stationary"};
1602 
1603     if (wl == WILL_INVULN)
1604         return vector<string>{"will blink"};
1605 
1606     const int success = hex_success_chance(wl, pow, 100);
1607     return vector<string>{make_stringf("chance to teleport: %d%%", success)};
1608 }
1609 
_mon_threat_string(const CrawlStoreValue & mon_store)1610 static string _mon_threat_string(const CrawlStoreValue &mon_store)
1611 {
1612     monster dummy;
1613     dummy.type = static_cast<monster_type>(mon_store.get_int());
1614     define_monster(dummy);
1615 
1616     int col;
1617     string desc;
1618     monster_info(&dummy).to_string(1, desc, col, true, nullptr, false);
1619     const string col_name = colour_to_str(col);
1620 
1621     return "<" + col_name + ">" + article_a(desc) + "</" + col_name + ">";
1622 }
1623 
1624 // Include success chance in targeter for spells checking monster WL.
desc_wl_success_chance(const monster_info & mi,int pow,targeter * hitfunc)1625 vector<string> desc_wl_success_chance(const monster_info& mi, int pow,
1626                                       targeter* hitfunc)
1627 {
1628     targeter_beam* beam_hitf = dynamic_cast<targeter_beam*>(hitfunc);
1629     const int wl = mi.willpower();
1630     if (wl == WILL_INVULN)
1631         return vector<string>{"infinite will"};
1632     if (hitfunc && !hitfunc->affects_monster(mi))
1633         return vector<string>{"not susceptible"};
1634     vector<string> descs;
1635     if (beam_hitf && beam_hitf->beam.flavour == BEAM_POLYMORPH)
1636     {
1637         // Polymorph has a special effect on ugly things and shapeshifters that
1638         // does not require passing an WL check.
1639         if (mi.type == MONS_UGLY_THING || mi.type == MONS_VERY_UGLY_THING)
1640             return vector<string>{"will change colour"};
1641         if (mi.is(MB_SHAPESHIFTER))
1642             return vector<string>{"will change shape"};
1643         if (mi.type == MONS_SLIME_CREATURE && mi.slime_size > 1)
1644             descs.push_back("will probably split");
1645 
1646         // list out the normal poly set
1647         if (!mi.props.exists(POLY_SET_KEY))
1648             return vector<string>{"not susceptible"};
1649         const CrawlVector &set = mi.props[POLY_SET_KEY].get_vector();
1650         if (set.size() <= 0)
1651             return vector<string>{"not susceptible"};
1652         descs.push_back("will become "
1653                         + comma_separated_fn(set.begin(), set.end(),
1654                                              _mon_threat_string, ", or "));
1655     }
1656 
1657     const int success = hex_success_chance(wl, pow, 100);
1658     descs.push_back(make_stringf("chance to affect: %d%%", success));
1659 
1660     return descs;
1661 }
1662 
1663 class spell_targeting_behaviour : public targeting_behaviour
1664 {
1665 public:
spell_targeting_behaviour(spell_type _spell)1666     spell_targeting_behaviour(spell_type _spell)
1667         : targeting_behaviour(false), spell(_spell),
1668           err(spell_uselessness_reason(spell, true, false, true))
1669     {
1670     }
1671 
targeted()1672     bool targeted() override
1673     {
1674         return !!(get_spell_flags(spell) & spflag::targeting_mask);
1675     }
1676 
get_error()1677     string get_error() override
1678     {
1679         return err;
1680     }
1681 
1682     // TODO: provide useful errors for specific targets via get_monster_desc?
1683 
1684 private:
1685     spell_type spell;
1686     string err;
1687 };
1688 
1689 // TODO: is there a way for this to be part of targeter objects, or
1690 // direction_chooser itself?
targeter_addl_desc(spell_type spell,int powc,spell_flags flags,targeter * hitfunc)1691 desc_filter targeter_addl_desc(spell_type spell, int powc, spell_flags flags,
1692                                        targeter *hitfunc)
1693 {
1694     // Add success chance to targeted spells checking monster WL
1695     const bool wl_check = testbits(flags, spflag::WL_check)
1696                           && !testbits(flags, spflag::helpful);
1697     if (wl_check && spell != SPELL_DISPERSAL)
1698     {
1699         const zap_type zap = spell_to_zap(spell);
1700         const int eff_pow = zap != NUM_ZAPS ? zap_ench_power(zap, powc,
1701                                                              false)
1702                                             :
1703               testbits(flags, spflag::area) ? ( powc * 3 ) / 2
1704                                             : powc;
1705         return bind(desc_wl_success_chance, placeholders::_1,
1706                     eff_pow, hitfunc);
1707     }
1708     switch (spell)
1709     {
1710         case SPELL_INTOXICATE:
1711             return bind(_desc_intoxicate_chance, placeholders::_1,
1712                         hitfunc, powc);
1713         case SPELL_ENGLACIATION:
1714             return bind(_desc_englaciate_chance, placeholders::_1,
1715                         hitfunc, powc);
1716         case SPELL_DAZZLING_FLASH:
1717             return bind(_desc_dazzle_chance, placeholders::_1, powc);
1718         case SPELL_MEPHITIC_CLOUD:
1719             return bind(_desc_meph_chance, placeholders::_1);
1720         case SPELL_VAMPIRIC_DRAINING:
1721             return bind(_desc_vampiric_draining_valid, placeholders::_1);
1722         case SPELL_STARBURST:
1723         {
1724             targeter_starburst* burst_hitf =
1725                 dynamic_cast<targeter_starburst*>(hitfunc);
1726             if (!burst_hitf)
1727                 break;
1728             targeter_starburst_beam* beam_hitf = &burst_hitf->beams[0];
1729             return bind(_desc_hit_chance, placeholders::_1, beam_hitf);
1730         }
1731         case SPELL_DISPERSAL:
1732             return bind(_desc_dispersal_chance, placeholders::_1, powc);
1733         default:
1734             break;
1735     }
1736     targeter_beam* beam_hitf = dynamic_cast<targeter_beam*>(hitfunc);
1737     if (beam_hitf && beam_hitf->beam.hit > 0 && !beam_hitf->beam.is_explosion)
1738         return bind(_desc_hit_chance, placeholders::_1, hitfunc);
1739     return nullptr;
1740 }
1741 
1742 /**
1743  * Targets and fires player-cast spells & spell-like effects.
1744  *
1745  * Not all of these are actually real spells; invocations, decks or misc.
1746  * effects might also land us here.
1747  * Others are currently unused or unimplemented.
1748  *
1749  * @param spell         The type of spell being cast.
1750  * @param powc          Spellpower.
1751  * @param allow_fail    true if it is a spell being cast normally.
1752  *                      false if the spell is evoked or from an innate or divine ability
1753  *
1754  * @param evoked_wand   The wand the spell was evoked from if applicable, or
1755                         nullptr.
1756  * @return spret::success if spell is successfully cast for purposes of
1757  * exercising, spret::fail otherwise, or spret::abort if the player cancelled
1758  * the casting.
1759  **/
your_spells(spell_type spell,int powc,bool allow_fail,const item_def * const evoked_wand,dist * target)1760 spret your_spells(spell_type spell, int powc, bool allow_fail,
1761                        const item_def* const evoked_wand, dist *target)
1762 {
1763     ASSERT(!crawl_state.game_is_arena());
1764     ASSERT(!(allow_fail && evoked_wand));
1765     ASSERT(!evoked_wand || evoked_wand->base_type == OBJ_WANDS);
1766 
1767     const bool wiz_cast = (crawl_state.prev_cmd == CMD_WIZARD && !allow_fail);
1768 
1769     dist target_local;
1770     if (!target)
1771         target = &target_local;
1772     bolt beam;
1773     beam.origin_spell = spell;
1774 
1775     // [dshaligram] Any action that depends on the spellcasting attempt to have
1776     // succeeded must be performed after the switch.
1777     if (!wiz_cast && _spellcasting_aborted(spell, !allow_fail))
1778         return spret::abort;
1779 
1780     const spell_flags flags = get_spell_flags(spell);
1781 
1782     ASSERT(wiz_cast || !(flags & spflag::testing));
1783 
1784     if (!powc)
1785         powc = calc_spell_power(spell, true);
1786 
1787     const int range = calc_spell_range(spell, powc, allow_fail);
1788     beam.range = range;
1789 
1790     unique_ptr<targeter> hitfunc = find_spell_targeter(spell, powc, range);
1791     const bool is_targeted = !!(flags & spflag::targeting_mask);
1792 
1793     const god_type god =
1794         (crawl_state.is_god_acting()) ? crawl_state.which_god_acting()
1795                                       : GOD_NO_GOD;
1796 
1797     // XXX: This handles only some of the cases where spells need
1798     // targeting. There are others that do their own that will be
1799     // missed by this (and thus will not properly ESC without cost
1800     // because of it). Hopefully, those will eventually be fixed. - bwr
1801     // TODO: what's the status of the above comment in 2020+?
1802     const bool use_targeter = is_targeted
1803         || !god // Don't allow targeting spells cast by Xom
1804            && hitfunc
1805            && (target->fire_context // force static targeters when called in
1806                                     // "fire" mode
1807                || Options.always_use_static_targeters
1808                || Options.force_targeter.count(spell) > 0);
1809 
1810     if (use_targeter)
1811     {
1812         const targ_mode_type targ =
1813               testbits(flags, spflag::neutral)    ? TARG_ANY :
1814               testbits(flags, spflag::helpful)    ? TARG_FRIEND :
1815               testbits(flags, spflag::obj)        ? TARG_MOVABLE_OBJECT :
1816                                                    TARG_HOSTILE;
1817 
1818         const targeting_type dir =
1819              testbits(flags, spflag::target) ? DIR_TARGET : DIR_NONE;
1820 
1821         // TODO: it's extremely inconsistent when this prompt shows up, not
1822         // sure why
1823         const char *prompt = get_spell_target_prompt(spell);
1824 
1825         const bool needs_path = !testbits(flags, spflag::target)
1826                                 // Apportation must be spflag::target, since a
1827                                 // shift-direction makes no sense for it, but
1828                                 // it nevertheless requires line-of-fire.
1829                                 || spell == SPELL_APPORTATION;
1830 
1831         desc_filter additional_desc
1832             = targeter_addl_desc(spell, powc, flags, hitfunc.get());
1833 
1834         // `true` on fourth param skips MP check and a few others that have
1835         // already been carried out
1836         const bool useless = spell_is_useless(spell, true, false, true);
1837         const char *spell_title_color = useless ? "darkgrey" : "w";
1838         const string verb = wait_spell_active(spell)
1839             ? "<lightred>Restarting spell</lightred>"
1840             : is_targeted ? "Aiming" : "Casting";
1841         string title = make_stringf("%s: <%s>%s</%s>", verb.c_str(),
1842                     spell_title_color, spell_title(spell), spell_title_color);
1843         if (allow_fail)
1844         {
1845             title += make_stringf(" <lightgrey>(%s)</lightgrey>",
1846                 _spell_failure_rate_description(spell).c_str());
1847         }
1848 
1849         spell_targeting_behaviour beh(spell);
1850 
1851         direction_chooser_args args;
1852         args.hitfunc = hitfunc.get();
1853         args.restricts = dir;
1854         args.mode = targ;
1855         args.range = range;
1856         args.needs_path = needs_path;
1857         args.target_prefix = prompt;
1858         args.top_prompt = title;
1859         args.behaviour = &beh;
1860 
1861         // if the spell is useless and we have somehow gotten this far, it's
1862         // a forced cast. Setting this prevents the direction chooser from
1863         // looking for selecting a default target (which doesn't factor in
1864         // the spell's capabilities).
1865         // Also ensure we don't look for a target for static targeters. It might
1866         // be better to move to an affected position if any?
1867         if (useless || !is_targeted)
1868             args.default_place = you.pos();
1869         if (hitfunc && hitfunc->can_affect_walls())
1870         {
1871             args.show_floor_desc = true;
1872             args.show_boring_feats = false; // don't show "The floor."
1873         }
1874         if (testbits(flags, spflag::not_self))
1875             args.self = confirm_prompt_type::cancel;
1876         else
1877             args.self = confirm_prompt_type::none;
1878         args.get_desc_func = additional_desc;
1879         if (!spell_direction(*target, beam, &args))
1880             return spret::abort;
1881 
1882         if (testbits(flags, spflag::not_self) && target->isMe())
1883         {
1884             if (spell == SPELL_TELEPORT_OTHER)
1885                 mpr("Sorry, this spell works on others only.");
1886             else
1887                 canned_msg(MSG_UNTHINKING_ACT);
1888 
1889             return spret::abort;
1890         }
1891     }
1892 
1893     if (evoked_wand)
1894     {
1895         powc = player_adjust_evoc_power(powc);
1896         surge_power_wand(wand_mp_cost());
1897     }
1898     else if (allow_fail)
1899         surge_power(_spell_enhancement(spell));
1900 
1901     // Enhancers only matter for calc_spell_power() and raw_spell_fail().
1902     // Not sure about this: is it flavour or misleading? (jpeg)
1903 
1904     int fail = 0;
1905     if (evoked_wand && evoked_wand->charges == 0)
1906         return spret::fail;
1907     else if (allow_fail)
1908     {
1909         int spfl = random2avg(100, 3);
1910 
1911         if (!you_worship(GOD_SIF_MUNA)
1912             && you.penance[GOD_SIF_MUNA] && one_chance_in(20))
1913         {
1914             god_speaks(GOD_SIF_MUNA, "You feel a surge of divine spite.");
1915 
1916             // This will cause failure and increase the miscast effect.
1917             spfl = -you.penance[GOD_SIF_MUNA];
1918         }
1919         else if (spell_typematch(spell, spschool::necromancy)
1920                  && !you_worship(GOD_KIKUBAAQUDGHA)
1921                  && you.penance[GOD_KIKUBAAQUDGHA]
1922                  && one_chance_in(20))
1923         {
1924             // And you thought you'd Necromutate your way out of penance...
1925             simple_god_message(" does not allow the disloyal to dabble in "
1926                                "death!", GOD_KIKUBAAQUDGHA);
1927 
1928             // The spell still goes through, but you get a miscast anyway.
1929             miscast_effect(you, nullptr,
1930                            {miscast_source::god, GOD_KIKUBAAQUDGHA},
1931                            spschool::necromancy,
1932                            spell_difficulty(spell),
1933                            you.experience_level,
1934                            "the malice of Kikubaaqudgha");
1935         }
1936         else if (vehumet_supports_spell(spell)
1937                  && !you_worship(GOD_VEHUMET)
1938                  && you.penance[GOD_VEHUMET]
1939                  && one_chance_in(20))
1940         {
1941             // And you thought you'd Fire Storm your way out of penance...
1942             simple_god_message(" does not allow the disloyal to dabble in "
1943                                "destruction!", GOD_VEHUMET);
1944 
1945             // The spell still goes through, but you get a miscast anyway.
1946             miscast_effect(you, nullptr, {miscast_source::god, GOD_VEHUMET},
1947                            spschool::conjuration,
1948                            spell_difficulty(spell),
1949                            you.experience_level,
1950                            "the malice of Vehumet");
1951         }
1952 
1953         const int spfail_chance = raw_spell_fail(spell);
1954 
1955         if (spfl < spfail_chance)
1956             fail = spfail_chance - spfl;
1957     }
1958 
1959     dprf("Spell #%d, power=%d", spell, powc);
1960 
1961     // Have to set aim first, in case the spellcast kills its first target
1962     if (you.props.exists("battlesphere") && allow_fail)
1963         aim_battlesphere(&you, spell);
1964 
1965     const auto orig_target = monster_at(beam.target);
1966     const bool self_target = you.pos() == beam.target;
1967     const bool had_tele = orig_target && orig_target->has_ench(ENCH_TP);
1968 
1969     spret cast_result = _do_cast(spell, powc, *target, beam, god, fail);
1970 
1971     switch (cast_result)
1972     {
1973     case spret::success:
1974     {
1975         const int demonic_magic = you.get_mutation_level(MUT_DEMONIC_MAGIC);
1976 
1977         if ((demonic_magic == 3 && evoked_wand)
1978             || (demonic_magic > 0 && allow_fail))
1979         {
1980             do_demonic_magic(spell_difficulty(spell) * 6, demonic_magic);
1981         }
1982 
1983         if (you.props.exists("battlesphere") && allow_fail
1984             && battlesphere_can_mirror(spell))
1985         {
1986             trigger_battlesphere(&you);
1987         }
1988 
1989         const auto victim = monster_at(beam.target);
1990         if (will_have_passive(passive_t::shadow_spells)
1991             && allow_fail
1992             && !god_hates_spell(spell, you.religion, !allow_fail)
1993             && (flags & spflag::targeting_mask)
1994             && !(flags & spflag::neutral)
1995             && (beam.is_enchantment()
1996                 || battlesphere_can_mirror(spell))
1997             // Must have a target, but that can't be the player.
1998             && !self_target
1999             && orig_target
2000             // For teleport other, only mimic if the spell hit who we
2001             // originally targeted and if we failed to change the target's
2002             // teleport status. This way the mimic won't just undo the effect
2003             // of a successful cast.
2004             && (spell != SPELL_TELEPORT_OTHER
2005                 || (orig_target == victim
2006                     && had_tele == victim->has_ench(ENCH_TP))))
2007         {
2008             dithmenos_shadow_spell(&beam, spell);
2009         }
2010         _spellcasting_side_effects(spell, god, !allow_fail);
2011         return spret::success;
2012     }
2013     case spret::fail:
2014     {
2015         mprf("You miscast %s.", spell_title(spell));
2016         flush_input_buffer(FLUSH_ON_FAILURE);
2017         learned_something_new(HINT_SPELL_MISCAST);
2018         miscast_effect(spell, fail);
2019 
2020         return spret::fail;
2021     }
2022 
2023     case spret::abort:
2024         return spret::abort;
2025 
2026     case spret::none:
2027 #ifdef WIZARD
2028         if (you.wizard && !allow_fail && is_valid_spell(spell)
2029             && (flags & spflag::monster))
2030         {
2031             _try_monster_cast(spell, powc, *target, beam);
2032             return spret::success;
2033         }
2034 #endif
2035 
2036         if (is_valid_spell(spell))
2037         {
2038             mprf(MSGCH_ERROR, "Spell '%s' is not a player castable spell.",
2039                  spell_title(spell));
2040         }
2041         else
2042             mprf(MSGCH_ERROR, "Invalid spell!");
2043 
2044         return spret::abort;
2045     }
2046 
2047     return spret::success;
2048 }
2049 
2050 // Returns spret::success, spret::abort, spret::fail
2051 // or spret::none (not a player spell).
_do_cast(spell_type spell,int powc,const dist & spd,bolt & beam,god_type god,bool fail)2052 static spret _do_cast(spell_type spell, int powc, const dist& spd,
2053                            bolt& beam, god_type god, bool fail)
2054 {
2055     const coord_def target = spd.isTarget ? beam.target : you.pos() + spd.delta;
2056     if (spell == SPELL_FREEZE)
2057     {
2058         if (!adjacent(you.pos(), target))
2059             return spret::abort;
2060     }
2061 
2062     switch (spell)
2063     {
2064     case SPELL_FREEZE:
2065         return cast_freeze(powc, monster_at(target), fail);
2066 
2067     case SPELL_SANDBLAST:
2068         return cast_sandblast(powc, beam, fail);
2069 
2070     case SPELL_IOOD:
2071         return cast_iood(&you, powc, &beam, 0, 0, MHITNOT, fail);
2072 
2073     // Clouds and explosions.
2074     case SPELL_POISONOUS_CLOUD:
2075     case SPELL_HOLY_BREATH:
2076     case SPELL_FREEZING_CLOUD:
2077         return cast_big_c(powc, spell, &you, beam, fail);
2078 
2079     case SPELL_FIRE_STORM:
2080         return cast_fire_storm(powc, beam, fail);
2081 
2082     // Demonspawn ability, no failure.
2083     case SPELL_CALL_DOWN_DAMNATION:
2084         return cast_smitey_damnation(powc, beam) ? spret::success : spret::abort;
2085 
2086     // LOS spells
2087 
2088     // Beogh ability, no failure.
2089     case SPELL_SMITING:
2090         return cast_smiting(powc, monster_at(target)) ? spret::success
2091                                                       : spret::abort;
2092 
2093     case SPELL_AIRSTRIKE:
2094         return cast_airstrike(powc, spd, fail);
2095 
2096     case SPELL_LRD:
2097         return cast_fragmentation(powc, &you, spd.target, fail);
2098 
2099     case SPELL_GRAVITAS:
2100         return cast_gravitas(powc, beam.target, fail);
2101 
2102     // other effects
2103     case SPELL_DISCHARGE:
2104         return cast_discharge(powc, you, fail);
2105 
2106     case SPELL_CHAIN_LIGHTNING:
2107         return cast_chain_lightning(powc, you, fail);
2108 
2109     case SPELL_DISPERSAL:
2110         return cast_dispersal(powc, fail);
2111 
2112     case SPELL_SHATTER:
2113         return cast_shatter(powc, fail);
2114 
2115     case SPELL_IRRADIATE:
2116         return cast_irradiate(powc, &you, fail);
2117 
2118     case SPELL_LEDAS_LIQUEFACTION:
2119         return cast_liquefaction(powc, fail);
2120 
2121     case SPELL_OZOCUBUS_REFRIGERATION:
2122         return fire_los_attack_spell(spell, powc, &you, fail);
2123 
2124     case SPELL_OLGREBS_TOXIC_RADIANCE:
2125         return cast_toxic_radiance(&you, powc, fail);
2126 
2127     case SPELL_IGNITE_POISON:
2128         return cast_ignite_poison(&you, powc, fail);
2129 
2130     case SPELL_POLAR_VORTEX:
2131         return cast_polar_vortex(powc, fail);
2132 
2133     case SPELL_THUNDERBOLT:
2134         return cast_thunderbolt(&you, powc, target, fail);
2135 
2136     case SPELL_DAZZLING_FLASH:
2137         return cast_dazzling_flash(powc, fail);
2138 
2139     case SPELL_CHAIN_OF_CHAOS:
2140         return cast_chain_spell(SPELL_CHAIN_OF_CHAOS, powc, &you, fail);
2141 
2142     case SPELL_IGNITION:
2143         return cast_ignition(&you, powc, fail);
2144 
2145     case SPELL_FROZEN_RAMPARTS:
2146         return cast_frozen_ramparts(powc, fail);
2147 
2148     // Summoning spells, and other spells that create new monsters.
2149     // If a god is making you cast one of these spells, any monsters
2150     // produced will count as god gifts.
2151     case SPELL_SUMMON_SMALL_MAMMAL:
2152         return cast_summon_small_mammal(powc, god, fail);
2153 
2154     case SPELL_CALL_CANINE_FAMILIAR:
2155         return cast_call_canine_familiar(powc, god, fail);
2156 
2157     case SPELL_ANIMATE_ARMOUR:
2158         return cast_summon_armour_spirit(powc, god, fail);
2159 
2160     case SPELL_SUMMON_ICE_BEAST:
2161         return cast_summon_ice_beast(powc, god, fail);
2162 
2163     case SPELL_MONSTROUS_MENAGERIE:
2164         return cast_monstrous_menagerie(&you, powc, god, fail);
2165 
2166     case SPELL_SUMMON_DRAGON:
2167         return cast_summon_dragon(&you, powc, god, fail);
2168 
2169     case SPELL_DRAGON_CALL:
2170         return cast_dragon_call(powc, fail);
2171 
2172     case SPELL_SUMMON_HYDRA:
2173         return cast_summon_hydra(&you, powc, god, fail);
2174 
2175     case SPELL_SUMMON_MANA_VIPER:
2176         return cast_summon_mana_viper(powc, god, fail);
2177 
2178     case SPELL_CONJURE_BALL_LIGHTNING:
2179         return cast_conjure_ball_lightning(powc, god, fail);
2180 
2181     case SPELL_SUMMON_LIGHTNING_SPIRE:
2182         return cast_summon_lightning_spire(powc, god, fail);
2183 
2184     case SPELL_SUMMON_GUARDIAN_GOLEM:
2185         return cast_summon_guardian_golem(powc, god, fail);
2186 
2187     case SPELL_CALL_IMP:
2188         return cast_call_imp(powc, god, fail);
2189 
2190     case SPELL_SHADOW_CREATURES:
2191         return cast_shadow_creatures(spell, god, level_id::current(), fail);
2192 
2193     case SPELL_SUMMON_HORRIBLE_THINGS:
2194         return cast_summon_horrible_things(powc, god, fail);
2195 
2196     case SPELL_MALIGN_GATEWAY:
2197         return cast_malign_gateway(&you, powc, god, fail);
2198 
2199     case SPELL_SUMMON_FOREST:
2200         return cast_summon_forest(&you, powc, god, fail);
2201 
2202     case SPELL_ANIMATE_SKELETON:
2203         return cast_animate_skeleton(powc, god, fail);
2204 
2205     case SPELL_ANIMATE_DEAD:
2206         return cast_animate_dead(powc, god, fail);
2207 
2208     case SPELL_SIMULACRUM:
2209         return cast_simulacrum(powc, god, fail);
2210 
2211     case SPELL_HAUNT:
2212         return cast_haunt(powc, beam.target, god, fail);
2213 
2214     case SPELL_DEATH_CHANNEL:
2215         return cast_death_channel(powc, god, fail);
2216 
2217     case SPELL_SPELLFORGED_SERVITOR:
2218         return cast_spellforged_servitor(powc, god, fail);
2219 
2220     case SPELL_BATTLESPHERE:
2221         return cast_battlesphere(&you, powc, god, fail);
2222 
2223     case SPELL_INFESTATION:
2224         return cast_infestation(powc, beam, fail);
2225 
2226     case SPELL_FOXFIRE:
2227         return cast_foxfire(you, powc, god, fail);
2228 
2229     case SPELL_NOXIOUS_BOG:
2230         return cast_noxious_bog(powc, fail);
2231 
2232     // Enchantments.
2233     case SPELL_CONFUSING_TOUCH:
2234         return cast_confusing_touch(powc, fail);
2235 
2236     case SPELL_CAUSE_FEAR:
2237         return mass_enchantment(ENCH_FEAR, powc, fail);
2238 
2239     case SPELL_INTOXICATE:
2240         return cast_intoxicate(powc, fail);
2241 
2242     case SPELL_DISCORD:
2243         return mass_enchantment(ENCH_INSANE, powc, fail);
2244 
2245     case SPELL_ENGLACIATION:
2246         return cast_englaciation(powc, fail);
2247 
2248     case SPELL_EXCRUCIATING_WOUNDS:
2249         return cast_excruciating_wounds(powc, fail);
2250 
2251     // Transformations.
2252     case SPELL_BEASTLY_APPENDAGE:
2253         return cast_transform(powc, transformation::appendage, fail);
2254 
2255     case SPELL_BLADE_HANDS:
2256         return cast_transform(powc, transformation::blade_hands, fail);
2257 
2258     case SPELL_SPIDER_FORM:
2259         return cast_transform(powc, transformation::spider, fail);
2260 
2261     case SPELL_STATUE_FORM:
2262         return cast_transform(powc, transformation::statue, fail);
2263 
2264     case SPELL_ICE_FORM:
2265         return cast_transform(powc, transformation::ice_beast, fail);
2266 
2267     case SPELL_STORM_FORM:
2268         return cast_transform(powc, transformation::storm, fail);
2269 
2270     case SPELL_DRAGON_FORM:
2271         return cast_transform(powc, transformation::dragon, fail);
2272 
2273     case SPELL_NECROMUTATION:
2274         return cast_transform(powc, transformation::lich, fail);
2275 
2276     case SPELL_SWIFTNESS:
2277         return cast_swiftness(powc, fail);
2278 
2279     case SPELL_OZOCUBUS_ARMOUR:
2280         return ice_armour(powc, fail);
2281 
2282     case SPELL_SILENCE:
2283         return cast_silence(powc, fail);
2284 
2285     case SPELL_WEREBLOOD:
2286         return cast_wereblood(powc, fail);
2287 
2288     case SPELL_PORTAL_PROJECTILE:
2289         return cast_portal_projectile(powc, fail);
2290 
2291     // other
2292     case SPELL_BORGNJORS_REVIVIFICATION:
2293         return cast_revivification(powc, fail);
2294 
2295     case SPELL_SUBLIMATION_OF_BLOOD:
2296         return cast_sublimation_of_blood(powc, fail);
2297 
2298     case SPELL_DEATHS_DOOR:
2299         return cast_deaths_door(powc, fail);
2300 
2301     case SPELL_INVISIBILITY:
2302         return cast_invisibility(powc, fail);
2303 
2304     // Escape spells.
2305     case SPELL_BLINK:
2306         return cast_blink(fail);
2307 
2308     case SPELL_CONJURE_FLAME:
2309         return conjure_flame(powc, fail);
2310 
2311     case SPELL_PASSWALL:
2312         return cast_passwall(beam.target, powc, fail);
2313 
2314     case SPELL_APPORTATION:
2315         return cast_apportation(powc, beam, fail);
2316 
2317     case SPELL_DISJUNCTION:
2318         return cast_disjunction(powc, fail);
2319 
2320     case SPELL_MANIFOLD_ASSAULT:
2321         return cast_manifold_assault(powc, fail);
2322 
2323     case SPELL_CORPSE_ROT:
2324         return cast_corpse_rot(fail);
2325 
2326     case SPELL_GOLUBRIAS_PASSAGE:
2327         return cast_golubrias_passage(beam.target, fail);
2328 
2329     case SPELL_FULMINANT_PRISM:
2330         return cast_fulminating_prism(&you, powc, beam.target, fail);
2331 
2332     case SPELL_SEARING_RAY:
2333         return cast_searing_ray(powc, beam, fail);
2334 
2335     case SPELL_GLACIATE:
2336         return cast_glaciate(&you, powc, target, fail);
2337 
2338     case SPELL_POISONOUS_VAPOURS:
2339         return cast_poisonous_vapours(powc, spd, fail);
2340 
2341     case SPELL_BLINKBOLT:
2342         return blinkbolt(powc, beam, fail);
2343 
2344     case SPELL_STARBURST:
2345         return cast_starburst(powc, fail);
2346 
2347     case SPELL_HAILSTORM:
2348         return cast_hailstorm(powc, fail);
2349 
2350     case SPELL_MAXWELLS_COUPLING:
2351         return cast_maxwells_coupling(powc, fail);
2352 
2353     case SPELL_ISKENDERUNS_MYSTIC_BLAST:
2354         return cast_imb(powc, fail);
2355 
2356     // non-player spells that have a zap, but that shouldn't be called (e.g
2357     // because they will crash as a player zap).
2358     case SPELL_DRAIN_LIFE:
2359         return spret::none;
2360 
2361     default:
2362         if (spell_removed(spell))
2363         {
2364             mpr("Sorry, this spell is gone!");
2365             return spret::abort;
2366         }
2367         break;
2368     }
2369 
2370     // Finally, try zaps.
2371     zap_type zap = spell_to_zap(spell);
2372     if (zap != NUM_ZAPS)
2373     {
2374         return zapping(zap, spell_zap_power(spell, powc), beam, true, nullptr,
2375                        fail);
2376     }
2377 
2378     return spret::none;
2379 }
2380 
2381 // get_true_fail_rate: Takes the raw failure to-beat number
2382 // and converts it to the actual chance of failure:
2383 // the probability that random2avg(100,3) < raw_fail.
2384 // Should probably use more constants, though I doubt the spell
2385 // success algorithms will really change *that* much.
2386 // Called only by failure_rate_to_int
_get_true_fail_rate(int raw_fail)2387 static double _get_true_fail_rate(int raw_fail)
2388 {
2389     // Need 3*random2avg(100,3) = random2(101) + random2(101) + random2(100)
2390     // to be (strictly) less than 3*raw_fail. Fun with tetrahedral numbers!
2391 
2392     // How many possible outcomes, considering all three dice?
2393     const int outcomes = 101 * 101 * 100;
2394     const int target = raw_fail * 3;
2395 
2396     if (target <= 100)
2397     {
2398         // The failures are exactly the triples of nonnegative integers
2399         // that sum to < target.
2400         return double(_tetrahedral_number(target)) / outcomes;
2401     }
2402     if (target <= 200)
2403     {
2404         // Some of the triples that sum to < target would have numbers
2405         // greater than 100, or a last number greater than 99, so aren't
2406         // possible outcomes. Apply the principle of inclusion-exclusion
2407         // by subtracting out these cases. The set of triples with first
2408         // number > 100 is isomorphic to the set of triples that sum to
2409         // 101 less; likewise for the second and third numbers (100 less
2410         // in the last case). Two or more out-of-range numbers would have
2411         // resulted in a sum of at least 201, so there is no overlap
2412         // among the three cases we are subtracting.
2413         return double(_tetrahedral_number(target)
2414                       - 2 * _tetrahedral_number(target - 101)
2415                       - _tetrahedral_number(target - 100)) / outcomes;
2416     }
2417     // The random2avg distribution is symmetric, so the last interval is
2418     // essentially the same as the first interval.
2419     return double(outcomes - _tetrahedral_number(300 - target)) / outcomes;
2420 }
2421 
2422 const double fail_hp_fraction[] =
2423 {
2424     .10,
2425     .30,
2426     .50,
2427     .70,
2428 };
2429 /**
2430  * Compute the maximum miscast damage from the given spell
2431  *
2432  * The miscast code uses
2433  *     dam = div_rand_round(roll_dice(level, level + raw_fail), MISCAST_DIVISOR)
2434  */
max_miscast_damage(spell_type spell)2435 int max_miscast_damage(spell_type spell)
2436 {
2437     int raw_fail = raw_spell_fail(spell);
2438     int level = spell_difficulty(spell);
2439 
2440     // Impossible to get a damaging miscast
2441     if (level * level * raw_fail <= MISCAST_THRESHOLD)
2442         return 0;
2443 
2444     return div_round_up(level * (raw_fail + level), MISCAST_DIVISOR);
2445 }
2446 
2447 
2448 /**
2449  * Compute the tier of maximum severity of a miscast
2450  * @param spell     The spell to be checked.
2451  *
2452  * Tiers are defined by the relation between the maximum miscast damage
2453  * (given a miscast occurs):
2454  *
2455  * - safe, no chance of dangerous effect
2456  * - slightly dangerous, mdam <= 10% mhp
2457  * - dangerous, mdam <= 30% mhp
2458  * - quite dangerous, mdam <= 50% mhp
2459  * - extremely dangerous, mdam <= 70% mhp
2460  * - potentially lethal, higher mdam
2461  */
fail_severity(spell_type spell)2462 int fail_severity(spell_type spell)
2463 {
2464     const int raw_fail = raw_spell_fail(spell);
2465     const int level = spell_difficulty(spell);
2466 
2467     // Impossible to get a damaging miscast
2468     if (level * level * raw_fail <= MISCAST_THRESHOLD)
2469         return 0;
2470 
2471     const int max_damage = max_miscast_damage(spell);
2472 
2473     for (int i = 0; i < 4; ++i)
2474         if (max_damage <= fail_hp_fraction[i] * get_real_hp(true))
2475             return i + 1;
2476 
2477     return 5;
2478 }
2479 
2480 const char *fail_severity_adjs[] =
2481 {
2482     "safe",
2483     "mildly dangerous",
2484     "dangerous",
2485     "quite dangerous",
2486     "extremely dangerous",
2487     "potentially lethal",
2488 };
2489 COMPILE_CHECK(ARRAYSZ(fail_severity_adjs) > 3);
2490 
2491 // Chooses a colour for the failure rate display for a spell. The colour is
2492 // based on the chance of getting a severity >= 2 miscast.
failure_rate_colour(spell_type spell)2493 int failure_rate_colour(spell_type spell)
2494 {
2495     const int severity = fail_severity(spell);
2496     return severity == 0 ? LIGHTGREY :
2497            severity == 1 ? WHITE :
2498            severity == 2 ? YELLOW :
2499            severity == 3 ? LIGHTRED :
2500            severity == 4 ? RED
2501                          : MAGENTA;
2502 }
2503 
2504 //Converts the raw failure rate into a number to be displayed.
failure_rate_to_int(int fail)2505 int failure_rate_to_int(int fail)
2506 {
2507     if (fail <= 0)
2508         return 0;
2509     else if (fail >= 100)
2510         return (fail + 100)/2;
2511     else
2512         return max(1, (int) (100 * _get_true_fail_rate(fail)));
2513 }
2514 
2515 /**
2516  * Convert the given failure rate into a percent, and return it as a string.
2517  *
2518  * @param fail      A raw failure rate (not a percent!)
2519  * @return          E.g. "79%".
2520  */
failure_rate_to_string(int fail)2521 string failure_rate_to_string(int fail)
2522 {
2523     return make_stringf("%d%%", failure_rate_to_int(fail));
2524 }
2525 
spell_failure_rate_string(spell_type spell)2526 string spell_failure_rate_string(spell_type spell)
2527 {
2528     const string failure = failure_rate_to_string(raw_spell_fail(spell));
2529     const string colour = colour_to_str(failure_rate_colour(spell));
2530     return make_stringf("<%s>%s</%s>",
2531             colour.c_str(), failure.c_str(), colour.c_str());
2532 }
2533 
_spell_failure_rate_description(spell_type spell)2534 static string _spell_failure_rate_description(spell_type spell)
2535 {
2536     const string failure = failure_rate_to_string(raw_spell_fail(spell));
2537     const char *severity_adj = fail_severity_adjs[fail_severity(spell)];
2538     const string colour = colour_to_str(failure_rate_colour(spell));
2539     const char *col = colour.c_str();
2540 
2541     return make_stringf("<%s>%s</%s>; <%s>%s</%s> risk of failure",
2542             col, severity_adj, col, col, failure.c_str(), col);
2543 }
2544 
spell_noise_string(spell_type spell,int chop_wiz_display_width)2545 string spell_noise_string(spell_type spell, int chop_wiz_display_width)
2546 {
2547     const int casting_noise = spell_noise(spell);
2548     int effect_noise = spell_effect_noise(spell);
2549     zap_type zap = spell_to_zap(spell);
2550     if (effect_noise == 0 && zap != NUM_ZAPS)
2551     {
2552         bolt beem;
2553         zappy(zap, 0, false, beem);
2554         effect_noise = beem.loudness;
2555     }
2556 
2557     // A typical amount of noise.
2558     if (spell == SPELL_POLAR_VORTEX)
2559         effect_noise = 15;
2560 
2561     const int noise = max(casting_noise, effect_noise);
2562 
2563     const char* noise_descriptions[] =
2564     {
2565         "Silent", "Almost silent", "Quiet", "A bit loud", "Loud", "Very loud",
2566         "Extremely loud", "Deafening"
2567     };
2568 
2569     const int breakpoints[] = { 1, 2, 4, 8, 15, 20, 30 };
2570     COMPILE_CHECK(ARRAYSZ(noise_descriptions) == 1 + ARRAYSZ(breakpoints));
2571 
2572     const char* desc = noise_descriptions[breakpoint_rank(noise, breakpoints,
2573                                                 ARRAYSZ(breakpoints))];
2574 
2575 #ifdef WIZARD
2576     if (you.wizard)
2577     {
2578         if (chop_wiz_display_width > 0)
2579         {
2580             ostringstream shortdesc;
2581             shortdesc << chop_string(desc, chop_wiz_display_width)
2582                       << "(" << to_string(noise) << ")";
2583             return shortdesc.str();
2584         }
2585         else
2586             return make_stringf("%s (%d)", desc, noise);
2587     }
2588     else
2589 #endif
2590         return desc;
2591 }
2592 
power_to_barcount(int power)2593 int power_to_barcount(int power)
2594 {
2595     if (power == -1)
2596         return -1;
2597 
2598     const int breakpoints[] = { 10, 15, 25, 35, 50, 75, 100, 150, 200 };
2599     return breakpoint_rank(power, breakpoints, ARRAYSZ(breakpoints)) + 1;
2600 }
2601 
_spell_power(spell_type spell,bool evoked)2602 static int _spell_power(spell_type spell, bool evoked)
2603 {
2604     const int cap = spell_power_cap(spell);
2605     if (cap == 0)
2606         return -1;
2607     const int pow = evoked ? wand_power()
2608                            : calc_spell_power(spell, true, false, false);
2609     return min(pow, cap);
2610 }
2611 
2612 #ifdef WIZARD
_wizard_spell_power_numeric_string(spell_type spell)2613 static string _wizard_spell_power_numeric_string(spell_type spell)
2614 {
2615     const int cap = spell_power_cap(spell);
2616     if (cap == 0)
2617         return "N/A";
2618     const int power = min(calc_spell_power(spell, true, false, false), cap);
2619     return make_stringf("%d (%d)", power, cap);
2620 }
2621 #endif
2622 
_spell_damage(spell_type spell,bool evoked)2623 static dice_def _spell_damage(spell_type spell, bool evoked)
2624 {
2625     const int power = _spell_power(spell, evoked);
2626     if (power < 0)
2627         return dice_def(0,0);
2628     switch (spell)
2629     {
2630         case SPELL_FREEZE:
2631             return freeze_damage(power);
2632         case SPELL_FULMINANT_PRISM:
2633             return prism_damage(prism_hd(power, false), true);
2634         case SPELL_CONJURE_BALL_LIGHTNING:
2635             return ball_lightning_damage(ball_lightning_hd(power, false));
2636         case SPELL_IOOD:
2637             return iood_damage(power, INFINITE_DISTANCE);
2638         case SPELL_IRRADIATE:
2639             return irradiate_damage(power, false);
2640         case SPELL_SHATTER:
2641             return shatter_damage(power);
2642         case SPELL_BATTLESPHERE:
2643             return battlesphere_damage(power);
2644         case SPELL_FROZEN_RAMPARTS:
2645             return ramparts_damage(power, false);
2646         case SPELL_LRD:
2647             return base_fragmentation_damage(power);
2648         default:
2649             break;
2650     }
2651     const zap_type zap = spell_to_zap(spell);
2652     if (zap == NUM_ZAPS)
2653         return dice_def(0,0);
2654     return zap_damage(zap, power, false, false);
2655 }
2656 
spell_damage_string(spell_type spell,bool evoked)2657 string spell_damage_string(spell_type spell, bool evoked)
2658 {
2659     switch (spell)
2660     {
2661         case SPELL_MAXWELLS_COUPLING:
2662             return "∞";
2663         case SPELL_CONJURE_FLAME:
2664             return desc_cloud_damage(CLOUD_FIRE, false);
2665         case SPELL_FREEZING_CLOUD:
2666             return desc_cloud_damage(CLOUD_COLD, false);
2667         default:
2668             break;
2669     }
2670     const dice_def dam = _spell_damage(spell, evoked);
2671     if (dam.num == 0 || dam.size == 0)
2672         return "";
2673     string mult = "";
2674     switch (spell)
2675     {
2676         case SPELL_FOXFIRE:
2677             mult = "2x";
2678             break;
2679         case SPELL_CONJURE_BALL_LIGHTNING:
2680             mult = "3x";
2681             break;
2682         default:
2683             break;
2684     }
2685     const string dam_str = make_stringf("%s%dd%d", mult.c_str(), dam.num, dam.size);
2686     if (spell == SPELL_LRD || spell == SPELL_SHATTER)
2687         return dam_str + "*"; // many special cases of more/less damage
2688     return dam_str;
2689 }
2690 
spell_acc(spell_type spell)2691 int spell_acc(spell_type spell)
2692 {
2693     const zap_type zap = spell_to_zap(spell);
2694     if (zap == NUM_ZAPS)
2695         return -1;
2696     if (zap_explodes(zap) || zap_is_enchantment(zap))
2697         return -1;
2698     const int power = _spell_power(spell, false);
2699     if (power < 0)
2700         return -1;
2701     const int acc = zap_to_hit(zap, power, false);
2702     if (acc == AUTOMATIC_HIT)
2703         return -1;
2704     return acc;
2705 }
2706 
spell_power_percent(spell_type spell)2707 int spell_power_percent(spell_type spell)
2708 {
2709     const int pow = calc_spell_power(spell, true);
2710     const int max_pow = spell_power_cap(spell);
2711     if (max_pow == 0)
2712         return -1; // should never happen for player spells
2713     return pow * 100 / max_pow;
2714 }
2715 
spell_power_string(spell_type spell)2716 string spell_power_string(spell_type spell)
2717 {
2718 #ifdef WIZARD
2719     if (you.wizard)
2720         return _wizard_spell_power_numeric_string(spell);
2721 #endif
2722 
2723     const int percent = spell_power_percent(spell);
2724     if (percent < 0)
2725         return "N/A";
2726     else
2727         return make_stringf("%d%%", percent);
2728 }
2729 
calc_spell_range(spell_type spell,int power,bool allow_bonus,bool ignore_shadows)2730 int calc_spell_range(spell_type spell, int power, bool allow_bonus,
2731                      bool ignore_shadows)
2732 {
2733     if (power == 0)
2734         power = calc_spell_power(spell, true, false, false);
2735     const int range = spell_range(spell, power, allow_bonus, ignore_shadows);
2736 
2737     return range;
2738 }
2739 
2740 /**
2741  * Give a string visually describing a given spell's range, as cast by the
2742  * player.
2743  *
2744  * @param spell     The spell in question.
2745  * @return          Something like "@-->.."
2746  */
spell_range_string(spell_type spell)2747 string spell_range_string(spell_type spell)
2748 {
2749     if (spell == SPELL_HAILSTORM)
2750         return "@.->"; // Special case: hailstorm is a ring
2751 
2752     const int cap      = spell_power_cap(spell);
2753     const int range    = calc_spell_range(spell, 0);
2754     const int maxrange = calc_spell_range(spell, cap, true, true);
2755 
2756     return range_string(range, maxrange, '@');
2757 }
2758 
2759 /**
2760  * Give a string visually describing a given spell's range.
2761  *
2762  * E.g., for a spell of fixed range 1 (melee), "@>"
2763  *       for a spell of range 3, max range 5, "@-->.."
2764  *
2765  * @param range         The current range of the spell.
2766  * @param maxrange      The range the spell would have at max power.
2767  * @param caster_char   The character used to represent the caster.
2768  *                      Usually @ for the player.
2769  * @return              See above.
2770  */
range_string(int range,int maxrange,char32_t caster_char)2771 string range_string(int range, int maxrange, char32_t caster_char)
2772 {
2773     if (range <= 0)
2774         return "N/A";
2775 
2776     return stringize_glyph(caster_char) + string(range - 1, '-')
2777            + string(">") + string(maxrange - range, '.');
2778 }
2779 
spell_schools_string(spell_type spell)2780 string spell_schools_string(spell_type spell)
2781 {
2782     string desc;
2783 
2784     bool already = false;
2785     for (const auto bit : spschools_type::range())
2786     {
2787         if (spell_typematch(spell, bit))
2788         {
2789             if (already)
2790                 desc += "/";
2791             desc += spelltype_long_name(bit);
2792             already = true;
2793         }
2794     }
2795 
2796     return desc;
2797 }
2798 
spell_skills(spell_type spell,set<skill_type> & skills)2799 void spell_skills(spell_type spell, set<skill_type> &skills)
2800 {
2801     const spschools_type disciplines = get_spell_disciplines(spell);
2802     for (const auto bit : spschools_type::range())
2803         if (disciplines & bit)
2804             skills.insert(spell_type2skill(bit));
2805 }
2806 
do_demonic_magic(int pow,int rank)2807 void do_demonic_magic(int pow, int rank)
2808 {
2809     if (rank < 1)
2810         return;
2811 
2812     mprf("Malevolent energies surge around you.");
2813 
2814     for (radius_iterator ri(you.pos(), rank, C_SQUARE, LOS_NO_TRANS, true); ri; ++ri)
2815     {
2816         monster *mons = monster_at(*ri);
2817 
2818         if (!mons || mons->wont_attack() || !mons_is_threatening(*mons))
2819             continue;
2820 
2821         if (mons->check_willpower(pow) <= 0)
2822             mons->paralyse(&you, 1 + roll_dice(1,4));
2823     }
2824 }
2825