1 /* NetHack 3.7	mondata.c	$NHDT-Date: 1606473489 2020/11/27 10:38:09 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.87 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed.  See license for details. */
5 
6 #include "hack.h"
7 /*
8  *      These routines provide basic data for any type of monster.
9  */
10 
11 /* set up an individual monster's base type (initial creation, shapechange) */
12 void
set_mon_data(struct monst * mon,struct permonst * ptr)13 set_mon_data(struct monst* mon, struct permonst* ptr)
14 {
15     int new_speed, old_speed = mon->data ? mon->data->mmove : 0;
16 
17     mon->data = ptr;
18     mon->mnum = (short) monsndx(ptr);
19 
20     if (mon->movement) { /* used to adjust poly'd hero as well as monsters */
21         new_speed = ptr->mmove;
22         /* prorate unused movement if new form is slower so that
23            it doesn't get extra moves leftover from previous form;
24            if new form is faster, leave unused movement as is */
25         if (new_speed < old_speed) {
26             /*
27              * Some static analysis warns that this might divide by 0
28                mon->movement = new_speed * mon->movement / old_speed;
29              * so add a redundant test to suppress that.
30              */
31             mon->movement *= new_speed;
32             if (old_speed > 0) /* old > new and new >= 0, so always True */
33                 mon->movement /= old_speed;
34         }
35     }
36     return;
37 }
38 
39 /* does monster-type have any attack for a specific type of damage? */
40 struct attack *
attacktype_fordmg(struct permonst * ptr,int atyp,int dtyp)41 attacktype_fordmg(struct permonst* ptr, int atyp, int dtyp)
42 {
43     struct attack *a;
44 
45     for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
46         if (a->aatyp == atyp && (dtyp == AD_ANY || a->adtyp == dtyp))
47             return a;
48     return (struct attack *) 0;
49 }
50 
51 /* does monster-type have a particular type of attack */
52 boolean
attacktype(struct permonst * ptr,int atyp)53 attacktype(struct permonst* ptr, int atyp)
54 {
55     return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE;
56 }
57 
58 /* returns True if monster doesn't attack, False if it does */
59 boolean
noattacks(struct permonst * ptr)60 noattacks(struct permonst* ptr)
61 {
62     int i;
63     struct attack *mattk = ptr->mattk;
64 
65     for (i = 0; i < NATTK; i++) {
66         /* AT_BOOM "passive attack" (gas spore's explosion upon death)
67            isn't an attack as far as our callers are concerned */
68         if (mattk[i].aatyp == AT_BOOM)
69             continue;
70 
71         if (mattk[i].aatyp)
72             return FALSE;
73     }
74     return TRUE;
75 }
76 
77 /* does monster-type transform into something else when petrified? */
78 boolean
poly_when_stoned(struct permonst * ptr)79 poly_when_stoned(struct permonst* ptr)
80 {
81     /* non-stone golems turn into stone golems unless latter is genocided */
82     return (boolean) (is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM]
83                       && !(g.mvitals[PM_STONE_GOLEM].mvflags & G_GENOD));
84     /* allow G_EXTINCT */
85 }
86 
87 /* returns True if monster is drain-life resistant */
88 boolean
resists_drli(struct monst * mon)89 resists_drli(struct monst* mon)
90 {
91     struct permonst *ptr = mon->data;
92     struct obj *wep;
93 
94     if (resists_drain(ptr) || is_vampshifter(mon)
95         || (mon == &g.youmonst && u.ulycn >= LOW_PM))
96         return TRUE;
97     wep = (mon == &g.youmonst) ? uwep : MON_WEP(mon);
98     return (boolean) (wep && wep->oartifact && defends(AD_DRLI, wep));
99 }
100 
101 /* True if monster is magic-missile (actually, general magic) resistant */
102 boolean
resists_magm(struct monst * mon)103 resists_magm(struct monst* mon)
104 {
105     struct permonst *ptr = mon->data;
106     boolean is_you = (mon == &g.youmonst);
107     long slotmask;
108     struct obj *o;
109 
110     if (resists_mgc(ptr))
111         return TRUE;
112     /* check for magic resistance granted by wielded weapon */
113     o = is_you ? uwep : MON_WEP(mon);
114     if (o && o->oartifact && defends(AD_MAGM, o))
115         return TRUE;
116     /* check for magic resistance granted by worn or carried items */
117     o = is_you ? g.invent : mon->minvent;
118     slotmask = W_ARMOR | W_ACCESSORY;
119     if (!is_you /* assumes monsters don't wield non-weapons */
120         || (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))))
121         slotmask |= W_WEP;
122     if (is_you && u.twoweap)
123         slotmask |= W_SWAPWEP;
124     for (; o; o = o->nobj)
125         if (((o->owornmask & slotmask) != 0L
126              && objects[o->otyp].oc_oprop == ANTIMAGIC)
127             || (o->oartifact && defends_when_carried(AD_MAGM, o)))
128             return TRUE;
129     return FALSE;
130 }
131 
132 /* True iff monster is fire resistant */
133 boolean
resists_fire(struct monst * mon)134 resists_fire(struct monst* mon)
135 {
136     struct obj *otmp;
137     if (mon == &g.youmonst) {
138         return !!Fire_resistance;
139     }
140     if (mon_resistancebits(mon) & MR_FIRE) {
141         /* this assumes any monster will have mextrinsics set for worn items
142          * that naturally provide fire resistance via oc_oprop
143          * (update_mon_intrinsics) */
144         return TRUE;
145     }
146     /* currently only Itlachiayaque provides fire resistance by a means that
147      * update_mon_intrinsics can't capture, because it also provides reflection.
148      * So this doesn't currently need to check for artifacts that provide fire
149      * resistance when worn or wielded. */
150     for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
151         if (otmp->oartifact && defends_when_carried(AD_FIRE, otmp)) {
152             return TRUE;
153         }
154     }
155     return FALSE;
156 }
157 
158 /* True iff monster is resistant to light-induced blindness */
159 boolean
resists_blnd(struct monst * mon)160 resists_blnd(struct monst* mon)
161 {
162     struct permonst *ptr = mon->data;
163     boolean is_you = (mon == &g.youmonst);
164     long slotmask;
165     struct obj *o;
166 
167     if (is_you ? (Blind || Unaware)
168                : (mon->mblinded || !mon->mcansee || !haseyes(ptr)
169                   /* BUG: temporary sleep sets mfrozen, but since
170                           paralysis does too, we can't check it */
171                   || mon->msleeping))
172         return TRUE;
173     /* yellow light, Archon; !dust vortex, !cobra, !raven */
174     if (dmgtype_fromattack(ptr, AD_BLND, AT_EXPL)
175         || dmgtype_fromattack(ptr, AD_BLND, AT_GAZE))
176         return TRUE;
177     o = is_you ? uwep : MON_WEP(mon);
178     if (o && o->oartifact && defends(AD_BLND, o))
179         return TRUE;
180     o = is_you ? g.invent : mon->minvent;
181     slotmask = W_ARMOR | W_ACCESSORY;
182     if (!is_you /* assumes monsters don't wield non-weapons */
183         || (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))))
184         slotmask |= W_WEP;
185     if (is_you && u.twoweap)
186         slotmask |= W_SWAPWEP;
187     for (; o; o = o->nobj)
188         if (((o->owornmask & slotmask) != 0L
189              && objects[o->otyp].oc_oprop == BLINDED)
190             || (o->oartifact && defends_when_carried(AD_BLND, o)))
191             return TRUE;
192     return FALSE;
193 }
194 
195 /* True iff monster can be blinded by the given attack;
196    note: may return True when mdef is blind (e.g. new cream-pie attack)
197    magr can be NULL.
198 */
199 boolean
can_blnd(struct monst * magr,struct monst * mdef,uchar aatyp,struct obj * obj)200 can_blnd(
201     struct monst *magr, /* NULL == no specific aggressor */
202     struct monst *mdef,
203     uchar aatyp,
204     struct obj *obj) /* aatyp == AT_WEAP, AT_SPIT */
205 {
206     boolean is_you = (mdef == &g.youmonst);
207     boolean check_visor = FALSE;
208     struct obj *o;
209 
210     /* no eyes protect against all attacks for now */
211     if (!haseyes(mdef->data))
212         return FALSE;
213 
214     /* /corvus oculum corvi non eruit/
215        a saying expressed in Latin rather than a zoological observation:
216        "a crow will not pluck out the eye of another crow"
217        so prevent ravens from blinding each other */
218     if (magr && magr->data == &mons[PM_RAVEN] && mdef->data == &mons[PM_RAVEN])
219         return FALSE;
220 
221     switch (aatyp) {
222     case AT_EXPL:
223     case AT_BOOM:
224     case AT_GAZE:
225     case AT_MAGC:
226     case AT_BREA: /* assumed to be lightning */
227         /* light-based attacks may be cancelled or resisted */
228         if (magr && magr->mcan)
229             return FALSE;
230         return !resists_blnd(mdef);
231 
232     case AT_WEAP:
233     case AT_SPIT:
234     case AT_NONE:
235         /* an object is used (thrown/spit/other) */
236         if (obj && (obj->otyp == CREAM_PIE)) {
237             if (is_you && Blindfolded)
238                 return FALSE;
239         } else if (obj && (obj->otyp == BLINDING_VENOM)) {
240             /* all ublindf, including LENSES, protect, cream-pies too */
241             if (is_you && (ublindf || u.ucreamed))
242                 return FALSE;
243             check_visor = TRUE;
244         } else if (obj && (obj->otyp == POT_BLINDNESS)) {
245             return TRUE; /* no defense */
246         } else
247             return FALSE; /* other objects cannot cause blindness yet */
248         if ((magr == &g.youmonst) && u.uswallow)
249             return FALSE; /* can't affect eyes while inside monster */
250         break;
251 
252     case AT_ENGL:
253         if (is_you && (Blindfolded || Unaware || u.ucreamed))
254             return FALSE;
255         if (!is_you && mdef->msleeping)
256             return FALSE;
257         break;
258 
259     case AT_CLAW:
260         /* e.g. raven: all ublindf, including LENSES, protect */
261         if (is_you && ublindf)
262             return FALSE;
263         if ((magr == &g.youmonst) && u.uswallow)
264             return FALSE; /* can't affect eyes while inside monster */
265         check_visor = TRUE;
266         break;
267 
268     case AT_TUCH:
269     case AT_STNG:
270         /* some physical, blind-inducing attacks can be cancelled */
271         if (magr && magr->mcan)
272             return FALSE;
273         break;
274 
275     default:
276         break;
277     }
278 
279     /* check if wearing a visor (only checked if visor might help) */
280     if (check_visor) {
281         o = (mdef == &g.youmonst) ? g.invent : mdef->minvent;
282         for (; o; o = o->nobj)
283             if ((o->owornmask & W_ARMH)
284                 && objdescr_is(o, "visored helmet"))
285                 return FALSE;
286     }
287 
288     return TRUE;
289 }
290 
291 /* returns True if monster can attack at range */
292 boolean
ranged_attk(struct permonst * ptr)293 ranged_attk(struct permonst* ptr)
294 {
295     register int i, atyp;
296     long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
297 
298     /* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP)
299      *       || attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE)
300      *       || attacktype(ptr, AT_MAGC));
301      * but that's too slow -dlc
302      */
303     for (i = 0; i < NATTK; i++) {
304         atyp = ptr->mattk[i].aatyp;
305         if (atyp >= AT_WEAP)
306             return TRUE;
307         /* assert(atyp < 32); */
308         if ((atk_mask & (1L << atyp)) != 0L)
309             return TRUE;
310     }
311     return FALSE;
312 }
313 
314 /* True if specific monster is especially affected by weapons of the given
315  * material type */
316 boolean
mon_hates_material(struct monst * mon,int material)317 mon_hates_material(struct monst *mon, int material)
318 {
319     if (hates_material(mon->data, material))
320         return TRUE;
321 
322     /* extra case: shapeshifted vampires still hate silver */
323     if (material == SILVER && is_vampshifter(mon))
324         return TRUE;
325 
326     /* extra extra case: lycanthrope player (monster lycanthropes all fall under
327      * hates_material, and non-lycanthropes can't currently be infected) */
328     if (mon == &g.youmonst && material == SILVER && u.ulycn >= LOW_PM)
329         return TRUE;
330 
331     return FALSE;
332 }
333 
334 /* True if monster-type is especially affected by weapons of the given material
335  * type */
336 boolean
hates_material(register struct permonst * ptr,int material)337 hates_material(register struct permonst *ptr, int material)
338 {
339     if (material == SILVER) {
340         if (ptr->mlet == S_IMP) {
341             /* impish creatures that aren't actually demonic */
342             if (ptr == &mons[PM_TENGU])
343                 return FALSE;
344         }
345         return (is_were(ptr) || ptr->mlet == S_VAMPIRE
346                 || is_demon(ptr) || ptr == &mons[PM_SHADE]
347                 || (ptr->mlet == S_IMP));
348     }
349     else if (material == IRON) {
350         if (is_undead(ptr)) {
351             return FALSE;
352         }
353         /* cold iron: fairy/fae creatures hate it */
354         return (ptr->mlet == S_ELF || is_elf(ptr) || ptr->mlet == S_NYMPH
355                 || ptr->mlet == S_IMP);
356     }
357     else if (material == COPPER) {
358         /* copper has antibacterial and antifungal properties,
359          * very good versus sickness, mold and decay */
360         return (ptr->mlet == S_FUNGUS || dmgtype(ptr, AD_DISE)
361                 || dmgtype(ptr, AD_DCAY) || dmgtype(ptr, AD_PEST));
362     }
363     return FALSE;
364 }
365 
366 /* Return amount of damage a monster will take from coming into contact with a
367  * material it hates. */
368 int
sear_damage(int material)369 sear_damage(int material)
370 {
371     switch (material) {
372     case SILVER:
373         return 20;
374     case IRON:
375     default:
376         return 6;
377     }
378 }
379 
380 /* True if specific monster is especially affected by light-emitting weapons */
381 boolean
mon_hates_light(struct monst * mon)382 mon_hates_light(struct monst* mon)
383 {
384     return (boolean) (hates_light(mon->data));
385 }
386 
387 /* True iff the type of monster pass through iron bars */
388 boolean
passes_bars(struct permonst * mptr)389 passes_bars(struct permonst* mptr)
390 {
391     return (boolean) (passes_walls(mptr) || amorphous(mptr) || unsolid(mptr)
392                       || is_whirly(mptr) || verysmall(mptr)
393                       /* rust monsters and some puddings can destroy bars */
394                       || dmgtype(mptr, AD_RUST) || dmgtype(mptr, AD_CORR)
395                       /* rock moles can eat bars */
396                       || metallivorous(mptr)
397                       || (slithy(mptr) && !bigmonst(mptr)));
398 }
399 
400 /* returns True if monster can blow (whistle, etc) */
401 boolean
can_blow(struct monst * mtmp)402 can_blow(struct monst* mtmp)
403 {
404     if ((is_silent(mtmp->data) || mtmp->data->msound == MS_BUZZ)
405         && (breathless(mtmp->data) || verysmall(mtmp->data)
406             || !has_head(mtmp->data) || mtmp->data->mlet == S_EEL))
407         return FALSE;
408     if ((mtmp == &g.youmonst) && Strangled)
409         return FALSE;
410     return TRUE;
411 }
412 
413 /* for casting spells and reading scrolls while blind */
414 boolean
can_chant(struct monst * mtmp)415 can_chant(struct monst* mtmp)
416 {
417     if ((mtmp == &g.youmonst && Strangled)
418         || is_silent(mtmp->data) || !has_head(mtmp->data)
419         || mtmp->data->msound == MS_BUZZ || mtmp->data->msound == MS_BURBLE)
420         return FALSE;
421     return TRUE;
422 }
423 
424 /* True if mon is vulnerable to strangulation */
425 boolean
can_be_strangled(struct monst * mon)426 can_be_strangled(struct monst* mon)
427 {
428     struct obj *mamul;
429     boolean nonbreathing, nobrainer;
430 
431     /* For amulet of strangulation support:  here we're considering
432        strangulation to be loss of blood flow to the brain due to
433        constriction of the arteries in the neck, so all headless
434        creatures are immune (no neck) as are mindless creatures
435        who don't need to breathe (brain, if any, doesn't care).
436        Mindless creatures who do need to breath are vulnerable, as
437        are non-breathing creatures which have higher brain function. */
438     if (!has_head(mon->data))
439         return FALSE;
440     if (mon == &g.youmonst) {
441         /* hero can't be mindless but poly'ing into mindless form can
442            confer strangulation protection */
443         nobrainer = mindless(g.youmonst.data);
444         nonbreathing = Breathless;
445     } else {
446         nobrainer = mindless(mon->data);
447         /* monsters don't wear amulets of magical breathing,
448            so second part doesn't achieve anything useful... */
449         nonbreathing = (breathless(mon->data)
450                         || ((mamul = which_armor(mon, W_AMUL)) != 0
451                             && (mamul->otyp == AMULET_OF_MAGICAL_BREATHING)));
452     }
453     return (boolean) (!nobrainer || !nonbreathing);
454 }
455 
456 /* returns True if monster can track well */
457 boolean
can_track(register struct permonst * ptr)458 can_track(register struct permonst* ptr)
459 {
460     if (uwep && uwep->oartifact == ART_EXCALIBUR)
461         return TRUE;
462     else
463         return (boolean) haseyes(ptr);
464 }
465 
466 /* creature will slide out of armor */
467 boolean
sliparm(register struct permonst * ptr)468 sliparm(register struct permonst* ptr)
469 {
470     return (boolean) (is_whirly(ptr) || ptr->msize <= MZ_SMALL
471                       || noncorporeal(ptr)
472                       || (slithy(ptr) && !humanoid(ptr)
473                           && ptr->msize < MZ_GIGANTIC));
474 }
475 
476 /* creature will break out of armor */
477 boolean
breakarm(register struct permonst * ptr)478 breakarm(register struct permonst* ptr)
479 {
480     if (sliparm(ptr))
481         return FALSE;
482 
483     return (boolean) (bigmonst(ptr)
484                       || (ptr->msize > MZ_SMALL && !humanoid(ptr))
485                       /* special cases of humanoids that cannot wear suits */
486                       || ptr == &mons[PM_MARILITH]
487                       || ptr == &mons[PM_WINGED_GARGOYLE]);
488 }
489 
490 /* creature sticks other creatures it hits */
491 boolean
sticks(register struct permonst * ptr)492 sticks(register struct permonst* ptr)
493 {
494     return (boolean) (dmgtype(ptr, AD_STCK) || dmgtype(ptr, AD_WRAP)
495                       || attacktype(ptr, AT_HUGS));
496 }
497 
498 /* some monster-types can't vomit */
499 boolean
cantvomit(struct permonst * ptr)500 cantvomit(struct permonst* ptr)
501 {
502     /* rats and mice are incapable of vomiting;
503        which other creatures have the same limitation? */
504     if (ptr->mlet == S_RODENT && ptr != &mons[PM_ROCK_MOLE]
505         && ptr != &mons[PM_WOODCHUCK])
506         return TRUE;
507     return FALSE;
508 }
509 
510 /* number of horns this type of monster has on its head */
511 int
num_horns(struct permonst * ptr)512 num_horns(struct permonst* ptr)
513 {
514     switch (monsndx(ptr)) {
515     case PM_HORNED_DEVIL: /* ? "more than one" */
516     case PM_MINOTAUR:
517     case PM_ASMODEUS:
518     case PM_BALROG:
519         return 2;
520     case PM_WHITE_UNICORN:
521     case PM_GRAY_UNICORN:
522     case PM_BLACK_UNICORN:
523     case PM_KI_RIN:
524         return 1;
525     default:
526         break;
527     }
528     return 0;
529 }
530 
531 /* does monster-type deal out a particular type of damage from a particular
532    type of attack? */
533 struct attack *
dmgtype_fromattack(struct permonst * ptr,int dtyp,int atyp)534 dmgtype_fromattack(struct permonst* ptr, int dtyp, int atyp)
535 {
536     struct attack *a;
537 
538     for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
539         if (a->adtyp == dtyp && (atyp == AT_ANY || a->aatyp == atyp))
540             return a;
541     return (struct attack *) 0;
542 }
543 
544 /* does monster-type deal out a particular type of damage from any attack */
545 boolean
dmgtype(struct permonst * ptr,int dtyp)546 dmgtype(struct permonst* ptr, int dtyp)
547 {
548     return dmgtype_fromattack(ptr, dtyp, AT_ANY) ? TRUE : FALSE;
549 }
550 
551 /* returns the maximum damage a defender can do to the attacker via
552    a passive defense */
553 int
max_passive_dmg(register struct monst * mdef,register struct monst * magr)554 max_passive_dmg(register struct monst* mdef, register struct monst* magr)
555 {
556     int i, dmg, multi2 = 0;
557     uchar adtyp;
558 
559     /* each attack by magr can result in passive damage */
560     for (i = 0; i < NATTK; i++)
561         switch (magr->data->mattk[i].aatyp) {
562         case AT_CLAW:
563         case AT_BITE:
564         case AT_KICK:
565         case AT_BUTT:
566         case AT_TUCH:
567         case AT_STNG:
568         case AT_HUGS:
569         case AT_ENGL:
570         case AT_TENT:
571         case AT_WEAP:
572             multi2++;
573             break;
574         default:
575             break;
576         }
577 
578     dmg = 0;
579     for (i = 0; i < NATTK; i++)
580         if (mdef->data->mattk[i].aatyp == AT_NONE
581             || mdef->data->mattk[i].aatyp == AT_BOOM) {
582             adtyp = mdef->data->mattk[i].adtyp;
583             if ((adtyp == AD_FIRE && completelyburns(magr->data))
584                 || (adtyp == AD_DCAY && completelyrots(magr->data))
585                 || (adtyp == AD_RUST && completelyrusts(magr->data))) {
586                 dmg = magr->mhp;
587             } else if ((adtyp == AD_ACID && !resists_acid(magr))
588                        || (adtyp == AD_COLD && !resists_cold(magr))
589                        || (adtyp == AD_FIRE && !resists_fire(magr))
590                        || (adtyp == AD_ELEC && !resists_elec(magr))
591                        || adtyp == AD_PHYS) {
592                 dmg = mdef->data->mattk[i].damn;
593                 if (!dmg)
594                     dmg = mdef->data->mlevel + 1;
595                 dmg *= mdef->data->mattk[i].damd;
596             }
597             dmg *= multi2;
598             break;
599         }
600     return dmg;
601 }
602 
603 /* determine whether two monster types are from the same species */
604 boolean
same_race(struct permonst * pm1,struct permonst * pm2)605 same_race(struct permonst* pm1, struct permonst* pm2)
606 {
607     char let1 = pm1->mlet, let2 = pm2->mlet;
608 
609     if (pm1 == pm2)
610         return TRUE; /* exact match */
611     /* player races have their own predicates */
612     if (is_human(pm1))
613         return is_human(pm2);
614     if (is_elf(pm1))
615         return is_elf(pm2);
616     if (is_dwarf(pm1))
617         return is_dwarf(pm2);
618     if (is_gnome(pm1))
619         return is_gnome(pm2);
620     if (is_orc(pm1))
621         return is_orc(pm2);
622     /* other creatures are less precise */
623     if (is_giant(pm1))
624         return is_giant(pm2); /* open to quibbling here */
625     if (is_golem(pm1))
626         return is_golem(pm2); /* even moreso... */
627     if (is_mind_flayer(pm1))
628         return is_mind_flayer(pm2);
629     if (let1 == S_KOBOLD || pm1 == &mons[PM_KOBOLD_ZOMBIE]
630         || pm1 == &mons[PM_KOBOLD_MUMMY])
631         return (let2 == S_KOBOLD || pm2 == &mons[PM_KOBOLD_ZOMBIE]
632                 || pm2 == &mons[PM_KOBOLD_MUMMY]);
633     if (let1 == S_OGRE)
634         return (let2 == S_OGRE);
635     if (let1 == S_NYMPH)
636         return (let2 == S_NYMPH);
637     if (let1 == S_CENTAUR)
638         return (let2 == S_CENTAUR);
639     if (is_unicorn(pm1))
640         return is_unicorn(pm2);
641     if (let1 == S_DRAGON)
642         return (let2 == S_DRAGON);
643     if (let1 == S_NAGA)
644         return (let2 == S_NAGA);
645     /* other critters get steadily messier */
646     if (is_rider(pm1))
647         return is_rider(pm2); /* debatable */
648     if (is_minion(pm1))
649         return is_minion(pm2); /* [needs work?] */
650     /* tengu don't match imps (first test handled case of both being tengu) */
651     if (pm1 == &mons[PM_TENGU] || pm2 == &mons[PM_TENGU])
652         return FALSE;
653     if (let1 == S_IMP)
654         return (let2 == S_IMP);
655     /* and minor demons (imps) don't match major demons */
656     else if (let2 == S_IMP)
657         return FALSE;
658     if (is_demon(pm1))
659         return is_demon(pm2);
660     if (is_undead(pm1)) {
661         if (let1 == S_ZOMBIE)
662             return (let2 == S_ZOMBIE);
663         if (let1 == S_MUMMY)
664             return (let2 == S_MUMMY);
665         if (let1 == S_VAMPIRE)
666             return (let2 == S_VAMPIRE);
667         if (let1 == S_LICH)
668             return (let2 == S_LICH);
669         if (let1 == S_WRAITH)
670             return (let2 == S_WRAITH);
671     } else if (is_undead(pm2))
672         return FALSE;
673 
674     /* check for monsters which grow into more mature forms */
675     if (let1 == let2) {
676         int m1 = monsndx(pm1), m2 = monsndx(pm2), prv, nxt;
677 
678         /* we know m1 != m2 (very first check above); test all smaller
679            forms of m1 against m2, then all larger ones; don't need to
680            make the corresponding tests for variants of m2 against m1 */
681         for (prv = m1, nxt = big_to_little(m1); nxt != prv;
682              prv = nxt, nxt = big_to_little(nxt))
683             if (nxt == m2)
684                 return TRUE;
685         for (prv = m1, nxt = little_to_big(m1); nxt != prv;
686              prv = nxt, nxt = little_to_big(nxt))
687             if (nxt == m2)
688                 return TRUE;
689     }
690     /* not caught by little/big handling */
691     if (pm1 == &mons[PM_GARGOYLE] || pm1 == &mons[PM_WINGED_GARGOYLE])
692         return (pm2 == &mons[PM_GARGOYLE]
693                 || pm2 == &mons[PM_WINGED_GARGOYLE]);
694     if (pm1 == &mons[PM_KILLER_BEE] || pm1 == &mons[PM_QUEEN_BEE])
695         return (pm2 == &mons[PM_KILLER_BEE] || pm2 == &mons[PM_QUEEN_BEE]);
696 
697     if (is_longworm(pm1))
698         return is_longworm(pm2); /* handles tail */
699     /* [currently there's no reason to bother matching up
700         assorted bugs and blobs with their closest variants] */
701     /* didn't match */
702     return FALSE;
703 }
704 
705 /* return an index into the mons array */
706 int
monsndx(struct permonst * ptr)707 monsndx(struct permonst* ptr)
708 {
709     register int i;
710 
711     i = (int) (ptr - &mons[0]);
712     if (i < LOW_PM || i >= NUMMONS) {
713         panic("monsndx - could not index monster (%s)",
714               fmt_ptr((genericptr_t) ptr));
715         return NON_PM; /* will not get here */
716     }
717     return i;
718 }
719 
720 /* for handling alternate spellings */
721 struct alt_spl {
722     const char *name;
723     short pm_val;
724     int genderhint;
725 };
726 
727 /* figure out what type of monster a user-supplied string is specifying;
728    ingore anything past the monster name */
729 int
name_to_mon(const char * in_str,int * gender_name_var)730 name_to_mon(const char *in_str, int * gender_name_var)
731 {
732     return name_to_monplus(in_str, (const char **) 0, gender_name_var);
733 }
734 
735 /* figure out what type of monster a user-supplied string is specifying;
736    return a pointer to whatever is past the monster name--necessary if
737    caller wants to strip off the name and it matches one of the alternate
738    names rather the canonical mons[].mname */
739 int
name_to_monplus(const char * in_str,const char ** remainder_p,int * gender_name_var)740 name_to_monplus(
741     const char *in_str,
742     const char **remainder_p,
743     int *gender_name_var)
744 {
745     /* Be careful.  We must check the entire string in case it was
746      * something such as "ettin zombie corpse".  The calling routine
747      * doesn't know about the "corpse" until the monster name has
748      * already been taken off the front, so we have to be able to
749      * read the name with extraneous stuff such as "corpse" stuck on
750      * the end.
751      * This causes a problem for names which prefix other names such
752      * as "ettin" on "ettin zombie".  In this case we want the _longest_
753      * name which exists.
754      * This also permits plurals created by adding suffixes such as 's'
755      * or 'es'.  Other plurals must still be handled explicitly.
756      */
757     register int i;
758     register int mntmp = NON_PM;
759     register char *s, *str, *term;
760     char buf[BUFSZ];
761     int len, slen, mgend;
762     boolean exact_match = FALSE;
763 
764     if (remainder_p)
765         *remainder_p = (const char *) 0;
766 
767     str = strcpy(buf, in_str);
768 
769     if (!strncmp(str, "a ", 2))
770         str += 2;
771     else if (!strncmp(str, "an ", 3))
772         str += 3;
773     else if (!strncmp(str, "the ", 4))
774         str += 4;
775 
776     slen = strlen(str);
777     term = str + slen;
778 
779     if ((s = strstri(str, "vortices")) != 0)
780         Strcpy(s + 4, "ex");
781     /* be careful with "ies"; "priest", "zombies" */
782     else if (slen > 3 && !strcmpi(term - 3, "ies")
783              && (slen < 7 || strcmpi(term - 7, "zombies")))
784         Strcpy(term - 3, "y");
785     /* luckily no monster names end in fe or ve with ves plurals */
786     else if (slen > 3 && !strcmpi(term - 3, "ves"))
787         Strcpy(term - 3, "f");
788 
789     slen = strlen(str); /* length possibly needs recomputing */
790 
791     {
792         static const struct alt_spl names[] = {
793             /* Alternate spellings */
794             { "grey dragon", PM_GRAY_DRAGON, NEUTRAL },
795             { "baby grey dragon", PM_BABY_GRAY_DRAGON, NEUTRAL },
796             { "grey unicorn", PM_GRAY_UNICORN, NEUTRAL },
797             { "grey ooze", PM_GRAY_OOZE, NEUTRAL },
798             { "gray-elf", PM_GREY_ELF, NEUTRAL },
799             { "mindflayer", PM_MIND_FLAYER, NEUTRAL },
800             { "master mindflayer", PM_MASTER_MIND_FLAYER, NEUTRAL },
801             /* More alternates; priest and priestess are separate monster
802                types but that isn't the case for {aligned,high} priests */
803             { "aligned priest", PM_ALIGNED_CLERIC, MALE },
804             { "aligned priestess", PM_ALIGNED_CLERIC, FEMALE },
805             { "high priest", PM_HIGH_CLERIC, MALE },
806             { "high priestess", PM_HIGH_CLERIC, FEMALE },
807             /* Inappropriate singularization by -ves check above */
808             { "master of thief", PM_MASTER_OF_THIEVES, NEUTRAL },
809             /* Potential misspellings where we want to avoid falling back
810                to the rank title prefix (input has been singularized) */
811             { "master thief", PM_MASTER_OF_THIEVES, NEUTRAL },
812             { "master of assassin", PM_MASTER_ASSASSIN, NEUTRAL },
813             /* Outdated names */
814             { "invisible stalker", PM_STALKER, NEUTRAL },
815             { "high-elf", PM_ELVEN_MONARCH, NEUTRAL }, /* PM_HIGH_ELF is obsolete */
816             /* other misspellings or incorrect words */
817             { "wood-elf", PM_WOODLAND_ELF, NEUTRAL },
818             { "wood elf", PM_WOODLAND_ELF, NEUTRAL },
819             { "woodland nymph", PM_WOOD_NYMPH, NEUTRAL },
820             { "halfling", PM_HOBBIT, NEUTRAL },    /* potential guess for polyself */
821             { "genie", PM_DJINNI, NEUTRAL }, /* potential guess for ^G/#wizgenesis */
822             /* prefix used to workaround duplicate monster names for
823                monsters with alternate forms */
824             { "human wererat", PM_HUMAN_WERERAT, NEUTRAL },
825             { "human werejackal", PM_HUMAN_WEREJACKAL, NEUTRAL },
826             { "human werewolf", PM_HUMAN_WEREWOLF, NEUTRAL },
827             /* for completeness */
828             { "rat wererat", PM_WERERAT, NEUTRAL },
829             { "jackal werejackal", PM_WEREJACKAL, NEUTRAL },
830             { "wolf werewolf", PM_WEREWOLF, NEUTRAL },
831             /* Hyphenated names -- it would be nice to handle these via
832                fuzzymatch() but it isn't able to ignore trailing stuff */
833             { "ki rin", PM_KI_RIN, NEUTRAL },
834             { "kirin", PM_KI_RIN, NEUTRAL },
835             { "uruk hai", PM_URUK_HAI, NEUTRAL },
836             { "orc captain", PM_ORC_CAPTAIN, NEUTRAL },
837             { "woodland elf", PM_WOODLAND_ELF, NEUTRAL },
838             { "green elf", PM_GREEN_ELF, NEUTRAL },
839             { "grey elf", PM_GREY_ELF, NEUTRAL },
840             { "gray elf", PM_GREY_ELF, NEUTRAL },
841             { "elf lady", PM_ELF_NOBLE, FEMALE },
842             { "elf lord", PM_ELF_NOBLE, MALE },
843             { "elf noble", PM_ELF_NOBLE, NEUTRAL },
844             { "olog hai", PM_OLOG_HAI, NEUTRAL },
845             { "arch lich", PM_ARCH_LICH, NEUTRAL },
846             { "archlich", PM_ARCH_LICH, NEUTRAL },
847             /* Some irregular plurals */
848             { "incubi", PM_AMOROUS_DEMON, MALE },
849             { "succubi", PM_AMOROUS_DEMON, FEMALE },
850             { "violet fungi", PM_VIOLET_FUNGUS, NEUTRAL },
851             { "homunculi", PM_HOMUNCULUS, NEUTRAL },
852             { "baluchitheria", PM_BALUCHITHERIUM, NEUTRAL },
853             { "lurkers above", PM_LURKER_ABOVE, NEUTRAL },
854             { "cavemen", PM_CAVE_DWELLER, MALE },
855             { "cavewomen", PM_CAVE_DWELLER, FEMALE },
856             { "watchmen", PM_WATCHMAN, NEUTRAL },
857             { "djinn", PM_DJINNI, NEUTRAL },
858             { "mumakil", PM_MUMAK, NEUTRAL },
859             { "erinyes", PM_ERINYS, NEUTRAL },
860             /* end of list */
861             { 0, NON_PM, NEUTRAL }
862         };
863         register const struct alt_spl *namep;
864 
865         for (namep = names; namep->name; namep++) {
866             len = (int) strlen(namep->name);
867             if (!strncmpi(str, namep->name, len)
868                 /* force full word (which could conceivably be possessive) */
869                 && (!str[len] || str[len] == ' ' || str[len] == '\'')) {
870                 if (remainder_p)
871                     *remainder_p = in_str + (&str[len] - buf);
872                 if (gender_name_var != (int *) 0)
873                     *gender_name_var = namep->genderhint;
874                 return namep->pm_val;
875             }
876         }
877     }
878 
879     for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
880       for (mgend = MALE; mgend < NUM_MGENDERS; mgend++) {
881         int m_i_len;
882 
883         if (!mons[i].pmnames[mgend])
884             continue;
885 
886         m_i_len = (int) strlen(mons[i].pmnames[mgend]);
887         if (m_i_len > len && !strncmpi(mons[i].pmnames[mgend], str, m_i_len)) {
888             if (m_i_len == slen) {
889                 mntmp = i;
890                 len = m_i_len;
891                 if (gender_name_var != (int *) 0)
892                     *gender_name_var = mgend;
893                 exact_match = TRUE;
894                 break; /* exact match */
895             } else if (slen > m_i_len
896                        && (str[m_i_len] == ' '
897                            || !strcmpi(&str[m_i_len], "s")
898                            || !strncmpi(&str[m_i_len], "s ", 2)
899                            || !strcmpi(&str[m_i_len], "'")
900                            || !strncmpi(&str[m_i_len], "' ", 2)
901                            || !strcmpi(&str[m_i_len], "'s")
902                            || !strncmpi(&str[m_i_len], "'s ", 3)
903                            || !strcmpi(&str[m_i_len], "es")
904                            || !strncmpi(&str[m_i_len], "es ", 3))) {
905                 mntmp = i;
906                 len = m_i_len;
907             }
908         }
909     }
910       if (exact_match)
911         break;
912     }
913     if (mntmp == NON_PM)
914         mntmp = title_to_mon(str, (int *) 0, &len);
915     if (len && remainder_p)
916         *remainder_p = in_str + (&str[len] - buf);
917     return mntmp;
918 }
919 
920 /* monster class from user input; used for genocide and controlled polymorph;
921    returns 0 rather than MAXMCLASSES if no match is found */
922 int
name_to_monclass(const char * in_str,int * mndx_p)923 name_to_monclass(const char *in_str, int * mndx_p)
924 {
925     /* Single letters are matched against def_monsyms[].sym; words
926        or phrases are first matched against def_monsyms[].explain
927        to check class description; if not found there, then against
928        mons[].pmnames[] to test individual monster types.  Input can be a
929        substring of the full description or pmname, but to be accepted,
930        such partial matches must start at beginning of a word.  Some
931        class descriptions include "foo or bar" and "foo or other foo"
932        so we don't want to accept "or", "other", "or other" there. */
933     static NEARDATA const char *const falsematch[] = {
934         /* multiple-letter input which matches any of these gets rejected */
935         "an", "the", "or", "other", "or other", 0
936     };
937     /* positive pm_val => specific monster; negative => class */
938     static NEARDATA const struct alt_spl truematch[] = {
939         /* "long worm" won't match "worm" class but would accidentally match
940            "long worm tail" class before the comparison with monster types */
941         { "long worm", PM_LONG_WORM, NEUTRAL },
942         /* matches wrong--or at least suboptimal--class */
943         { "demon", -S_DEMON, NEUTRAL }, /* hits "imp or minor demon" */
944         /* matches specific monster (overly restrictive) */
945         { "devil", -S_DEMON, NEUTRAL }, /* always "horned devil" */
946         /* some plausible guesses which need help */
947         { "bug", -S_XAN, NEUTRAL },  /* would match bugbear... */
948         { "fish", -S_EEL, NEUTRAL }, /* wouldn't match anything */
949         /* end of list */
950         { 0, NON_PM, NEUTRAL}
951     };
952     const char *p, *x;
953     int i, len;
954 
955     if (mndx_p)
956         *mndx_p = NON_PM; /* haven't [yet] matched a specific type */
957 
958     if (!in_str || !in_str[0]) {
959         /* empty input */
960         return 0;
961     } else if (!in_str[1]) {
962         /* single character */
963         i = def_char_to_monclass(*in_str);
964         if (i == S_MIMIC_DEF) { /* ']' -> 'm' */
965             i = S_MIMIC;
966         } else if (i == S_WORM_TAIL) { /* '~' -> 'w' */
967             i = S_WORM;
968             if (mndx_p)
969                 *mndx_p = PM_LONG_WORM;
970         } else if (i == MAXMCLASSES) /* maybe 'I' */
971             i = (*in_str == DEF_INVISIBLE) ? S_invisible : 0;
972         return i;
973     } else {
974         /* multiple characters */
975         if (!strcmpi(in_str, "long")) /* not enough to match "long worm" */
976             return 0; /* avoid false whole-word match with "long worm tail" */
977         in_str = makesingular(in_str);
978         /* check for special cases */
979         for (i = 0; falsematch[i]; i++)
980             if (!strcmpi(in_str, falsematch[i]))
981                 return 0;
982         for (i = 0; truematch[i].name; i++)
983             if (!strcmpi(in_str, truematch[i].name)) {
984                 i = truematch[i].pm_val;
985                 if (i < 0)
986                     return -i; /* class */
987                 if (mndx_p)
988                     *mndx_p = i; /* monster */
989                 return mons[i].mlet;
990             }
991         /* check monster class descriptions */
992         len = (int) strlen(in_str);
993         for (i = 1; i < MAXMCLASSES; i++) {
994             x = def_monsyms[i].explain;
995             if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' ')
996                 && ((int) strlen(p) >= len
997                     && (p[len] == '\0' || p[len] == ' ')))
998                 return i;
999         }
1000         /* check individual species names */
1001         i = name_to_mon(in_str, (int *) 0);
1002         if (i != NON_PM) {
1003             if (mndx_p)
1004                 *mndx_p = i;
1005             return mons[i].mlet;
1006         }
1007     }
1008     return 0;
1009 }
1010 
1011 /* returns 3 values (0=male, 1=female, 2=none) */
1012 int
gender(register struct monst * mtmp)1013 gender(register struct monst* mtmp)
1014 {
1015     if (is_neuter(mtmp->data))
1016         return 2;
1017     return mtmp->female;
1018 }
1019 
1020 /* Like gender(), but unseen humanoids are "it" rather than "he" or "she"
1021    and lower animals and such are "it" even when seen; hallucination might
1022    yield "they".  This is the one we want to use when printing messages. */
1023 int
pronoun_gender(register struct monst * mtmp,unsigned pg_flags)1024 pronoun_gender(
1025     register struct monst *mtmp,
1026     unsigned pg_flags) /* flags&1: 'no it' unless neuter,
1027                     * flags&2: random if hallucinating */
1028 {
1029     boolean override_vis = (pg_flags & PRONOUN_NO_IT) ? TRUE : FALSE,
1030             hallu_rand = (pg_flags & PRONOUN_HALLU) ? TRUE : FALSE;
1031 
1032     if (hallu_rand && Hallucination)
1033         return rn2(4); /* 0..3 */
1034     if (!override_vis && !canspotmon(mtmp))
1035         return 2;
1036     if (is_neuter(mtmp->data))
1037         return 2;
1038     return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ)
1039             || type_is_pname(mtmp->data)) ? (int) mtmp->female : 2;
1040 }
1041 
1042 /* used for nearby monsters when you go to another level */
1043 boolean
levl_follower(struct monst * mtmp)1044 levl_follower(struct monst* mtmp)
1045 {
1046     if (mtmp == u.usteed)
1047         return TRUE;
1048 
1049     /* Wizard with Amulet won't bother trying to follow across levels */
1050     if (mtmp->iswiz && mon_has_amulet(mtmp))
1051         return FALSE;
1052     /* some monsters will follow even while intending to flee from you */
1053     if (mtmp->mtame || mtmp->iswiz || is_fshk(mtmp))
1054         return TRUE;
1055     /* stalking types follow, but won't when fleeing unless you hold
1056        the Amulet */
1057     return (boolean) ((mtmp->data->mflags2 & M2_STALK)
1058                       && (!mtmp->mflee || u.uhave.amulet));
1059 }
1060 
1061 static const short grownups[][2] = {
1062     { PM_CHICKATRICE, PM_COCKATRICE },
1063     { PM_LITTLE_DOG, PM_DOG },
1064     { PM_DOG, PM_LARGE_DOG },
1065     { PM_HELL_HOUND_PUP, PM_HELL_HOUND },
1066     { PM_WINTER_WOLF_CUB, PM_WINTER_WOLF },
1067     { PM_KITTEN, PM_HOUSECAT },
1068     { PM_HOUSECAT, PM_LARGE_CAT },
1069     { PM_PONY, PM_HORSE },
1070     { PM_HORSE, PM_WARHORSE },
1071     { PM_KOBOLD, PM_LARGE_KOBOLD },
1072     { PM_LARGE_KOBOLD, PM_KOBOLD_LEADER },
1073     { PM_GNOME, PM_GNOME_LEADER },
1074     { PM_GNOME_LEADER, PM_GNOME_RULER },
1075     { PM_DWARF, PM_DWARF_LEADER },
1076     { PM_DWARF_LEADER, PM_DWARF_RULER },
1077     { PM_MIND_FLAYER, PM_MASTER_MIND_FLAYER },
1078     { PM_ORC, PM_ORC_CAPTAIN },
1079     { PM_HILL_ORC, PM_ORC_CAPTAIN },
1080     { PM_MORDOR_ORC, PM_ORC_CAPTAIN },
1081     { PM_URUK_HAI, PM_ORC_CAPTAIN },
1082     { PM_SEWER_RAT, PM_GIANT_RAT },
1083     { PM_CAVE_SPIDER, PM_GIANT_SPIDER },
1084     { PM_OGRE, PM_OGRE_LEADER },
1085     { PM_OGRE_LEADER, PM_OGRE_TYRANT },
1086     { PM_ELF, PM_ELF_NOBLE },
1087     { PM_WOODLAND_ELF, PM_ELF_NOBLE },
1088     { PM_GREEN_ELF, PM_ELF_NOBLE },
1089     { PM_GREY_ELF, PM_ELF_NOBLE },
1090     { PM_ELF_NOBLE, PM_ELVEN_MONARCH },
1091     { PM_LICH, PM_DEMILICH },
1092     { PM_DEMILICH, PM_MASTER_LICH },
1093     { PM_MASTER_LICH, PM_ARCH_LICH },
1094     { PM_VAMPIRE, PM_VAMPIRE_LEADER },
1095     { PM_BAT, PM_GIANT_BAT },
1096     { PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON },
1097     { PM_BABY_SILVER_DRAGON, PM_SILVER_DRAGON },
1098 #if 0 /* DEFERRED */
1099     {PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
1100 #endif
1101     { PM_BABY_RED_DRAGON, PM_RED_DRAGON },
1102     { PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON },
1103     { PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON },
1104     { PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON },
1105     { PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON },
1106     { PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON },
1107     { PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON },
1108     { PM_RED_NAGA_HATCHLING, PM_RED_NAGA },
1109     { PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA },
1110     { PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA },
1111     { PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA },
1112     { PM_SMALL_MIMIC, PM_LARGE_MIMIC },
1113     { PM_LARGE_MIMIC, PM_GIANT_MIMIC },
1114     { PM_BABY_LONG_WORM, PM_LONG_WORM },
1115     { PM_BABY_PURPLE_WORM, PM_PURPLE_WORM },
1116     { PM_BABY_CROCODILE, PM_CROCODILE },
1117     { PM_SOLDIER, PM_SERGEANT },
1118     { PM_SERGEANT, PM_LIEUTENANT },
1119     { PM_LIEUTENANT, PM_CAPTAIN },
1120     { PM_WATCHMAN, PM_WATCH_CAPTAIN },
1121     { PM_ALIGNED_CLERIC, PM_HIGH_CLERIC },
1122     { PM_STUDENT, PM_ARCHEOLOGIST },
1123     { PM_ATTENDANT, PM_HEALER },
1124     { PM_PAGE, PM_KNIGHT },
1125     { PM_ACOLYTE, PM_CLERIC },
1126     { PM_APPRENTICE, PM_WIZARD },
1127     { PM_MANES, PM_LEMURE },
1128     { PM_KEYSTONE_KOP, PM_KOP_SERGEANT },
1129     { PM_KOP_SERGEANT, PM_KOP_LIEUTENANT },
1130     { PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN },
1131     { NON_PM, NON_PM }
1132 };
1133 
1134 int
little_to_big(int montype)1135 little_to_big(int montype)
1136 {
1137     register int i;
1138 
1139     for (i = 0; grownups[i][0] >= LOW_PM; i++)
1140         if (montype == grownups[i][0]) {
1141             montype = grownups[i][1];
1142             break;
1143         }
1144     return montype;
1145 }
1146 
1147 int
big_to_little(int montype)1148 big_to_little(int montype)
1149 {
1150     register int i;
1151 
1152     for (i = 0; grownups[i][0] >= LOW_PM; i++)
1153         if (montype == grownups[i][1]) {
1154             montype = grownups[i][0];
1155             break;
1156         }
1157     return montype;
1158 }
1159 
1160 /* determine whether two permonst indices are part of the same progression;
1161    existence of progressions with more than one step makes it a bit tricky */
1162 boolean
big_little_match(int montyp1,int montyp2)1163 big_little_match(int montyp1, int montyp2)
1164 {
1165     int l, b;
1166 
1167     /* simplest case: both are same pm */
1168     if (montyp1 == montyp2)
1169         return TRUE;
1170     /* assume it isn't possible to grow from one class letter to another */
1171     if (mons[montyp1].mlet != mons[montyp2].mlet)
1172         return FALSE;
1173     /* check whether montyp1 can grow up into montyp2 */
1174     for (l = montyp1; (b = little_to_big(l)) != l; l = b)
1175         if (b == montyp2)
1176             return TRUE;
1177     /* check whether montyp2 can grow up into montyp1 */
1178     for (l = montyp2; (b = little_to_big(l)) != l; l = b)
1179         if (b == montyp1)
1180             return TRUE;
1181     /* neither grows up to become the other; no match */
1182     return FALSE;
1183 }
1184 
1185 /*
1186  * Return the permonst ptr for the race of the monster.
1187  * Returns correct pointer for non-polymorphed and polymorphed
1188  * player.  It does not return a pointer to player role character.
1189  */
1190 const struct permonst *
raceptr(struct monst * mtmp)1191 raceptr(struct monst* mtmp)
1192 {
1193     if (mtmp == &g.youmonst && !Upolyd)
1194         return &mons[g.urace.malenum];
1195     else
1196         return mtmp->data;
1197 }
1198 
1199 static const char *levitate[4] = { "float", "Float", "wobble", "Wobble" };
1200 static const char *flys[4] = { "fly", "Fly", "flutter", "Flutter" };
1201 static const char *flyl[4] = { "fly", "Fly", "stagger", "Stagger" };
1202 static const char *slither[4] = { "slither", "Slither", "falter", "Falter" };
1203 static const char *ooze[4] = { "ooze", "Ooze", "tremble", "Tremble" };
1204 static const char *immobile[4] = { "wiggle", "Wiggle", "pulsate", "Pulsate" };
1205 static const char *crawl[4] = { "crawl", "Crawl", "falter", "Falter" };
1206 
1207 const char *
locomotion(const struct permonst * ptr,const char * def)1208 locomotion(const struct permonst* ptr, const char* def)
1209 {
1210     int capitalize = (*def == highc(*def));
1211 
1212     return (is_floater(ptr) ? levitate[capitalize]
1213             : (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize]
1214               : (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize]
1215                 : slithy(ptr) ? slither[capitalize]
1216                   : amorphous(ptr) ? ooze[capitalize]
1217                     : !ptr->mmove ? immobile[capitalize]
1218                       : nolimbs(ptr) ? crawl[capitalize]
1219                         : def);
1220 }
1221 
1222 const char *
stagger(const struct permonst * ptr,const char * def)1223 stagger(const struct permonst* ptr, const char* def)
1224 {
1225     int capitalize = 2 + (*def == highc(*def));
1226 
1227     return (is_floater(ptr) ? levitate[capitalize]
1228             : (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize]
1229               : (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize]
1230                 : slithy(ptr) ? slither[capitalize]
1231                   : amorphous(ptr) ? ooze[capitalize]
1232                     : !ptr->mmove ? immobile[capitalize]
1233                       : nolimbs(ptr) ? crawl[capitalize]
1234                         : def);
1235 }
1236 
1237 /* return phrase describing the effect of fire attack on a type of monster */
1238 const char *
on_fire(struct permonst * mptr,struct attack * mattk)1239 on_fire(struct permonst* mptr, struct attack* mattk)
1240 {
1241     const char *what;
1242 
1243     switch (monsndx(mptr)) {
1244     case PM_FLAMING_SPHERE:
1245     case PM_FIRE_VORTEX:
1246     case PM_FIRE_ELEMENTAL:
1247     case PM_SALAMANDER:
1248         what = "already on fire";
1249         break;
1250     case PM_WATER_ELEMENTAL:
1251     case PM_FOG_CLOUD:
1252     case PM_STEAM_VORTEX:
1253         what = "boiling";
1254         break;
1255     case PM_ICE_VORTEX:
1256     case PM_GLASS_GOLEM:
1257         what = "melting";
1258         break;
1259     case PM_STONE_GOLEM:
1260     case PM_CLAY_GOLEM:
1261     case PM_GOLD_GOLEM:
1262     case PM_AIR_ELEMENTAL:
1263     case PM_EARTH_ELEMENTAL:
1264     case PM_DUST_VORTEX:
1265     case PM_ENERGY_VORTEX:
1266         what = "heating up";
1267         break;
1268     default:
1269         what = (mattk->aatyp == AT_HUGS) ? "being roasted" : "on fire";
1270         break;
1271     }
1272     return what;
1273 }
1274 
1275 /*
1276  * Returns:
1277  *      True if monster is presumed to have a sense of smell.
1278  *      False if monster definitely does not have a sense of smell.
1279  *
1280  * Do not base this on presence of a head or nose, since many
1281  * creatures sense smells other ways (feelers, forked-tongues, etc.)
1282  * We're assuming all insects can smell at a distance too.
1283  */
1284 boolean
olfaction(struct permonst * mdat)1285 olfaction(struct permonst* mdat)
1286 {
1287     if (is_golem(mdat)
1288         || mdat->mlet == S_EYE /* spheres  */
1289         || mdat->mlet == S_JELLY || mdat->mlet == S_PUDDING
1290         || mdat->mlet == S_BLOB || mdat->mlet == S_VORTEX
1291         || mdat->mlet == S_ELEMENTAL
1292         || mdat->mlet == S_FUNGUS /* mushrooms and fungi */
1293         || mdat->mlet == S_LIGHT)
1294         return FALSE;
1295     return TRUE;
1296 }
1297 
1298 /* Return the material a monster is composed of.
1299  * Don't get too specific; most monsters should return 0 from here. We're only
1300  * interested if it's something unusual. */
1301 int
monmaterial(int mndx)1302 monmaterial(int mndx)
1303 {
1304     switch (mndx) {
1305     case PM_GARGOYLE:
1306     case PM_WINGED_GARGOYLE:
1307     case PM_EARTH_ELEMENTAL:
1308     case PM_CLAY_GOLEM:
1309     case PM_STONE_GOLEM:
1310         return MINERAL;
1311     case PM_SKELETON:
1312         return BONE;
1313     case PM_PAPER_GOLEM:
1314         return PAPER;
1315     case PM_GOLD_GOLEM:
1316         return GOLD;
1317     case PM_LEATHER_GOLEM:
1318         return LEATHER;
1319     case PM_WOOD_GOLEM:
1320         return WOOD;
1321     case PM_GLASS_GOLEM:
1322         return GLASS;
1323     case PM_IRON_GOLEM:
1324         return IRON;
1325     default:
1326         return 0;
1327     }
1328 }
1329 
1330 /* Return the radius at which a monster is supposed to emit light, or 0 if it
1331  * does not emit any light. (The return value is also commonly used as a boolean
1332  * expression.)
1333  * This was moved out of mondata.h because it was becoming a rather complex
1334  * macro.
1335  */
1336 int
emits_light(struct permonst * ptr)1337 emits_light(struct permonst *ptr)
1338 {
1339     if (!ptr) {
1340         impossible("emits_light: null permonst!");
1341         return 0;
1342     }
1343     if (ptr->mlet == S_LIGHT) {
1344         if (ptr == &mons[PM_YELLOW_LIGHT]) {
1345             return 2;
1346         }
1347         return 1;
1348     }
1349     switch(monsndx(ptr)) {
1350     case PM_FIRE_ELEMENTAL:
1351         return 2;
1352     case PM_FLAMING_SPHERE:
1353     case PM_SHOCKING_SPHERE:
1354     case PM_FIRE_VORTEX:
1355         return 1;
1356     }
1357     return 0;
1358 }
1359 
1360 /* Return TRUE if the monster has flesh. */
1361 boolean
is_fleshy(const struct permonst * ptr)1362 is_fleshy(const struct permonst *ptr)
1363 {
1364     if (vegetarian(ptr)) {
1365         /* vegetarian monsters generally don't have flesh */
1366         return FALSE;
1367     }
1368     if (noncorporeal(ptr)) {
1369         /* these certainly don't have flesh */
1370         return FALSE;
1371     }
1372     if (!nonliving(ptr)) {
1373         /* nonvegetarian, alive monsters generally do */
1374         return TRUE;
1375     }
1376     if (ptr->mlet == S_MUMMY || ptr->mlet == S_VAMPIRE
1377         || (ptr->mlet == S_ZOMBIE && ptr != &mons[PM_SKELETON])
1378         || ptr == &mons[PM_FLESH_GOLEM]) {
1379         /* Exceptions: non-living monsters that do have flesh */
1380         return TRUE;
1381     }
1382     return FALSE;
1383 }
1384 
1385 /*mondata.c*/
1386