1 /**
2 * \file mon-spell.c
3 * \brief Monster spell casting and selection
4 *
5 * Copyright (c) 2010-14 Chris Carr and Nick McConnell
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 #include "angband.h"
19 #include "effects.h"
20 #include "init.h"
21 #include "mon-attack.h"
22 #include "mon-desc.h"
23 #include "mon-lore.h"
24 #include "mon-make.h"
25 #include "mon-predicate.h"
26 #include "mon-spell.h"
27 #include "mon-timed.h"
28 #include "mon-util.h"
29 #include "obj-knowledge.h"
30 #include "player-timed.h"
31 #include "player-util.h"
32 #include "project.h"
33
34 /**
35 * ------------------------------------------------------------------------
36 * Spell casting
37 * ------------------------------------------------------------------------ */
38 typedef enum {
39 SPELL_TAG_NONE,
40 SPELL_TAG_NAME,
41 SPELL_TAG_PRONOUN,
42 SPELL_TAG_TARGET,
43 SPELL_TAG_TYPE,
44 SPELL_TAG_OF_TYPE
45 } spell_tag_t;
46
spell_tag_lookup(const char * tag)47 static spell_tag_t spell_tag_lookup(const char *tag)
48 {
49 if (strncmp(tag, "name", 4) == 0)
50 return SPELL_TAG_NAME;
51 else if (strncmp(tag, "pronoun", 7) == 0)
52 return SPELL_TAG_PRONOUN;
53 else if (strncmp(tag, "target", 6) == 0)
54 return SPELL_TAG_TARGET;
55 else if (strncmp(tag, "type", 4) == 0)
56 return SPELL_TAG_TYPE;
57 else if (strncmp(tag, "oftype", 6) == 0)
58 return SPELL_TAG_OF_TYPE;
59 else
60 return SPELL_TAG_NONE;
61 }
62
63 /**
64 * Print a monster spell message.
65 *
66 * We fill in the monster name and/or pronoun where necessary in
67 * the message to replace instances of {name} or {pronoun}.
68 */
spell_message(struct monster * mon,const struct monster_spell * spell,bool seen,bool hits)69 static void spell_message(struct monster *mon,
70 const struct monster_spell *spell,
71 bool seen, bool hits)
72 {
73 char buf[1024] = "\0";
74 const char *next;
75 const char *s;
76 const char *tag;
77 const char *in_cursor;
78 size_t end = 0;
79 struct monster_spell_level *level = spell->level;
80 struct monster *t_mon = NULL;
81
82 /* Get the right level of message */
83 while (level->next && mon->race->spell_power >= level->next->power) {
84 level = level->next;
85 }
86
87 /* Get the target monster, if any */
88 if (mon->target.midx > 0) {
89 t_mon = cave_monster(cave, mon->target.midx);
90 }
91
92 /* Get the message */
93 if (!seen) {
94 if (t_mon) {
95 return;
96 } else {
97 in_cursor = level->blind_message;
98 }
99 } else if (!hits) {
100 in_cursor = level->miss_message;
101 } else {
102 in_cursor = level->message;
103 }
104
105 next = strchr(in_cursor, '{');
106 while (next) {
107 /* Copy the text leading up to this { */
108 strnfcat(buf, 1024, &end, "%.*s", next - in_cursor, in_cursor);
109
110 s = next + 1;
111 while (*s && isalpha((unsigned char) *s)) s++;
112
113 /* Valid tag */
114 if (*s == '}') {
115 /* Start the tag after the { */
116 tag = next + 1;
117 in_cursor = s + 1;
118
119 switch (spell_tag_lookup(tag)) {
120 case SPELL_TAG_NAME: {
121 char m_name[80];
122 monster_desc(m_name, sizeof(m_name), mon, MDESC_STANDARD);
123
124 strnfcat(buf, sizeof(buf), &end, m_name);
125 break;
126 }
127
128 case SPELL_TAG_PRONOUN: {
129 char m_poss[80];
130
131 /* Get the monster possessive ("his"/"her"/"its") */
132 monster_desc(m_poss, sizeof(m_poss), mon, MDESC_PRO_VIS | MDESC_POSS);
133
134 strnfcat(buf, sizeof(buf), &end, m_poss);
135 break;
136 }
137
138 case SPELL_TAG_TARGET: {
139 char m_name[80];
140 struct monster *t_mon;
141 if (mon->target.midx > 0) {
142 t_mon = cave_monster(cave, mon->target.midx);
143 monster_desc(m_name, sizeof(m_name), t_mon, MDESC_TARG);
144 strnfcat(buf, sizeof(buf), &end, m_name);
145 } else {
146 strnfcat(buf, sizeof(buf), &end, "you");
147 }
148 break;
149 }
150
151 case SPELL_TAG_TYPE: {
152 /* Get the attack type (assuming lash) */
153 int type = mon->race->blow[0].effect->lash_type;
154 char *type_name = projections[type].lash_desc;
155
156 strnfcat(buf, sizeof(buf), &end, type_name);
157 break;
158 }
159
160 case SPELL_TAG_OF_TYPE: {
161 /* Get the attack type (assuming lash) */
162 int type = mon->race->blow[0].effect->lash_type;
163 char *type_name = projections[type].lash_desc;
164
165 if (type_name) {
166 strnfcat(buf, sizeof(buf), &end, " of ");
167 strnfcat(buf, sizeof(buf), &end, type_name);
168 }
169 break;
170 }
171
172 default: {
173 break;
174 }
175 }
176 } else {
177 /* An invalid tag, skip it */
178 in_cursor = next + 1;
179 }
180
181 next = strchr(in_cursor, '{');
182 }
183 strnfcat(buf, 1024, &end, in_cursor);
184
185 msgt(spell->msgt, "%s", buf);
186 }
187
monster_spell_by_index(int index)188 const struct monster_spell *monster_spell_by_index(int index)
189 {
190 const struct monster_spell *spell = monster_spells;
191 while (spell) {
192 if (spell->index == index)
193 break;
194 spell = spell->next;
195 }
196 return spell;
197 }
198
199 /**
200 * Check if a spell effect which has been saved against would also have
201 * been prevented by an object property, and learn the appropriate rune
202 */
spell_check_for_fail_rune(const struct monster_spell * spell)203 static void spell_check_for_fail_rune(const struct monster_spell *spell)
204 {
205 struct effect *effect = spell->effect;
206 while (effect) {
207 if (effect->index == EF_TELEPORT_LEVEL) {
208 /* Special case - teleport level */
209 equip_learn_element(player, ELEM_NEXUS);
210 } else if (effect->index == EF_TIMED_INC) {
211 /* Timed effects */
212 (void) player_inc_check(player, effect->subtype, false);
213 }
214 effect = effect->next;
215 }
216 }
217
218 /**
219 * Process a monster spell
220 *
221 * \param index is the monster spell flag (RSF_FOO)
222 * \param mon is the attacking monster
223 * \param seen is whether the player can see the monster at this moment
224 */
do_mon_spell(int index,struct monster * mon,bool seen)225 void do_mon_spell(int index, struct monster *mon, bool seen)
226 {
227 const struct monster_spell *spell = monster_spell_by_index(index);
228
229 bool ident = false;
230 bool hits;
231 int target_mon = mon->target.midx;
232
233 /* See if it hits */
234 if (spell->hit == 100) {
235 hits = true;
236 } else if (spell->hit == 0) {
237 hits = false;
238 } else {
239 int rlev = MAX(mon->race->level, 1);
240 int conf_level = monster_effect_level(mon, MON_TMD_CONF);
241 int accuracy = 100;
242 while (conf_level) {
243 accuracy *= (100 - CONF_HIT_REDUCTION);
244 accuracy /= 100;
245 conf_level--;
246 }
247 if (target_mon > 0) {
248 hits = check_hit_monster(cave_monster(cave, target_mon),
249 spell->hit, rlev, accuracy);
250 } else {
251 hits = check_hit(player, spell->hit, rlev, accuracy);
252 }
253 }
254
255 /* Tell the player what's going on */
256 disturb(player);
257 spell_message(mon, spell, seen, hits);
258
259 if (hits) {
260 struct monster_spell_level *level = spell->level;
261
262 /* Get the right level of save message */
263 while (level->next && mon->race->spell_power >= level->next->power) {
264 level = level->next;
265 }
266
267 /* Try a saving throw if available */
268 if (level->save_message && (target_mon <= 0) &&
269 randint0(100) < player->state.skills[SKILL_SAVE]) {
270 msg("%s", level->save_message);
271 spell_check_for_fail_rune(spell);
272 } else {
273 effect_do(spell->effect, source_monster(mon->midx), NULL, &ident, true, 0, 0, 0, NULL);
274 }
275 }
276 }
277
278 /**
279 * ------------------------------------------------------------------------
280 * Spell selection
281 * ------------------------------------------------------------------------ */
282 /**
283 * Types of monster spells used for spell selection.
284 */
285 static const struct mon_spell_info {
286 u16b index; /* Numerical index (RSF_FOO) */
287 int type; /* Type bitflag */
288 } mon_spell_types[] = {
289 #define RSF(a, b) { RSF_##a, b },
290 #include "list-mon-spells.h"
291 #undef RSF
292 };
293
294
mon_spell_is_valid(int index)295 static bool mon_spell_is_valid(int index)
296 {
297 return index > RSF_NONE && index < RSF_MAX;
298 }
299
monster_spell_is_breath(int index)300 static bool monster_spell_is_breath(int index)
301 {
302 return (mon_spell_types[index].type & RST_BREATH) ? true : false;
303 }
304
mon_spell_has_damage(int index)305 static bool mon_spell_has_damage(int index)
306 {
307 return (mon_spell_types[index].type & RST_DAMAGE) ? true : false;
308 }
309
mon_spell_is_innate(int index)310 bool mon_spell_is_innate(int index)
311 {
312 return mon_spell_types[index].type & (RST_INNATE);
313 }
314
315 /**
316 * Test a spell bitflag for a type of spell.
317 * Returns true if any desired type is among the flagset
318 *
319 * \param f is the set of spell flags we're testing
320 * \param types is the spell type(s) we're looking for
321 */
test_spells(bitflag * f,int types)322 bool test_spells(bitflag *f, int types)
323 {
324 const struct mon_spell_info *info;
325
326 for (info = mon_spell_types; info->index < RSF_MAX; info++)
327 if (rsf_has(f, info->index) && (info->type & types))
328 return true;
329
330 return false;
331 }
332
333 /**
334 * Set a spell bitflag to ignore a specific set of spell types.
335 *
336 * \param f is the set of spell flags we're pruning
337 * \param types is the spell type(s) we're ignoring
338 */
ignore_spells(bitflag * f,int types)339 void ignore_spells(bitflag *f, int types)
340 {
341 const struct mon_spell_info *info;
342
343 for (info = mon_spell_types; info->index < RSF_MAX; info++)
344 if (rsf_has(f, info->index) && (info->type & types))
345 rsf_off(f, info->index);
346 }
347
348 /**
349 * Turn off spells with a side effect or a proj_type that is resisted by
350 * something in flags, subject to intelligence and chance.
351 *
352 * \param spells is the set of spells we're pruning
353 * \param flags is the set of object flags we're testing
354 * \param pflags is the set of player flags we're testing
355 * \param el is what we know about the player's elemental resists
356 * \param race is the monster type we're operating on
357 */
unset_spells(bitflag * spells,bitflag * flags,bitflag * pflags,struct element_info * el,const struct monster * mon)358 void unset_spells(bitflag *spells, bitflag *flags, bitflag *pflags,
359 struct element_info *el, const struct monster *mon)
360 {
361 const struct mon_spell_info *info;
362 bool smart = monster_is_smart(mon);
363
364 for (info = mon_spell_types; info->index < RSF_MAX; info++) {
365 const struct monster_spell *spell = monster_spell_by_index(info->index);
366 const struct effect *effect;
367
368 /* Ignore missing spells */
369 if (!spell) continue;
370 if (!rsf_has(spells, info->index)) continue;
371
372 /* Get the effect */
373 effect = spell->effect;
374
375 /* First we test the elemental spells */
376 if (info->type & (RST_BOLT | RST_BALL | RST_BREATH)) {
377 int element = effect->subtype;
378 int learn_chance = el[element].res_level * (smart ? 50 : 25);
379 if (randint0(100) < learn_chance) {
380 rsf_off(spells, info->index);
381 }
382 } else {
383 /* Now others with resisted effects */
384 while (effect) {
385 /* Timed effects */
386 if ((smart || !one_in_(3)) &&
387 effect->index == EF_TIMED_INC &&
388 of_has(flags, timed_effects[effect->subtype].fail))
389 break;
390
391 /* Mana drain */
392 if ((smart || one_in_(2)) &&
393 effect->index == EF_DRAIN_MANA &&
394 pf_has(pflags, PF_NO_MANA))
395 break;
396
397 effect = effect->next;
398 }
399 if (effect)
400 rsf_off(spells, info->index);
401 }
402 }
403 }
404
405 /**
406 * Determine the damage of a spell attack which ignores monster hp
407 * (i.e. bolts and balls, including arrows/boulders/storms/etc.)
408 *
409 * \param spell is the attack type
410 * \param race is the monster race of the attacker
411 * \param dam_aspect is the damage calc required (min, avg, max, random)
412 */
nonhp_dam(const struct monster_spell * spell,const struct monster_race * race,aspect dam_aspect)413 static int nonhp_dam(const struct monster_spell *spell,
414 const struct monster_race *race, aspect dam_aspect)
415 {
416 int dam = 0;
417 struct effect *effect = spell->effect;
418
419 /* Set the reference race for calculations */
420 ref_race = race;
421
422 /* Now add the damage for each effect */
423 while (effect) {
424 random_value rand;
425 /* Lash needs special treatment bacause it depends on monster blows */
426 if (effect->index == EF_LASH) {
427 int i;
428
429 /* Scan through all blows for damage */
430 for (i = 0; i < z_info->mon_blows_max; i++) {
431 /* Extract the attack infomation */
432 random_value dice = race->blow[i].dice;
433
434 /* Full damage of first blow, plus half damage of others */
435 dam += randcalc(dice, race->level, dam_aspect) / (i ? 2 : 1);
436 }
437 } else if (effect->dice && (effect->index != EF_TIMED_INC)) {
438 /* Timed effects increases don't count as damage in lore */
439 dice_roll(effect->dice, &rand);
440 dam += randcalc(rand, 0, dam_aspect);
441 }
442 effect = effect->next;
443 }
444
445 ref_race = NULL;
446
447 return dam;
448 }
449
450 /**
451 * Determine the damage of a monster breath attack
452 *
453 * \param type is the attack element type
454 * \param hp is the monster's hp
455 */
breath_dam(int type,int hp)456 int breath_dam(int type, int hp)
457 {
458 struct projection *element = &projections[type];
459 int dam;
460
461 /* Damage is based on monster's current hp */
462 dam = hp / element->divisor;
463
464 /* Check for maximum damage */
465 if (dam > element->damage_cap)
466 dam = element->damage_cap;
467
468 return dam;
469 }
470
471 /**
472 * Calculate the damage of a monster spell.
473 *
474 * \param index is the index of the spell in question.
475 * \param hp is the hp of the casting monster.
476 * \param race is the race of the casting monster.
477 * \param dam_aspect is the damage calc we want (min, max, avg, random).
478 */
mon_spell_dam(int index,int hp,const struct monster_race * race,aspect dam_aspect)479 static int mon_spell_dam(int index, int hp, const struct monster_race *race,
480 aspect dam_aspect)
481 {
482 const struct monster_spell *spell = monster_spell_by_index(index);
483
484 if (monster_spell_is_breath(index))
485 return breath_dam(spell->effect->subtype, hp);
486 else
487 return nonhp_dam(spell, race, dam_aspect);
488 }
489
490
491 /**
492 * Create a mask of monster spell flags of a specific type.
493 *
494 * \param f is the flag array we're filling
495 * \param ... is the list of flags we're looking for
496 *
497 * N.B. RST_NONE must be the last item in the ... list
498 */
create_mon_spell_mask(bitflag * f,...)499 void create_mon_spell_mask(bitflag *f, ...)
500 {
501 const struct mon_spell_info *rs;
502 int i;
503 va_list args;
504
505 rsf_wipe(f);
506
507 va_start(args, f);
508
509 /* Process each type in the va_args */
510 for (i = va_arg(args, int); i != RST_NONE; i = va_arg(args, int)) {
511 for (rs = mon_spell_types; rs->index < RSF_MAX; rs++) {
512 if (rs->type & i) {
513 rsf_on(f, rs->index);
514 }
515 }
516 }
517
518 va_end(args);
519
520 return;
521 }
522
mon_spell_lore_description(int index,const struct monster_race * race)523 const char *mon_spell_lore_description(int index,
524 const struct monster_race *race)
525 {
526 if (mon_spell_is_valid(index)) {
527 const struct monster_spell *spell = monster_spell_by_index(index);
528
529 /* Get the right level of description */
530 struct monster_spell_level *level = spell->level;
531 while (level->next && race->spell_power >= level->next->power) {
532 level = level->next;
533 }
534 return level->lore_desc;
535 } else {
536 return "";
537 }
538 }
539
mon_spell_lore_damage(int index,const struct monster_race * race,bool know_hp)540 int mon_spell_lore_damage(int index, const struct monster_race *race,
541 bool know_hp)
542 {
543 if (mon_spell_is_valid(index) && mon_spell_has_damage(index)) {
544 int hp = know_hp ? race->avg_hp : 0;
545 return mon_spell_dam(index, hp, race, MAXIMISE);
546 } else {
547 return 0;
548 }
549 }
550