1 /*
2  *  File:       mon-util.cc
3  *  Summary:    Misc monster related functions.
4  *  Written by: Linley Henzell
5  *
6  *  Change History (most recent first):
7  *
8  *   <2>    11/04/99        cdl     added a break to spell selection
9  *                                  for kobold Summoners
10  *                                  print just "[Ii]t" for invisible undead
11  *                                  renamed params to monam()
12  *   <1>     -/--/--        LRH     Created
13  */
14 
15 // $pellbinder: (c) D.G.S.E 1998
16 // some routines snatched from former monsstat.cc
17 
18 #include "AppHdr.h"
19 #include "mon-util.h"
20 #include "monstuff.h"
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 
27 #include "externs.h"
28 
29 #include "debug.h"
30 #include "itemname.h"
31 #include "mstuff2.h"
32 #include "player.h"
33 #include "randart.h"
34 #include "stuff.h"
35 #include "view.h"
36 
37 //jmf: moved from inside function
38 static FixedVector < int, NUM_MONSTERS > mon_entry;
39 
40 // really important extern -- screen redraws suck w/o it {dlb}
41 FixedVector < unsigned short, 1000 > mcolour;
42 
43 static struct monsterentry mondata[] = {
44 #include "mon-data.h"
45 };
46 
47 #define MONDATASIZE (sizeof(mondata)/sizeof(struct monsterentry))
48 
49 static int mspell_list[][7] = {
50 #include "mon-spll.h"
51 };
52 
53 #if DEBUG_DIAGNOSTICS
54 static const char *monster_spell_name[] = {
55     "Magic Missile",
56     "Throw Flame",
57     "Throw Frost",
58     "Paralysis",
59     "Slow",
60     "Haste",
61     "Confuse",
62     "Venom Bolt",
63     "Fire Bolt",
64     "Cold Bolt",
65     "Lightning Bolt",
66     "Invisibility",
67     "Fireball",
68     "Heal",
69     "Teleport",
70     "Teleport Other",
71     "Blink",
72     "Crystal Spear",
73     "Dig",
74     "Negative Bolt",
75     "Hellfire Burst",
76     "Vampire Summon",
77     "Orb Energy",
78     "Brain Feed",
79     "Level Summon",
80     "Fake Rakshasa Summon",
81     "Steam Ball",
82     "Summon Demon",
83     "Animate Dead",
84     "Pain",
85     "Smite",
86     "Sticky Flame",
87     "Poison Blast",
88     "Summon Demon Lesser",
89     "Summon Ufetubus",
90     "Purple Blast",
91     "Summon Beast",
92     "Energy Bolt",
93     "Sting",
94     "Iron Bolt",
95     "Stone Arrow",
96     "Poison Splash",
97     "Summon Undead",
98     "Mutation",
99     "Cantrip",
100     "Disintegrate",
101     "Marsh Gas",
102     "Quicksilver Bolt",
103     "Torment",
104     "Hellfire",
105     "Metal Splinters",
106     "Summon Demon Greater",
107     "Banishment",
108 };
109 #endif
110 
111 static int mons_exp_mod(int mclass);
112 static monsterentry *seekmonster(int *p_monsterid);
113 
114 // macro that saves some typing, nothing more
115 #define smc seekmonster(&mc)
116 
117 /* ******************** BEGIN PUBLIC FUNCTIONS ******************** */
mons_init(FixedVector<unsigned short,1000> & colour)118 void mons_init(FixedVector < unsigned short, 1000 > &colour)
119 {
120     unsigned int x;             // must be unsigned to match size_t {dlb}
121 
122     for (x = 0; x < MONDATASIZE; x++)
123         colour[mondata[x].mc] = mondata[x].colour;
124 
125     //unsigned int x = 0;    // must be unsigned to match size_t {dlb}
126 
127     // first, fill static array with dummy values {dlb};
128     for (x = 0; x < NUM_MONSTERS; x++)
129         mon_entry[x] = -1;
130 
131     // next, fill static array with location of entry in mondata[] {dlb}:
132     for (x = 0; x < MONDATASIZE; x++)
133         mon_entry[mondata[x].mc] = x;
134 
135     // finally, monsters yet with dummy entries point to TTTSNB(tm) {dlb}:
136     for (x = 0; x < NUM_MONSTERS; x++)
137     {
138         if (mon_entry[x] == -1)
139             mon_entry[x] = mon_entry[MONS_PROGRAM_BUG];
140     }
141     //return (monsterentry *) 0; // return value should not matter here {dlb}
142 }                               // end mons_init()
143 
144 
mons_flag(int mc,int bf)145 int mons_flag(int mc, int bf)
146 {
147     return ((smc->bitfields & bf) != 0);
148 }                               // end mons_flag()
149 
scan_mon_inv_randarts(struct monsters * mon,int ra_prop)150 static int scan_mon_inv_randarts( struct monsters *mon, int ra_prop )
151 {
152     int ret = 0;
153 
154     if (mons_itemuse( mon->type ) >= MONUSE_STARTING_EQUIPMENT)
155     {
156         const int weapon = mon->inv[MSLOT_WEAPON];
157         const int second = mon->inv[MSLOT_MISSILE]; // ettins/two-head oges
158         const int armour = mon->inv[MSLOT_ARMOUR];
159 
160         if (weapon != NON_ITEM && mitm[weapon].base_type == OBJ_WEAPONS
161             && is_random_artefact( mitm[weapon] ))
162         {
163             ret += randart_wpn_property( mitm[weapon], ra_prop );
164         }
165 
166         if (second != NON_ITEM && mitm[second].base_type == OBJ_WEAPONS
167             && is_random_artefact( mitm[second] ))
168         {
169             ret += randart_wpn_property( mitm[second], ra_prop );
170         }
171 
172         if (armour != NON_ITEM && mitm[armour].base_type == OBJ_ARMOUR
173             && is_random_artefact( mitm[armour] ))
174         {
175             ret += randart_wpn_property( mitm[armour], ra_prop );
176         }
177     }
178 
179     return (ret);
180 }
181 
182 
mons_holiness(int mc)183 int mons_holiness(int mc)
184 {
185     return (smc->holiness);
186 }                               // end mons_holiness()
187 
mons_is_mimic(int mc)188 bool mons_is_mimic( int mc )
189 {
190     return (mons_charclass( mc ) == MONS_GOLD_MIMIC);
191 }
192 
mons_is_demon(int mc)193 bool mons_is_demon( int mc )
194 {
195     const int show_char = mons_char( mc );
196 
197     // Not every demonic monster is a demon (ie hell hog, hell hound)
198     if (mons_holiness( mc ) == MH_DEMONIC
199         && (isdigit( show_char ) || show_char == '&'))
200     {
201         return (true);
202     }
203 
204     return (false);
205 }
206 
207 // Used for elven Glamour ability. -- bwr
mons_is_humanoid(int mc)208 bool mons_is_humanoid( int mc )
209 {
210     switch (mons_char( mc))
211     {
212     case 'o':   // orcs
213     case 'e':   // elvens (deep)
214     case 'c':   // centaurs
215     case 'C':   // giants
216     case 'O':   // ogres
217     case 'K':   // kobolds
218     case 'N':   // nagas
219     case '@':   // adventuring humans
220     case 'T':   // trolls
221         return (true);
222 
223     case 'g':   // goblines, hobgoblins, gnolls, boggarts -- but not gargoyles
224         if (mc != MONS_GARGOYLE
225             && mc != MONS_METAL_GARGOYLE
226             && mc != MONS_MOLTEN_GARGOYLE)
227         {
228             return (true);
229         }
230 
231     default:
232         break;
233     }
234 
235     return (false);
236 }
237 
mons_zombie_size(int mc)238 int mons_zombie_size(int mc)
239 {
240     return (smc->zombie_size);
241 }                               // end mons_zombie_size()
242 
243 
mons_weight(int mc)244 int mons_weight(int mc)
245 {
246     return (smc->weight);
247 }                               // end mons_weight()
248 
249 
mons_corpse_thingy(int mc)250 int mons_corpse_thingy(int mc)
251 {
252     return (smc->corpse_thingy);
253 }                               // end mons_corpse_thingy()
254 
255 
mons_charclass(int mc)256 int mons_charclass(int mc)
257 {
258     return (smc->charclass);
259 }                               // end mons_charclass()
260 
261 
mons_shouts(int mc)262 char mons_shouts(int mc)
263 {
264     int u = smc->shouts;
265 
266     if (u == -1)
267         u = random2(12);
268 
269     return (u);
270 }                               // end mons_shouts()
271 
mons_is_unique(int mc)272 bool mons_is_unique( int mc )
273 {
274     if (mc <= MONS_PROGRAM_BUG
275         || (mc >= MONS_NAGA_MAGE && mc <= MONS_ROYAL_JELLY)
276         || (mc >= MONS_ANCIENT_LICH
277             && (mc != MONS_PLAYER_GHOST && mc != MONS_PANDEMONIUM_DEMON)))
278     {
279         return (false);
280     }
281 
282     return (true);
283 }
284 
mons_see_invis(struct monsters * mon)285 char mons_see_invis( struct monsters *mon )
286 {
287     if (mon->type == MONS_PLAYER_GHOST || mon->type == MONS_PANDEMONIUM_DEMON)
288         return (ghost.values[ GVAL_SEE_INVIS ]);
289     else if (((seekmonster(&mon->type))->bitfields & M_SEE_INVIS) != 0)
290         return (1);
291     else if (scan_mon_inv_randarts( mon, RAP_EYESIGHT ) > 0)
292         return (1);
293 
294     return (0);
295 }                               // end mons_see_invis()
296 
297 
298 // This does NOT do line of sight!  It checks the targ's visibility
299 // with respect to mon's perception, but doesn't do walls or range.
mons_monster_visible(struct monsters * mon,struct monsters * targ)300 bool mons_monster_visible( struct monsters *mon, struct monsters *targ )
301 {
302     if (mons_has_ench(targ, ENCH_SUBMERGED)
303         || (mons_has_ench(targ, ENCH_INVIS) && !mons_see_invis(mon)))
304     {
305         return (false);
306     }
307 
308     return (true);
309 }
310 
311 // This does NOT do line of sight!  It checks the player's visibility
312 // with respect to mon's perception, but doesn't do walls or range.
mons_player_visible(struct monsters * mon)313 bool mons_player_visible( struct monsters *mon )
314 {
315     if (you.invis)
316     {
317         if (player_in_water())
318             return (true);
319 
320         if (mons_see_invis( mon ))
321             return (true);
322 
323         return (false);
324     }
325 
326     return (true);
327 }
328 
mons_char(int mc)329 unsigned char mons_char(int mc)
330 {
331     return (unsigned char) smc->showchar;
332 }                               // end mons_char()
333 
334 
mons_itemuse(int mc)335 char mons_itemuse(int mc)
336 {
337     return (smc->gmon_use);
338 }                               // end mons_itemuse()
339 
mons_colour(int mc)340 unsigned char mons_colour(int mc)
341 {
342     return (smc->colour);
343 }                               // end mons_colour()
344 
345 
mons_damage(int mc,int rt)346 int mons_damage(int mc, int rt)
347 {
348     ASSERT(rt >= 0);
349     ASSERT(rt <= 3);
350 
351     if (rt < 0 || rt > 3)       // make it fool-proof
352         return (0);
353 
354     if (rt == 0 && (mc == MONS_PLAYER_GHOST || mc == MONS_PANDEMONIUM_DEMON))
355         return (ghost.values[ GVAL_DAMAGE ]);
356 
357     return (smc->damage[rt]);
358 }                               // end mons_damage()
359 
mons_resist_magic(struct monsters * mon)360 int mons_resist_magic( struct monsters *mon )
361 {
362     int u = (seekmonster(&mon->type))->resist_magic;
363 
364     // negative values get multiplied with mhd
365     if (u < 0)
366         u = mon->hit_dice * (-u * 2);
367 
368     u += scan_mon_inv_randarts( mon, RAP_MAGIC );
369 
370     // ego armour resistance
371     const int armour = mon->inv[MSLOT_ARMOUR];
372 
373     if (armour != NON_ITEM
374         && get_armour_ego_type( mitm[armour] ) == SPARM_MAGIC_RESISTANCE )
375     {
376         u += 30;
377     }
378 
379     return (u);
380 }                               // end mon_resist_magic()
381 
382 
383 // Returns true if the monster made its save against hostile
384 // enchantments/some other magics.
check_mons_resist_magic(struct monsters * monster,int pow)385 bool check_mons_resist_magic( struct monsters *monster, int pow )
386 {
387     int mrs = mons_resist_magic(monster);
388 
389     if (mrs == 5000)
390         return (true);
391 
392     // Evil, evil hack to make weak one hd monsters easier for first
393     // level characters who have resistable 1st level spells. Six is
394     // a very special value because mrs = hd * 2 * 3 for most monsters,
395     // and the weak, low level monsters have been adjusted so that the
396     // "3" is typically a 1.  There are some notable one hd monsters
397     // that shouldn't fall under this, so we do < 6, instead of <= 6...
398     // or checking monster->hit_dice.  The goal here is to make the
399     // first level easier for these classes and give them a better
400     // shot at getting to level two or three and spells that can help
401     // them out (or building a level or two of their base skill so they
402     // aren't resisted as often). -- bwr
403     if (mrs < 6 && coinflip())
404         return (false);
405 
406     pow = stepdown_value( pow, 30, 40, 100, 120 );
407 
408     const int mrchance = (100 + mrs) - pow;
409     const int mrch2 = random2(100) + random2(101);
410 
411 #if DEBUG_DIAGNOSTICS
412     snprintf( info, INFO_SIZE,
413               "Power: %d, monster's MR: %d, target: %d, roll: %d",
414               pow, mrs, mrchance, mrch2 );
415 
416     mpr( info, MSGCH_DIAGNOSTICS );
417 #endif
418 
419     return ((mrch2 < mrchance) ? true : false);
420 }                               // end check_mons_resist_magic()
421 
422 
mons_res_elec(struct monsters * mon)423 int mons_res_elec( struct monsters *mon )
424 {
425     int mc = mon->type;
426 
427     if (mc == MONS_PLAYER_GHOST || mc == MONS_PANDEMONIUM_DEMON)
428         return (ghost.values[ GVAL_RES_ELEC ]);
429 
430     /* this is a variable, not a player_xx() function, so can be above 1 */
431     int u = 0, f = (seekmonster(&mc))->bitfields;
432 
433     // of course it makes no sense setting them both :)
434     if (f & M_RES_ELEC)
435         u++;                    //if(f&M_ED_ELEC) u--;
436 
437     // don't bother checking equipment if the monster can't use it
438     if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
439     {
440         u += scan_mon_inv_randarts( mon, RAP_ELECTRICITY );
441 
442         // no ego armour, but storm dragon.
443         const int armour = mon->inv[MSLOT_ARMOUR];
444         if (armour != NON_ITEM && mitm[armour].base_type == OBJ_ARMOUR
445             && mitm[armour].sub_type == ARM_STORM_DRAGON_ARMOUR)
446         {
447             u += 1;
448         }
449     }
450 
451     return (u);
452 }                               // end mons_res_elec()
453 
454 
mons_res_poison(struct monsters * mon)455 int mons_res_poison( struct monsters *mon )
456 {
457     int mc = mon->type;
458 
459     int u = 0, f = (seekmonster(&mc))->bitfields;
460 
461     if (f & M_RES_POISON)
462         u++;
463 
464     if (f & M_ED_POISON)
465         u--;
466 
467     if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
468     {
469         u += scan_mon_inv_randarts( mon, RAP_POISON );
470 
471         const int armour = mon->inv[MSLOT_ARMOUR];
472         if (armour != NON_ITEM && mitm[armour].base_type == OBJ_ARMOUR)
473         {
474             // intrinsic armour abilities
475             switch (mitm[armour].sub_type)
476             {
477             case ARM_SWAMP_DRAGON_ARMOUR: u += 1; break;
478             case ARM_GOLD_DRAGON_ARMOUR:  u += 1; break;
479             default:                              break;
480             }
481 
482             // ego armour resistance
483             if (get_armour_ego_type( mitm[armour] ) == SPARM_POISON_RESISTANCE)
484                 u += 1;
485         }
486     }
487 
488     return (u);
489 }                               // end mons_res_poison()
490 
491 
mons_res_fire(struct monsters * mon)492 int mons_res_fire( struct monsters *mon )
493 {
494     int mc = mon->type;
495 
496     if (mc == MONS_PLAYER_GHOST || mc == MONS_PANDEMONIUM_DEMON)
497         return (ghost.values[ GVAL_RES_FIRE ]);
498 
499     int u = 0, f = (seekmonster(&mc))->bitfields;
500 
501     // no Big Prize (tm) here either if you set all three flags. It's a pity uh?
502     //
503     // Note that natural monster resistance is two levels, this is duplicate
504     // the fact that having this flag used to be a lot better than armour
505     // for monsters (it used to make them immune in a lot of cases) -- bwr
506     if (f & M_RES_HELLFIRE)
507         u += 3;
508     else if (f & M_RES_FIRE)
509         u += 2;
510     else if (f & M_ED_FIRE)
511         u--;
512 
513     if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
514     {
515         u += scan_mon_inv_randarts( mon, RAP_POISON );
516 
517         const int armour = mon->inv[MSLOT_ARMOUR];
518         if (armour != NON_ITEM && mitm[armour].base_type == OBJ_ARMOUR)
519         {
520             // intrinsic armour abilities
521             switch (mitm[armour].sub_type)
522             {
523             case ARM_DRAGON_ARMOUR:      u += 2; break;
524             case ARM_GOLD_DRAGON_ARMOUR: u += 1; break;
525             case ARM_ICE_DRAGON_ARMOUR:  u -= 1; break;
526             default:                             break;
527             }
528 
529             // check ego resistance
530             const int ego = get_armour_ego_type( mitm[armour] );
531             if (ego == SPARM_FIRE_RESISTANCE || ego == SPARM_RESISTANCE)
532                 u += 1;
533         }
534     }
535 
536     return (u);
537 }                               // end mons_res_fire()
538 
539 
mons_res_cold(struct monsters * mon)540 int mons_res_cold( struct monsters *mon )
541 {
542     int mc = mon->type;
543 
544     if (mc == MONS_PLAYER_GHOST || mc == MONS_PANDEMONIUM_DEMON)
545         return (ghost.values[ GVAL_RES_COLD ]);
546 
547     int u = 0, f = (seekmonster(&mc))->bitfields;
548 
549     // Note that natural monster resistance is two levels, this is duplicate
550     // the fact that having this flag used to be a lot better than armour
551     // for monsters (it used to make them immune in a lot of cases) -- bwr
552     if (f & M_RES_COLD)
553         u += 2;
554     else if (f & M_ED_COLD)
555         u--;
556 
557     if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
558     {
559         u += scan_mon_inv_randarts( mon, RAP_POISON );
560 
561         const int armour = mon->inv[MSLOT_ARMOUR];
562         if (armour != NON_ITEM && mitm[armour].base_type == OBJ_ARMOUR)
563         {
564             // intrinsic armour abilities
565             switch (mitm[armour].sub_type)
566             {
567             case ARM_ICE_DRAGON_ARMOUR:  u += 2; break;
568             case ARM_GOLD_DRAGON_ARMOUR: u += 1; break;
569             case ARM_DRAGON_ARMOUR:      u -= 1; break;
570             default:                             break;
571             }
572 
573             // check ego resistance
574             const int ego = get_armour_ego_type( mitm[armour] );
575             if (ego == SPARM_COLD_RESISTANCE || ego == SPARM_RESISTANCE)
576                 u += 1;
577         }
578     }
579 
580     return (u);
581 }                               // end mons_res_cold()
582 
mons_res_negative_energy(struct monsters * mon)583 int mons_res_negative_energy( struct monsters *mon )
584 {
585     int mc = mon->type;
586 
587     if (mons_holiness( mon->type ) == MH_UNDEAD
588         || mons_holiness( mon->type ) == MH_DEMONIC
589         || mons_holiness( mon->type ) == MH_NONLIVING
590         || mons_holiness( mon->type ) == MH_PLANT
591         || mon->type == MONS_SHADOW_DRAGON)
592     {
593         return (3);  // to match the value for players
594     }
595 
596     int u = 0;
597 
598     if (mons_itemuse(mc) >= MONUSE_STARTING_EQUIPMENT)
599     {
600         u += scan_mon_inv_randarts( mon, RAP_NEGATIVE_ENERGY );
601 
602         const int armour = mon->inv[MSLOT_ARMOUR];
603         if (armour != NON_ITEM && mitm[armour].base_type == OBJ_ARMOUR)
604         {
605             // check for ego resistance
606             if (get_armour_ego_type( mitm[armour] ) == SPARM_POSITIVE_ENERGY)
607                 u += 1;
608         }
609     }
610 
611     return (u);
612 }                               // end mons_res_negative_energy()
613 
mons_skeleton(int mc)614 int mons_skeleton(int mc)
615 {
616     if (mons_zombie_size(mc) == 0
617         || mons_weight(mc) == 0 || ((smc->bitfields & M_NO_SKELETON) != 0))
618     {
619         return (0);
620     }
621 
622     return (1);
623 }                               // end mons_skeleton()
624 
mons_class_flies(int mc)625 char mons_class_flies(int mc)
626 {
627     if (mc == MONS_PANDEMONIUM_DEMON)
628         return (ghost.values[ GVAL_DEMONLORD_FLY ]);
629 
630     int f = smc->bitfields;
631 
632     if (f & M_FLIES)
633         return (1);
634 
635     if (f & M_LEVITATE)
636         return (2);
637 
638     return (0);
639 }
640 
mons_flies(struct monsters * mon)641 char mons_flies( struct monsters *mon )
642 {
643     char ret = mons_class_flies( mon->type );
644 
645     return (ret ? ret : (scan_mon_inv_randarts(mon, RAP_LEVITATE) > 0) ? 2 : 0);
646 }                               // end mons_flies()
647 
648 
649 // this nice routine we keep in exactly the way it was
hit_points(int hit_dice,int min_hp,int rand_hp)650 int hit_points(int hit_dice, int min_hp, int rand_hp)
651 {
652     int hrolled = 0;
653 
654     for (int hroll = 0; hroll < hit_dice; hroll++)
655     {
656         hrolled += random2(1 + rand_hp);
657         hrolled += min_hp;
658     }
659 
660     return (hrolled);
661 }                               // end hit_points()
662 
663 // This function returns the standard number of hit dice for a type
664 // of monster, not a pacticular monsters current hit dice. -- bwr
mons_type_hit_dice(int type)665 int mons_type_hit_dice( int type )
666 {
667     struct monsterentry *mon_class = seekmonster( &type );
668 
669     if (mon_class)
670         return (mon_class->hpdice[0]);
671 
672     return (0);
673 }
674 
675 
exper_value(struct monsters * monster)676 int exper_value( struct monsters *monster )
677 {
678     long x_val = 0;
679 
680     // these three are the original arguments:
681     const int  mclass      = monster->type;
682     const int  mHD         = monster->hit_dice;
683     const int  maxhp       = monster->max_hit_points;
684 
685     // these are some values we care about:
686     const int  speed       = mons_speed(mclass);
687     const int  modifier    = mons_exp_mod(mclass);
688     const int  item_usage  = mons_itemuse(mclass);
689 
690     // XXX: shapeshifters can qualify here, even though they can't cast:
691     const bool spellcaster = mons_flag( mclass, M_SPELLCASTER );
692 
693     // early out for no XP monsters
694     if (mons_flag(mclass, M_NO_EXP_GAIN))
695         return (0);
696 
697     // These undead take damage to maxhp, so we use only HD. -- bwr
698     if (mclass == MONS_ZOMBIE_SMALL
699         || mclass == MONS_ZOMBIE_LARGE
700         || mclass == MONS_SIMULACRUM_SMALL
701         || mclass == MONS_SIMULACRUM_LARGE
702         || mclass == MONS_SKELETON_SMALL
703         || mclass == MONS_SKELETON_LARGE)
704     {
705         x_val = (16 + mHD * 4) * (mHD * mHD) / 10;
706     }
707     else
708     {
709         x_val = (16 + maxhp) * (mHD * mHD) / 10;
710     }
711 
712 
713     // Let's calculate a simple difficulty modifier -- bwr
714     int diff = 0;
715 
716     // Let's look for big spells:
717     if (spellcaster)
718     {
719         const int msecc = ((mclass == MONS_HELLION) ? MST_BURNING_DEVIL :
720                  (mclass == MONS_PANDEMONIUM_DEMON) ? MST_GHOST
721                                                     : monster->number);
722 
723         int hspell_pass[6] = { MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL,
724                                MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL };
725 
726         mons_spell_list( msecc, hspell_pass );
727 
728         for (int i = 0; i < 6; i++)
729         {
730             switch (hspell_pass[i])
731             {
732             case MS_PARALYSIS:
733             case MS_SMITE:
734             case MS_HELLFIRE_BURST:
735             case MS_HELLFIRE:
736             case MS_TORMENT:
737             case MS_IRON_BOLT:
738                 diff += 25;
739                 break;
740 
741             case MS_LIGHTNING_BOLT:
742             case MS_NEGATIVE_BOLT:
743             case MS_VENOM_BOLT:
744             case MS_STICKY_FLAME:
745             case MS_DISINTEGRATE:
746             case MS_SUMMON_DEMON_GREATER:
747             case MS_BANISHMENT:
748             case MS_CRYSTAL_SPEAR:
749             case MS_TELEPORT:
750             case MS_TELEPORT_OTHER:
751                 diff += 10;
752                 break;
753 
754             default:
755                 break;
756             }
757         }
758     }
759 
760     // let's look at regeneration
761     if (monster_descriptor( mclass, MDSC_REGENERATES ))
762         diff += 15;
763 
764     // Monsters at normal or fast speed with big melee damage
765     if (speed >= 10)
766     {
767         int max_melee = 0;
768         for (int i = 0; i < 4; i++)
769             max_melee += mons_damage( mclass, i );
770 
771         if (max_melee > 30)
772             diff += (max_melee / ((speed == 10) ? 2 : 1));
773     }
774 
775     // Monsters who can use equipment (even if only the equipment
776     // they are given) can be considerably enhanced because of
777     // the way weapons work for monsters. -- bwr
778     if (item_usage == MONUSE_STARTING_EQUIPMENT
779         || item_usage == MONUSE_WEAPONS_ARMOUR)
780     {
781         diff += 30;
782     }
783 
784     // Set a reasonable range on the difficulty modifier...
785     // Currently 70% - 200% -- bwr
786     if (diff > 100)
787         diff = 100;
788     else if (diff < -30)
789         diff = -30;
790 
791     // Apply difficulty
792     x_val *= (100 + diff);
793     x_val /= 100;
794 
795     // Basic speed modification
796     if (speed > 0)
797     {
798         x_val *= speed;
799         x_val /= 10;
800     }
801 
802     // Slow monsters without spells and items often have big HD which
803     // cause the experience value to be overly large... this tries
804     // to reduce the inappropriate amount of XP that results. -- bwr
805     if (speed < 10 && !spellcaster && item_usage < MONUSE_STARTING_EQUIPMENT)
806     {
807         x_val /= 2;
808     }
809 
810     // Apply the modifier in the monster's definition
811     if (modifier > 0)
812     {
813         x_val *= modifier;
814         x_val /= 10;
815     }
816 
817     // Reductions for big values. -- bwr
818     if (x_val > 100)
819         x_val = 100 + ((x_val - 100) * 3) / 4;
820     if (x_val > 1000)
821         x_val = 1000 + (x_val - 1000) / 2;
822 
823     // guarantee the value is within limits
824     if (x_val <= 0)
825         x_val = 1;
826     else if (x_val > 15000)
827         x_val = 15000;
828 
829     return (x_val);
830 }                               // end exper_value()
831 
832 
833 // this needs to be rewritten a la the monsterseek rewrite {dlb}:
mons_spell_list(unsigned char sec,int splist[6])834 void mons_spell_list( unsigned char sec, int splist[6] )
835 {
836     unsigned int x;
837 
838     for (x = 0; x < NUM_MSTYPES; x++)
839     {
840         if (mspell_list[x][0] == sec)
841             break;
842     }
843 
844     if (x >= NUM_MSTYPES)
845         return;
846 
847     // I *KNOW* this can easily be done in a loop
848     splist[0] = mspell_list[x][1];      // bolt spell
849     splist[1] = mspell_list[x][2];      // enchantment
850     splist[2] = mspell_list[x][3];      // self_ench
851     splist[3] = mspell_list[x][4];      // misc
852     splist[4] = mspell_list[x][5];      // misc2
853     splist[5] = mspell_list[x][6];      // emergency
854 
855     if (sec == MST_GHOST)             /* ghost */
856     {
857         for (x = 0; x < 6; x++)
858             splist[x] = ghost.values[ GVAL_SPELL_1 + x ];
859     }
860 }                               // end mons_spell_list()
861 
862 #if DEBUG_DIAGNOSTICS
mons_spell_name(int spell)863 const char *mons_spell_name( int spell )
864 {
865     if (spell == MS_NO_SPELL || spell >= NUM_MONSTER_SPELLS || spell < 0)
866         return ("No spell");
867 
868     return (monster_spell_name[ spell ]);
869 }
870 #endif
871 
872 // generate a shiny new and unscarred monster
define_monster(int k)873 void define_monster(int k)
874 {
875     int temp_rand = 0;          // probability determination {dlb}
876     int m2_class = menv[k].type;
877     int m2_HD, m2_hp, m2_hp_max, m2_AC, m2_ev, m2_speed;
878     int m2_sec = menv[k].number;
879     struct monsterentry *m = seekmonster(&m2_class);
880 
881     m2_HD = m->hpdice[0];
882 
883     // misc
884     m2_AC = m->AC;
885     m2_ev = m->ev;
886 
887     // speed
888     m2_speed = m->speed;
889 
890     // some monsters are randomized:
891     // did I get them all?    // I don't think so {dlb}
892     if (mons_is_mimic( m2_class ))
893         m2_sec = get_mimic_colour( &menv[k] );
894     else
895     {
896         switch (m2_class)
897         {
898         case MONS_ABOMINATION_SMALL:
899             m2_HD = 4 + random2(4);
900             m2_AC = 3 + random2(7);
901             m2_ev = 7 + random2(6);
902             m2_speed = 7 + random2avg(9, 2);
903 
904             if (m2_sec == 250)
905                 m2_sec = random_colour();
906             break;
907 
908         case MONS_ZOMBIE_SMALL:
909             m2_HD = (coinflip() ? 1 : 2);
910             break;
911 
912         case MONS_ZOMBIE_LARGE:
913             m2_HD = 3 + random2(5);
914             break;
915 
916         case MONS_ABOMINATION_LARGE:
917             m2_HD = 8 + random2(4);
918             m2_AC = 5 + random2avg(9, 2);
919             m2_ev = 3 + random2(5);
920             m2_speed = 6 + random2avg(7, 2);
921 
922             if (m2_sec == 250)
923                 m2_sec = random_colour();
924             break;
925 
926         case MONS_BEAST:
927             m2_HD = 4 + random2(4);
928             m2_AC = 2 + random2(5);
929             m2_ev = 7 + random2(5);
930             m2_speed = 8 + random2(5);
931             break;
932 
933         case MONS_HYDRA:
934             m2_sec = 4 + random2(5);
935             break;
936 
937         case MONS_DEEP_ELF_FIGHTER:
938         case MONS_DEEP_ELF_KNIGHT:
939         case MONS_DEEP_ELF_SOLDIER:
940         case MONS_ORC_WIZARD:
941             m2_sec = MST_ORC_WIZARD_I + random2(3);
942             break;
943 
944         case MONS_LICH:
945         case MONS_ANCIENT_LICH:
946             m2_sec = MST_LICH_I + random2(4);
947             break;
948 
949         case MONS_HELL_KNIGHT:
950             m2_sec = (coinflip() ? MST_HELL_KNIGHT_I : MST_HELL_KNIGHT_II);
951             break;
952 
953         case MONS_NECROMANCER:
954             m2_sec = (coinflip() ? MST_NECROMANCER_I : MST_NECROMANCER_II);
955             break;
956 
957         case MONS_WIZARD:
958         case MONS_OGRE_MAGE:
959         case MONS_EROLCHA:
960         case MONS_DEEP_ELF_MAGE:
961             m2_sec = MST_WIZARD_I + random2(5);
962             break;
963 
964         case MONS_DEEP_ELF_CONJURER:
965             m2_sec = (coinflip()? MST_DEEP_ELF_CONJURER_I : MST_DEEP_ELF_CONJURER_II);
966             break;
967 
968         case MONS_BUTTERFLY:
969         case MONS_SPATIAL_VORTEX:
970         case MONS_KILLER_KLOWN:
971             m2_sec = random_colour();
972             break;
973 
974         case MONS_GILA_MONSTER:
975             temp_rand = random2(7);
976 
977             m2_sec = (temp_rand >= 5 ? LIGHTRED :                   // 2/7
978                       temp_rand >= 3 ? LIGHTMAGENTA :               // 2/7
979                       temp_rand == 2 ? RED :                        // 1/7
980                       temp_rand == 1 ? MAGENTA                      // 1/7
981                                      : YELLOW);                     // 1/7
982             break;
983 
984         case MONS_HUMAN:
985         case MONS_ELF:
986             // these are supposed to only be created by polymorph
987             m2_HD += random2(10);
988             m2_AC += random2(5);
989             m2_ev += random2(5);
990             break;
991 
992         default:
993             break;
994         }
995     }
996 
997     // some calculations
998     m2_hp = hit_points(m2_HD, m->hpdice[1], m->hpdice[2]);
999     m2_hp += m->hpdice[3];
1000     m2_hp_max = m2_hp;
1001 
1002     if (m2_sec == 250)
1003         m2_sec = m->sec;
1004 
1005     // so let it be written, so let it be done
1006     menv[k].hit_dice = m2_HD;
1007     menv[k].hit_points = m2_hp;
1008     menv[k].max_hit_points = m2_hp_max;
1009     menv[k].armour_class = m2_AC;
1010     menv[k].evasion = m2_ev;
1011     menv[k].speed = m2_speed;
1012     menv[k].speed_increment = 70;
1013     menv[k].number = m2_sec;
1014     menv[k].flags = 0;
1015 
1016     // reset monster enchantments
1017     for (int i = 0; i < NUM_MON_ENCHANTS; i++)
1018         menv[k].enchantment[i] = ENCH_NONE;
1019 }                               // end define_monster()
1020 
1021 
1022 /* ------------------------- monam/moname ------------------------- */
ptr_monam(struct monsters * mon,char desc)1023 const char *ptr_monam( struct monsters *mon, char desc )
1024 {
1025     // We give an item type description for mimics now, note that
1026     // since gold mimics only have one description (to match the
1027     // examine code in direct.cc), we won't bother going through
1028     // this for them. -- bwr
1029     if (mons_is_mimic( mon->type ) && mon->type != MONS_GOLD_MIMIC)
1030     {
1031         static char mimic_name_buff[ ITEMNAME_SIZE ];
1032 
1033         item_def  item;
1034         get_mimic_item( mon, item );
1035         item_name( item, desc, mimic_name_buff );
1036 
1037         return (mimic_name_buff);
1038     }
1039 
1040     return (monam( mon->number, mon->type, player_monster_visible( mon ),
1041                    desc, mon->inv[MSLOT_WEAPON] ));
1042 }
1043 
monam(int mons_num,int mons,bool vis,char desc,int mons_wpn)1044 const char *monam( int mons_num, int mons, bool vis, char desc, int mons_wpn )
1045 {
1046     static char gmo_n[ ITEMNAME_SIZE ];
1047     char gmo_n2[ ITEMNAME_SIZE ] = "";
1048 
1049     gmo_n[0] = '\0';
1050 
1051     // If you can't see the critter, let moname() print [Ii]t.
1052     if (!vis)
1053     {
1054         moname( mons, vis, desc, gmo_n );
1055         return (gmo_n);
1056     }
1057 
1058     // These need their description level handled here instead of
1059     // in monam().
1060     if (mons == MONS_SPECTRAL_THING)
1061     {
1062         switch (desc)
1063         {
1064         case DESC_CAP_THE:
1065             strcpy(gmo_n, "The");
1066             break;
1067         case DESC_NOCAP_THE:
1068             strcpy(gmo_n, "the");
1069             break;
1070         case DESC_CAP_A:
1071             strcpy(gmo_n, "A");
1072             break;
1073         case DESC_NOCAP_A:
1074             strcpy(gmo_n, "a");
1075             break;
1076         case DESC_PLAIN:         /* do nothing */ ;
1077             break;
1078             //default: DEBUGSTR("bad desc flag");
1079         }
1080     }
1081 
1082     switch (mons)
1083     {
1084     case MONS_ZOMBIE_SMALL:
1085     case MONS_ZOMBIE_LARGE:
1086         moname(mons_num, vis, desc, gmo_n);
1087         strcat(gmo_n, " zombie");
1088         break;
1089 
1090     case MONS_SKELETON_SMALL:
1091     case MONS_SKELETON_LARGE:
1092         moname(mons_num, vis, desc, gmo_n);
1093         strcat(gmo_n, " skeleton");
1094         break;
1095 
1096     case MONS_SIMULACRUM_SMALL:
1097     case MONS_SIMULACRUM_LARGE:
1098         moname(mons_num, vis, desc, gmo_n);
1099         strcat(gmo_n, " simulacrum");
1100         break;
1101 
1102     case MONS_SPECTRAL_THING:
1103         strcat(gmo_n, " spectral ");
1104         moname(mons_num, vis, DESC_PLAIN, gmo_n2);
1105         strcat(gmo_n, gmo_n2);
1106         break;
1107 
1108     case MONS_DANCING_WEAPON:
1109         // safety check -- if we don't have/know the weapon use default name
1110         if (mons_wpn == NON_ITEM)
1111             moname( mons, vis, desc, gmo_n );
1112         else
1113         {
1114             item_def item = mitm[mons_wpn];
1115             unset_ident_flags( item, ISFLAG_KNOW_CURSE | ISFLAG_KNOW_PLUSES );
1116             item_name( item, desc, gmo_n );
1117         }
1118         break;
1119 
1120     case MONS_PLAYER_GHOST:
1121         strcpy(gmo_n, ghost.name);
1122         strcat(gmo_n, "'s ghost");
1123         break;
1124 
1125     case MONS_PANDEMONIUM_DEMON:
1126         strcpy(gmo_n, ghost.name);
1127         break;
1128 
1129     default:
1130         moname(mons, vis, desc, gmo_n);
1131         break;
1132     }
1133 
1134     return (gmo_n);
1135 }                               // end monam()
1136 
moname(int mons_num,bool vis,char descrip,char glog[ITEMNAME_SIZE])1137 void moname(int mons_num, bool vis, char descrip, char glog[ ITEMNAME_SIZE ])
1138 {
1139     glog[0] = '\0';
1140 
1141     char gmon_name[ ITEMNAME_SIZE ] = "";
1142     strcpy( gmon_name, seekmonster( &mons_num )->name );
1143 
1144     if (!vis)
1145     {
1146         switch (descrip)
1147         {
1148         case DESC_CAP_THE:
1149         case DESC_CAP_A:
1150             strcpy(glog, "It");
1151             break;
1152         case DESC_NOCAP_THE:
1153         case DESC_NOCAP_A:
1154         case DESC_PLAIN:
1155             strcpy(glog, "it");
1156             break;
1157         }
1158 
1159         strcpy(gmon_name, glog);
1160         return;
1161     }
1162 
1163     if (!mons_is_unique( mons_num ))
1164     {
1165         switch (descrip)
1166         {
1167         case DESC_CAP_THE:
1168             strcpy(glog, "The ");
1169             break;
1170         case DESC_NOCAP_THE:
1171             strcpy(glog, "the ");
1172             break;
1173         case DESC_CAP_A:
1174             strcpy(glog, "A");
1175             break;
1176         case DESC_NOCAP_A:
1177             strcpy(glog, "a");
1178             break;
1179         case DESC_PLAIN:
1180             break;
1181         // default: DEBUGSTR("bad monster descrip flag");
1182         }
1183 
1184         if (descrip == DESC_CAP_A || descrip == DESC_NOCAP_A)
1185         {
1186             switch (toupper(gmon_name[0]))
1187             {
1188             case 'A':
1189             case 'E':
1190             case 'I':
1191             case 'O':
1192             case 'U':
1193                 strcat(glog, "n ");
1194                 break;
1195 
1196             default:
1197                 strcat(glog, " ");
1198                 break;
1199             }
1200         }
1201     }
1202 
1203     strcat(glog, gmon_name);
1204 }                               // end moname()
1205 
1206 /* ********************* END PUBLIC FUNCTIONS ********************* */
1207 
1208 // see mons_init for initialization of mon_entry array.
seekmonster(int * p_monsterid)1209 static struct monsterentry *seekmonster(int *p_monsterid)
1210 {
1211     ASSERT(p_monsterid != 0);
1212 
1213     int me = mon_entry[(*p_monsterid)];
1214 
1215     if (me >= 0)                // PARANOIA
1216         return (&mondata[mon_entry[(*p_monsterid)]]);
1217     else
1218         return (NULL);
1219 }                               // end seekmonster()
1220 
mons_exp_mod(int mc)1221 static int mons_exp_mod(int mc)
1222 {
1223     return (smc->exp_mod);
1224 }                               // end mons_exp_mod()
1225 
1226 
mons_speed(int mc)1227 int mons_speed(int mc)
1228 {
1229     return (smc->speed);
1230 }                               // end mons_speed()
1231 
1232 
mons_intel(int mc)1233 int mons_intel(int mc)          //jmf: "fixed" to work with new I_ types
1234 {
1235     switch (smc->intel)
1236     {
1237     case I_PLANT:
1238         return (I_PLANT);
1239     case I_INSECT:
1240     case I_REPTILE:
1241         return (I_INSECT);
1242     case I_ANIMAL:
1243     case I_ANIMAL_LIKE:
1244         return (I_ANIMAL);
1245     case I_NORMAL:
1246         return (I_NORMAL);
1247     case I_HIGH:
1248         return (I_HIGH);
1249     default:
1250         return (I_NORMAL);
1251     }
1252 }                               // ens mons_intel()
1253 
1254 
mons_intel_type(int mc)1255 int mons_intel_type(int mc)     //jmf: new, used by my spells
1256 {
1257     return (smc->intel);
1258 }                               // end mons_intel_type()
1259 
mons_power(int mc)1260 int mons_power(int mc)
1261 {
1262     // for now,  just return monster hit dice.
1263     return (smc->hpdice[0]);
1264 }
1265 
mons_aligned(int m1,int m2)1266 bool mons_aligned(int m1, int m2)
1267 {
1268     bool fr1, fr2;
1269     struct monsters *mon1, *mon2;
1270 
1271     if (m1 == MHITNOT || m2 == MHITNOT)
1272         return (true);
1273 
1274     if (m1 == MHITYOU)
1275         fr1 = true;
1276     else
1277     {
1278         mon1 = &menv[m1];
1279         fr1 = (mon1->attitude == ATT_FRIENDLY) || mons_has_ench(mon1, ENCH_CHARM);
1280     }
1281 
1282     if (m2 == MHITYOU)
1283         fr2 = true;
1284     else
1285     {
1286         mon2 = &menv[m2];
1287         fr2 = (mon2->attitude == ATT_FRIENDLY) || mons_has_ench(mon2, ENCH_CHARM);
1288     }
1289 
1290     return (fr1 == fr2);
1291 }
1292 
mons_friendly(struct monsters * m)1293 bool mons_friendly(struct monsters *m)
1294 {
1295     return (m->attitude == ATT_FRIENDLY || mons_has_ench(m, ENCH_CHARM));
1296 }
1297 
1298 /* ******************************************************************
1299 
1300 // In the name of England, I declare this function wasteful! {dlb}
1301 
1302 static monsterentry *seekmonster( int mc )
1303 {
1304 
1305     ASSERT(mc >= 0);
1306 
1307     int x = 0;
1308 
1309     while (x < mondatasize)
1310     {
1311         if (mondata[x].mc == mc)
1312           return &mondata[x];
1313 
1314         x++;
1315     }
1316 
1317     ASSERT(false);
1318 
1319     return seekmonster(MONS_PROGRAM_BUG);    // see the disasters coming if there is no 250?
1320 
1321 }          // end seekmonster()
1322 ****************************************************************** */
1323 
1324 
1325 /* ******************************************************************
1326 
1327 // only used once, and internal to this file, to boot {dlb}:
1328 
1329 // These are easy to implement here. The difficult (dull!) work of converting
1330 // the data structures is finally finished now!
1331 inline char *mons_name( int mc )
1332 {
1333 
1334     return smc->name;
1335 
1336 }          // end mons_name()
1337 ****************************************************************** */
1338 
1339 /*****************************************************************
1340 
1341   Used to determine whether or not a monster should fire a beam (MUST be
1342   called _after_ fire_tracer() for meaningful result.
1343 
1344 */
1345 
mons_should_fire(struct bolt & beam)1346 bool mons_should_fire(struct bolt &beam)
1347 {
1348     // use of foeRatio:
1349     // the higher this number, the more monsters
1350     // will _avoid_ collateral damage to their friends.
1351     // setting this to zero will in fact have all
1352     // monsters ignore their friends when considering
1353     // collateral damage.
1354 
1355     // quick check - did we in fact get any foes?
1356     if (beam.foe_count == 0)
1357         return (false);
1358 
1359     // if we either hit no friends, or monster too dumb to care
1360     if (beam.fr_count == 0 || !beam.smartMonster)
1361         return (true);
1362 
1363     // only fire if they do acceptably low collateral damage
1364     // the default for this is 50%;  in other words, don't
1365     // hit a foe unless you hit 2 or fewer friends.
1366     if (beam.foe_power >= (beam.foeRatio * beam.fr_power) / 100)
1367         return (true);
1368 
1369     return (false);
1370 }
1371 
mons_has_ench(struct monsters * mon,unsigned int ench,unsigned int ench2)1372 int mons_has_ench(struct monsters *mon, unsigned int ench, unsigned int ench2)
1373 {
1374     // silliness
1375     if (ench == ENCH_NONE)
1376         return (ench);
1377 
1378     if (ench2 == ENCH_NONE)
1379         ench2 = ench;
1380 
1381     for (int p = 0; p < NUM_MON_ENCHANTS; p++)
1382     {
1383         if (mon->enchantment[p] >= ench && mon->enchantment[p] <= ench2)
1384             return (mon->enchantment[p]);
1385     }
1386 
1387     return (ENCH_NONE);
1388 }
1389 
1390 // Returning the deleted enchantment is important!  See abjuration. -- bwr
mons_del_ench(struct monsters * mon,unsigned int ench,unsigned int ench2,bool quiet)1391 int mons_del_ench( struct monsters *mon, unsigned int ench, unsigned int ench2,
1392                    bool quiet )
1393 {
1394     unsigned int p;
1395     int ret_val = ENCH_NONE;
1396 
1397     // silliness
1398     if (ench == ENCH_NONE)
1399         return (ENCH_NONE);
1400 
1401     if (ench2 == ENCH_NONE)
1402         ench2 = ench;
1403 
1404     for (p = 0; p < NUM_MON_ENCHANTS; p++)
1405     {
1406         if (mon->enchantment[p] >= ench && mon->enchantment[p] <= ench2)
1407             break;
1408     }
1409 
1410     if (p == NUM_MON_ENCHANTS)
1411         return (ENCH_NONE);
1412 
1413     ret_val = mon->enchantment[p];
1414     mon->enchantment[p] = ENCH_NONE;
1415 
1416     // check for slow/haste
1417     if (ench == ENCH_HASTE)
1418     {
1419         if (mon->speed >= 100)
1420             mon->speed = 100 + ((mon->speed - 100) / 2);
1421         else
1422             mon->speed /= 2;
1423     }
1424 
1425     if (ench == ENCH_SLOW)
1426     {
1427         if (mon->speed >= 100)
1428             mon->speed = 100 + ((mon->speed - 100) * 2);
1429         else
1430             mon->speed *= 2;
1431     }
1432 
1433     if (ench == ENCH_FEAR)
1434     {
1435         if (!quiet)
1436             simple_monster_message(mon, " seems to regain its courage.");
1437 
1438         // reevaluate behaviour
1439         behaviour_event(mon, ME_EVAL);
1440     }
1441 
1442     if (ench == ENCH_CONFUSION)
1443     {
1444         if (!quiet)
1445             simple_monster_message(mon, " seems less confused.");
1446 
1447         // reevaluate behaviour
1448         behaviour_event(mon, ME_EVAL);
1449     }
1450 
1451     if (ench == ENCH_INVIS)
1452     {
1453         // invisible monsters stay invisible
1454         if (mons_flag(mon->type, M_INVIS))
1455         {
1456             mon->enchantment[p] = ENCH_INVIS;
1457         }
1458         else if (mons_near(mon) && !player_see_invis()
1459                     && !mons_has_ench( mon, ENCH_SUBMERGED ))
1460         {
1461             if (!quiet)
1462             {
1463                 strcpy( info, ptr_monam( mon, DESC_CAP_A ) );
1464                 strcat( info, " appears!" );
1465                 mpr( info );
1466             }
1467         }
1468     }
1469 
1470     if (ench == ENCH_CHARM)
1471     {
1472         if (!quiet)
1473             simple_monster_message(mon, " is no longer charmed.");
1474 
1475         // reevaluate behaviour
1476         behaviour_event(mon, ME_EVAL);
1477     }
1478 
1479     if (ench == ENCH_BACKLIGHT_I)
1480     {
1481         if (!quiet)
1482             simple_monster_message(mon, " stops glowing.");
1483     }
1484 
1485     if (ench == ENCH_STICKY_FLAME_I || ench == ENCH_YOUR_STICKY_FLAME_I)
1486     {
1487         if (!quiet)
1488             simple_monster_message(mon, " stops burning.");
1489     }
1490 
1491     if (ench == ENCH_POISON_I || ench == ENCH_YOUR_POISON_I)
1492     {
1493         if (!quiet)
1494             simple_monster_message(mon, " looks more healthy.");
1495     }
1496 
1497     if (ench == ENCH_YOUR_ROT_I)
1498     {
1499         if (!quiet)
1500             simple_monster_message(mon, " is no longer rotting.");
1501     }
1502 
1503     return (ret_val);
1504 }
1505 
mons_add_ench(struct monsters * mon,unsigned int ench)1506 bool mons_add_ench(struct monsters *mon, unsigned int ench)
1507 {
1508     // silliness
1509     if (ench == ENCH_NONE)
1510         return (false);
1511 
1512     int newspot = -1;
1513 
1514     // don't double-add
1515     for (int p = 0; p < NUM_MON_ENCHANTS; p++)
1516     {
1517         if (mon->enchantment[p] == ench)
1518             return (true);
1519 
1520         if (mon->enchantment[p] == ENCH_NONE && newspot < 0)
1521             newspot = p;
1522     }
1523 
1524     if (newspot < 0)
1525         return (false);
1526 
1527     mon->enchantment[newspot] = ench;
1528 //    if ench == ENCH_FEAR //mv: withou this fear & repel undead spell doesn't work
1529 
1530 
1531     // check for slow/haste
1532     if (ench == ENCH_HASTE)
1533     {
1534         if (mon->speed >= 100)
1535             mon->speed = 100 + ((mon->speed - 100) * 2);
1536         else
1537             mon->speed *= 2;
1538     }
1539 
1540     if (ench == ENCH_SLOW)
1541     {
1542         if (mon->speed >= 100)
1543             mon->speed = 100 + ((mon->speed - 100) / 2);
1544         else
1545             mon->speed /= 2;
1546     }
1547 
1548     return (true);
1549 }
1550 
1551 // used to determine whether or not a monster should always
1552 // fire this spell if selected.  If not, we should use a
1553 // tracer.
1554 
1555 // note - this function assumes that the monster is "nearby"
1556 // its target!
1557 
ms_requires_tracer(int monspell)1558 bool ms_requires_tracer(int monspell)
1559 {
1560     bool requires = false;
1561 
1562     switch(monspell)
1563     {
1564         case MS_BANISHMENT:
1565         case MS_COLD_BOLT:
1566         case MS_CONFUSE:
1567         case MS_CRYSTAL_SPEAR:
1568         case MS_DISINTEGRATE:
1569         case MS_ENERGY_BOLT:
1570         case MS_FIRE_BOLT:
1571         case MS_FIREBALL:
1572         case MS_FLAME:
1573         case MS_FROST:
1574         case MS_HELLFIRE:
1575         case MS_IRON_BOLT:
1576         case MS_LIGHTNING_BOLT:
1577         case MS_MARSH_GAS:
1578         case MS_METAL_SPLINTERS:
1579         case MS_MMISSILE:
1580         case MS_NEGATIVE_BOLT:
1581         case MS_ORB_ENERGY:
1582         case MS_PAIN:
1583         case MS_PARALYSIS:
1584         case MS_POISON_BLAST:
1585         case MS_POISON_SPLASH:
1586         case MS_QUICKSILVER_BOLT:
1587         case MS_SLOW:
1588         case MS_STEAM_BALL:
1589         case MS_STICKY_FLAME:
1590         case MS_STING:
1591         case MS_STONE_ARROW:
1592         case MS_TELEPORT_OTHER:
1593         case MS_VENOM_BOLT:
1594             requires = true;
1595             break;
1596 
1597         // self-niceties and direct effects
1598         case MS_ANIMATE_DEAD:
1599         case MS_BLINK:
1600         case MS_BRAIN_FEED:
1601         case MS_DIG:
1602         case MS_FAKE_RAKSHASA_SUMMON:
1603         case MS_HASTE:
1604         case MS_HEAL:
1605         case MS_HELLFIRE_BURST:
1606         case MS_INVIS:
1607         case MS_LEVEL_SUMMON:
1608         case MS_MUTATION:
1609         case MS_SMITE:
1610         case MS_SUMMON_BEAST:
1611         case MS_SUMMON_DEMON_LESSER:
1612         case MS_SUMMON_DEMON:
1613         case MS_SUMMON_DEMON_GREATER:
1614         case MS_SUMMON_UFETUBUS:
1615         case MS_TELEPORT:
1616         case MS_TORMENT:
1617         case MS_VAMPIRE_SUMMON:
1618         case MS_CANTRIP:
1619 
1620         // meaningless, but sure, why not?
1621         case MS_NO_SPELL:
1622             break;
1623 
1624         default:
1625             break;
1626 
1627     }
1628 
1629     return (requires);
1630 }
1631 
1632 // returns true if the spell is something you wouldn't want done if
1633 // you had a friendly target..  only returns a meaningful value for
1634 // non-beam spells
1635 
ms_direct_nasty(int monspell)1636 bool ms_direct_nasty(int monspell)
1637 {
1638     bool nasty = true;
1639 
1640     switch(monspell)
1641     {
1642         // self-niceties/summonings
1643         case MS_ANIMATE_DEAD:
1644         case MS_BLINK:
1645         case MS_DIG:
1646         case MS_FAKE_RAKSHASA_SUMMON:
1647         case MS_HASTE:
1648         case MS_HEAL:
1649         case MS_INVIS:
1650         case MS_LEVEL_SUMMON:
1651         case MS_SUMMON_BEAST:
1652         case MS_SUMMON_DEMON_LESSER:
1653         case MS_SUMMON_DEMON:
1654         case MS_SUMMON_DEMON_GREATER:
1655         case MS_SUMMON_UFETUBUS:
1656         case MS_TELEPORT:
1657         case MS_VAMPIRE_SUMMON:
1658             nasty = false;
1659             break;
1660 
1661         case MS_BRAIN_FEED:
1662         case MS_HELLFIRE_BURST:
1663         case MS_MUTATION:
1664         case MS_SMITE:
1665         case MS_TORMENT:
1666 
1667         // meaningless, but sure, why not?
1668         case MS_NO_SPELL:
1669             break;
1670 
1671         default:
1672             break;
1673 
1674     }
1675 
1676     return (nasty);
1677 }
1678 
1679 // Spells a monster may want to cast if fleeing from the player, and
1680 // the player is not in sight.
ms_useful_fleeing_out_of_sight(struct monsters * mon,int monspell)1681 bool ms_useful_fleeing_out_of_sight( struct monsters *mon, int monspell )
1682 {
1683     if (ms_waste_of_time( mon, monspell ))
1684         return (false);
1685 
1686     switch (monspell)
1687     {
1688     case MS_HASTE:
1689     case MS_INVIS:
1690     case MS_HEAL:
1691     case MS_ANIMATE_DEAD:
1692         return (true);
1693 
1694     case MS_VAMPIRE_SUMMON:
1695     case MS_SUMMON_UFETUBUS:
1696     case MS_FAKE_RAKSHASA_SUMMON:
1697     case MS_LEVEL_SUMMON:
1698     case MS_SUMMON_DEMON:
1699     case MS_SUMMON_DEMON_LESSER:
1700     case MS_SUMMON_BEAST:
1701     case MS_SUMMON_UNDEAD:
1702     case MS_SUMMON_DEMON_GREATER:
1703         if (one_chance_in(10))    // only summon friends some of the time
1704             return (true);
1705         break;
1706 
1707     default:
1708         break;
1709     }
1710 
1711     return (false);
1712 }
1713 
ms_low_hitpoint_cast(struct monsters * mon,int monspell)1714 bool ms_low_hitpoint_cast( struct monsters *mon, int monspell )
1715 {
1716     bool ret = false;
1717 
1718     bool targ_adj = false;
1719 
1720     if (mon->foe == MHITYOU || mon->foe == MHITNOT)
1721     {
1722         if (adjacent(you.x_pos, you.y_pos, mon->x, mon->y))
1723             targ_adj = true;
1724     }
1725     else if (adjacent( menv[mon->foe].x, menv[mon->foe].y, mon->x, mon->y ))
1726     {
1727         targ_adj = true;
1728     }
1729 
1730     switch (monspell)
1731     {
1732     case MS_TELEPORT:
1733     case MS_TELEPORT_OTHER:
1734     case MS_HEAL:
1735         ret = true;
1736         break;
1737 
1738     case MS_BLINK:
1739         if (targ_adj)
1740             ret = true;
1741         break;
1742 
1743     case MS_VAMPIRE_SUMMON:
1744     case MS_SUMMON_UFETUBUS:
1745     case MS_FAKE_RAKSHASA_SUMMON:
1746         if (!targ_adj)
1747             ret = true;
1748         break;
1749     }
1750 
1751     return (ret);
1752 }
1753 
1754 // Checks to see if a particular spell is worth casting in the first place.
ms_waste_of_time(struct monsters * mon,int monspell)1755 bool ms_waste_of_time( struct monsters *mon, int monspell )
1756 {
1757     bool  ret = false;
1758     int intel, est_magic_resist, power, diff;
1759     struct monsters *targ;
1760 
1761 
1762     // Eventually, we'll probably want to be able to have monsters
1763     // learn which of their elemental bolts were resisted and have those
1764     // handled here as well. -- bwr
1765     switch (monspell)
1766     {
1767     case MS_HASTE:
1768         if (mons_has_ench( mon, ENCH_HASTE ))
1769             ret = true;
1770         break;
1771 
1772     case MS_INVIS:
1773         if (mons_has_ench( mon, ENCH_INVIS ))
1774             ret = true;
1775         break;
1776 
1777     case MS_HEAL:
1778         if (mon->hit_points > mon->max_hit_points / 2)
1779             ret = true;
1780         break;
1781 
1782     case MS_TELEPORT:
1783         // Monsters aren't smart enough to know when to cancel teleport.
1784         if (mons_has_ench( mon, ENCH_TP_I, ENCH_TP_IV ))
1785             ret = true;
1786         break;
1787 
1788     case MS_TELEPORT_OTHER:
1789         // Monsters aren't smart enough to know when to cancel teleport.
1790         if (mon->foe == MHITYOU)
1791         {
1792             if (you.duration[DUR_TELEPORT])
1793                 return (true);
1794         }
1795         else if (mon->foe != MHITNOT)
1796         {
1797             if (mons_has_ench( &menv[mon->foe], ENCH_TP_I, ENCH_TP_IV))
1798                 return (true);
1799         }
1800         // intentional fall-through
1801 
1802     case MS_SLOW:
1803     case MS_CONFUSE:
1804     case MS_PAIN:
1805     case MS_BANISHMENT:
1806     case MS_DISINTEGRATE:
1807     case MS_PARALYSIS:
1808         // occasionally we don't estimate... just fire and see:
1809         if (one_chance_in(5))
1810             return (false);
1811 
1812         // Only intelligent monsters estimate.
1813         intel = mons_intel( mon->type );
1814         if (intel != I_NORMAL && intel != I_HIGH)
1815             return (false);
1816 
1817         // We'll estimate the target's resistance to magic, by first getting
1818         // the actual value and then randomizing it.
1819         est_magic_resist = (mon->foe == MHITNOT) ? 10000 : 0;
1820 
1821         if (mon->foe != MHITNOT)
1822         {
1823             if (mon->foe == MHITYOU)
1824                 est_magic_resist = player_res_magic();
1825             else
1826             {
1827                 targ = &menv[ mon->foe ];
1828                 est_magic_resist = mons_resist_magic( targ );
1829             }
1830 
1831             // now randomize (normal intels less accurate than high):
1832             if (intel == I_NORMAL)
1833                 est_magic_resist += random2(80) - 40;
1834             else
1835                 est_magic_resist += random2(30) - 15;
1836         }
1837 
1838         power = 12 * mon->hit_dice * (monspell == MS_PAIN ? 2 : 1);
1839         power = stepdown_value( power, 30, 40, 100, 120 );
1840 
1841         // Determine the amount of chance allowed by the benefit from
1842         // the spell.  The estimated difficulty is the probability
1843         // of rolling over 100 + diff on 2d100. -- bwr
1844         diff = (monspell == MS_PAIN
1845                 || monspell == MS_SLOW
1846                 || monspell == MS_CONFUSE) ? 0 : 50;
1847 
1848         if (est_magic_resist - power > diff)
1849             ret = true;
1850 
1851         break;
1852 
1853     default:
1854         break;
1855     }
1856 
1857     return (ret);
1858 }
1859 
ms_ranged_spell(int monspell)1860 static bool ms_ranged_spell( int monspell )
1861 {
1862     switch (monspell)
1863     {
1864     case MS_HASTE:
1865     case MS_HEAL:
1866     case MS_TELEPORT:
1867     case MS_INVIS:
1868     case MS_BLINK:
1869         return (false);
1870 
1871     default:
1872         break;
1873     }
1874 
1875     return (true);
1876 }
1877 
mons_has_ranged_spell(struct monsters * mon)1878 bool mons_has_ranged_spell( struct monsters *mon )
1879 {
1880     const int  mclass = mon->type;
1881 
1882     if (mons_flag( mclass, M_SPELLCASTER ))
1883     {
1884         const int  msecc = ((mclass == MONS_HELLION) ? MST_BURNING_DEVIL :
1885                   (mclass == MONS_PANDEMONIUM_DEMON) ? MST_GHOST
1886                                                      : mon->number);
1887 
1888         int hspell_pass[6] = { MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL,
1889                                MS_NO_SPELL, MS_NO_SPELL, MS_NO_SPELL };
1890 
1891         mons_spell_list( msecc, hspell_pass );
1892 
1893         for (int i = 0; i < 6; i++)
1894         {
1895             if (ms_ranged_spell( hspell_pass[i] ))
1896                 return (true);
1897         }
1898     }
1899 
1900     return (false);
1901 }
1902 
mons_has_ranged_attack(struct monsters * mon)1903 bool mons_has_ranged_attack( struct monsters *mon )
1904 {
1905     const int weapon = mon->inv[MSLOT_WEAPON];
1906     const int ammo = mon->inv[MSLOT_MISSILE];
1907 
1908     const int lnchClass = (weapon != NON_ITEM) ? mitm[weapon].base_type : -1;
1909     const int lnchType  = (weapon != NON_ITEM) ? mitm[weapon].sub_type  :  0;
1910 
1911     const int ammoClass = (ammo != NON_ITEM) ? mitm[ammo].base_type : -1;
1912     const int ammoType  = (ammo != NON_ITEM) ? mitm[ammo].sub_type  :  0;
1913 
1914     bool launched = false;
1915     bool thrown = false;
1916 
1917     throw_type( lnchClass, lnchType, ammoClass, ammoType, launched, thrown );
1918 
1919     if (launched || thrown)
1920         return (true);
1921 
1922     return (false);
1923 }
1924 
1925 
1926 // use of variant:
1927 // 0 : She is tap dancing.
1928 // 1 : It seems she is tap dancing. (lower case pronoun)
1929 // 2 : Her sword explodes!          (upper case possessive)
1930 // 3 : It sticks to her sword!      (lower case possessive)
1931 // ... as needed
1932 
mons_pronoun(int mon_type,int variant)1933 const char *mons_pronoun(int mon_type, int variant)
1934 {
1935     int gender = GENDER_NEUTER;
1936 
1937     if (mons_is_unique( mon_type ))
1938     {
1939         switch(mon_type)
1940         {
1941             case MONS_JESSICA:
1942             case MONS_PSYCHE:
1943             case MONS_JOSEPHINE:
1944             case MONS_AGNES:
1945             case MONS_MAUD:
1946             case MONS_LOUISE:
1947             case MONS_FRANCES:
1948             case MONS_MARGERY:
1949             case MONS_EROLCHA:
1950             case MONS_ERICA:
1951                 gender = GENDER_FEMALE;
1952                 break;
1953             default:
1954                 gender = GENDER_MALE;
1955                 break;
1956         }
1957     }
1958 
1959     switch(variant)
1960     {
1961         case PRONOUN_CAP:
1962             return ((gender == 0) ? "It" :
1963                     (gender == 1) ? "He" : "She");
1964 
1965         case PRONOUN_NOCAP:
1966             return ((gender == 0) ? "it" :
1967                     (gender == 1) ? "he" : "she");
1968 
1969         case PRONOUN_CAP_POSSESSIVE:
1970             return ((gender == 0) ? "Its" :
1971                     (gender == 1) ? "His" : "Her");
1972 
1973         case PRONOUN_NOCAP_POSSESSIVE:
1974             return ((gender == 0) ? "its" :
1975                     (gender == 1) ? "his" : "her");
1976 
1977         case PRONOUN_REFLEXIVE:  // awkward at start of sentence, always lower
1978             return ((gender == 0) ? "itself"  :
1979                     (gender == 1) ? "himself" : "herself");
1980     }
1981 
1982     return ("");
1983 }
1984