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. */
7 /* These routines provide basic data for any type of monster. */
9 /* set up an individual monster's base type (initial creation, shapechange) */
11 set_mon_data(mon, ptr, flag)
18 return; /* "don't care" */
21 mon->mintrinsics |= (ptr->mresists & 0x00FF);
23 mon->mintrinsics = (ptr->mresists & 0x00FF);
27 /* does monster-type have any attack for a specific type of damage? */
29 attacktype_fordmg(ptr, atyp, dtyp)
35 for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
36 if (a->aatyp == atyp && (dtyp == AD_ANY || a->adtyp == dtyp))
38 return (struct attack *) 0;
41 /* does monster-type have a particular type of attack */
47 return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE;
50 /* returns True if monster doesn't attack, False if it does */
56 struct attack *mattk = ptr->mattk;
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)
70 /* does monster-type transform into something else when petrified? */
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));
81 /* returns True if monster is drain-life resistant */
86 struct permonst *ptr = mon->data;
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))
94 wep = (mon == &youmonst) ? uwep : MON_WEP(mon);
95 return (boolean) (wep && wep->oartifact && defends(AD_DRLI, wep));
98 /* True if monster is magic-missile (actually, general magic) resistant */
103 struct permonst *ptr = mon->data;
104 boolean is_you = (mon == &youmonst);
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 */
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))
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))))
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)))
132 /* True iff monster is resistant to light-induced blindness */
137 struct permonst *ptr = mon->data;
138 boolean is_you = (mon == &youmonst);
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 */
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))
152 o = is_you ? uwep : MON_WEP(mon);
153 if (o && o->oartifact && defends(AD_BLND, o))
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))))
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)))
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) */
173 can_blnd(magr, mdef, aatyp, obj)
174 struct monst *magr; /* NULL == no specific aggressor */
177 struct obj *obj; /* aatyp == AT_WEAP, AT_SPIT */
179 boolean is_you = (mdef == &youmonst);
180 boolean check_visor = FALSE;
184 /* no eyes protect against all attacks for now */
185 if (!haseyes(mdef->data))
193 case AT_BREA: /* assumed to be lightning */
194 /* light-based attacks may be cancelled or resisted */
195 if (magr && magr->mcan)
197 return !resists_blnd(mdef);
202 /* an object is used (thrown/spit/other) */
203 if (obj && (obj->otyp == CREAM_PIE)) {
204 if (is_you && Blindfolded)
206 } else if (obj && (obj->otyp == BLINDING_VENOM)) {
207 /* all ublindf, including LENSES, protect, cream-pies too */
208 if (is_you && (ublindf || u.ucreamed))
211 } else if (obj && (obj->otyp == POT_BLINDNESS)) {
212 return TRUE; /* no defense */
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 */
220 if (is_you && (Blindfolded || Unaware || u.ucreamed))
222 if (!is_you && mdef->msleeping)
227 /* e.g. raven: all ublindf, including LENSES, protect */
228 if (is_you && ublindf)
230 if ((magr == &youmonst) && u.uswallow)
231 return FALSE; /* can't affect eyes while inside monster */
237 /* some physical, blind-inducing attacks can be cancelled */
238 if (magr && magr->mcan)
246 /* check if wearing a visor (only checked if visor might help) */
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"))
259 /* returns True if monster can attack at range */
262 struct permonst *ptr;
264 register int i, atyp;
265 long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
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
272 for (i = 0; i < NATTK; i++) {
273 atyp = ptr->mattk[i].aatyp;
276 /* assert(atyp < 32); */
277 if ((atk_mask & (1L << atyp)) != 0L)
283 /* True if specific monster is especially affected by silver weapons */
285 mon_hates_silver(mon)
288 return (boolean) (is_vampshifter(mon) || hates_silver(mon->data));
291 /* True if monster-type is especially affected by silver weapons */
294 register struct permonst *ptr;
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]));
301 /* True iff the type of monster pass through iron bars */
304 struct permonst *mptr;
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)));
312 /* returns True if monster can blow (whistle, etc) */
315 register struct monst *mtmp;
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))
321 if ((mtmp == &youmonst) && Strangled)
326 /* True if mon is vulnerable to strangulation */
328 can_be_strangled(mon)
332 boolean nonbreathing, nobrainer;
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))
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;
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)));
356 return (boolean) (!nobrainer || !nonbreathing);
359 /* returns True if monster can track well */
362 register struct permonst *ptr;
364 if (uwep && uwep->oartifact == ART_EXCALIBUR)
367 return (boolean) haseyes(ptr);
370 /* creature will slide out of armor */
373 register struct permonst *ptr;
375 return (boolean) (is_whirly(ptr) || ptr->msize <= MZ_SMALL
376 || noncorporeal(ptr));
379 /* creature will break out of armor */
382 register struct permonst *ptr;
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]);
394 /* creature sticks other creatures it hits */
397 register struct permonst *ptr;
399 return (boolean) (dmgtype(ptr, AD_STCK) || dmgtype(ptr, AD_WRAP)
400 || attacktype(ptr, AT_HUGS));
403 /* some monster-types can't vomit */
406 struct permonst *ptr;
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])
416 /* number of horns this type of monster has on its head */
419 struct permonst *ptr;
421 switch (monsndx(ptr)) {
422 case PM_HORNED_DEVIL: /* ? "more than one" */
427 case PM_WHITE_UNICORN:
428 case PM_GRAY_UNICORN:
429 case PM_BLACK_UNICORN:
438 /* does monster-type deal out a particular type of damage from a particular
441 dmgtype_fromattack(ptr, dtyp, atyp)
442 struct permonst *ptr;
447 for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
448 if (a->adtyp == dtyp && (atyp == AT_ANY || a->aatyp == atyp))
450 return (struct attack *) 0;
453 /* does monster-type deal out a particular type of damage from any attack */
456 struct permonst *ptr;
459 return dmgtype_fromattack(ptr, dtyp, AT_ANY) ? TRUE : FALSE;
462 /* returns the maximum damage a defender can do to the attacker via
465 max_passive_dmg(mdef, magr)
466 register struct monst *mdef, *magr;
468 int i, dmg = 0, multi2 = 0;
471 /* each attack by magr can result in passive damage */
472 for (i = 0; i < NATTK; i++)
473 switch (magr->data->mattk[i].aatyp) {
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;
501 dmg = mdef->data->mlevel + 1;
502 dmg *= mdef->data->mattk[i].damd;
511 /* determine whether two monster types are from the same species */
514 struct permonst *pm1, *pm2;
516 char let1 = pm1->mlet, let2 = pm2->mlet;
519 return TRUE; /* exact match */
520 /* player races have their own predicates */
522 return is_human(pm2);
526 return is_dwarf(pm2);
528 return is_gnome(pm2);
531 /* other creatures are less precise */
533 return is_giant(pm2); /* open to quibbling here */
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]);
543 return (let2 == S_OGRE);
545 return (let2 == S_NYMPH);
546 if (let1 == S_CENTAUR)
547 return (let2 == S_CENTAUR);
549 return is_unicorn(pm2);
550 if (let1 == S_DRAGON)
551 return (let2 == S_DRAGON);
553 return (let2 == S_NAGA);
554 /* other critters get steadily messier */
556 return is_rider(pm2); /* debatable */
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])
563 return (let2 == S_IMP);
564 /* and minor demons (imps) don't match major demons */
565 else if (let2 == S_IMP)
568 return is_demon(pm2);
569 if (is_undead(pm1)) {
570 if (let1 == S_ZOMBIE)
571 return (let2 == S_ZOMBIE);
573 return (let2 == S_MUMMY);
574 if (let1 == S_VAMPIRE)
575 return (let2 == S_VAMPIRE);
577 return (let2 == S_LICH);
578 if (let1 == S_WRAITH)
579 return (let2 == S_WRAITH);
581 return (let2 == S_GHOST);
582 } else if (is_undead(pm2))
585 /* check for monsters which grow into more mature forms */
587 int m1 = monsndx(pm1), m2 = monsndx(pm2), prv, nxt;
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))
596 for (prv = m1, nxt = little_to_big(m1); nxt != prv;
597 prv = nxt, nxt = little_to_big(nxt))
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]);
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] */
616 /* return an index into the mons array */
619 struct permonst *ptr;
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 */
632 /* for handling alternate spellings */
638 /* figure out what type of monster a user-supplied string is specifying */
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
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_
652 * This also permits plurals created by adding suffixes such as 's'
653 * or 'es'. Other plurals must still be handled explicitly.
656 register int mntmp = NON_PM;
657 register char *s, *str, *term;
661 str = strcpy(buf, in_str);
663 if (!strncmp(str, "a ", 2))
665 else if (!strncmp(str, "an ", 3))
667 else if (!strncmp(str, "the ", 4))
673 if ((s = strstri(str, "vortices")) != 0)
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");
683 slen = strlen(str); /* length possibly needs recomputing */
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 },
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 },
735 register const struct alt_spl *namep;
737 for (namep = names; namep->name; namep++)
738 if (!strncmpi(str, namep->name, (int) strlen(namep->name)))
739 return namep->pm_val;
742 for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
743 register int m_i_len = strlen(mons[i].mname);
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))) {
764 mntmp = title_to_mon(str, (int *) 0, (int *) 0);
768 /* monster class from user input; used for genocide and controlled polymorph;
769 returns 0 rather than MAXMCLASSES if no match is found */
771 name_to_monclass(in_str, mndx_p)
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
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 */
806 *mndx_p = NON_PM; /* haven't [yet] matched a specific type */
808 if (!in_str || !in_str[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' */
816 } else if (i == S_WORM_TAIL) { /* '~' -> 'w' */
819 *mndx_p = PM_LONG_WORM;
820 } else if (i == MAXMCLASSES) /* maybe 'I' */
821 i = (*in_str == DEF_INVISIBLE) ? S_invisible : 0;
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]))
830 for (i = 0; truematch[i].name; i++)
831 if (!strcmpi(in_str, truematch[i].name)) {
832 i = truematch[i].pm_val;
834 return -i; /* class */
836 *mndx_p = i; /* monster */
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) == ' '))
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++) {
849 if ((p = strstri(x, in_str)) != 0
850 && (p == x || *(p - 1) == ' ')) {
860 /* returns 3 values (0=male, 1=female, 2=none) */
863 register struct monst *mtmp;
865 if (is_neuter(mtmp->data))
870 /* Like gender(), but lower animals and such are still "it".
871 This is the one we want to use when printing messages. */
874 register struct monst *mtmp;
876 if (is_neuter(mtmp->data) || !canspotmon(mtmp))
878 return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ)
879 || type_is_pname(mtmp->data)) ? (int) mtmp->female : 2;
882 /* used for nearby monsters when you go to another level */
887 if (mtmp == u.usteed)
890 /* Wizard with Amulet won't bother trying to follow across levels */
891 if (mtmp->iswiz && mon_has_amulet(mtmp))
893 /* some monsters will follow even while intending to flee from you */
894 if (mtmp->mtame || mtmp->iswiz || is_fshk(mtmp))
896 /* stalking types follow, but won't when fleeing unless you hold
898 return (boolean) ((mtmp->data->mflags2 & M2_STALK)
899 && (!mtmp->mflee || u.uhave.amulet));
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 },
940 {PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
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 },
976 little_to_big(montype)
981 for (i = 0; grownups[i][0] >= LOW_PM; i++)
982 if (montype == grownups[i][0]) {
983 montype = grownups[i][1];
990 big_to_little(montype)
995 for (i = 0; grownups[i][0] >= LOW_PM; i++)
996 if (montype == grownups[i][1]) {
997 montype = grownups[i][0];
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.
1008 const struct permonst *
1012 if (mtmp == &youmonst && !Upolyd)
1013 return &mons[urace.malenum];
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" };
1027 locomotion(ptr, def)
1028 const struct permonst *ptr;
1031 int capitalize = (*def == highc(*def));
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]
1045 const struct permonst *ptr;
1048 int capitalize = 2 + (*def == highc(*def));
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]
1060 /* return phrase describing the effect of fire attack on a type of monster */
1062 on_fire(mptr, mattk)
1063 struct permonst *mptr;
1064 struct attack *mattk;
1068 switch (monsndx(mptr)) {
1069 case PM_FLAMING_SPHERE:
1070 case PM_FIRE_VORTEX:
1071 case PM_FIRE_ELEMENTAL:
1073 what = "already on fire";
1075 case PM_WATER_ELEMENTAL:
1077 case PM_STEAM_VORTEX:
1081 case PM_GLASS_GOLEM:
1084 case PM_STONE_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";
1094 what = (mattk->aatyp == AT_HUGS) ? "being roasted" : "on fire";
1102 * True if monster is presumed to have a sense of smell.
1103 * False if monster definitely does not have a sense of smell.
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.
1111 struct permonst *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)