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