1 /**
2 * \file player-spell.c
3 * \brief Spell and prayer casting/praying
4 *
5 * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6 *
7 * This work is free software; you can redistribute it and/or modify it
8 * under the terms of either:
9 *
10 * a) the GNU General Public License as published by the Free Software
11 * Foundation, version 2, or
12 *
13 * b) the "Angband licence":
14 * This software may be copied and distributed for educational, research,
15 * and not for profit purposes provided that this copyright and statement
16 * are included in all such copies. Other copyrights may also apply.
17 */
18
19 #include "angband.h"
20 #include "cave.h"
21 #include "cmd-core.h"
22 #include "effects.h"
23 #include "init.h"
24 #include "monster.h"
25 #include "obj-gear.h"
26 #include "obj-tval.h"
27 #include "obj-util.h"
28 #include "object.h"
29 #include "player-calcs.h"
30 #include "player-spell.h"
31 #include "player-timed.h"
32 #include "player-util.h"
33 #include "project.h"
34 #include "target.h"
35
36 /**
37 * Stat Table (INT/WIS) -- Minimum failure rate (percentage)
38 */
39 static const int adj_mag_fail[STAT_RANGE] =
40 {
41 99 /* 3 */,
42 99 /* 4 */,
43 99 /* 5 */,
44 99 /* 6 */,
45 99 /* 7 */,
46 50 /* 8 */,
47 30 /* 9 */,
48 20 /* 10 */,
49 15 /* 11 */,
50 12 /* 12 */,
51 11 /* 13 */,
52 10 /* 14 */,
53 9 /* 15 */,
54 8 /* 16 */,
55 7 /* 17 */,
56 6 /* 18/00-18/09 */,
57 6 /* 18/10-18/19 */,
58 5 /* 18/20-18/29 */,
59 5 /* 18/30-18/39 */,
60 5 /* 18/40-18/49 */,
61 4 /* 18/50-18/59 */,
62 4 /* 18/60-18/69 */,
63 4 /* 18/70-18/79 */,
64 4 /* 18/80-18/89 */,
65 3 /* 18/90-18/99 */,
66 3 /* 18/100-18/109 */,
67 2 /* 18/110-18/119 */,
68 2 /* 18/120-18/129 */,
69 2 /* 18/130-18/139 */,
70 2 /* 18/140-18/149 */,
71 1 /* 18/150-18/159 */,
72 1 /* 18/160-18/169 */,
73 1 /* 18/170-18/179 */,
74 1 /* 18/180-18/189 */,
75 1 /* 18/190-18/199 */,
76 0 /* 18/200-18/209 */,
77 0 /* 18/210-18/219 */,
78 0 /* 18/220+ */
79 };
80
81 /**
82 * Stat Table (INT/WIS) -- failure rate adjustment
83 */
84 static const int adj_mag_stat[STAT_RANGE] =
85 {
86 -5 /* 3 */,
87 -4 /* 4 */,
88 -3 /* 5 */,
89 -3 /* 6 */,
90 -2 /* 7 */,
91 -1 /* 8 */,
92 0 /* 9 */,
93 0 /* 10 */,
94 0 /* 11 */,
95 0 /* 12 */,
96 0 /* 13 */,
97 1 /* 14 */,
98 2 /* 15 */,
99 3 /* 16 */,
100 4 /* 17 */,
101 5 /* 18/00-18/09 */,
102 6 /* 18/10-18/19 */,
103 7 /* 18/20-18/29 */,
104 8 /* 18/30-18/39 */,
105 9 /* 18/40-18/49 */,
106 10 /* 18/50-18/59 */,
107 11 /* 18/60-18/69 */,
108 12 /* 18/70-18/79 */,
109 15 /* 18/80-18/89 */,
110 18 /* 18/90-18/99 */,
111 21 /* 18/100-18/109 */,
112 24 /* 18/110-18/119 */,
113 27 /* 18/120-18/129 */,
114 30 /* 18/130-18/139 */,
115 33 /* 18/140-18/149 */,
116 36 /* 18/150-18/159 */,
117 39 /* 18/160-18/169 */,
118 42 /* 18/170-18/179 */,
119 45 /* 18/180-18/189 */,
120 48 /* 18/190-18/199 */,
121 51 /* 18/200-18/209 */,
122 54 /* 18/210-18/219 */,
123 57 /* 18/220+ */
124 };
125
126 /**
127 * Initialise player spells
128 */
player_spells_init(struct player * p)129 void player_spells_init(struct player *p)
130 {
131 int i, num_spells = p->class->magic.total_spells;
132
133 /* None */
134 if (!num_spells) return;
135
136 /* Allocate */
137 p->spell_flags = mem_zalloc(num_spells * sizeof(byte));
138 p->spell_order = mem_zalloc(num_spells * sizeof(byte));
139
140 /* None of the spells have been learned yet */
141 for (i = 0; i < num_spells; i++)
142 p->spell_order[i] = 99;
143 }
144
145 /**
146 * Free player spells
147 */
player_spells_free(struct player * p)148 void player_spells_free(struct player *p)
149 {
150 mem_free(p->spell_flags);
151 mem_free(p->spell_order);
152 }
153
154 /**
155 * Make a list of the spell realms the player's class has books from
156 */
class_magic_realms(const struct player_class * c,int * count)157 struct magic_realm *class_magic_realms(const struct player_class *c, int *count)
158 {
159 int i;
160 struct magic_realm *r = mem_zalloc(sizeof(struct magic_realm));
161
162 *count = 0;
163
164 if (!c->magic.total_spells) {
165 mem_free(r);
166 return NULL;
167 }
168
169 for (i = 0; i < c->magic.num_books; i++) {
170 struct magic_realm *r_test = r;
171 struct class_book *book = &c->magic.books[i];
172 bool found = false;
173
174 /* Test for first realm */
175 if (r->name == NULL) {
176 memcpy(r, book->realm, sizeof(struct magic_realm));
177 r->next = NULL;
178 (*count)++;
179 continue;
180 }
181
182 /* Test for already recorded */
183 while (r_test) {
184 if (streq(r_test->name, book->realm->name)) {
185 found = true;
186 }
187 r_test = r_test->next;
188 }
189 if (found) continue;
190
191 /* Add it */
192 r_test = mem_zalloc(sizeof(struct magic_realm));
193 r_test->next = r;
194 r = r_test;
195 (*count)++;
196 }
197
198 return r;
199 }
200
201
202 /**
203 * Get the spellbook structure from any object which is a book
204 */
object_kind_to_book(const struct object_kind * kind)205 const struct class_book *object_kind_to_book(const struct object_kind *kind)
206 {
207 struct player_class *class = classes;
208 while (class) {
209 int i;
210
211 for (i = 0; i < class->magic.num_books; i++)
212 if ((kind->tval == class->magic.books[i].tval) &&
213 (kind->sval == class->magic.books[i].sval)) {
214 return &class->magic.books[i];
215 }
216 class = class->next;
217 }
218
219 return NULL;
220 }
221
222 /**
223 * Get the spellbook structure from an object which is a book the player can
224 * cast from
225 */
player_object_to_book(struct player * p,const struct object * obj)226 const struct class_book *player_object_to_book(struct player *p,
227 const struct object *obj)
228 {
229 int i;
230
231 for (i = 0; i < p->class->magic.num_books; i++)
232 if ((obj->tval == p->class->magic.books[i].tval) &&
233 (obj->sval == p->class->magic.books[i].sval))
234 return &p->class->magic.books[i];
235
236 return NULL;
237 }
238
spell_by_index(int index)239 const struct class_spell *spell_by_index(int index)
240 {
241 int book = 0, count = 0;
242 const struct class_magic *magic = &player->class->magic;
243
244 /* Check index validity */
245 if (index < 0 || index >= magic->total_spells)
246 return NULL;
247
248 /* Find the book, count the spells in previous books */
249 while (count + magic->books[book].num_spells - 1 < index)
250 count += magic->books[book++].num_spells;
251
252 /* Find the spell */
253 return &magic->books[book].spells[index - count];
254 }
255
256 /**
257 * Collect spells from a book into the spells[] array, allocating
258 * appropriate memory.
259 */
spell_collect_from_book(const struct object * obj,int ** spells)260 int spell_collect_from_book(const struct object *obj, int **spells)
261 {
262 const struct class_book *book = player_object_to_book(player, obj);
263 int i, n_spells = 0;
264
265 if (!book) {
266 return n_spells;
267 }
268
269 /* Count the spells */
270 for (i = 0; i < book->num_spells; i++)
271 n_spells++;
272
273 /* Allocate the array */
274 *spells = mem_zalloc(n_spells * sizeof(*spells));
275
276 /* Write the spells */
277 for (i = 0; i < book->num_spells; i++)
278 (*spells)[i] = book->spells[i].sidx;
279
280 return n_spells;
281 }
282
283
284 /**
285 * Return the number of castable spells in the spellbook 'obj'.
286 */
spell_book_count_spells(const struct object * obj,bool (* tester)(int spell))287 int spell_book_count_spells(const struct object *obj,
288 bool (*tester)(int spell))
289 {
290 const struct class_book *book = player_object_to_book(player, obj);
291 int i, n_spells = 0;
292
293 if (!book) {
294 return n_spells;
295 }
296
297 for (i = 0; i < book->num_spells; i++)
298 if (tester(book->spells[i].sidx))
299 n_spells++;
300
301 return n_spells;
302 }
303
304
305 /**
306 * True if at least one spell in spells[] is OK according to spell_test.
307 */
spell_okay_list(bool (* spell_test)(int spell),const int spells[],int n_spells)308 bool spell_okay_list(bool (*spell_test)(int spell),
309 const int spells[], int n_spells)
310 {
311 int i;
312 bool okay = false;
313
314 for (i = 0; i < n_spells; i++)
315 if (spell_test(spells[i]))
316 okay = true;
317
318 return okay;
319 }
320
321 /**
322 * True if the spell is castable.
323 */
spell_okay_to_cast(int spell)324 bool spell_okay_to_cast(int spell)
325 {
326 return (player->spell_flags[spell] & PY_SPELL_LEARNED);
327 }
328
329 /**
330 * True if the spell can be studied.
331 */
spell_okay_to_study(int spell_index)332 bool spell_okay_to_study(int spell_index)
333 {
334 const struct class_spell *spell = spell_by_index(spell_index);
335 if (!spell) return false;
336 return (spell->slevel <= player->lev) &&
337 !(player->spell_flags[spell_index] & PY_SPELL_LEARNED);
338 }
339
340 /**
341 * True if the spell is browsable.
342 */
spell_okay_to_browse(int spell_index)343 bool spell_okay_to_browse(int spell_index)
344 {
345 const struct class_spell *spell = spell_by_index(spell_index);
346 if (!spell) return false;
347 return (spell->slevel < 99);
348 }
349
350 /**
351 * Spell failure adjustment by casting stat level
352 */
fail_adjust(struct player * p,const struct class_spell * spell)353 static int fail_adjust(struct player *p, const struct class_spell *spell)
354 {
355 int stat = spell->realm->stat;
356 return adj_mag_stat[p->state.stat_ind[stat]];
357 }
358
359 /**
360 * Spell minimum failure by casting stat level
361 */
min_fail(struct player * p,const struct class_spell * spell)362 static int min_fail(struct player *p, const struct class_spell *spell)
363 {
364 int stat = spell->realm->stat;
365 return adj_mag_fail[p->state.stat_ind[stat]];
366 }
367
368 /**
369 * Returns chance of failure for a spell
370 */
spell_chance(int spell_index)371 s16b spell_chance(int spell_index)
372 {
373 int chance = 100, minfail;
374
375 const struct class_spell *spell;
376
377 /* Paranoia -- must be literate */
378 if (!player->class->magic.total_spells) return chance;
379
380 /* Get the spell */
381 spell = spell_by_index(spell_index);
382 if (!spell) return chance;
383
384 /* Extract the base spell failure rate */
385 chance = spell->sfail;
386
387 /* Reduce failure rate by "effective" level adjustment */
388 chance -= 3 * (player->lev - spell->slevel);
389
390 /* Reduce failure rate by casting stat level adjustment */
391 chance -= fail_adjust(player, spell);
392
393 /* Not enough mana to cast */
394 if (spell->smana > player->csp)
395 chance += 5 * (spell->smana - player->csp);
396
397 /* Get the minimum failure rate for the casting stat level */
398 minfail = min_fail(player, spell);
399
400 /* Non zero-fail characters never get better than 5 percent */
401 if (!player_has(player, PF_ZERO_FAIL) && minfail < 5) {
402 minfail = 5;
403 }
404
405 /* Necromancers are punished by being on lit squares */
406 if (player_has(player, PF_UNLIGHT) && square_islit(cave, player->grid)) {
407 chance += 25;
408 }
409
410 /* Fear makes spells harder (before minfail) */
411 /* Note that spells that remove fear have a much lower fail rate than
412 * surrounding spells, to make sure this doesn't cause mega fail */
413 if (player_of_has(player, OF_AFRAID)) chance += 20;
414
415 /* Minimal and maximal failure rate */
416 if (chance < minfail) chance = minfail;
417 if (chance > 50) chance = 50;
418
419 /* Stunning makes spells harder (after minfail) */
420 if (player->timed[TMD_STUN] > 50) {
421 chance += 25;
422 } else if (player->timed[TMD_STUN]) {
423 chance += 15;
424 }
425
426 /* Amnesia makes spells very difficult */
427 if (player->timed[TMD_AMNESIA]) {
428 chance = 50 + chance / 2;
429 }
430
431 /* Always a 5 percent chance of working */
432 if (chance > 95) {
433 chance = 95;
434 }
435
436 /* Return the chance */
437 return (chance);
438 }
439
440
441 /**
442 * Learn the specified spell.
443 */
spell_learn(int spell_index)444 void spell_learn(int spell_index)
445 {
446 int i;
447 const struct class_spell *spell = spell_by_index(spell_index);
448
449 /* Learn the spell */
450 player->spell_flags[spell_index] |= PY_SPELL_LEARNED;
451
452 /* Find the next open entry in "spell_order[]" */
453 for (i = 0; i < player->class->magic.total_spells; i++)
454 if (player->spell_order[i] == 99) break;
455
456 /* Add the spell to the known list */
457 player->spell_order[i] = spell_index;
458
459 /* Mention the result */
460 msgt(MSG_STUDY, "You have learned the %s of %s.", spell->realm->spell_noun,
461 spell->name);
462
463 /* One less spell available */
464 player->upkeep->new_spells--;
465
466 /* Message if needed */
467 if (player->upkeep->new_spells)
468 msg("You can learn %d more %s%s.", player->upkeep->new_spells,
469 spell->realm->spell_noun, PLURAL(player->upkeep->new_spells));
470
471 /* Redraw Study Status */
472 player->upkeep->redraw |= (PR_STUDY | PR_OBJECT);
473 }
474
beam_chance(void)475 static int beam_chance(void)
476 {
477 int plev = player->lev;
478 return (player_has(player, PF_BEAM) ? plev : (plev / 2));
479 }
480
481 /**
482 * Cast the specified spell
483 */
spell_cast(int spell_index,int dir,struct command * cmd)484 bool spell_cast(int spell_index, int dir, struct command *cmd)
485 {
486 int chance;
487 bool *ident = mem_zalloc(sizeof(*ident));
488 int beam = beam_chance();
489
490 /* Get the spell */
491 const struct class_spell *spell = spell_by_index(spell_index);
492
493 /* Spell failure chance */
494 chance = spell_chance(spell_index);
495
496 /* Fail or succeed */
497 if (randint0(100) < chance) {
498 event_signal(EVENT_INPUT_FLUSH);
499 msg("You failed to concentrate hard enough!");
500 } else {
501 /* Cast the spell */
502 if (!effect_do(spell->effect, source_player(), NULL, ident, true, dir,
503 beam, 0, cmd)) {
504 mem_free(ident);
505 return false;
506 }
507
508 /* Reward COMBAT_REGEN with small HP recovery */
509 if (player_has(player, PF_COMBAT_REGEN)) {
510 convert_mana_to_hp(player, spell->smana << 16);
511 }
512
513 /* A spell was cast */
514 sound(MSG_SPELL);
515
516 if (!(player->spell_flags[spell_index] & PY_SPELL_WORKED)) {
517 int e = spell->sexp;
518
519 /* The spell worked */
520 player->spell_flags[spell_index] |= PY_SPELL_WORKED;
521
522 /* Gain experience */
523 player_exp_gain(player, e * spell->slevel);
524
525 /* Redraw object recall */
526 player->upkeep->redraw |= (PR_OBJECT);
527 }
528 }
529
530 /* Sufficient mana? */
531 if (spell->smana <= player->csp) {
532 /* Use some mana */
533 player->csp -= spell->smana;
534 } else {
535 int oops = spell->smana - player->csp;
536
537 /* No mana left */
538 player->csp = 0;
539 player->csp_frac = 0;
540
541 /* Over-exert the player */
542 player_over_exert(player, PY_EXERT_FAINT, 100, 5 * oops + 1);
543 player_over_exert(player, PY_EXERT_CON, 50, 0);
544 }
545
546 /* Redraw mana */
547 player->upkeep->redraw |= (PR_MANA);
548
549 mem_free(ident);
550 return true;
551 }
552
553
spell_needs_aim(int spell_index)554 bool spell_needs_aim(int spell_index)
555 {
556 const struct class_spell *spell = spell_by_index(spell_index);
557 assert(spell);
558 return effect_aim(spell->effect);
559 }
560
append_random_value_string(char * buffer,size_t size,random_value * rv)561 static size_t append_random_value_string(char *buffer, size_t size,
562 random_value *rv)
563 {
564 size_t offset = 0;
565
566 if (rv->base > 0) {
567 offset += strnfmt(buffer + offset, size - offset, "%d", rv->base);
568
569 if (rv->dice > 0 && rv->sides > 0) {
570 offset += strnfmt(buffer + offset, size - offset, "+");
571 }
572 }
573
574 if (rv->dice == 1 && rv->sides > 0) {
575 offset += strnfmt(buffer + offset, size - offset, "d%d", rv->sides);
576 } else if (rv->dice > 1 && rv->sides > 0) {
577 offset += strnfmt(buffer + offset, size - offset, "%dd%d", rv->dice,
578 rv->sides);
579 }
580
581 return offset;
582 }
583
spell_effect_append_value_info(const struct effect * effect,char * p,size_t len)584 static void spell_effect_append_value_info(const struct effect *effect,
585 char *p, size_t len)
586 {
587 random_value rv;
588 const char *type = NULL;
589 const char *special = NULL;
590 size_t offset = strlen(p);
591
592 type = effect_info(effect);
593
594 if (effect->dice != NULL)
595 dice_roll(effect->dice, &rv);
596
597 /* Handle some special cases where we want to append some additional info */
598 switch (effect->index) {
599 case EF_HEAL_HP:
600 /* Append percentage only, as the fixed value is always displayed */
601 if (rv.m_bonus) special = format("/%d%%", rv.m_bonus);
602 break;
603 case EF_TELEPORT:
604 /* m_bonus means it's a weird random thing */
605 if (rv.m_bonus) special = "random";
606 break;
607 case EF_SPHERE:
608 /* Append radius */
609 if (effect->radius) {
610 int rad = effect->radius;
611 special = format(", rad %d", rad);
612 } else {
613 special = ", rad 2";
614 }
615 break;
616 case EF_BALL:
617 /* Append radius */
618 if (effect->radius) {
619 int rad = effect->radius;
620 if (effect->other) {
621 rad += player->lev / effect->other;
622 }
623 special = format(", rad %d", rad);
624 } else {
625 special = "rad 2";
626 }
627 break;
628 case EF_STRIKE:
629 /* Append radius */
630 if (effect->radius) {
631 special = format(", rad %d", effect->radius);
632 }
633 break;
634 case EF_SHORT_BEAM: {
635 /* Append length of beam */
636 int len = effect->radius;
637 if (effect->other) {
638 len += player->lev / effect->other;
639 }
640 special = format(", len %d", len);
641 break;
642 }
643 case EF_SWARM:
644 /* Append number of projectiles. */
645 special = format("x%d", rv.m_bonus);
646 break;
647 default:
648 break;
649 }
650
651 if (type == NULL)
652 return;
653
654 if (offset) {
655 offset += strnfmt(p + offset, len - offset, ";");
656 }
657
658 if ((rv.base > 0) || (rv.dice > 0 && rv.sides > 0)) {
659 offset += strnfmt(p + offset, len - offset, " %s ", type);
660 offset += append_random_value_string(p + offset, len - offset, &rv);
661
662 if (special != NULL)
663 strnfmt(p + offset, len - offset, "%s", special);
664 }
665 }
666
get_spell_info(int spell_index,char * p,size_t len)667 void get_spell_info(int spell_index, char *p, size_t len)
668 {
669 struct effect *effect = spell_by_index(spell_index)->effect;
670
671 p[0] = '\0';
672
673 while (effect) {
674 spell_effect_append_value_info(effect, p, len);
675 effect = effect->next;
676 }
677 }
678
spell_value_base_spell_power(void)679 static int spell_value_base_spell_power(void)
680 {
681 int power = 0;
682
683 /* Check the reference race first */
684 if (ref_race)
685 power = ref_race->spell_power;
686 /* Otherwise the current monster if there is one */
687 else if (cave->mon_current > 0)
688 power = cave_monster(cave, cave->mon_current)->race->spell_power;
689
690 return power;
691 }
692
spell_value_base_player_level(void)693 static int spell_value_base_player_level(void)
694 {
695 return player->lev;
696 }
697
spell_value_base_dungeon_level(void)698 static int spell_value_base_dungeon_level(void)
699 {
700 return cave->depth;
701 }
702
spell_value_base_max_sight(void)703 static int spell_value_base_max_sight(void)
704 {
705 return z_info->max_sight;
706 }
707
spell_value_base_weapon_damage(void)708 static int spell_value_base_weapon_damage(void)
709 {
710 struct object *obj = player->body.slots[slot_by_name(player, "weapon")].obj;
711 if (!obj) {
712 return 0;
713 }
714 return (damroll(obj->dd, obj->ds) + obj->to_d);
715 }
716
spell_value_base_player_hp(void)717 static int spell_value_base_player_hp(void)
718 {
719 return player->chp;
720 }
721
spell_value_base_monster_percent_hp_gone(void)722 static int spell_value_base_monster_percent_hp_gone(void)
723 {
724 /* Get the targeted monster, fail horribly if none */
725 struct monster *mon = target_get_monster();
726
727 return mon ? (((mon->maxhp - mon->hp) * 100) / mon->maxhp) : 0;
728 }
729
spell_value_base_by_name(const char * name)730 expression_base_value_f spell_value_base_by_name(const char *name)
731 {
732 static const struct value_base_s {
733 const char *name;
734 expression_base_value_f function;
735 } value_bases[] = {
736 { "SPELL_POWER", spell_value_base_spell_power },
737 { "PLAYER_LEVEL", spell_value_base_player_level },
738 { "DUNGEON_LEVEL", spell_value_base_dungeon_level },
739 { "MAX_SIGHT", spell_value_base_max_sight },
740 { "WEAPON_DAMAGE", spell_value_base_weapon_damage },
741 { "PLAYER_HP", spell_value_base_player_hp },
742 { "MONSTER_PERCENT_HP_GONE", spell_value_base_monster_percent_hp_gone },
743 { NULL, NULL },
744 };
745 const struct value_base_s *current = value_bases;
746
747 while (current->name != NULL && current->function != NULL) {
748 if (my_stricmp(name, current->name) == 0)
749 return current->function;
750
751 current++;
752 }
753
754 return NULL;
755 }
756