1 /* NetHack 3.6 mondata.c $NHDT-Date: 1550525093 2019/02/18 21:24:53 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.72 $ */
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. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
9 /* JNetHack may be freely redistributed. See license for details. */
13 * These routines provide basic data for any type of monster.
16 /* set up an individual monster's base type (initial creation, shapechange) */
18 set_mon_data(mon, ptr)
22 int new_speed, old_speed = mon->data ? mon->data->mmove : 0;
25 mon->mnum = (short) monsndx(ptr);
27 if (mon->movement) { /* used to adjust poly'd hero as well as monsters */
28 new_speed = ptr->mmove;
29 /* prorate unused movement if new form is slower so that
30 it doesn't get extra moves leftover from previous form;
31 if new form is faster, leave unused movement as is */
32 if (new_speed < old_speed) {
34 * Some static analysis warns that this might divide by 0
35 mon->movement = new_speed * mon->movement / old_speed;
36 * so add a redundant test to suppress that.
38 mon->movement *= new_speed;
39 if (old_speed > 0) /* old > new and new >= 0, so always True */
40 mon->movement /= old_speed;
46 /* does monster-type have any attack for a specific type of damage? */
48 attacktype_fordmg(ptr, atyp, dtyp)
54 for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
55 if (a->aatyp == atyp && (dtyp == AD_ANY || a->adtyp == dtyp))
57 return (struct attack *) 0;
60 /* does monster-type have a particular type of attack */
66 return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE;
69 /* returns True if monster doesn't attack, False if it does */
75 struct attack *mattk = ptr->mattk;
77 for (i = 0; i < NATTK; i++) {
78 /* AT_BOOM "passive attack" (gas spore's explosion upon death)
79 isn't an attack as far as our callers are concerned */
80 if (mattk[i].aatyp == AT_BOOM)
89 /* does monster-type transform into something else when petrified? */
94 /* non-stone golems turn into stone golems unless latter is genocided */
95 return (boolean) (is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM]
96 && !(mvitals[PM_STONE_GOLEM].mvflags & G_GENOD));
100 /* returns True if monster is drain-life resistant */
105 struct permonst *ptr = mon->data;
108 if (is_undead(ptr) || is_demon(ptr) || is_were(ptr)
109 /* is_were() doesn't handle hero in human form */
110 || (mon == &youmonst && u.ulycn >= LOW_PM)
111 || ptr == &mons[PM_DEATH] || is_vampshifter(mon))
113 wep = (mon == &youmonst) ? uwep : MON_WEP(mon);
114 return (boolean) (wep && wep->oartifact && defends(AD_DRLI, wep));
117 /* True if monster is magic-missile (actually, general magic) resistant */
122 struct permonst *ptr = mon->data;
123 boolean is_you = (mon == &youmonst);
127 /* as of 3.2.0: gray dragons, Angels, Oracle, Yeenoghu */
128 if (dmgtype(ptr, AD_MAGM) || ptr == &mons[PM_BABY_GRAY_DRAGON]
129 || dmgtype(ptr, AD_RBRE)) /* Chromatic Dragon */
131 /* check for magic resistance granted by wielded weapon */
132 o = is_you ? uwep : MON_WEP(mon);
133 if (o && o->oartifact && defends(AD_MAGM, o))
135 /* check for magic resistance granted by worn or carried items */
136 o = is_you ? invent : mon->minvent;
137 slotmask = W_ARMOR | W_ACCESSORY;
138 if (!is_you /* assumes monsters don't wield non-weapons */
139 || (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))))
141 if (is_you && u.twoweap)
142 slotmask |= W_SWAPWEP;
143 for (; o; o = o->nobj)
144 if (((o->owornmask & slotmask) != 0L
145 && objects[o->otyp].oc_oprop == ANTIMAGIC)
146 || (o->oartifact && defends_when_carried(AD_MAGM, o)))
151 /* True iff monster is resistant to light-induced blindness */
156 struct permonst *ptr = mon->data;
157 boolean is_you = (mon == &youmonst);
161 if (is_you ? (Blind || Unaware)
162 : (mon->mblinded || !mon->mcansee || !haseyes(ptr)
163 /* BUG: temporary sleep sets mfrozen, but since
164 paralysis does too, we can't check it */
167 /* yellow light, Archon; !dust vortex, !cobra, !raven */
168 if (dmgtype_fromattack(ptr, AD_BLND, AT_EXPL)
169 || dmgtype_fromattack(ptr, AD_BLND, AT_GAZE))
171 o = is_you ? uwep : MON_WEP(mon);
172 if (o && o->oartifact && defends(AD_BLND, o))
174 o = is_you ? invent : mon->minvent;
175 slotmask = W_ARMOR | W_ACCESSORY;
176 if (!is_you /* assumes monsters don't wield non-weapons */
177 || (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))))
179 if (is_you && u.twoweap)
180 slotmask |= W_SWAPWEP;
181 for (; o; o = o->nobj)
182 if (((o->owornmask & slotmask) != 0L
183 && objects[o->otyp].oc_oprop == BLINDED)
184 || (o->oartifact && defends_when_carried(AD_BLND, o)))
189 /* True iff monster can be blinded by the given attack;
190 note: may return True when mdef is blind (e.g. new cream-pie attack) */
192 can_blnd(magr, mdef, aatyp, obj)
193 struct monst *magr; /* NULL == no specific aggressor */
196 struct obj *obj; /* aatyp == AT_WEAP, AT_SPIT */
198 boolean is_you = (mdef == &youmonst);
199 boolean check_visor = FALSE;
203 /* no eyes protect against all attacks for now */
204 if (!haseyes(mdef->data))
212 case AT_BREA: /* assumed to be lightning */
213 /* light-based attacks may be cancelled or resisted */
214 if (magr && magr->mcan)
216 return !resists_blnd(mdef);
221 /* an object is used (thrown/spit/other) */
222 if (obj && (obj->otyp == CREAM_PIE)) {
223 if (is_you && Blindfolded)
225 } else if (obj && (obj->otyp == BLINDING_VENOM)) {
226 /* all ublindf, including LENSES, protect, cream-pies too */
227 if (is_you && (ublindf || u.ucreamed))
230 } else if (obj && (obj->otyp == POT_BLINDNESS)) {
231 return TRUE; /* no defense */
233 return FALSE; /* other objects cannot cause blindness yet */
234 if ((magr == &youmonst) && u.uswallow)
235 return FALSE; /* can't affect eyes while inside monster */
239 if (is_you && (Blindfolded || Unaware || u.ucreamed))
241 if (!is_you && mdef->msleeping)
246 /* e.g. raven: all ublindf, including LENSES, protect */
247 if (is_you && ublindf)
249 if ((magr == &youmonst) && u.uswallow)
250 return FALSE; /* can't affect eyes while inside monster */
256 /* some physical, blind-inducing attacks can be cancelled */
257 if (magr && magr->mcan)
265 /* check if wearing a visor (only checked if visor might help) */
267 o = (mdef == &youmonst) ? invent : mdef->minvent;
268 for (; o; o = o->nobj)
270 if ((o->owornmask & W_ARMH)
271 && (s = OBJ_DESCR(objects[o->otyp])) != (char *) 0
272 && !strcmp(s, "visored helmet"))
274 if ((o->owornmask & W_ARMH)
275 && (s = OBJ_DESCR(objects[o->otyp])) != (char *) 0
276 && !strcmp(s, "
\96Ê
\96j
\95t
\82«
\82Ì
\8a\95"))
284 /* returns True if monster can attack at range */
287 struct permonst *ptr;
289 register int i, atyp;
290 long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
292 /* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP)
293 * || attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE)
294 * || attacktype(ptr, AT_MAGC));
295 * but that's too slow -dlc
297 for (i = 0; i < NATTK; i++) {
298 atyp = ptr->mattk[i].aatyp;
301 /* assert(atyp < 32); */
302 if ((atk_mask & (1L << atyp)) != 0L)
308 /* True if specific monster is especially affected by silver weapons */
310 mon_hates_silver(mon)
313 return (boolean) (is_vampshifter(mon) || hates_silver(mon->data));
316 /* True if monster-type is especially affected by silver weapons */
319 register struct permonst *ptr;
321 return (boolean) (is_were(ptr) || ptr->mlet == S_VAMPIRE || is_demon(ptr)
322 || ptr == &mons[PM_SHADE]
323 || (ptr->mlet == S_IMP && ptr != &mons[PM_TENGU]));
326 /* True if specific monster is especially affected by light-emitting weapons */
331 return (boolean) (hates_light(mon->data));
334 /* True iff the type of monster pass through iron bars */
337 struct permonst *mptr;
339 return (boolean) (passes_walls(mptr) || amorphous(mptr) || unsolid(mptr)
340 || is_whirly(mptr) || verysmall(mptr)
341 || dmgtype(mptr, AD_CORR) || dmgtype(mptr, AD_RUST)
342 || (slithy(mptr) && !bigmonst(mptr)));
345 /* returns True if monster can blow (whistle, etc) */
350 if ((is_silent(mtmp->data) || mtmp->data->msound == MS_BUZZ)
351 && (breathless(mtmp->data) || verysmall(mtmp->data)
352 || !has_head(mtmp->data) || mtmp->data->mlet == S_EEL))
354 if ((mtmp == &youmonst) && Strangled)
359 /* for casting spells and reading scrolls while blind */
364 if ((mtmp == &youmonst && Strangled)
365 || is_silent(mtmp->data) || !has_head(mtmp->data)
366 || mtmp->data->msound == MS_BUZZ || mtmp->data->msound == MS_BURBLE)
371 /* True if mon is vulnerable to strangulation */
373 can_be_strangled(mon)
377 boolean nonbreathing, nobrainer;
379 /* For amulet of strangulation support: here we're considering
380 strangulation to be loss of blood flow to the brain due to
381 constriction of the arteries in the neck, so all headless
382 creatures are immune (no neck) as are mindless creatures
383 who don't need to breathe (brain, if any, doesn't care).
384 Mindless creatures who do need to breath are vulnerable, as
385 are non-breathing creatures which have higher brain function. */
386 if (!has_head(mon->data))
388 if (mon == &youmonst) {
389 /* hero can't be mindless but poly'ing into mindless form can
390 confer strangulation protection */
391 nobrainer = mindless(youmonst.data);
392 nonbreathing = Breathless;
394 nobrainer = mindless(mon->data);
395 /* monsters don't wear amulets of magical breathing,
396 so second part doesn't achieve anything useful... */
397 nonbreathing = (breathless(mon->data)
398 || ((mamul = which_armor(mon, W_AMUL)) != 0
399 && (mamul->otyp == AMULET_OF_MAGICAL_BREATHING)));
401 return (boolean) (!nobrainer || !nonbreathing);
404 /* returns True if monster can track well */
407 register struct permonst *ptr;
409 if (uwep && uwep->oartifact == ART_EXCALIBUR)
412 return (boolean) haseyes(ptr);
415 /* creature will slide out of armor */
418 register struct permonst *ptr;
420 return (boolean) (is_whirly(ptr) || ptr->msize <= MZ_SMALL
421 || noncorporeal(ptr));
424 /* creature will break out of armor */
427 register struct permonst *ptr;
432 return (boolean) (bigmonst(ptr)
433 || (ptr->msize > MZ_SMALL && !humanoid(ptr))
434 /* special cases of humanoids that cannot wear suits */
435 || ptr == &mons[PM_MARILITH]
436 || ptr == &mons[PM_WINGED_GARGOYLE]);
439 /* creature sticks other creatures it hits */
442 register struct permonst *ptr;
444 return (boolean) (dmgtype(ptr, AD_STCK) || dmgtype(ptr, AD_WRAP)
445 || attacktype(ptr, AT_HUGS));
448 /* some monster-types can't vomit */
451 struct permonst *ptr;
453 /* rats and mice are incapable of vomiting;
454 which other creatures have the same limitation? */
455 if (ptr->mlet == S_RODENT && ptr != &mons[PM_ROCK_MOLE]
456 && ptr != &mons[PM_WOODCHUCK])
461 /* number of horns this type of monster has on its head */
464 struct permonst *ptr;
466 switch (monsndx(ptr)) {
467 case PM_HORNED_DEVIL: /* ? "more than one" */
472 case PM_WHITE_UNICORN:
473 case PM_GRAY_UNICORN:
474 case PM_BLACK_UNICORN:
483 /* does monster-type deal out a particular type of damage from a particular
486 dmgtype_fromattack(ptr, dtyp, atyp)
487 struct permonst *ptr;
492 for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
493 if (a->adtyp == dtyp && (atyp == AT_ANY || a->aatyp == atyp))
495 return (struct attack *) 0;
498 /* does monster-type deal out a particular type of damage from any attack */
501 struct permonst *ptr;
504 return dmgtype_fromattack(ptr, dtyp, AT_ANY) ? TRUE : FALSE;
507 /* returns the maximum damage a defender can do to the attacker via
510 max_passive_dmg(mdef, magr)
511 register struct monst *mdef, *magr;
513 int i, dmg = 0, multi2 = 0;
516 /* each attack by magr can result in passive damage */
517 for (i = 0; i < NATTK; i++)
518 switch (magr->data->mattk[i].aatyp) {
535 for (i = 0; i < NATTK; i++)
536 if (mdef->data->mattk[i].aatyp == AT_NONE
537 || mdef->data->mattk[i].aatyp == AT_BOOM) {
538 adtyp = mdef->data->mattk[i].adtyp;
539 if ((adtyp == AD_ACID && !resists_acid(magr))
540 || (adtyp == AD_COLD && !resists_cold(magr))
541 || (adtyp == AD_FIRE && !resists_fire(magr))
542 || (adtyp == AD_ELEC && !resists_elec(magr))
543 || adtyp == AD_PHYS) {
544 dmg = mdef->data->mattk[i].damn;
546 dmg = mdef->data->mlevel + 1;
547 dmg *= mdef->data->mattk[i].damd;
556 /* determine whether two monster types are from the same species */
559 struct permonst *pm1, *pm2;
561 char let1 = pm1->mlet, let2 = pm2->mlet;
564 return TRUE; /* exact match */
565 /* player races have their own predicates */
567 return is_human(pm2);
571 return is_dwarf(pm2);
573 return is_gnome(pm2);
576 /* other creatures are less precise */
578 return is_giant(pm2); /* open to quibbling here */
580 return is_golem(pm2); /* even moreso... */
581 if (is_mind_flayer(pm1))
582 return is_mind_flayer(pm2);
583 if (let1 == S_KOBOLD || pm1 == &mons[PM_KOBOLD_ZOMBIE]
584 || pm1 == &mons[PM_KOBOLD_MUMMY])
585 return (let2 == S_KOBOLD || pm2 == &mons[PM_KOBOLD_ZOMBIE]
586 || pm2 == &mons[PM_KOBOLD_MUMMY]);
588 return (let2 == S_OGRE);
590 return (let2 == S_NYMPH);
591 if (let1 == S_CENTAUR)
592 return (let2 == S_CENTAUR);
594 return is_unicorn(pm2);
595 if (let1 == S_DRAGON)
596 return (let2 == S_DRAGON);
598 return (let2 == S_NAGA);
599 /* other critters get steadily messier */
601 return is_rider(pm2); /* debatable */
603 return is_minion(pm2); /* [needs work?] */
604 /* tengu don't match imps (first test handled case of both being tengu) */
605 if (pm1 == &mons[PM_TENGU] || pm2 == &mons[PM_TENGU])
608 return (let2 == S_IMP);
609 /* and minor demons (imps) don't match major demons */
610 else if (let2 == S_IMP)
613 return is_demon(pm2);
614 if (is_undead(pm1)) {
615 if (let1 == S_ZOMBIE)
616 return (let2 == S_ZOMBIE);
618 return (let2 == S_MUMMY);
619 if (let1 == S_VAMPIRE)
620 return (let2 == S_VAMPIRE);
622 return (let2 == S_LICH);
623 if (let1 == S_WRAITH)
624 return (let2 == S_WRAITH);
626 return (let2 == S_GHOST);
627 } else if (is_undead(pm2))
630 /* check for monsters which grow into more mature forms */
632 int m1 = monsndx(pm1), m2 = monsndx(pm2), prv, nxt;
634 /* we know m1 != m2 (very first check above); test all smaller
635 forms of m1 against m2, then all larger ones; don't need to
636 make the corresponding tests for variants of m2 against m1 */
637 for (prv = m1, nxt = big_to_little(m1); nxt != prv;
638 prv = nxt, nxt = big_to_little(nxt))
641 for (prv = m1, nxt = little_to_big(m1); nxt != prv;
642 prv = nxt, nxt = little_to_big(nxt))
646 /* not caught by little/big handling */
647 if (pm1 == &mons[PM_GARGOYLE] || pm1 == &mons[PM_WINGED_GARGOYLE])
648 return (pm2 == &mons[PM_GARGOYLE]
649 || pm2 == &mons[PM_WINGED_GARGOYLE]);
650 if (pm1 == &mons[PM_KILLER_BEE] || pm1 == &mons[PM_QUEEN_BEE])
651 return (pm2 == &mons[PM_KILLER_BEE] || pm2 == &mons[PM_QUEEN_BEE]);
653 if (is_longworm(pm1))
654 return is_longworm(pm2); /* handles tail */
655 /* [currently there's no reason to bother matching up
656 assorted bugs and blobs with their closest variants] */
661 /* return an index into the mons array */
664 struct permonst *ptr;
668 i = (int) (ptr - &mons[0]);
669 if (i < LOW_PM || i >= NUMMONS) {
670 panic("monsndx - could not index monster (%s)",
671 fmt_ptr((genericptr_t) ptr));
672 return NON_PM; /* will not get here */
677 /* for handling alternate spellings */
683 /* figure out what type of monster a user-supplied string is specifying */
688 /* Be careful. We must check the entire string in case it was
689 * something such as "ettin zombie corpse". The calling routine
690 * doesn't know about the "corpse" until the monster name has
691 * already been taken off the front, so we have to be able to
692 * read the name with extraneous stuff such as "corpse" stuck on
694 * This causes a problem for names which prefix other names such
695 * as "ettin" on "ettin zombie". In this case we want the _longest_
697 * This also permits plurals created by adding suffixes such as 's'
698 * or 'es'. Other plurals must still be handled explicitly.
701 register int mntmp = NON_PM;
702 register char *s, *str, *term;
706 str = strcpy(buf, in_str);
708 if (!strncmp(str, "a ", 2))
710 else if (!strncmp(str, "an ", 3))
712 else if (!strncmp(str, "the ", 4))
718 if ((s = strstri(str, "vortices")) != 0)
720 /* be careful with "ies"; "priest", "zombies" */
721 else if (slen > 3 && !strcmpi(term - 3, "ies")
722 && (slen < 7 || strcmpi(term - 7, "zombies")))
723 Strcpy(term - 3, "y");
724 /* luckily no monster names end in fe or ve with ves plurals */
725 else if (slen > 3 && !strcmpi(term - 3, "ves"))
726 Strcpy(term - 3, "f");
728 slen = strlen(str); /* length possibly needs recomputing */
731 static const struct alt_spl names[] = {
732 /* Alternate spellings */
733 { "grey dragon", PM_GRAY_DRAGON },
734 { "baby grey dragon", PM_BABY_GRAY_DRAGON },
735 { "grey unicorn", PM_GRAY_UNICORN },
736 { "grey ooze", PM_GRAY_OOZE },
737 { "gray-elf", PM_GREY_ELF },
738 { "mindflayer", PM_MIND_FLAYER },
739 { "master mindflayer", PM_MASTER_MIND_FLAYER },
740 /* More alternates; priest and priestess are separate monster
741 types but that isn't the case for {aligned,high} priests */
742 { "aligned priestess", PM_ALIGNED_PRIEST },
743 { "high priestess", PM_HIGH_PRIEST },
744 /* Inappropriate singularization by -ves check above */
745 { "master of thief", PM_MASTER_OF_THIEVES },
746 /* Potential misspellings where we want to avoid falling back
747 to the rank title prefix (input has been singularized) */
748 { "master thief", PM_MASTER_OF_THIEVES },
749 { "master of assassin", PM_MASTER_ASSASSIN },
751 { "invisible stalker", PM_STALKER },
752 { "high-elf", PM_ELVENKING }, /* PM_HIGH_ELF is obsolete */
753 /* other misspellings or incorrect words */
754 { "wood-elf", PM_WOODLAND_ELF },
755 { "wood elf", PM_WOODLAND_ELF },
756 { "woodland nymph", PM_WOOD_NYMPH },
757 { "halfling", PM_HOBBIT }, /* potential guess for polyself */
758 { "genie", PM_DJINNI }, /* potential guess for ^G/#wizgenesis */
759 /* Hyphenated names -- it would be nice to handle these via
760 fuzzymatch() but it isn't able to ignore trailing stuff */
761 { "ki rin", PM_KI_RIN },
762 { "uruk hai", PM_URUK_HAI },
763 { "orc captain", PM_ORC_CAPTAIN },
764 { "woodland elf", PM_WOODLAND_ELF },
765 { "green elf", PM_GREEN_ELF },
766 { "grey elf", PM_GREY_ELF },
767 { "gray elf", PM_GREY_ELF },
768 { "elf lord", PM_ELF_LORD },
769 { "olog hai", PM_OLOG_HAI },
770 { "arch lich", PM_ARCH_LICH },
771 /* Some irregular plurals */
772 { "incubi", PM_INCUBUS },
773 { "succubi", PM_SUCCUBUS },
774 { "violet fungi", PM_VIOLET_FUNGUS },
775 { "homunculi", PM_HOMUNCULUS },
776 { "baluchitheria", PM_BALUCHITHERIUM },
777 { "lurkers above", PM_LURKER_ABOVE },
778 { "cavemen", PM_CAVEMAN },
779 { "cavewomen", PM_CAVEWOMAN },
780 { "watchmen", PM_WATCHMAN },
781 { "djinn", PM_DJINNI },
782 { "mumakil", PM_MUMAK },
783 { "erinyes", PM_ERINYS },
787 register const struct alt_spl *namep;
789 for (namep = names; namep->name; namep++)
790 if (!strncmpi(str, namep->name, (int) strlen(namep->name)))
791 return namep->pm_val;
794 for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
795 register int m_i_len = (int) strlen(mons[i].mname);
797 if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) {
798 if (m_i_len == slen) {
800 break; /* exact match */
801 } else if (slen > m_i_len
803 && (str[m_i_len] == ' '
804 || !strcmpi(&str[m_i_len], "s")
805 || !strncmpi(&str[m_i_len], "s ", 2)
806 || !strcmpi(&str[m_i_len], "'")
807 || !strncmpi(&str[m_i_len], "' ", 2)
808 || !strcmpi(&str[m_i_len], "'s")
809 || !strncmpi(&str[m_i_len], "'s ", 3)
810 || !strcmpi(&str[m_i_len], "es")
811 || !strncmpi(&str[m_i_len], "es ", 3))) {
813 && !strncmp(&str[m_i_len], "
\82Ì", 2)) {
821 mntmp = title_to_mon(str, (int *) 0, (int *) 0);
825 /* monster class from user input; used for genocide and controlled polymorph;
826 returns 0 rather than MAXMCLASSES if no match is found */
828 name_to_monclass(in_str, mndx_p)
832 /* Single letters are matched against def_monsyms[].sym; words
833 or phrases are first matched against def_monsyms[].explain
834 to check class description; if not found there, then against
835 mons[].mname to test individual monster types. Input can be a
836 substring of the full description or mname, but to be accepted,
837 such partial matches must start at beginning of a word. Some
838 class descriptions include "foo or bar" and "foo or other foo"
839 so we don't want to accept "or", "other", "or other" there. */
840 static NEARDATA const char *const falsematch[] = {
841 /* multiple-letter input which matches any of these gets rejected */
842 "an", "the", "or", "other", "or other", 0
844 /* positive pm_val => specific monster; negative => class */
845 static NEARDATA const struct alt_spl truematch[] = {
846 /* "long worm" won't match "worm" class but would accidentally match
847 "long worm tail" class before the comparison with monster types */
848 { "long worm", PM_LONG_WORM },
849 /* matches wrong--or at least suboptimal--class */
850 { "demon", -S_DEMON }, /* hits "imp or minor demon" */
851 /* matches specific monster (overly restrictive) */
852 { "devil", -S_DEMON }, /* always "horned devil" */
853 /* some plausible guesses which need help */
854 { "bug", -S_XAN }, /* would match bugbear... */
855 { "fish", -S_EEL }, /* wouldn't match anything */
863 *mndx_p = NON_PM; /* haven't [yet] matched a specific type */
865 if (!in_str || !in_str[0]) {
868 } else if (!in_str[1]) {
869 /* single character */
870 i = def_char_to_monclass(*in_str);
871 if (i == S_MIMIC_DEF) { /* ']' -> 'm' */
873 } else if (i == S_WORM_TAIL) { /* '~' -> 'w' */
876 *mndx_p = PM_LONG_WORM;
877 } else if (i == MAXMCLASSES) /* maybe 'I' */
878 i = (*in_str == DEF_INVISIBLE) ? S_invisible : 0;
881 /* multiple characters */
882 if (!strcmpi(in_str, "long")) /* not enough to match "long worm" */
883 return 0; /* avoid false whole-word match with "long worm tail" */
884 in_str = makesingular(in_str);
885 /* check for special cases */
886 for (i = 0; falsematch[i]; i++)
887 if (!strcmpi(in_str, falsematch[i]))
889 for (i = 0; truematch[i].name; i++)
890 if (!strcmpi(in_str, truematch[i].name)) {
891 i = truematch[i].pm_val;
893 return -i; /* class */
895 *mndx_p = i; /* monster */
898 /* check monster class descriptions */
899 len = (int) strlen(in_str);
900 for (i = 1; i < MAXMCLASSES; i++) {
901 x = def_monsyms[i].explain;
902 if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' ')
903 && ((int) strlen(p) >= len
904 && (p[len] == '\0' || p[len] == ' ')))
907 /* check individual species names */
908 i = name_to_mon(in_str);
918 /* returns 3 values (0=male, 1=female, 2=none) */
921 register struct monst *mtmp;
923 if (is_neuter(mtmp->data))
928 /* Like gender(), but lower animals and such are still "it".
929 This is the one we want to use when printing messages. */
931 pronoun_gender(mtmp, override_vis)
932 register struct monst *mtmp;
933 boolean override_vis; /* if True then 'no it' unless neuter */
935 if (!override_vis && !canspotmon(mtmp))
937 if (is_neuter(mtmp->data))
939 return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ)
940 || type_is_pname(mtmp->data)) ? (int) mtmp->female : 2;
943 /* used for nearby monsters when you go to another level */
948 if (mtmp == u.usteed)
951 /* Wizard with Amulet won't bother trying to follow across levels */
952 if (mtmp->iswiz && mon_has_amulet(mtmp))
954 /* some monsters will follow even while intending to flee from you */
955 if (mtmp->mtame || mtmp->iswiz || is_fshk(mtmp))
957 /* stalking types follow, but won't when fleeing unless you hold
959 return (boolean) ((mtmp->data->mflags2 & M2_STALK)
960 && (!mtmp->mflee || u.uhave.amulet));
963 static const short grownups[][2] = {
964 { PM_CHICKATRICE, PM_COCKATRICE },
965 { PM_LITTLE_DOG, PM_DOG },
966 { PM_DOG, PM_LARGE_DOG },
967 { PM_HELL_HOUND_PUP, PM_HELL_HOUND },
968 { PM_WINTER_WOLF_CUB, PM_WINTER_WOLF },
969 { PM_KITTEN, PM_HOUSECAT },
970 { PM_HOUSECAT, PM_LARGE_CAT },
971 { PM_PONY, PM_HORSE },
972 { PM_HORSE, PM_WARHORSE },
973 { PM_KOBOLD, PM_LARGE_KOBOLD },
974 { PM_LARGE_KOBOLD, PM_KOBOLD_LORD },
975 { PM_GNOME, PM_GNOME_LORD },
976 { PM_GNOME_LORD, PM_GNOME_KING },
977 { PM_DWARF, PM_DWARF_LORD },
978 { PM_DWARF_LORD, PM_DWARF_KING },
979 { PM_MIND_FLAYER, PM_MASTER_MIND_FLAYER },
980 { PM_ORC, PM_ORC_CAPTAIN },
981 { PM_HILL_ORC, PM_ORC_CAPTAIN },
982 { PM_MORDOR_ORC, PM_ORC_CAPTAIN },
983 { PM_URUK_HAI, PM_ORC_CAPTAIN },
984 { PM_SEWER_RAT, PM_GIANT_RAT },
985 { PM_CAVE_SPIDER, PM_GIANT_SPIDER },
986 { PM_OGRE, PM_OGRE_LORD },
987 { PM_OGRE_LORD, PM_OGRE_KING },
988 { PM_ELF, PM_ELF_LORD },
989 { PM_WOODLAND_ELF, PM_ELF_LORD },
990 { PM_GREEN_ELF, PM_ELF_LORD },
991 { PM_GREY_ELF, PM_ELF_LORD },
992 { PM_ELF_LORD, PM_ELVENKING },
993 { PM_LICH, PM_DEMILICH },
994 { PM_DEMILICH, PM_MASTER_LICH },
995 { PM_MASTER_LICH, PM_ARCH_LICH },
996 { PM_VAMPIRE, PM_VAMPIRE_LORD },
997 { PM_BAT, PM_GIANT_BAT },
998 { PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON },
999 { PM_BABY_SILVER_DRAGON, PM_SILVER_DRAGON },
1000 #if 0 /* DEFERRED */
1001 {PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
1003 { PM_BABY_RED_DRAGON, PM_RED_DRAGON },
1004 { PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON },
1005 { PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON },
1006 { PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON },
1007 { PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON },
1008 { PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON },
1009 { PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON },
1010 { PM_RED_NAGA_HATCHLING, PM_RED_NAGA },
1011 { PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA },
1012 { PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA },
1013 { PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA },
1014 { PM_SMALL_MIMIC, PM_LARGE_MIMIC },
1015 { PM_LARGE_MIMIC, PM_GIANT_MIMIC },
1016 { PM_BABY_LONG_WORM, PM_LONG_WORM },
1017 { PM_BABY_PURPLE_WORM, PM_PURPLE_WORM },
1018 { PM_BABY_CROCODILE, PM_CROCODILE },
1019 { PM_SOLDIER, PM_SERGEANT },
1020 { PM_SERGEANT, PM_LIEUTENANT },
1021 { PM_LIEUTENANT, PM_CAPTAIN },
1022 { PM_WATCHMAN, PM_WATCH_CAPTAIN },
1023 { PM_ALIGNED_PRIEST, PM_HIGH_PRIEST },
1024 { PM_STUDENT, PM_ARCHEOLOGIST },
1025 { PM_ATTENDANT, PM_HEALER },
1026 { PM_PAGE, PM_KNIGHT },
1027 { PM_ACOLYTE, PM_PRIEST },
1028 { PM_APPRENTICE, PM_WIZARD },
1029 { PM_MANES, PM_LEMURE },
1030 { PM_KEYSTONE_KOP, PM_KOP_SERGEANT },
1031 { PM_KOP_SERGEANT, PM_KOP_LIEUTENANT },
1032 { PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN },
1037 little_to_big(montype)
1042 for (i = 0; grownups[i][0] >= LOW_PM; i++)
1043 if (montype == grownups[i][0]) {
1044 montype = grownups[i][1];
1051 big_to_little(montype)
1056 for (i = 0; grownups[i][0] >= LOW_PM; i++)
1057 if (montype == grownups[i][1]) {
1058 montype = grownups[i][0];
1064 /* determine whether two permonst indices are part of the same progression;
1065 existence of progressions with more than one step makes it a bit tricky */
1067 big_little_match(montyp1, montyp2)
1068 int montyp1, montyp2;
1072 /* simplest case: both are same pm */
1073 if (montyp1 == montyp2)
1075 /* assume it isn't possible to grow from one class letter to another */
1076 if (mons[montyp1].mlet != mons[montyp2].mlet)
1078 /* check whether montyp1 can grow up into montyp2 */
1079 for (l = montyp1; (b = little_to_big(l)) != l; l = b)
1082 /* check whether montyp2 can grow up into montyp1 */
1083 for (l = montyp2; (b = little_to_big(l)) != l; l = b)
1086 /* neither grows up to become the other; no match */
1091 * Return the permonst ptr for the race of the monster.
1092 * Returns correct pointer for non-polymorphed and polymorphed
1093 * player. It does not return a pointer to player role character.
1095 const struct permonst *
1099 if (mtmp == &youmonst && !Upolyd)
1100 return &mons[urace.malenum];
1106 static const char *levitate[4] = { "float", "Float", "wobble", "Wobble" };
1108 static const char *levitate[4] = { "
\95\82\82", "
\95\82\82", "
\82æ
\82ë
\82ß
\82", "
\82æ
\82ë
\82ß
\82" };
1110 static const char *flys[4] = { "fly", "Fly", "flutter", "Flutter" };
1112 static const char *flys[4] = { "
\94ò
\82Ô", "
\94ò
\82Ô", "
\82¨
\82Ì
\82Ì
\82", "
\82¨
\82Ì
\82Ì
\82" };
1114 static const char *flyl[4] = { "fly", "Fly", "stagger", "Stagger" };
1116 static const char *flyl[4] = { "
\94ò
\82Ô", "
\94ò
\82Ô", "
\82æ
\82ë
\82ß
\82", "
\82æ
\82ë
\82ß
\82" };
1118 static const char *slither[4] = { "slither", "Slither", "falter", "Falter" };
1120 static const char *slither[4] = { "
\8a\8a\82é", "
\8a\8a\82é", "
\82½
\82¶
\82ë
\82®", "
\82½
\82¶
\82ë
\82®" };
1122 static const char *ooze[4] = { "ooze", "Ooze", "tremble", "Tremble" };
1124 static const char *ooze[4] = { "
\82É
\82¶
\82Ý
\8fo
\82é", "
\82É
\82¶
\82Ý
\8fo
\82é", "
\90g
\90k
\82¢
\82·
\82é", "
\90g
\90k
\82¢
\82·
\82é" };
1126 static const char *immobile[4] = { "wiggle", "Wiggle", "pulsate", "Pulsate" };
1128 static const char *immobile[4] = { "
\93®
\82", "
\93®
\82", "
\90k
\82¦
\82é", "
\90k
\82¦
\82é" };
1130 static const char *crawl[4] = { "crawl", "Crawl", "falter", "Falter" };
1132 static const char *crawl[4] = { "
\82Í
\82¢
\82¸
\82é", "
\82Í
\82¢
\82¸
\82é", "
\82½
\82¶
\82ë
\82®", "
\82½
\82¶
\82ë
\82®" };
1135 locomotion(ptr, def)
1136 const struct permonst *ptr;
1139 int capitalize = (*def == highc(*def));
1141 return (is_floater(ptr) ? levitate[capitalize]
1142 : (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize]
1143 : (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize]
1144 : slithy(ptr) ? slither[capitalize]
1145 : amorphous(ptr) ? ooze[capitalize]
1146 : !ptr->mmove ? immobile[capitalize]
1147 : nolimbs(ptr) ? crawl[capitalize]
1152 *
\81u
\82æ
\82ë
\82ß
\82
\81v
\82ð
\89ö
\95¨
\82Ì
\8eí
\97Þ
\82É
\82æ
\82Á
\82Ä
\95Ï
\82¦
\82é
\81B
1153 *
\8e©
\95ª
\82É
\91Î
\82µ
\82Ä
\8eg
\82¤
\8fê
\8d\87\82É
\82Í
\8aù
\82É
\81u
\82
\82ç
\82
\82ç
\82·
\82é
\81v
\82ª
\8eg
\82í
\82ê
\82Ä
\82¢
\82é
\82Ì
\82Å
\81A
1154 *
\95Ï
\89»
\82µ
\82Ä
\82¢
\82Ä
\82à
\82»
\82Ì
\82Ü
\82Ü
\82É
\82·
\82é
\81B
1155 *
\91\8a\8eè
\82É
\91Î
\82µ
\82Ä
\8eg
\82¤
\8fê
\8d\87\82Í
\81u
\82
\82ç
\82
\82ç
\82·
\82é
\81v
\82Í
\95s
\8e©
\91R
\82È
\82Ì
\82Å
\82±
\82ê
\82ð
\8eg
\82¤
\81B
1159 const struct permonst *ptr;
1162 int capitalize = 2 + (*def == highc(*def));
1164 return (is_floater(ptr) ? levitate[capitalize]
1165 : (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize]
1166 : (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize]
1167 : slithy(ptr) ? slither[capitalize]
1168 : amorphous(ptr) ? ooze[capitalize]
1169 : !ptr->mmove ? immobile[capitalize]
1170 : nolimbs(ptr) ? crawl[capitalize]
1174 static const char *levitate2 = "
\95\82\82«
\8fo
\82½";
1175 static const char *fly2 = "
\94ò
\82Ñ
\8fo
\82½";
1176 static const char *slither2 = "
\8a\8a\82è
\8fo
\82½";
1177 static const char *ooze2 = "
\82É
\82¶
\82Ý
\8fo
\82½";
1178 static const char *crawl2 = "
\82Í
\82¢
\82¸
\82è
\8fo
\82½";
1181 jumpedthrough(ptr, def)
1182 const struct permonst *ptr;
1186 is_floater(ptr) ? levitate2 :
1187 is_flyer(ptr) ? fly2 :
1188 slithy(ptr) ? slither2 :
1189 amorphous(ptr) ? ooze2 :
1190 nolimbs(ptr) ? crawl2 :
1196 /* return phrase describing the effect of fire attack on a type of monster */
1198 on_fire(mptr, mattk)
1199 struct permonst *mptr;
1200 struct attack *mattk;
1204 switch (monsndx(mptr)) {
1205 case PM_FLAMING_SPHERE:
1206 case PM_FIRE_VORTEX:
1207 case PM_FIRE_ELEMENTAL:
1210 what = "already on fire";
1212 what = "
\82·
\82Å
\82É
\89\8a\82É
\82Â
\82Â
\82Ü
\82ê
\82Ä
\82¢
\82é";
1214 case PM_WATER_ELEMENTAL:
1216 case PM_STEAM_VORTEX:
1220 what = "
\95¦
\93«
\82µ
\82½";
1223 case PM_GLASS_GOLEM:
1227 what = "
\97n
\82¯
\82½";
1229 case PM_STONE_GOLEM:
1232 case PM_AIR_ELEMENTAL:
1233 case PM_EARTH_ELEMENTAL:
1234 case PM_DUST_VORTEX:
1235 case PM_ENERGY_VORTEX:
1237 what = "heating up";
1239 what = "
\94M
\82
\82È
\82Á
\82½";
1243 what = (mattk->aatyp == AT_HUGS) ? "being roasted" : "on fire";
1245 what = (mattk->aatyp == AT_HUGS) ? "
\8aÛ
\8fÄ
\82¯
\82É
\82È
\82Á
\82½" : "
\89Î
\82¾
\82é
\82Ü
\82É
\82È
\82Á
\82½";
1253 * True if monster is presumed to have a sense of smell.
1254 * False if monster definitely does not have a sense of smell.
1256 * Do not base this on presence of a head or nose, since many
1257 * creatures sense smells other ways (feelers, forked-tongues, etc.)
1258 * We're assuming all insects can smell at a distance too.
1262 struct permonst *mdat;
1265 || mdat->mlet == S_EYE /* spheres */
1266 || mdat->mlet == S_JELLY || mdat->mlet == S_PUDDING
1267 || mdat->mlet == S_BLOB || mdat->mlet == S_VORTEX
1268 || mdat->mlet == S_ELEMENTAL
1269 || mdat->mlet == S_FUNGUS /* mushrooms and fungi */
1270 || mdat->mlet == S_LIGHT)