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