OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / src / mondata.c
1 /* NetHack 3.6  mondata.c       $NHDT-Date: 1446604115 2015/11/04 02:28:35 $  $NHDT-Branch: master $:$NHDT-Revision: 1.58 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6
7 /*      These routines provide basic data for any type of monster. */
8
9 /* set up an individual monster's base type (initial creation, shapechange) */
10 void
11 set_mon_data(mon, ptr, flag)
12 struct monst *mon;
13 struct permonst *ptr;
14 int flag;
15 {
16     mon->data = ptr;
17     if (flag == -1)
18         return; /* "don't care" */
19
20     if (flag == 1)
21         mon->mintrinsics |= (ptr->mresists & 0x00FF);
22     else
23         mon->mintrinsics = (ptr->mresists & 0x00FF);
24     return;
25 }
26
27 /* does monster-type have any attack for a specific type of damage? */
28 struct attack *
29 attacktype_fordmg(ptr, atyp, dtyp)
30 struct permonst *ptr;
31 int atyp, dtyp;
32 {
33     struct attack *a;
34
35     for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
36         if (a->aatyp == atyp && (dtyp == AD_ANY || a->adtyp == dtyp))
37             return a;
38     return (struct attack *) 0;
39 }
40
41 /* does monster-type have a particular type of attack */
42 boolean
43 attacktype(ptr, atyp)
44 struct permonst *ptr;
45 int atyp;
46 {
47     return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE;
48 }
49
50 /* returns True if monster doesn't attack, False if it does */
51 boolean
52 noattacks(ptr)
53 struct permonst *ptr;
54 {
55     int i;
56     struct attack *mattk = ptr->mattk;
57
58     for (i = 0; i < NATTK; i++) {
59         /* AT_BOOM "passive attack" (gas spore's explosion upon death)
60            isn't an attack as far as our callers are concerned */
61         if (mattk[i].aatyp == AT_BOOM)
62             continue;
63
64         if (mattk[i].aatyp)
65             return FALSE;
66     }
67     return TRUE;
68 }
69
70 /* does monster-type transform into something else when petrified? */
71 boolean
72 poly_when_stoned(ptr)
73 struct permonst *ptr;
74 {
75     /* non-stone golems turn into stone golems unless latter is genocided */
76     return (boolean) (is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM]
77                       && !(mvitals[PM_STONE_GOLEM].mvflags & G_GENOD));
78     /* allow G_EXTINCT */
79 }
80
81 /* returns True if monster is drain-life resistant */
82 boolean
83 resists_drli(mon)
84 struct monst *mon;
85 {
86     struct permonst *ptr = mon->data;
87     struct obj *wep;
88
89     if (is_undead(ptr) || is_demon(ptr) || is_were(ptr)
90         /* is_were() doesn't handle hero in human form */
91         || (mon == &youmonst && u.ulycn >= LOW_PM)
92         || ptr == &mons[PM_DEATH] || is_vampshifter(mon))
93         return TRUE;
94     wep = (mon == &youmonst) ? uwep : MON_WEP(mon);
95     return (boolean) (wep && wep->oartifact && defends(AD_DRLI, wep));
96 }
97
98 /* True if monster is magic-missile (actually, general magic) resistant */
99 boolean
100 resists_magm(mon)
101 struct monst *mon;
102 {
103     struct permonst *ptr = mon->data;
104     boolean is_you = (mon == &youmonst);
105     long slotmask;
106     struct obj *o;
107
108     /* as of 3.2.0:  gray dragons, Angels, Oracle, Yeenoghu */
109     if (dmgtype(ptr, AD_MAGM) || ptr == &mons[PM_BABY_GRAY_DRAGON]
110         || dmgtype(ptr, AD_RBRE)) /* Chromatic Dragon */
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 ? 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 resistant to light-induced blindness */
133 boolean
134 resists_blnd(mon)
135 struct monst *mon;
136 {
137     struct permonst *ptr = mon->data;
138     boolean is_you = (mon == &youmonst);
139     long slotmask;
140     struct obj *o;
141
142     if (is_you ? (Blind || Unaware)
143                : (mon->mblinded || !mon->mcansee || !haseyes(ptr)
144                   /* BUG: temporary sleep sets mfrozen, but since
145                           paralysis does too, we can't check it */
146                   || mon->msleeping))
147         return TRUE;
148     /* yellow light, Archon; !dust vortex, !cobra, !raven */
149     if (dmgtype_fromattack(ptr, AD_BLND, AT_EXPL)
150         || dmgtype_fromattack(ptr, AD_BLND, AT_GAZE))
151         return TRUE;
152     o = is_you ? uwep : MON_WEP(mon);
153     if (o && o->oartifact && defends(AD_BLND, o))
154         return TRUE;
155     o = is_you ? invent : mon->minvent;
156     slotmask = W_ARMOR | W_ACCESSORY;
157     if (!is_you /* assumes monsters don't wield non-weapons */
158         || (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))))
159         slotmask |= W_WEP;
160     if (is_you && u.twoweap)
161         slotmask |= W_SWAPWEP;
162     for (; o; o = o->nobj)
163         if (((o->owornmask & slotmask) != 0L
164              && objects[o->otyp].oc_oprop == BLINDED)
165             || (o->oartifact && defends_when_carried(AD_BLND, o)))
166             return TRUE;
167     return FALSE;
168 }
169
170 /* True iff monster can be blinded by the given attack;
171    note: may return True when mdef is blind (e.g. new cream-pie attack) */
172 boolean
173 can_blnd(magr, mdef, aatyp, obj)
174 struct monst *magr; /* NULL == no specific aggressor */
175 struct monst *mdef;
176 uchar aatyp;
177 struct obj *obj; /* aatyp == AT_WEAP, AT_SPIT */
178 {
179     boolean is_you = (mdef == &youmonst);
180     boolean check_visor = FALSE;
181     struct obj *o;
182     const char *s;
183
184     /* no eyes protect against all attacks for now */
185     if (!haseyes(mdef->data))
186         return FALSE;
187
188     switch (aatyp) {
189     case AT_EXPL:
190     case AT_BOOM:
191     case AT_GAZE:
192     case AT_MAGC:
193     case AT_BREA: /* assumed to be lightning */
194         /* light-based attacks may be cancelled or resisted */
195         if (magr && magr->mcan)
196             return FALSE;
197         return !resists_blnd(mdef);
198
199     case AT_WEAP:
200     case AT_SPIT:
201     case AT_NONE:
202         /* an object is used (thrown/spit/other) */
203         if (obj && (obj->otyp == CREAM_PIE)) {
204             if (is_you && Blindfolded)
205                 return FALSE;
206         } else if (obj && (obj->otyp == BLINDING_VENOM)) {
207             /* all ublindf, including LENSES, protect, cream-pies too */
208             if (is_you && (ublindf || u.ucreamed))
209                 return FALSE;
210             check_visor = TRUE;
211         } else if (obj && (obj->otyp == POT_BLINDNESS)) {
212             return TRUE; /* no defense */
213         } else
214             return FALSE; /* other objects cannot cause blindness yet */
215         if ((magr == &youmonst) && u.uswallow)
216             return FALSE; /* can't affect eyes while inside monster */
217         break;
218
219     case AT_ENGL:
220         if (is_you && (Blindfolded || Unaware || u.ucreamed))
221             return FALSE;
222         if (!is_you && mdef->msleeping)
223             return FALSE;
224         break;
225
226     case AT_CLAW:
227         /* e.g. raven: all ublindf, including LENSES, protect */
228         if (is_you && ublindf)
229             return FALSE;
230         if ((magr == &youmonst) && u.uswallow)
231             return FALSE; /* can't affect eyes while inside monster */
232         check_visor = TRUE;
233         break;
234
235     case AT_TUCH:
236     case AT_STNG:
237         /* some physical, blind-inducing attacks can be cancelled */
238         if (magr && magr->mcan)
239             return FALSE;
240         break;
241
242     default:
243         break;
244     }
245
246     /* check if wearing a visor (only checked if visor might help) */
247     if (check_visor) {
248         o = (mdef == &youmonst) ? invent : mdef->minvent;
249         for (; o; o = o->nobj)
250             if ((o->owornmask & W_ARMH)
251                 && (s = OBJ_DESCR(objects[o->otyp])) != (char *) 0
252                 && !strcmp(s, "visored helmet"))
253                 return FALSE;
254     }
255
256     return TRUE;
257 }
258
259 /* returns True if monster can attack at range */
260 boolean
261 ranged_attk(ptr)
262 struct permonst *ptr;
263 {
264     register int i, atyp;
265     long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
266
267     /* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP)
268      *       || attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE)
269      *       || attacktype(ptr, AT_MAGC));
270      * but that's too slow -dlc
271      */
272     for (i = 0; i < NATTK; i++) {
273         atyp = ptr->mattk[i].aatyp;
274         if (atyp >= AT_WEAP)
275             return TRUE;
276         /* assert(atyp < 32); */
277         if ((atk_mask & (1L << atyp)) != 0L)
278             return TRUE;
279     }
280     return FALSE;
281 }
282
283 /* True if specific monster is especially affected by silver weapons */
284 boolean
285 mon_hates_silver(mon)
286 struct monst *mon;
287 {
288     return (boolean) (is_vampshifter(mon) || hates_silver(mon->data));
289 }
290
291 /* True if monster-type is especially affected by silver weapons */
292 boolean
293 hates_silver(ptr)
294 register struct permonst *ptr;
295 {
296     return (boolean) (is_were(ptr) || ptr->mlet == S_VAMPIRE || is_demon(ptr)
297                       || ptr == &mons[PM_SHADE]
298                       || (ptr->mlet == S_IMP && ptr != &mons[PM_TENGU]));
299 }
300
301 /* True iff the type of monster pass through iron bars */
302 boolean
303 passes_bars(mptr)
304 struct permonst *mptr;
305 {
306     return (boolean) (passes_walls(mptr) || amorphous(mptr) || unsolid(mptr)
307                       || is_whirly(mptr) || verysmall(mptr)
308                       || dmgtype(mptr, AD_CORR) || dmgtype(mptr, AD_RUST)
309                       || (slithy(mptr) && !bigmonst(mptr)));
310 }
311
312 /* returns True if monster can blow (whistle, etc) */
313 boolean
314 can_blow(mtmp)
315 register struct monst *mtmp;
316 {
317     if ((is_silent(mtmp->data) || mtmp->data->msound == MS_BUZZ)
318         && (breathless(mtmp->data) || verysmall(mtmp->data)
319             || !has_head(mtmp->data) || mtmp->data->mlet == S_EEL))
320         return FALSE;
321     if ((mtmp == &youmonst) && Strangled)
322         return FALSE;
323     return TRUE;
324 }
325
326 /* True if mon is vulnerable to strangulation */
327 boolean
328 can_be_strangled(mon)
329 struct monst *mon;
330 {
331     struct obj *mamul;
332     boolean nonbreathing, nobrainer;
333
334     /* For amulet of strangulation support:  here we're considering
335        strangulation to be loss of blood flow to the brain due to
336        constriction of the arteries in the neck, so all headless
337        creatures are immune (no neck) as are mindless creatures
338        who don't need to breathe (brain, if any, doesn't care).
339        Mindless creatures who do need to breath are vulnerable, as
340        are non-breathing creatures which have higher brain function. */
341     if (!has_head(mon->data))
342         return FALSE;
343     if (mon == &youmonst) {
344         /* hero can't be mindless but poly'ing into mindless form can
345            confer strangulation protection */
346         nobrainer = mindless(youmonst.data);
347         nonbreathing = Breathless;
348     } else {
349         nobrainer = mindless(mon->data);
350         /* monsters don't wear amulets of magical breathing,
351            so second part doesn't achieve anything useful... */
352         nonbreathing = (breathless(mon->data)
353                         || ((mamul = which_armor(mon, W_AMUL)) != 0
354                             && (mamul->otyp == AMULET_OF_MAGICAL_BREATHING)));
355     }
356     return (boolean) (!nobrainer || !nonbreathing);
357 }
358
359 /* returns True if monster can track well */
360 boolean
361 can_track(ptr)
362 register struct permonst *ptr;
363 {
364     if (uwep && uwep->oartifact == ART_EXCALIBUR)
365         return TRUE;
366     else
367         return (boolean) haseyes(ptr);
368 }
369
370 /* creature will slide out of armor */
371 boolean
372 sliparm(ptr)
373 register struct permonst *ptr;
374 {
375     return (boolean) (is_whirly(ptr) || ptr->msize <= MZ_SMALL
376                       || noncorporeal(ptr));
377 }
378
379 /* creature will break out of armor */
380 boolean
381 breakarm(ptr)
382 register struct permonst *ptr;
383 {
384     if (sliparm(ptr))
385         return FALSE;
386
387     return (boolean) (bigmonst(ptr)
388                       || (ptr->msize > MZ_SMALL && !humanoid(ptr))
389                       /* special cases of humanoids that cannot wear suits */
390                       || ptr == &mons[PM_MARILITH]
391                       || ptr == &mons[PM_WINGED_GARGOYLE]);
392 }
393
394 /* creature sticks other creatures it hits */
395 boolean
396 sticks(ptr)
397 register struct permonst *ptr;
398 {
399     return (boolean) (dmgtype(ptr, AD_STCK) || dmgtype(ptr, AD_WRAP)
400                       || attacktype(ptr, AT_HUGS));
401 }
402
403 /* some monster-types can't vomit */
404 boolean
405 cantvomit(ptr)
406 struct permonst *ptr;
407 {
408     /* rats and mice are incapable of vomiting;
409        which other creatures have the same limitation? */
410     if (ptr->mlet == S_RODENT && ptr != &mons[PM_ROCK_MOLE]
411         && ptr != &mons[PM_WOODCHUCK])
412         return TRUE;
413     return FALSE;
414 }
415
416 /* number of horns this type of monster has on its head */
417 int
418 num_horns(ptr)
419 struct permonst *ptr;
420 {
421     switch (monsndx(ptr)) {
422     case PM_HORNED_DEVIL: /* ? "more than one" */
423     case PM_MINOTAUR:
424     case PM_ASMODEUS:
425     case PM_BALROG:
426         return 2;
427     case PM_WHITE_UNICORN:
428     case PM_GRAY_UNICORN:
429     case PM_BLACK_UNICORN:
430     case PM_KI_RIN:
431         return 1;
432     default:
433         break;
434     }
435     return 0;
436 }
437
438 /* does monster-type deal out a particular type of damage from a particular
439    type of attack? */
440 struct attack *
441 dmgtype_fromattack(ptr, dtyp, atyp)
442 struct permonst *ptr;
443 int dtyp, atyp;
444 {
445     struct attack *a;
446
447     for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
448         if (a->adtyp == dtyp && (atyp == AT_ANY || a->aatyp == atyp))
449             return a;
450     return (struct attack *) 0;
451 }
452
453 /* does monster-type deal out a particular type of damage from any attack */
454 boolean
455 dmgtype(ptr, dtyp)
456 struct permonst *ptr;
457 int dtyp;
458 {
459     return dmgtype_fromattack(ptr, dtyp, AT_ANY) ? TRUE : FALSE;
460 }
461
462 /* returns the maximum damage a defender can do to the attacker via
463    a passive defense */
464 int
465 max_passive_dmg(mdef, magr)
466 register struct monst *mdef, *magr;
467 {
468     int i, dmg = 0, multi2 = 0;
469     uchar adtyp;
470
471     /* each attack by magr can result in passive damage */
472     for (i = 0; i < NATTK; i++)
473         switch (magr->data->mattk[i].aatyp) {
474         case AT_CLAW:
475         case AT_BITE:
476         case AT_KICK:
477         case AT_BUTT:
478         case AT_TUCH:
479         case AT_STNG:
480         case AT_HUGS:
481         case AT_ENGL:
482         case AT_TENT:
483         case AT_WEAP:
484             multi2++;
485             break;
486         default:
487             break;
488         }
489
490     for (i = 0; i < NATTK; i++)
491         if (mdef->data->mattk[i].aatyp == AT_NONE
492             || mdef->data->mattk[i].aatyp == AT_BOOM) {
493             adtyp = mdef->data->mattk[i].adtyp;
494             if ((adtyp == AD_ACID && !resists_acid(magr))
495                 || (adtyp == AD_COLD && !resists_cold(magr))
496                 || (adtyp == AD_FIRE && !resists_fire(magr))
497                 || (adtyp == AD_ELEC && !resists_elec(magr))
498                 || adtyp == AD_PHYS) {
499                 dmg = mdef->data->mattk[i].damn;
500                 if (!dmg)
501                     dmg = mdef->data->mlevel + 1;
502                 dmg *= mdef->data->mattk[i].damd;
503             } else
504                 dmg = 0;
505
506             return dmg * multi2;
507         }
508     return 0;
509 }
510
511 /* determine whether two monster types are from the same species */
512 boolean
513 same_race(pm1, pm2)
514 struct permonst *pm1, *pm2;
515 {
516     char let1 = pm1->mlet, let2 = pm2->mlet;
517
518     if (pm1 == pm2)
519         return TRUE; /* exact match */
520     /* player races have their own predicates */
521     if (is_human(pm1))
522         return is_human(pm2);
523     if (is_elf(pm1))
524         return is_elf(pm2);
525     if (is_dwarf(pm1))
526         return is_dwarf(pm2);
527     if (is_gnome(pm1))
528         return is_gnome(pm2);
529     if (is_orc(pm1))
530         return is_orc(pm2);
531     /* other creatures are less precise */
532     if (is_giant(pm1))
533         return is_giant(pm2); /* open to quibbling here */
534     if (is_golem(pm1))
535         return is_golem(pm2); /* even moreso... */
536     if (is_mind_flayer(pm1))
537         return is_mind_flayer(pm2);
538     if (let1 == S_KOBOLD || pm1 == &mons[PM_KOBOLD_ZOMBIE]
539         || pm1 == &mons[PM_KOBOLD_MUMMY])
540         return (let2 == S_KOBOLD || pm2 == &mons[PM_KOBOLD_ZOMBIE]
541                 || pm2 == &mons[PM_KOBOLD_MUMMY]);
542     if (let1 == S_OGRE)
543         return (let2 == S_OGRE);
544     if (let1 == S_NYMPH)
545         return (let2 == S_NYMPH);
546     if (let1 == S_CENTAUR)
547         return (let2 == S_CENTAUR);
548     if (is_unicorn(pm1))
549         return is_unicorn(pm2);
550     if (let1 == S_DRAGON)
551         return (let2 == S_DRAGON);
552     if (let1 == S_NAGA)
553         return (let2 == S_NAGA);
554     /* other critters get steadily messier */
555     if (is_rider(pm1))
556         return is_rider(pm2); /* debatable */
557     if (is_minion(pm1))
558         return is_minion(pm2); /* [needs work?] */
559     /* tengu don't match imps (first test handled case of both being tengu) */
560     if (pm1 == &mons[PM_TENGU] || pm2 == &mons[PM_TENGU])
561         return FALSE;
562     if (let1 == S_IMP)
563         return (let2 == S_IMP);
564     /* and minor demons (imps) don't match major demons */
565     else if (let2 == S_IMP)
566         return FALSE;
567     if (is_demon(pm1))
568         return is_demon(pm2);
569     if (is_undead(pm1)) {
570         if (let1 == S_ZOMBIE)
571             return (let2 == S_ZOMBIE);
572         if (let1 == S_MUMMY)
573             return (let2 == S_MUMMY);
574         if (let1 == S_VAMPIRE)
575             return (let2 == S_VAMPIRE);
576         if (let1 == S_LICH)
577             return (let2 == S_LICH);
578         if (let1 == S_WRAITH)
579             return (let2 == S_WRAITH);
580         if (let1 == S_GHOST)
581             return (let2 == S_GHOST);
582     } else if (is_undead(pm2))
583         return FALSE;
584
585     /* check for monsters which grow into more mature forms */
586     if (let1 == let2) {
587         int m1 = monsndx(pm1), m2 = monsndx(pm2), prv, nxt;
588
589         /* we know m1 != m2 (very first check above); test all smaller
590            forms of m1 against m2, then all larger ones; don't need to
591            make the corresponding tests for variants of m2 against m1 */
592         for (prv = m1, nxt = big_to_little(m1); nxt != prv;
593              prv = nxt, nxt = big_to_little(nxt))
594             if (nxt == m2)
595                 return TRUE;
596         for (prv = m1, nxt = little_to_big(m1); nxt != prv;
597              prv = nxt, nxt = little_to_big(nxt))
598             if (nxt == m2)
599                 return TRUE;
600     }
601     /* not caught by little/big handling */
602     if (pm1 == &mons[PM_GARGOYLE] || pm1 == &mons[PM_WINGED_GARGOYLE])
603         return (pm2 == &mons[PM_GARGOYLE]
604                 || pm2 == &mons[PM_WINGED_GARGOYLE]);
605     if (pm1 == &mons[PM_KILLER_BEE] || pm1 == &mons[PM_QUEEN_BEE])
606         return (pm2 == &mons[PM_KILLER_BEE] || pm2 == &mons[PM_QUEEN_BEE]);
607
608     if (is_longworm(pm1))
609         return is_longworm(pm2); /* handles tail */
610     /* [currently there's no reason to bother matching up
611         assorted bugs and blobs with their closest variants] */
612     /* didn't match */
613     return FALSE;
614 }
615
616 /* return an index into the mons array */
617 int
618 monsndx(ptr)
619 struct permonst *ptr;
620 {
621     register int i;
622
623     i = (int) (ptr - &mons[0]);
624     if (i < LOW_PM || i >= NUMMONS) {
625         panic("monsndx - could not index monster (%s)",
626               fmt_ptr((genericptr_t) ptr));
627         return NON_PM; /* will not get here */
628     }
629     return i;
630 }
631
632 /* for handling alternate spellings */
633 struct alt_spl {
634     const char *name;
635     short pm_val;
636 };
637
638 /* figure out what type of monster a user-supplied string is specifying */
639 int
640 name_to_mon(in_str)
641 const char *in_str;
642 {
643     /* Be careful.  We must check the entire string in case it was
644      * something such as "ettin zombie corpse".  The calling routine
645      * doesn't know about the "corpse" until the monster name has
646      * already been taken off the front, so we have to be able to
647      * read the name with extraneous stuff such as "corpse" stuck on
648      * the end.
649      * This causes a problem for names which prefix other names such
650      * as "ettin" on "ettin zombie".  In this case we want the _longest_
651      * name which exists.
652      * This also permits plurals created by adding suffixes such as 's'
653      * or 'es'.  Other plurals must still be handled explicitly.
654      */
655     register int i;
656     register int mntmp = NON_PM;
657     register char *s, *str, *term;
658     char buf[BUFSZ];
659     int len, slen;
660
661     str = strcpy(buf, in_str);
662
663     if (!strncmp(str, "a ", 2))
664         str += 2;
665     else if (!strncmp(str, "an ", 3))
666         str += 3;
667     else if (!strncmp(str, "the ", 4))
668         str += 4;
669
670     slen = strlen(str);
671     term = str + slen;
672
673     if ((s = strstri(str, "vortices")) != 0)
674         Strcpy(s + 4, "ex");
675     /* be careful with "ies"; "priest", "zombies" */
676     else if (slen > 3 && !strcmpi(term - 3, "ies")
677              && (slen < 7 || strcmpi(term - 7, "zombies")))
678         Strcpy(term - 3, "y");
679     /* luckily no monster names end in fe or ve with ves plurals */
680     else if (slen > 3 && !strcmpi(term - 3, "ves"))
681         Strcpy(term - 3, "f");
682
683     slen = strlen(str); /* length possibly needs recomputing */
684
685     {
686         static const struct alt_spl names[] = {
687             /* Alternate spellings */
688             { "grey dragon", PM_GRAY_DRAGON },
689             { "baby grey dragon", PM_BABY_GRAY_DRAGON },
690             { "grey unicorn", PM_GRAY_UNICORN },
691             { "grey ooze", PM_GRAY_OOZE },
692             { "gray-elf", PM_GREY_ELF },
693             { "mindflayer", PM_MIND_FLAYER },
694             { "master mindflayer", PM_MASTER_MIND_FLAYER },
695             /* More alternates; priest and priestess are separate monster
696                types but that isn't the case for {aligned,high} priests */
697             { "aligned priestess", PM_ALIGNED_PRIEST },
698             { "high priestess", PM_HIGH_PRIEST },
699             /* Inappropriate singularization by -ves check above */
700             { "master of thief", PM_MASTER_OF_THIEVES },
701             /* Potential misspellings where we want to avoid falling back
702                to the rank title prefix (input has been singularized) */
703             { "master thief", PM_MASTER_OF_THIEVES },
704             { "master of assassin", PM_MASTER_ASSASSIN },
705             /* Outdated names */
706             { "invisible stalker", PM_STALKER },
707             { "high-elf", PM_ELVENKING }, /* PM_HIGH_ELF is obsolete */
708             { "halfling", PM_HOBBIT },    /* potential guess for polyself */
709             /* Hyphenated names */
710             { "ki rin", PM_KI_RIN },
711             { "uruk hai", PM_URUK_HAI },
712             { "orc captain", PM_ORC_CAPTAIN },
713             { "woodland elf", PM_WOODLAND_ELF },
714             { "green elf", PM_GREEN_ELF },
715             { "grey elf", PM_GREY_ELF },
716             { "gray elf", PM_GREY_ELF },
717             { "elf lord", PM_ELF_LORD },
718             { "olog hai", PM_OLOG_HAI },
719             { "arch lich", PM_ARCH_LICH },
720             /* Some irregular plurals */
721             { "incubi", PM_INCUBUS },
722             { "succubi", PM_SUCCUBUS },
723             { "violet fungi", PM_VIOLET_FUNGUS },
724             { "homunculi", PM_HOMUNCULUS },
725             { "baluchitheria", PM_BALUCHITHERIUM },
726             { "lurkers above", PM_LURKER_ABOVE },
727             { "cavemen", PM_CAVEMAN },
728             { "cavewomen", PM_CAVEWOMAN },
729             { "djinn", PM_DJINNI },
730             { "mumakil", PM_MUMAK },
731             { "erinyes", PM_ERINYS },
732             /* end of list */
733             { 0, NON_PM }
734         };
735         register const struct alt_spl *namep;
736
737         for (namep = names; namep->name; namep++)
738             if (!strncmpi(str, namep->name, (int) strlen(namep->name)))
739                 return namep->pm_val;
740     }
741
742     for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
743         register int m_i_len = strlen(mons[i].mname);
744
745         if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) {
746             if (m_i_len == slen) {
747                 return i; /* exact match */
748             } else if (slen > m_i_len
749                        && (str[m_i_len] == ' '
750                            || !strcmpi(&str[m_i_len], "s")
751                            || !strncmpi(&str[m_i_len], "s ", 2)
752                            || !strcmpi(&str[m_i_len], "'")
753                            || !strncmpi(&str[m_i_len], "' ", 2)
754                            || !strcmpi(&str[m_i_len], "'s")
755                            || !strncmpi(&str[m_i_len], "'s ", 3)
756                            || !strcmpi(&str[m_i_len], "es")
757                            || !strncmpi(&str[m_i_len], "es ", 3))) {
758                 mntmp = i;
759                 len = m_i_len;
760             }
761         }
762     }
763     if (mntmp == NON_PM)
764         mntmp = title_to_mon(str, (int *) 0, (int *) 0);
765     return mntmp;
766 }
767
768 /* monster class from user input; used for genocide and controlled polymorph;
769    returns 0 rather than MAXMCLASSES if no match is found */
770 int
771 name_to_monclass(in_str, mndx_p)
772 const char *in_str;
773 int *mndx_p;
774 {
775     /* Single letters are matched against def_monsyms[].sym; words
776        or phrases are first matched against def_monsyms[].explain
777        to check class description; if not found there, then against
778        mons[].mname to test individual monster types.  Input can be a
779        substring of the full description or mname, but to be accepted,
780        such partial matches must start at beginning of a word.  Some
781        class descriptions include "foo or bar" and "foo or other foo"
782        so we don't want to accept "or", "other", "or other" there. */
783     static NEARDATA const char *const falsematch[] = {
784         /* multiple-letter input which matches any of these gets rejected */
785         "an", "the", "or", "other", "or other", 0
786     };
787     /* positive pm_val => specific monster; negative => class */
788     static NEARDATA const struct alt_spl truematch[] = {
789         /* "long worm" won't match "worm" class but would accidentally match
790            "long worm tail" class before the comparison with monster types */
791         { "long worm", PM_LONG_WORM },
792         /* matches wrong--or at least suboptimal--class */
793         { "demon", -S_DEMON }, /* hits "imp or minor demon" */
794         /* matches specific monster (overly restrictive) */
795         { "devil", -S_DEMON }, /* always "horned devil" */
796         /* some plausible guesses which need help */
797         { "bug", -S_XAN },  /* would match bugbear... */
798         { "fish", -S_EEL }, /* wouldn't match anything */
799         /* end of list */
800         { 0, NON_PM }
801     };
802     const char *p, *x;
803     int i;
804
805     if (mndx_p)
806         *mndx_p = NON_PM; /* haven't [yet] matched a specific type */
807
808     if (!in_str || !in_str[0]) {
809         /* empty input */
810         return 0;
811     } else if (!in_str[1]) {
812         /* single character */
813         i = def_char_to_monclass(*in_str);
814         if (i == S_MIMIC_DEF) { /* ']' -> 'm' */
815             i = S_MIMIC;
816         } else if (i == S_WORM_TAIL) { /* '~' -> 'w' */
817             i = S_WORM;
818             if (mndx_p)
819                 *mndx_p = PM_LONG_WORM;
820         } else if (i == MAXMCLASSES) /* maybe 'I' */
821             i = (*in_str == DEF_INVISIBLE) ? S_invisible : 0;
822         return i;
823     } else {
824         /* multiple characters */
825         in_str = makesingular(in_str);
826         /* check for special cases */
827         for (i = 0; falsematch[i]; i++)
828             if (!strcmpi(in_str, falsematch[i]))
829                 return 0;
830         for (i = 0; truematch[i].name; i++)
831             if (!strcmpi(in_str, truematch[i].name)) {
832                 i = truematch[i].pm_val;
833                 if (i < 0)
834                     return -i; /* class */
835                 if (mndx_p)
836                     *mndx_p = i; /* monster */
837                 return mons[i].mlet;
838             }
839         /* check monster class descriptions */
840         for (i = 1; i < MAXMCLASSES; i++) {
841             x = def_monsyms[i].explain;
842             if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' '))
843                 return i;
844         }
845         /* check individual species names; not as thorough as mon_to_name()
846            but our caller can call that directly if desired */
847         for (i = LOW_PM; i < NUMMONS; i++) {
848             x = mons[i].mname;
849             if ((p = strstri(x, in_str)) != 0
850                 && (p == x || *(p - 1) == ' ')) {
851                 if (mndx_p)
852                     *mndx_p = i;
853                 return mons[i].mlet;
854             }
855         }
856     }
857     return 0;
858 }
859
860 /* returns 3 values (0=male, 1=female, 2=none) */
861 int
862 gender(mtmp)
863 register struct monst *mtmp;
864 {
865     if (is_neuter(mtmp->data))
866         return 2;
867     return mtmp->female;
868 }
869
870 /* Like gender(), but lower animals and such are still "it".
871    This is the one we want to use when printing messages. */
872 int
873 pronoun_gender(mtmp)
874 register struct monst *mtmp;
875 {
876     if (is_neuter(mtmp->data) || !canspotmon(mtmp))
877         return 2;
878     return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ)
879             || type_is_pname(mtmp->data)) ? (int) mtmp->female : 2;
880 }
881
882 /* used for nearby monsters when you go to another level */
883 boolean
884 levl_follower(mtmp)
885 struct monst *mtmp;
886 {
887     if (mtmp == u.usteed)
888         return TRUE;
889
890     /* Wizard with Amulet won't bother trying to follow across levels */
891     if (mtmp->iswiz && mon_has_amulet(mtmp))
892         return FALSE;
893     /* some monsters will follow even while intending to flee from you */
894     if (mtmp->mtame || mtmp->iswiz || is_fshk(mtmp))
895         return TRUE;
896     /* stalking types follow, but won't when fleeing unless you hold
897        the Amulet */
898     return (boolean) ((mtmp->data->mflags2 & M2_STALK)
899                       && (!mtmp->mflee || u.uhave.amulet));
900 }
901
902 static const short grownups[][2] = {
903     { PM_CHICKATRICE, PM_COCKATRICE },
904     { PM_LITTLE_DOG, PM_DOG },
905     { PM_DOG, PM_LARGE_DOG },
906     { PM_HELL_HOUND_PUP, PM_HELL_HOUND },
907     { PM_WINTER_WOLF_CUB, PM_WINTER_WOLF },
908     { PM_KITTEN, PM_HOUSECAT },
909     { PM_HOUSECAT, PM_LARGE_CAT },
910     { PM_PONY, PM_HORSE },
911     { PM_HORSE, PM_WARHORSE },
912     { PM_KOBOLD, PM_LARGE_KOBOLD },
913     { PM_LARGE_KOBOLD, PM_KOBOLD_LORD },
914     { PM_GNOME, PM_GNOME_LORD },
915     { PM_GNOME_LORD, PM_GNOME_KING },
916     { PM_DWARF, PM_DWARF_LORD },
917     { PM_DWARF_LORD, PM_DWARF_KING },
918     { PM_MIND_FLAYER, PM_MASTER_MIND_FLAYER },
919     { PM_ORC, PM_ORC_CAPTAIN },
920     { PM_HILL_ORC, PM_ORC_CAPTAIN },
921     { PM_MORDOR_ORC, PM_ORC_CAPTAIN },
922     { PM_URUK_HAI, PM_ORC_CAPTAIN },
923     { PM_SEWER_RAT, PM_GIANT_RAT },
924     { PM_CAVE_SPIDER, PM_GIANT_SPIDER },
925     { PM_OGRE, PM_OGRE_LORD },
926     { PM_OGRE_LORD, PM_OGRE_KING },
927     { PM_ELF, PM_ELF_LORD },
928     { PM_WOODLAND_ELF, PM_ELF_LORD },
929     { PM_GREEN_ELF, PM_ELF_LORD },
930     { PM_GREY_ELF, PM_ELF_LORD },
931     { PM_ELF_LORD, PM_ELVENKING },
932     { PM_LICH, PM_DEMILICH },
933     { PM_DEMILICH, PM_MASTER_LICH },
934     { PM_MASTER_LICH, PM_ARCH_LICH },
935     { PM_VAMPIRE, PM_VAMPIRE_LORD },
936     { PM_BAT, PM_GIANT_BAT },
937     { PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON },
938     { PM_BABY_SILVER_DRAGON, PM_SILVER_DRAGON },
939 #if 0 /* DEFERRED */
940     {PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
941 #endif
942     { PM_BABY_RED_DRAGON, PM_RED_DRAGON },
943     { PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON },
944     { PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON },
945     { PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON },
946     { PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON },
947     { PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON },
948     { PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON },
949     { PM_RED_NAGA_HATCHLING, PM_RED_NAGA },
950     { PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA },
951     { PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA },
952     { PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA },
953     { PM_SMALL_MIMIC, PM_LARGE_MIMIC },
954     { PM_LARGE_MIMIC, PM_GIANT_MIMIC },
955     { PM_BABY_LONG_WORM, PM_LONG_WORM },
956     { PM_BABY_PURPLE_WORM, PM_PURPLE_WORM },
957     { PM_BABY_CROCODILE, PM_CROCODILE },
958     { PM_SOLDIER, PM_SERGEANT },
959     { PM_SERGEANT, PM_LIEUTENANT },
960     { PM_LIEUTENANT, PM_CAPTAIN },
961     { PM_WATCHMAN, PM_WATCH_CAPTAIN },
962     { PM_ALIGNED_PRIEST, PM_HIGH_PRIEST },
963     { PM_STUDENT, PM_ARCHEOLOGIST },
964     { PM_ATTENDANT, PM_HEALER },
965     { PM_PAGE, PM_KNIGHT },
966     { PM_ACOLYTE, PM_PRIEST },
967     { PM_APPRENTICE, PM_WIZARD },
968     { PM_MANES, PM_LEMURE },
969     { PM_KEYSTONE_KOP, PM_KOP_SERGEANT },
970     { PM_KOP_SERGEANT, PM_KOP_LIEUTENANT },
971     { PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN },
972     { NON_PM, NON_PM }
973 };
974
975 int
976 little_to_big(montype)
977 int montype;
978 {
979     register int i;
980
981     for (i = 0; grownups[i][0] >= LOW_PM; i++)
982         if (montype == grownups[i][0]) {
983             montype = grownups[i][1];
984             break;
985         }
986     return montype;
987 }
988
989 int
990 big_to_little(montype)
991 int montype;
992 {
993     register int i;
994
995     for (i = 0; grownups[i][0] >= LOW_PM; i++)
996         if (montype == grownups[i][1]) {
997             montype = grownups[i][0];
998             break;
999         }
1000     return montype;
1001 }
1002
1003 /*
1004  * Return the permonst ptr for the race of the monster.
1005  * Returns correct pointer for non-polymorphed and polymorphed
1006  * player.  It does not return a pointer to player role character.
1007  */
1008 const struct permonst *
1009 raceptr(mtmp)
1010 struct monst *mtmp;
1011 {
1012     if (mtmp == &youmonst && !Upolyd)
1013         return &mons[urace.malenum];
1014     else
1015         return mtmp->data;
1016 }
1017
1018 static const char *levitate[4] = { "float", "Float", "wobble", "Wobble" };
1019 static const char *flys[4] = { "fly", "Fly", "flutter", "Flutter" };
1020 static const char *flyl[4] = { "fly", "Fly", "stagger", "Stagger" };
1021 static const char *slither[4] = { "slither", "Slither", "falter", "Falter" };
1022 static const char *ooze[4] = { "ooze", "Ooze", "tremble", "Tremble" };
1023 static const char *immobile[4] = { "wiggle", "Wiggle", "pulsate", "Pulsate" };
1024 static const char *crawl[4] = { "crawl", "Crawl", "falter", "Falter" };
1025
1026 const char *
1027 locomotion(ptr, def)
1028 const struct permonst *ptr;
1029 const char *def;
1030 {
1031     int capitalize = (*def == highc(*def));
1032
1033     return (is_floater(ptr) ? levitate[capitalize]
1034             : (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize]
1035               : (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize]
1036                 : slithy(ptr) ? slither[capitalize]
1037                   : amorphous(ptr) ? ooze[capitalize]
1038                     : !ptr->mmove ? immobile[capitalize]
1039                       : nolimbs(ptr) ? crawl[capitalize]
1040                         : def);
1041 }
1042
1043 const char *
1044 stagger(ptr, def)
1045 const struct permonst *ptr;
1046 const char *def;
1047 {
1048     int capitalize = 2 + (*def == highc(*def));
1049
1050     return (is_floater(ptr) ? levitate[capitalize]
1051             : (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize]
1052               : (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize]
1053                 : slithy(ptr) ? slither[capitalize]
1054                   : amorphous(ptr) ? ooze[capitalize]
1055                     : !ptr->mmove ? immobile[capitalize]
1056                       : nolimbs(ptr) ? crawl[capitalize]
1057                         : def);
1058 }
1059
1060 /* return phrase describing the effect of fire attack on a type of monster */
1061 const char *
1062 on_fire(mptr, mattk)
1063 struct permonst *mptr;
1064 struct attack *mattk;
1065 {
1066     const char *what;
1067
1068     switch (monsndx(mptr)) {
1069     case PM_FLAMING_SPHERE:
1070     case PM_FIRE_VORTEX:
1071     case PM_FIRE_ELEMENTAL:
1072     case PM_SALAMANDER:
1073         what = "already on fire";
1074         break;
1075     case PM_WATER_ELEMENTAL:
1076     case PM_FOG_CLOUD:
1077     case PM_STEAM_VORTEX:
1078         what = "boiling";
1079         break;
1080     case PM_ICE_VORTEX:
1081     case PM_GLASS_GOLEM:
1082         what = "melting";
1083         break;
1084     case PM_STONE_GOLEM:
1085     case PM_CLAY_GOLEM:
1086     case PM_GOLD_GOLEM:
1087     case PM_AIR_ELEMENTAL:
1088     case PM_EARTH_ELEMENTAL:
1089     case PM_DUST_VORTEX:
1090     case PM_ENERGY_VORTEX:
1091         what = "heating up";
1092         break;
1093     default:
1094         what = (mattk->aatyp == AT_HUGS) ? "being roasted" : "on fire";
1095         break;
1096     }
1097     return what;
1098 }
1099
1100 /*
1101  * Returns:
1102  *      True if monster is presumed to have a sense of smell.
1103  *      False if monster definitely does not have a sense of smell.
1104  *
1105  * Do not base this on presence of a head or nose, since many
1106  * creatures sense smells other ways (feelers, forked-tongues, etc.)
1107  * We're assuming all insects can smell at a distance too.
1108  */
1109 boolean
1110 olfaction(mdat)
1111 struct permonst *mdat;
1112 {
1113     if (is_golem(mdat)
1114         || mdat->mlet == S_EYE /* spheres  */
1115         || mdat->mlet == S_JELLY || mdat->mlet == S_PUDDING
1116         || mdat->mlet == S_BLOB || mdat->mlet == S_VORTEX
1117         || mdat->mlet == S_ELEMENTAL
1118         || mdat->mlet == S_FUNGUS /* mushrooms and fungi */
1119         || mdat->mlet == S_LIGHT)
1120         return FALSE;
1121     return TRUE;
1122 }
1123
1124 /*mondata.c*/