Doxygen: document spell_noise.
[crawl.git] / crawl-ref / source / spl-util.cc
blobb3877df8d6fdf8852032377b9f659ed413008436
1 /*
2 * File: spl-util.cc *
3 * Summary: data handlers for player-available spell list *
4 * Written by: don brodale <dbrodale@bigfootinteractive.com> *
5 */
7 #include "AppHdr.h"
9 #include "spl-util.h"
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <ctype.h>
14 #include <string.h>
15 #include <limits.h>
17 #include <algorithm>
19 #include "externs.h"
21 #include "beam.h"
22 #include "coord.h"
23 #include "coordit.h"
24 #include "directn.h"
25 #include "debug.h"
26 #include "godabil.h"
27 #include "stuff.h"
28 #include "env.h"
29 #include "libutil.h"
30 #include "mon-behv.h"
31 #include "mon-util.h"
32 #include "notes.h"
33 #include "player.h"
34 #include "religion.h"
35 #include "spl-cast.h"
36 #include "spl-book.h"
37 #include "spl-damage.h"
38 #include "spl-zap.h"
39 #include "terrain.h"
40 #include "item_use.h"
41 #include "transform.h"
44 struct spell_desc
46 int id;
47 const char *title;
48 unsigned int disciplines; // bitfield
49 unsigned int flags; // bitfield
50 unsigned int level;
52 // Usually in the range 0..200 (0 means uncapped).
53 // Note that some spells are also capped through zap_type.
54 // See spell_power_cap below.
55 int power_cap;
57 // At power 0, you get min_range. At power power_cap, you get max_range.
58 int min_range;
59 int max_range;
61 // Modify spell level for spell noise purposes.
62 int noise_mod;
64 const char *target_prompt;
66 // If a monster is casting this, does it need a tracer?
67 bool ms_needs_tracer;
69 // The spell can be used no matter what the monster's foe is.
70 bool ms_utility;
73 static struct spell_desc spelldata[] =
75 #include "spl-data.h"
78 static int spell_list[NUM_SPELLS];
80 #define SPELLDATASIZE (sizeof(spelldata)/sizeof(struct spell_desc))
82 static struct spell_desc *_seekspell(spell_type spellid);
83 static bool _cloud_helper(cloud_func func, const coord_def& where,
84 int pow, int spread_rate,
85 cloud_type ctype, const actor *agent, int colour,
86 std::string name, std::string tile);
89 // BEGIN PUBLIC FUNCTIONS
92 // All this does is merely refresh the internal spell list {dlb}:
93 void init_spell_descs(void)
95 for (int i = 0; i < NUM_SPELLS; i++)
96 spell_list[i] = -1;
98 for (unsigned int i = 0; i < SPELLDATASIZE; i++)
100 spell_desc &data = spelldata[i];
102 #ifdef DEBUG
103 if (data.id < SPELL_NO_SPELL || data.id >= NUM_SPELLS)
104 end(1, false, "spell #%d has invalid id %d", i, data.id);
106 if (data.title == NULL || strlen(data.title) == 0)
107 end(1, false, "spell #%d, id %d has no name", i, data.id);
109 if (data.level < 1 || data.level > 9)
111 end(1, false, "spell '%s' has invalid level %d",
112 data.title, data.level);
115 if (data.min_range > data.max_range)
117 end(1, false, "spell '%s' has min_range larger than max_range",
118 data.title);
121 if (data.flags & SPFLAG_TARGETING_MASK)
123 if (data.min_range <= -1 || data.max_range <= 0)
125 end(1, false, "targeted/directed spell '%s' has invalid range",
126 data.title);
129 #endif
131 spell_list[data.id] = i;
135 typedef std::map<std::string, spell_type> spell_name_map;
136 static spell_name_map spell_name_cache;
138 void init_spell_name_cache()
140 for (int i = 0; i < NUM_SPELLS; i++)
142 spell_type type = static_cast<spell_type>(i);
144 if (!is_valid_spell(type))
145 continue;
147 const char *sptitle = spell_title(type);
148 ASSERT(sptitle);
149 const std::string spell_name = lowercase_string(sptitle);
150 spell_name_cache[spell_name] = type;
154 spell_type spell_by_name(std::string name, bool partial_match)
156 if (name.empty())
157 return (SPELL_NO_SPELL);
159 lowercase(name);
161 if (!partial_match)
163 spell_name_map::iterator i = spell_name_cache.find(name);
165 if (i != spell_name_cache.end())
166 return (i->second);
168 return (SPELL_NO_SPELL);
171 int spellmatch = -1;
172 for (int i = 0; i < NUM_SPELLS; i++)
174 spell_type type = static_cast<spell_type>(i);
175 if (!is_valid_spell(type))
176 continue;
178 const char *sptitle = spell_title(type);
179 const std::string spell_name = lowercase_string(sptitle);
181 if (spell_name.find(name) != std::string::npos)
183 if (spell_name == name)
184 return static_cast<spell_type>(i);
186 spellmatch = i;
190 return (spellmatch != -1 ? static_cast<spell_type>(spellmatch)
191 : SPELL_NO_SPELL);
194 spschool_flag_type school_by_name(std::string name)
196 spschool_flag_type short_match, long_match;
197 int short_matches, long_matches;
199 short_match = long_match = SPTYP_NONE;
200 short_matches = long_matches = 0;
202 lowercase(name);
204 for (int i = 0; i <= SPTYP_RANDOM; i++)
206 spschool_flag_type type = (spschool_flag_type) (1 << i);
208 std::string short_name = spelltype_short_name(type);
209 std::string long_name = spelltype_long_name(type);
211 lowercase(short_name);
212 lowercase(long_name);
214 if (name == short_name)
215 return type;
216 if (name == long_name)
217 return type;
219 if (short_name.find(name) != std::string::npos)
221 short_match = type;
222 short_matches++;
224 if (long_name.find(name) != std::string::npos)
226 long_match = type;
227 long_matches++;
231 if (short_matches != 1 && long_matches != 1)
232 return SPTYP_NONE;
234 if (short_matches == 1 && long_matches != 1)
235 return short_match;
236 if (short_matches != 1 && long_matches == 1)
237 return long_match;
239 if (short_match == long_match)
240 return short_match;
242 return SPTYP_NONE;
245 int get_spell_slot_by_letter(char letter)
247 ASSERT(isaalpha(letter));
249 const int index = letter_to_index(letter);
251 if (you.spell_letter_table[ index ] == -1)
252 return (-1);
254 return (you.spell_letter_table[index]);
257 int get_spell_slot(spell_type spell)
259 for (int i = 0; i < MAX_KNOWN_SPELLS; i++)
260 if (you.spells[i] == spell)
261 return i;
263 return -1;
266 spell_type get_spell_by_letter(char letter)
268 ASSERT(isaalpha(letter));
270 const int slot = get_spell_slot_by_letter(letter);
272 return ((slot == -1) ? SPELL_NO_SPELL : you.spells[slot]);
275 bool add_spell_to_memory(spell_type spell)
277 int i, j;
279 // first we find a slot in our head:
280 for (i = 0; i < MAX_KNOWN_SPELLS; i++)
282 if (you.spells[i] == SPELL_NO_SPELL)
283 break;
286 you.spells[i] = spell;
288 // now we find an available label:
289 for (j = 0; j < 52; j++)
291 if (you.spell_letter_table[j] == -1)
292 break;
295 you.spell_letter_table[j] = i;
297 you.spell_no++;
299 take_note(Note(NOTE_LEARN_SPELL, spell));
301 #ifdef USE_TILE
302 tiles.layout_statcol();
303 redraw_screen();
304 #endif
306 return (true);
309 bool del_spell_from_memory_by_slot(int slot)
311 int j;
313 if (you.last_cast_spell == you.spells[slot])
314 you.last_cast_spell = SPELL_NO_SPELL;
316 you.spells[ slot ] = SPELL_NO_SPELL;
318 for (j = 0; j < 52; j++)
320 if (you.spell_letter_table[j] == slot)
321 you.spell_letter_table[j] = -1;
325 you.spell_no--;
327 #ifdef USE_TILE
328 tiles.layout_statcol();
329 redraw_screen();
330 #endif
332 return (true);
335 bool del_spell_from_memory(spell_type spell)
337 int i = get_spell_slot(spell);
338 if (i == -1)
339 return (false);
340 else
341 return del_spell_from_memory_by_slot(i);
344 int spell_hunger(spell_type which_spell, bool rod)
346 const int level = spell_difficulty(which_spell);
348 const int basehunger[] = {
349 50, 95, 160, 250, 350, 550, 700, 850, 1000
352 int hunger;
354 if (level < 10 && level > 0)
355 hunger = basehunger[level-1];
356 else
357 hunger = (basehunger[0] * level * level) / 4;
359 if (rod)
361 hunger -= 10 * you.skills[SK_EVOCATIONS];
362 hunger = std::max(hunger, level * 5);
364 else
365 hunger -= you.intel() * you.skills[SK_SPELLCASTING];
367 if (hunger < 0)
368 hunger = 0;
370 return hunger;
373 // Used to determine whether or not a monster should always fire this spell
374 // if selected. If not, we should use a tracer.
376 // Note - this function assumes that the monster is "nearby" its target!
377 bool spell_needs_tracer(spell_type spell)
379 return (_seekspell(spell)->ms_needs_tracer);
382 // Checks if the spell is an explosion that can be placed anywhere even without
383 // an unobstructed beam path, such as fire storm.
384 bool spell_is_direct_explosion(spell_type spell)
386 return (spell == SPELL_FIRE_STORM || spell == SPELL_HELLFIRE_BURST);
389 bool spell_needs_foe(spell_type spell)
391 return (!_seekspell(spell)->ms_utility);
394 bool spell_harms_target(spell_type spell)
396 const unsigned int flags = _seekspell(spell)->flags;
398 if (flags & (SPFLAG_HELPFUL | SPFLAG_NEUTRAL))
399 return false;
401 if (flags & SPFLAG_TARGETING_MASK)
402 return true;
404 return false;
407 bool spell_harms_area(spell_type spell)
409 const unsigned int flags = _seekspell(spell)->flags;
411 if (flags & (SPFLAG_HELPFUL | SPFLAG_NEUTRAL))
412 return false;
414 if (flags & SPFLAG_AREA)
415 return true;
417 return false;
420 bool spell_sanctuary_castable(spell_type spell)
422 return false;
425 // applied to spell misfires (more power = worse) and triggers
426 // for Xom acting (more power = more likely to grab his attention) {dlb}
427 int spell_mana(spell_type which_spell)
429 if (vehumet_supports_spell(which_spell)
430 && you.religion == GOD_VEHUMET
431 && !player_under_penance()
432 && you.piety >= piety_breakpoint(3)
433 && _seekspell(which_spell)->level >= 5)
435 return (_seekspell(which_spell)->level - 1);
438 return (_seekspell(which_spell)->level);
441 // applied in naughties (more difficult = higher level knowledge = worse)
442 // and triggers for Sif acting (same reasoning as above, just good) {dlb}
443 int spell_difficulty(spell_type which_spell)
445 return (_seekspell(which_spell)->level);
448 int spell_levels_required(spell_type which_spell)
450 int levels = spell_difficulty(which_spell);
452 if (which_spell == SPELL_DELAYED_FIREBALL
453 && you.has_spell(SPELL_FIREBALL))
455 levels -= spell_difficulty(SPELL_FIREBALL);
457 else if (which_spell == SPELL_FIREBALL
458 && you.has_spell(SPELL_DELAYED_FIREBALL))
460 levels = 0;
463 return (levels);
466 unsigned int get_spell_flags(spell_type which_spell)
468 return (_seekspell(which_spell)->flags);
471 const char *get_spell_target_prompt(spell_type which_spell)
473 return (_seekspell(which_spell)->target_prompt);
476 bool spell_typematch(spell_type which_spell, unsigned int which_discipline)
478 return (get_spell_disciplines(which_spell) & which_discipline);
481 //jmf: next two for simple bit handling
482 unsigned int get_spell_disciplines(spell_type spell)
484 unsigned int dis = _seekspell(spell)->disciplines;
485 if (spell == SPELL_DRAGON_FORM && player_genus(GENPC_DRACONIAN))
486 dis &= (~SPTYP_FIRE);
488 return dis;
491 int count_bits(unsigned int bits)
493 unsigned int n;
494 int c = 0;
496 for (n = 1; n < INT_MAX; n <<= 1)
497 if (n & bits)
498 c++;
500 return (c);
503 // NOTE: Assumes that any single spell won't belong to conflicting
504 // disciplines.
505 bool disciplines_conflict(unsigned int disc1, unsigned int disc2)
507 const unsigned int combined = disc1 | disc2;
509 return ((combined & SPTYP_EARTH) && (combined & SPTYP_AIR)
510 || (combined & SPTYP_FIRE) && (combined & SPTYP_ICE)
511 || (combined & SPTYP_HOLY) && (combined & SPTYP_NECROMANCY));
514 const char *spell_title(spell_type spell)
516 return (_seekspell(spell)->title);
520 // FUNCTION APPLICATORS: Idea from Juho Snellman <jsnell@lyseo.edu.ouka.fi>
521 // on the Roguelike News pages, Development section.
522 // <URL:http://www.skoardy.demon.co.uk/rlnews/>
523 // Here are some function applicators: sort of like brain-dead,
524 // home-grown iterators for the container "dungeon".
526 // Apply a function-pointer to all visible squares
527 // Returns summation of return values from passed in function.
528 int apply_area_visible(cell_func cf, int power,
529 bool pass_through_trans, actor *agent)
531 int rv = 0;
533 for (radius_iterator ri(you.pos(), LOS_RADIUS); ri; ++ri)
534 if (pass_through_trans || you.see_cell_no_trans(*ri))
535 rv += cf(*ri, power, 0, agent);
537 return (rv);
540 // Applies the effect to all nine squares around/including the target.
541 // Returns summation of return values from passed in function.
542 int apply_area_square(cell_func cf, const coord_def& where, int power,
543 actor *agent)
545 int rv = 0;
547 for (adjacent_iterator ai(where, false); ai; ++ai)
548 rv += cf(*ai, power, 0, agent);
550 return (rv);
554 // Applies the effect to the eight squares beside the target.
555 // Returns summation of return values from passed in function.
556 int apply_area_around_square(cell_func cf, const coord_def& where, int power,
557 actor *agent)
559 int rv = 0;
561 for (adjacent_iterator ai(where, true); ai; ++ai)
562 rv += cf(*ai, power, 0, agent);
564 return (rv);
567 // Like apply_area_around_square, but for monsters in those squares,
568 // and takes care not to affect monsters twice that change position.
569 int apply_monsters_around_square(monster_func mf, const coord_def& where,
570 int power)
572 int rv = 0;
573 std::set<const monster*> affected;
574 for (adjacent_iterator ai(where, true); ai; ++ai)
576 monster* mon = monster_at(*ai);
577 if (mon && affected.find(mon) == affected.end())
579 rv += mf(mon, power);
580 affected.insert(mon);
584 return (rv);
587 // Affect up to max_targs monsters around a point, chosen randomly.
588 // Return varies with the function called; return values will be added up.
589 int apply_random_around_square(cell_func cf, const coord_def& where,
590 bool exclude_center, int power, int max_targs,
591 actor *agent)
593 int rv = 0;
595 if (max_targs <= 0)
596 return 0;
598 if (max_targs >= 9 && !exclude_center)
599 return (apply_area_square(cf, where, power, agent));
601 if (max_targs >= 8 && exclude_center)
602 return (apply_area_around_square(cf, where, power, agent));
604 coord_def targs[8];
606 int count = 0;
608 for (adjacent_iterator ai(where, exclude_center); ai; ++ai)
610 if (monster_at(*ai) == NULL && *ai != you.pos())
611 continue;
613 // Found target
614 count++;
616 // Slight difference here over the basic algorithm...
618 // For cases where the number of choices <= max_targs it's
619 // obvious (all available choices will be selected).
621 // For choices > max_targs, here's a brief proof:
623 // Let m = max_targs, k = choices - max_targs, k > 0.
625 // Proof, by induction (over k):
627 // 1) Show n = m + 1 (k = 1) gives uniform distribution,
628 // P(new one not chosen) = 1 / (m + 1).
629 // m 1 1
630 // P(specific previous one replaced) = --- * --- = ---
631 // m+1 m m+1
633 // So the probablity is uniform (ie. any element has
634 // a 1/(m+1) chance of being in the unchosen slot).
636 // 2) Assume the distribution is uniform at n = m+k.
637 // (ie. the probablity that any of the found elements
638 // was chosen = m / (m+k) (the slots are symetric,
639 // so it's the sum of the probabilities of being in
640 // any of them)).
642 // 3) Show n = m + k + 1 gives a uniform distribution.
643 // P(new one chosen) = m / (m + k + 1)
644 // P(any specific previous choice remaining chosen)
645 // = [1 - P(swaped into m+k+1 position)] * P(prev. chosen)
646 // m 1 m
647 // = [ 1 - ----- * --- ] * ---
648 // m+k+1 m m+k
650 // m+k m m
651 // = ----- * --- = -----
652 // m+k+1 m+k m+k+1
654 // Therefore, it's uniform for n = m + k + 1. QED
656 // The important thing to note in calculating the last
657 // probability is that the chosen elements have already
658 // passed tests which verify that they *don't* belong
659 // in slots m+1...m+k, so the only positions an already
660 // chosen element can end up in are its original
661 // position (in one of the chosen slots), or in the
662 // new slot.
664 // The new item can, of course, be placed in any slot,
665 // swapping the value there into the new slot... we
666 // just don't care about the non-chosen slots enough
667 // to store them, so it might look like the item
668 // automatically takes the new slot when not chosen
669 // (although, by symetry all the non-chosen slots are
670 // the same... and similarly, by symetry, all chosen
671 // slots are the same).
673 // Yes, that's a long comment for a short piece of
674 // code, but I want people to have an understanding
675 // of why this works (or at least make them wary about
676 // changing it without proof and breaking this code). -- bwr
678 // Accept the first max_targs choices, then when
679 // new choices come up, replace one of the choices
680 // at random, max_targs/count of the time (the rest
681 // of the time it replaces an element in an unchosen
682 // slot -- but we don't care about them).
683 if (count <= max_targs)
685 targs[count - 1] = *ai;
687 else if (x_chance_in_y(max_targs, count))
689 const int pick = random2(max_targs);
690 targs[ pick ] = *ai;
694 const int targs_found = std::min(count, max_targs);
696 if (targs_found)
698 // Used to divide the power up among the targets here, but
699 // it's probably better to allow the full power through and
700 // balance the called function. -- bwr
701 for (int i = 0; i < targs_found; i++)
703 ASSERT(!targs[i].origin());
704 rv += cf(targs[i], power, 0, agent);
708 return (rv);
711 // Apply func to one square of player's choice beside the player.
712 int apply_one_neighbouring_square(cell_func cf, int power, actor *agent)
714 dist bmove;
715 direction_chooser_args args;
716 args.restricts = DIR_DIR;
717 args.mode = TARG_ANY;
719 mpr("Which direction? [ESC to cancel]", MSGCH_PROMPT);
720 direction(bmove, args);
722 if (!bmove.isValid)
724 canned_msg(MSG_OK);
725 return (-1);
728 return cf(you.pos() + bmove.delta, power, 1, agent);
731 int apply_area_within_radius(cell_func cf, const coord_def& where,
732 int pow, int radius, int ctype,
733 actor *agent)
736 int rv = 0;
738 for (radius_iterator ri(where, radius, false, false); ri; ++ri)
739 rv += cf(*ri, pow, ctype, agent);
741 return (rv);
744 // apply_area_cloud:
745 // Try to make a realistic cloud by expanding from a point, filling empty
746 // floor tiles until we run out of material (passed in as number).
747 // We really need some sort of a queue structure, since ideally I'd like
748 // to do a (shallow) breadth-first-search of the dungeon floor.
749 // This ought to work okay for small clouds.
750 void apply_area_cloud(cloud_func func, const coord_def& where,
751 int pow, int number, cloud_type ctype,
752 const actor *agent,
753 int spread_rate, int colour, std::string name,
754 std::string tile)
756 if (!in_bounds(where))
757 return;
759 int good_squares = 0;
760 int neighbours[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
762 if (number && _cloud_helper(func, where, pow, spread_rate, ctype, agent,
763 colour, name, tile))
764 number--;
766 if (number == 0)
767 return;
769 // These indices depend on the order in Compass (see main.cc)
770 int compass_order_orth[4] = { 2, 6, 4, 0 };
771 int compass_order_diag[4] = { 1, 3, 5, 7 };
773 int* const arrs[2] = { compass_order_orth, compass_order_diag };
775 for (int m = 0; m < 2; ++m)
777 // Randomise, but do orthogonals first and diagonals later.
778 std::random_shuffle(arrs[m], arrs[m] + 4);
779 for (int i = 0; i < 4 && number; ++i)
781 const int aux = arrs[m][i];
782 if (_cloud_helper(func, where + Compass[aux],
783 pow, spread_rate, ctype, agent, colour,
784 name, tile))
786 number--;
787 good_squares++;
788 neighbours[aux]++;
793 // Get a random permutation.
794 int perm[8];
795 for (int i = 0; i < 8; ++i)
796 perm[i] = i;
797 std::random_shuffle(perm, perm+8);
798 for (int i = 0; i < 8 && number; i++)
800 // Spread (in random order.)
801 const int j = perm[i];
803 if (neighbours[j] == 0)
804 continue;
806 int spread = number / good_squares;
807 number -= spread;
808 good_squares--;
809 apply_area_cloud(func, where + Compass[j], pow, spread, ctype, agent,
810 spread_rate, colour, name, tile);
814 // Select a spell direction and fill dist and pbolt appropriately.
815 // Return false if the user canceled, true otherwise.
816 // FIXME: this should accept a direction_chooser_args directly rather
817 // than move the arguments into one.
818 bool spell_direction(dist &spelld, bolt &pbolt,
819 targeting_type restrict, targ_mode_type mode,
820 int range,
821 bool needs_path, bool may_target_monster,
822 bool may_target_self, const char *target_prefix,
823 const char* top_prompt, bool cancel_at_self)
825 if (range < 1)
826 range = (pbolt.range < 1) ? LOS_RADIUS : pbolt.range;
828 direction_chooser_args args;
829 args.restricts = restrict;
830 args.mode = mode;
831 args.range = range;
832 args.just_looking = false;
833 args.needs_path = needs_path;
834 args.may_target_monster = may_target_monster;
835 args.may_target_self = may_target_self;
836 args.target_prefix = target_prefix;
837 if (top_prompt)
838 args.top_prompt = top_prompt;
839 args.behaviour = NULL;
840 args.cancel_at_self = cancel_at_self;
842 direction(spelld, args);
844 if (!spelld.isValid)
846 // Check for user cancel.
847 canned_msg(MSG_OK);
848 return (false);
851 pbolt.set_target(spelld);
852 pbolt.source = you.pos();
854 return (true);
857 const char* spelltype_short_name(int which_spelltype)
859 switch (which_spelltype)
861 case SPTYP_CONJURATION:
862 return ("Conj");
863 case SPTYP_HEXES:
864 return ("Hex");
865 case SPTYP_CHARMS:
866 return ("Chrm");
867 case SPTYP_FIRE:
868 return ("Fire");
869 case SPTYP_ICE:
870 return ("Ice");
871 case SPTYP_TRANSMUTATION:
872 return ("Trmt");
873 case SPTYP_NECROMANCY:
874 return ("Necr");
875 case SPTYP_HOLY:
876 return ("Holy");
877 case SPTYP_SUMMONING:
878 return ("Summ");
879 case SPTYP_DIVINATION:
880 return ("Divn");
881 case SPTYP_TRANSLOCATION:
882 return ("Tloc");
883 case SPTYP_POISON:
884 return ("Pois");
885 case SPTYP_EARTH:
886 return ("Erth");
887 case SPTYP_AIR:
888 return ("Air");
889 case SPTYP_RANDOM:
890 return ("Rndm");
891 default:
892 return "Bug";
896 const char* spelltype_long_name(int which_spelltype)
898 switch (which_spelltype)
900 case SPTYP_CONJURATION:
901 return ("Conjuration");
902 case SPTYP_HEXES:
903 return ("Hexes");
904 case SPTYP_CHARMS:
905 return ("Charms");
906 case SPTYP_FIRE:
907 return ("Fire");
908 case SPTYP_ICE:
909 return ("Ice");
910 case SPTYP_TRANSMUTATION:
911 return ("Transmutation");
912 case SPTYP_NECROMANCY:
913 return ("Necromancy");
914 case SPTYP_HOLY:
915 return ("Holy");
916 case SPTYP_SUMMONING:
917 return ("Summoning");
918 case SPTYP_DIVINATION:
919 return ("Divination");
920 case SPTYP_TRANSLOCATION:
921 return ("Translocation");
922 case SPTYP_POISON:
923 return ("Poison");
924 case SPTYP_EARTH:
925 return ("Earth");
926 case SPTYP_AIR:
927 return ("Air");
928 case SPTYP_RANDOM:
929 return ("Random");
930 default:
931 return "Bug";
935 skill_type spell_type2skill(unsigned int spelltype)
937 switch (spelltype)
939 case SPTYP_CONJURATION: return (SK_CONJURATIONS);
940 case SPTYP_HEXES: return (SK_HEXES);
941 case SPTYP_CHARMS: return (SK_CHARMS);
942 case SPTYP_FIRE: return (SK_FIRE_MAGIC);
943 case SPTYP_ICE: return (SK_ICE_MAGIC);
944 case SPTYP_TRANSMUTATION: return (SK_TRANSMUTATIONS);
945 case SPTYP_NECROMANCY: return (SK_NECROMANCY);
946 case SPTYP_SUMMONING: return (SK_SUMMONINGS);
947 case SPTYP_TRANSLOCATION: return (SK_TRANSLOCATIONS);
948 case SPTYP_POISON: return (SK_POISON_MAGIC);
949 case SPTYP_EARTH: return (SK_EARTH_MAGIC);
950 case SPTYP_AIR: return (SK_AIR_MAGIC);
952 default:
953 case SPTYP_HOLY:
954 case SPTYP_DIVINATION:
955 #ifdef DEBUG_DIAGNOSTICS
956 mprf(MSGCH_DIAGNOSTICS, "spell_type2skill: called with spelltype %u",
957 spelltype);
958 #endif
959 return (SK_NONE);
961 } // end spell_type2skill()
964 **************************************************
966 * END PUBLIC FUNCTIONS *
968 **************************************************
971 //jmf: Simplified; moved init code to top function, init_spell_descs().
972 static spell_desc *_seekspell(spell_type spell)
974 ASSERT(spell >= 0 && spell < NUM_SPELLS);
975 const int index = spell_list[spell];
976 ASSERT(index != -1);
978 return (&spelldata[index]);
981 bool is_valid_spell(spell_type spell)
983 return (spell > SPELL_NO_SPELL && spell < NUM_SPELLS
984 && spell_list[spell] != -1);
987 static bool _cloud_helper(cloud_func func, const coord_def& where,
988 int pow, int spread_rate,
989 cloud_type ctype, const actor* agent, int colour,
990 std::string name, std::string tile)
992 if (in_bounds(where)
993 && !feat_is_solid(grd(where))
994 && env.cgrid(where) == EMPTY_CLOUD)
996 func(where, pow, spread_rate, ctype, agent, colour, name, tile);
997 return (true);
1000 return (false);
1003 static bool _spell_range_varies(spell_type spell)
1005 int minrange = _seekspell(spell)->min_range;
1006 int maxrange = _seekspell(spell)->max_range;
1008 return (minrange < maxrange);
1011 int spell_power_cap(spell_type spell)
1013 const int scap = _seekspell(spell)->power_cap;
1014 const int zcap = spell_zap_power_cap(spell);
1016 if (scap == 0)
1017 return (zcap);
1018 else if (zcap == 0)
1019 return (scap);
1020 else
1022 // Two separate power caps; pre-zapping spell power
1023 // goes into range.
1024 if (scap <= zcap || _spell_range_varies(spell))
1025 return (scap);
1026 else
1027 return (zcap);
1031 int spell_range(spell_type spell, int pow, bool real_cast, bool player_spell)
1033 int minrange = _seekspell(spell)->min_range;
1034 int maxrange = _seekspell(spell)->max_range;
1035 ASSERT(maxrange >= minrange);
1037 // spells with no range have maxrange == minrange == -1
1038 if (maxrange < 0)
1039 return maxrange;
1041 // Sandblast is a special case.
1042 if (spell == SPELL_SANDBLAST && wielding_rocks())
1044 minrange++;
1045 maxrange++;
1048 if (player_spell
1049 && vehumet_supports_spell(spell)
1050 && you.religion == GOD_VEHUMET
1051 && spell != SPELL_STICKY_FLAME
1052 && spell != SPELL_FREEZE
1053 && !player_under_penance()
1054 && you.piety >= piety_breakpoint(2))
1056 if (maxrange < LOS_RADIUS)
1057 maxrange++;
1059 if (minrange < LOS_RADIUS)
1060 minrange++;
1063 if (minrange == maxrange)
1064 return minrange;
1066 const int powercap = spell_power_cap(spell);
1068 if (powercap <= pow)
1069 return maxrange;
1071 // Round appropriately.
1072 return ((pow * (maxrange - minrange) + powercap / 2) / powercap + minrange);
1076 * Spell casting noise.
1078 * Returns the noise generated by the casting of a spell. The noise depends on
1079 * the spell schools and level. A modifier (noise_mod) can be applied to the
1080 * spell level.
1081 * @see spl-data.h
1083 * \param spell The spell being casted.
1084 * \return The amount of noise generated.
1086 int spell_noise(spell_type spell)
1088 const spell_desc *desc = _seekspell(spell);
1090 return spell_noise(desc->disciplines, desc->level + desc->noise_mod);
1094 * Spell default noise.
1096 * Default value for spell noise given a level and a set of schools.
1097 * Formula (use first match):
1098 * - Conjuration (noisy) = \f$ level \f$
1099 * - Air and poison (quiet) = \f$ \frac{level}{2} \f$
1100 * - Other (normal) = \f$ \frac{3 \times level}{4} \f$
1102 * \param disciplines An integer which contain the school flags.
1103 * \param level The level of the spell.
1104 * \return The amount of noise generated.
1106 int spell_noise(unsigned int disciplines, int level)
1108 if (disciplines == SPTYP_NONE)
1109 return (0);
1110 else if (disciplines & SPTYP_CONJURATION)
1111 return (level);
1112 else if (disciplines && !(disciplines & (SPTYP_POISON | SPTYP_AIR)))
1113 return div_round_up(level * 3, 4);
1114 else
1115 return div_round_up(level, 2);
1118 spell_type zap_type_to_spell(zap_type zap)
1120 switch (zap)
1122 case ZAP_FLAME:
1123 return SPELL_THROW_FLAME;
1124 case ZAP_FROST:
1125 return SPELL_THROW_FROST;
1126 case ZAP_SLOWING:
1127 return SPELL_SLOW;
1128 case ZAP_HASTING:
1129 return SPELL_HASTE;
1130 case ZAP_MAGIC_DARTS:
1131 return SPELL_MAGIC_DART;
1132 case ZAP_HEALING:
1133 return SPELL_MAJOR_HEALING;
1134 case ZAP_PARALYSIS:
1135 return SPELL_PARALYSE;
1136 case ZAP_FIRE:
1137 return SPELL_BOLT_OF_FIRE;
1138 case ZAP_COLD:
1139 return SPELL_BOLT_OF_COLD;
1140 case ZAP_PRIMAL_WAVE:
1141 return SPELL_PRIMAL_WAVE;
1142 case ZAP_CONFUSION:
1143 return SPELL_CONFUSE;
1144 case ZAP_INVISIBILITY:
1145 return SPELL_INVISIBILITY;
1146 case ZAP_DIGGING:
1147 return SPELL_DIG;
1148 case ZAP_FIREBALL:
1149 return SPELL_FIREBALL;
1150 case ZAP_TELEPORTATION:
1151 return SPELL_TELEPORT_OTHER;
1152 case ZAP_LIGHTNING:
1153 return SPELL_LIGHTNING_BOLT;
1154 case ZAP_POLYMORPH_OTHER:
1155 return SPELL_POLYMORPH_OTHER;
1156 case ZAP_NEGATIVE_ENERGY:
1157 return SPELL_BOLT_OF_DRAINING;
1158 case ZAP_ENSLAVEMENT:
1159 return SPELL_ENSLAVEMENT;
1160 case ZAP_DISINTEGRATION:
1161 return SPELL_DISINTEGRATE;
1162 default:
1163 die("zap_type_to_spell() only handles wand zaps for now");
1165 return SPELL_NO_SPELL;
1168 bool spell_is_empowered(spell_type spell)
1170 if ((you.religion == GOD_VEHUMET)
1171 && vehumet_supports_spell(spell)
1172 && piety_rank() > 2)
1174 return (true);
1177 switch (spell)
1179 case SPELL_SWIFTNESS:
1180 // looking at player_movement_speed, this should be correct ~DMB
1181 if (player_movement_speed() > 6
1182 && you.duration[DUR_CONTROLLED_FLIGHT] > 0
1183 && you.duration[DUR_SWIFTNESS] < 1)
1185 return (true);
1187 break;
1188 case SPELL_STONESKIN:
1189 if (you.duration[DUR_TRANSFORMATION] > 0
1190 && you.form == TRAN_STATUE
1191 && you.duration[DUR_STONESKIN] < 1)
1193 return (true);
1195 break;
1196 case SPELL_OZOCUBUS_ARMOUR:
1197 if (you.duration[DUR_TRANSFORMATION] > 0
1198 && you.form == TRAN_ICE_BEAST
1199 && you.duration[DUR_ICY_ARMOUR] < 1)
1201 return (true);
1203 break;
1204 default:
1205 break;
1208 return (false);
1211 // This function attempts to determine if 'spell' is useless to
1212 // the player. if 'transient' is true, then it will include checks
1213 // for volatile or temporary states (such as status effects, mana, etc.)
1215 // its notably used by 'spell_highlight_by_utility'
1216 bool spell_is_useless(spell_type spell, bool transient)
1218 if (you_cannot_memorise(spell))
1219 return (true);
1221 if (transient)
1223 if (you.duration[DUR_CONF] > 0
1224 || spell_mana(spell) > you.magic_points
1225 || spell_no_hostile_in_range(spell, get_dist_to_nearest_monster()))
1227 return (true);
1231 switch (spell)
1233 case SPELL_BLINK:
1234 case SPELL_CONTROLLED_BLINK:
1235 case SPELL_TELEPORT_SELF:
1236 if (item_blocks_teleport(false, false))
1237 return true;
1238 break;
1239 case SPELL_SWIFTNESS:
1240 // looking at player_movement_speed, this should be correct ~DMB
1241 if (player_movement_speed() <= 6)
1242 return (true);
1243 break;
1244 case SPELL_LEVITATION:
1245 case SPELL_FLY:
1246 if (you.species == SP_KENKU && you.experience_level >= 15)
1247 return (true);
1248 if (transient && you.is_levitating())
1249 return (true);
1250 break;
1251 case SPELL_REGENERATION:
1252 if (you.species == SP_DEEP_DWARF)
1253 return (true);
1254 break;
1255 case SPELL_INVISIBILITY:
1256 if (transient && (you.duration[DUR_INVIS] > 0 || you.backlit()))
1257 return (true);
1258 break;
1259 case SPELL_CONTROL_TELEPORT:
1260 if (transient && you.duration[DUR_CONTROL_TELEPORT] > 0)
1261 return (true);
1262 break;
1263 case SPELL_SEE_INVISIBLE:
1264 if (you.can_see_invisible(false, false))
1265 return (true);
1266 break;
1267 // weapon branding is useless
1268 case SPELL_FIRE_BRAND:
1269 case SPELL_FREEZING_AURA:
1270 case SPELL_LETHAL_INFUSION:
1271 case SPELL_WARP_BRAND:
1272 case SPELL_EXCRUCIATING_WOUNDS:
1273 case SPELL_POISON_WEAPON:
1274 // could be useful if it didn't require wielding
1275 case SPELL_TUKIMAS_DANCE:
1276 if (you.species == SP_CAT)
1277 return (true);
1278 break;
1279 default:
1280 break; // quash unhandled constants warnings
1283 return (false);
1286 // This function takes a spell, and determines what color it should be
1287 // highlighted with. You shouldn't have to touch this unless you want
1288 // to add new highlighting options.
1290 // as you can see, the functions it uses to determine highlights are:
1291 // god_hates_spell(spell, god)
1292 // god_likes_spell(spell, god)
1293 // spell_is_empowered(spell)
1294 // spell_is_useless(spell, transient)
1295 int spell_highlight_by_utility(spell_type spell, int default_color,
1296 bool transient, bool rod_spell)
1298 // If your god hates the spell, that
1299 // overrides all other concerns
1300 if (god_hates_spell(spell, you.religion))
1301 return (COL_FORBIDDEN);
1303 if (spell_is_empowered(spell) && !rod_spell)
1304 default_color = COL_EMPOWERED;
1306 if (spell_is_useless(spell, transient))
1307 default_color = COL_USELESS;
1309 return (default_color);
1312 bool spell_no_hostile_in_range(spell_type spell, int minRange)
1314 if (minRange < 0)
1315 return (false);
1317 bool bonus = 0;
1318 switch (spell)
1320 // These don't target monsters.
1321 case SPELL_APPORTATION:
1322 case SPELL_PROJECTED_NOISE:
1323 case SPELL_CONJURE_FLAME:
1324 case SPELL_DIG:
1325 case SPELL_PASSWALL:
1326 case SPELL_GOLUBRIAS_PASSAGE:
1328 // Airstrike has LOS_RANGE and can go through glass walls.
1329 case SPELL_AIRSTRIKE:
1331 // These bounce and may be aimed elsewhere to bounce at monsters
1332 // outside range (I guess).
1333 case SPELL_SHOCK:
1334 case SPELL_LIGHTNING_BOLT:
1336 case SPELL_FIRE_STORM:
1337 return (false);
1339 case SPELL_EVAPORATE:
1340 case SPELL_MEPHITIC_CLOUD:
1341 case SPELL_FIREBALL:
1342 case SPELL_FREEZING_CLOUD:
1343 case SPELL_NOXIOUS_CLOUD:
1344 case SPELL_POISONOUS_CLOUD:
1345 // Increase range by one due to cloud radius.
1346 bonus = 1;
1347 break;
1349 default:
1350 break;
1353 // The healing spells.
1354 if (testbits(get_spell_flags(spell), SPFLAG_HELPFUL))
1355 return (false);
1357 const int range = calc_spell_range(spell);
1358 if (range < 0)
1359 return (false);
1361 const int rsq = (range + bonus) * (range + bonus) + 1;
1362 if (rsq < minRange)
1363 return (true);
1365 return (false);