1 /* NetHack 3.6 mondata.c $NHDT-Date: 1470966820 2016/08/12 01:53:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.61 $ */
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.
10 /* set up an individual monster's base type (initial creation, shapechange) */
12 set_mon_data(mon
, ptr
, flag
)
17 int new_speed
, old_speed
= mon
->data
? mon
->data
->mmove
: 0;
20 mon
->mnum
= (short) monsndx(ptr
);
22 return; /* "don't care" */
25 mon
->mintrinsics
|= (ptr
->mresists
& 0x00FF);
27 mon
->mintrinsics
= (ptr
->mresists
& 0x00FF);
29 if (mon
->movement
) { /* same adjustment as poly'd hero undergoes */
30 new_speed
= ptr
->mmove
;
31 /* prorate unused movement if new form is slower so that
32 it doesn't get extra moves leftover from previous form;
33 if new form is faster, leave unused movement as is */
34 if (new_speed
< old_speed
)
35 mon
->movement
= new_speed
* mon
->movement
/ old_speed
;
40 /* does monster-type have any attack for a specific type of damage? */
42 attacktype_fordmg(ptr
, atyp
, dtyp
)
48 for (a
= &ptr
->mattk
[0]; a
< &ptr
->mattk
[NATTK
]; a
++)
49 if (a
->aatyp
== atyp
&& (dtyp
== AD_ANY
|| a
->adtyp
== dtyp
))
51 return (struct attack
*) 0;
54 /* does monster-type have a particular type of attack */
60 return attacktype_fordmg(ptr
, atyp
, AD_ANY
) ? TRUE
: FALSE
;
63 /* returns True if monster doesn't attack, False if it does */
69 struct attack
*mattk
= ptr
->mattk
;
71 for (i
= 0; i
< NATTK
; i
++) {
72 /* AT_BOOM "passive attack" (gas spore's explosion upon death)
73 isn't an attack as far as our callers are concerned */
74 if (mattk
[i
].aatyp
== AT_BOOM
)
83 /* does monster-type transform into something else when petrified? */
88 /* non-stone golems turn into stone golems unless latter is genocided */
89 return (boolean
) (is_golem(ptr
) && ptr
!= &mons
[PM_STONE_GOLEM
]
90 && !(mvitals
[PM_STONE_GOLEM
].mvflags
& G_GENOD
));
94 /* returns True if monster is drain-life resistant */
99 struct permonst
*ptr
= mon
->data
;
102 if (is_undead(ptr
) || is_demon(ptr
) || is_were(ptr
)
103 /* is_were() doesn't handle hero in human form */
104 || (mon
== &youmonst
&& u
.ulycn
>= LOW_PM
)
105 || ptr
== &mons
[PM_DEATH
] || is_vampshifter(mon
))
107 wep
= (mon
== &youmonst
) ? uwep
: MON_WEP(mon
);
108 return (boolean
) (wep
&& wep
->oartifact
&& defends(AD_DRLI
, wep
));
111 /* True if monster is magic-missile (actually, general magic) resistant */
116 struct permonst
*ptr
= mon
->data
;
117 boolean is_you
= (mon
== &youmonst
);
121 /* as of 3.2.0: gray dragons, Angels, Oracle, Yeenoghu */
122 if (dmgtype(ptr
, AD_MAGM
) || ptr
== &mons
[PM_BABY_GRAY_DRAGON
]
123 || dmgtype(ptr
, AD_RBRE
)) /* Chromatic Dragon */
125 /* check for magic resistance granted by wielded weapon */
126 o
= is_you
? uwep
: MON_WEP(mon
);
127 if (o
&& o
->oartifact
&& defends(AD_MAGM
, o
))
129 /* check for magic resistance granted by worn or carried items */
130 o
= is_you
? invent
: mon
->minvent
;
131 slotmask
= W_ARMOR
| W_ACCESSORY
;
132 if (!is_you
/* assumes monsters don't wield non-weapons */
133 || (uwep
&& (uwep
->oclass
== WEAPON_CLASS
|| is_weptool(uwep
))))
135 if (is_you
&& u
.twoweap
)
136 slotmask
|= W_SWAPWEP
;
137 for (; o
; o
= o
->nobj
)
138 if (((o
->owornmask
& slotmask
) != 0L
139 && objects
[o
->otyp
].oc_oprop
== ANTIMAGIC
)
140 || (o
->oartifact
&& defends_when_carried(AD_MAGM
, o
)))
145 /* True iff monster is resistant to light-induced blindness */
150 struct permonst
*ptr
= mon
->data
;
151 boolean is_you
= (mon
== &youmonst
);
155 if (is_you
? (Blind
|| Unaware
)
156 : (mon
->mblinded
|| !mon
->mcansee
|| !haseyes(ptr
)
157 /* BUG: temporary sleep sets mfrozen, but since
158 paralysis does too, we can't check it */
161 /* yellow light, Archon; !dust vortex, !cobra, !raven */
162 if (dmgtype_fromattack(ptr
, AD_BLND
, AT_EXPL
)
163 || dmgtype_fromattack(ptr
, AD_BLND
, AT_GAZE
))
165 o
= is_you
? uwep
: MON_WEP(mon
);
166 if (o
&& o
->oartifact
&& defends(AD_BLND
, o
))
168 o
= is_you
? invent
: mon
->minvent
;
169 slotmask
= W_ARMOR
| W_ACCESSORY
;
170 if (!is_you
/* assumes monsters don't wield non-weapons */
171 || (uwep
&& (uwep
->oclass
== WEAPON_CLASS
|| is_weptool(uwep
))))
173 if (is_you
&& u
.twoweap
)
174 slotmask
|= W_SWAPWEP
;
175 for (; o
; o
= o
->nobj
)
176 if (((o
->owornmask
& slotmask
) != 0L
177 && objects
[o
->otyp
].oc_oprop
== BLINDED
)
178 || (o
->oartifact
&& defends_when_carried(AD_BLND
, o
)))
183 /* True iff monster can be blinded by the given attack;
184 note: may return True when mdef is blind (e.g. new cream-pie attack) */
186 can_blnd(magr
, mdef
, aatyp
, obj
)
187 struct monst
*magr
; /* NULL == no specific aggressor */
190 struct obj
*obj
; /* aatyp == AT_WEAP, AT_SPIT */
192 boolean is_you
= (mdef
== &youmonst
);
193 boolean check_visor
= FALSE
;
197 /* no eyes protect against all attacks for now */
198 if (!haseyes(mdef
->data
))
206 case AT_BREA
: /* assumed to be lightning */
207 /* light-based attacks may be cancelled or resisted */
208 if (magr
&& magr
->mcan
)
210 return !resists_blnd(mdef
);
215 /* an object is used (thrown/spit/other) */
216 if (obj
&& (obj
->otyp
== CREAM_PIE
)) {
217 if (is_you
&& Blindfolded
)
219 } else if (obj
&& (obj
->otyp
== BLINDING_VENOM
)) {
220 /* all ublindf, including LENSES, protect, cream-pies too */
221 if (is_you
&& (ublindf
|| u
.ucreamed
))
224 } else if (obj
&& (obj
->otyp
== POT_BLINDNESS
)) {
225 return TRUE
; /* no defense */
227 return FALSE
; /* other objects cannot cause blindness yet */
228 if ((magr
== &youmonst
) && u
.uswallow
)
229 return FALSE
; /* can't affect eyes while inside monster */
233 if (is_you
&& (Blindfolded
|| Unaware
|| u
.ucreamed
))
235 if (!is_you
&& mdef
->msleeping
)
240 /* e.g. raven: all ublindf, including LENSES, protect */
241 if (is_you
&& ublindf
)
243 if ((magr
== &youmonst
) && u
.uswallow
)
244 return FALSE
; /* can't affect eyes while inside monster */
250 /* some physical, blind-inducing attacks can be cancelled */
251 if (magr
&& magr
->mcan
)
259 /* check if wearing a visor (only checked if visor might help) */
261 o
= (mdef
== &youmonst
) ? invent
: mdef
->minvent
;
262 for (; o
; o
= o
->nobj
)
263 if ((o
->owornmask
& W_ARMH
)
264 && (s
= OBJ_DESCR(objects
[o
->otyp
])) != (char *) 0
265 && !strcmp(s
, "visored helmet"))
272 /* returns True if monster can attack at range */
275 struct permonst
*ptr
;
277 register int i
, atyp
;
278 long atk_mask
= (1L << AT_BREA
) | (1L << AT_SPIT
) | (1L << AT_GAZE
);
280 /* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP)
281 * || attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE)
282 * || attacktype(ptr, AT_MAGC));
283 * but that's too slow -dlc
285 for (i
= 0; i
< NATTK
; i
++) {
286 atyp
= ptr
->mattk
[i
].aatyp
;
289 /* assert(atyp < 32); */
290 if ((atk_mask
& (1L << atyp
)) != 0L)
296 /* True if specific monster is especially affected by silver weapons */
298 mon_hates_silver(mon
)
301 return (boolean
) (is_vampshifter(mon
) || hates_silver(mon
->data
));
304 /* True if monster-type is especially affected by silver weapons */
307 register struct permonst
*ptr
;
309 return (boolean
) (is_were(ptr
) || ptr
->mlet
== S_VAMPIRE
|| is_demon(ptr
)
310 || ptr
== &mons
[PM_SHADE
]
311 || (ptr
->mlet
== S_IMP
&& ptr
!= &mons
[PM_TENGU
]));
314 /* True iff the type of monster pass through iron bars */
317 struct permonst
*mptr
;
319 return (boolean
) (passes_walls(mptr
) || amorphous(mptr
) || unsolid(mptr
)
320 || is_whirly(mptr
) || verysmall(mptr
)
321 || dmgtype(mptr
, AD_CORR
) || dmgtype(mptr
, AD_RUST
)
322 || (slithy(mptr
) && !bigmonst(mptr
)));
325 /* returns True if monster can blow (whistle, etc) */
328 register struct monst
*mtmp
;
330 if ((is_silent(mtmp
->data
) || mtmp
->data
->msound
== MS_BUZZ
)
331 && (breathless(mtmp
->data
) || verysmall(mtmp
->data
)
332 || !has_head(mtmp
->data
) || mtmp
->data
->mlet
== S_EEL
))
334 if ((mtmp
== &youmonst
) && Strangled
)
339 /* True if mon is vulnerable to strangulation */
341 can_be_strangled(mon
)
345 boolean nonbreathing
, nobrainer
;
347 /* For amulet of strangulation support: here we're considering
348 strangulation to be loss of blood flow to the brain due to
349 constriction of the arteries in the neck, so all headless
350 creatures are immune (no neck) as are mindless creatures
351 who don't need to breathe (brain, if any, doesn't care).
352 Mindless creatures who do need to breath are vulnerable, as
353 are non-breathing creatures which have higher brain function. */
354 if (!has_head(mon
->data
))
356 if (mon
== &youmonst
) {
357 /* hero can't be mindless but poly'ing into mindless form can
358 confer strangulation protection */
359 nobrainer
= mindless(youmonst
.data
);
360 nonbreathing
= Breathless
;
362 nobrainer
= mindless(mon
->data
);
363 /* monsters don't wear amulets of magical breathing,
364 so second part doesn't achieve anything useful... */
365 nonbreathing
= (breathless(mon
->data
)
366 || ((mamul
= which_armor(mon
, W_AMUL
)) != 0
367 && (mamul
->otyp
== AMULET_OF_MAGICAL_BREATHING
)));
369 return (boolean
) (!nobrainer
|| !nonbreathing
);
372 /* returns True if monster can track well */
375 register struct permonst
*ptr
;
377 if (uwep
&& uwep
->oartifact
== ART_EXCALIBUR
)
380 return (boolean
) haseyes(ptr
);
383 /* creature will slide out of armor */
386 register struct permonst
*ptr
;
388 return (boolean
) (is_whirly(ptr
) || ptr
->msize
<= MZ_SMALL
389 || noncorporeal(ptr
));
392 /* creature will break out of armor */
395 register struct permonst
*ptr
;
400 return (boolean
) (bigmonst(ptr
)
401 || (ptr
->msize
> MZ_SMALL
&& !humanoid(ptr
))
402 /* special cases of humanoids that cannot wear suits */
403 || ptr
== &mons
[PM_MARILITH
]
404 || ptr
== &mons
[PM_WINGED_GARGOYLE
]);
407 /* creature sticks other creatures it hits */
410 register struct permonst
*ptr
;
412 return (boolean
) (dmgtype(ptr
, AD_STCK
) || dmgtype(ptr
, AD_WRAP
)
413 || attacktype(ptr
, AT_HUGS
));
416 /* some monster-types can't vomit */
419 struct permonst
*ptr
;
421 /* rats and mice are incapable of vomiting;
422 which other creatures have the same limitation? */
423 if (ptr
->mlet
== S_RODENT
&& ptr
!= &mons
[PM_ROCK_MOLE
]
424 && ptr
!= &mons
[PM_WOODCHUCK
])
429 /* number of horns this type of monster has on its head */
432 struct permonst
*ptr
;
434 switch (monsndx(ptr
)) {
435 case PM_HORNED_DEVIL
: /* ? "more than one" */
440 case PM_WHITE_UNICORN
:
441 case PM_GRAY_UNICORN
:
442 case PM_BLACK_UNICORN
:
451 /* does monster-type deal out a particular type of damage from a particular
454 dmgtype_fromattack(ptr
, dtyp
, atyp
)
455 struct permonst
*ptr
;
460 for (a
= &ptr
->mattk
[0]; a
< &ptr
->mattk
[NATTK
]; a
++)
461 if (a
->adtyp
== dtyp
&& (atyp
== AT_ANY
|| a
->aatyp
== atyp
))
463 return (struct attack
*) 0;
466 /* does monster-type deal out a particular type of damage from any attack */
469 struct permonst
*ptr
;
472 return dmgtype_fromattack(ptr
, dtyp
, AT_ANY
) ? TRUE
: FALSE
;
475 /* returns the maximum damage a defender can do to the attacker via
478 max_passive_dmg(mdef
, magr
)
479 register struct monst
*mdef
, *magr
;
481 int i
, dmg
= 0, multi2
= 0;
484 /* each attack by magr can result in passive damage */
485 for (i
= 0; i
< NATTK
; i
++)
486 switch (magr
->data
->mattk
[i
].aatyp
) {
503 for (i
= 0; i
< NATTK
; i
++)
504 if (mdef
->data
->mattk
[i
].aatyp
== AT_NONE
505 || mdef
->data
->mattk
[i
].aatyp
== AT_BOOM
) {
506 adtyp
= mdef
->data
->mattk
[i
].adtyp
;
507 if ((adtyp
== AD_ACID
&& !resists_acid(magr
))
508 || (adtyp
== AD_COLD
&& !resists_cold(magr
))
509 || (adtyp
== AD_FIRE
&& !resists_fire(magr
))
510 || (adtyp
== AD_ELEC
&& !resists_elec(magr
))
511 || adtyp
== AD_PHYS
) {
512 dmg
= mdef
->data
->mattk
[i
].damn
;
514 dmg
= mdef
->data
->mlevel
+ 1;
515 dmg
*= mdef
->data
->mattk
[i
].damd
;
524 /* determine whether two monster types are from the same species */
527 struct permonst
*pm1
, *pm2
;
529 char let1
= pm1
->mlet
, let2
= pm2
->mlet
;
532 return TRUE
; /* exact match */
533 /* player races have their own predicates */
535 return is_human(pm2
);
539 return is_dwarf(pm2
);
541 return is_gnome(pm2
);
544 /* other creatures are less precise */
546 return is_giant(pm2
); /* open to quibbling here */
548 return is_golem(pm2
); /* even moreso... */
549 if (is_mind_flayer(pm1
))
550 return is_mind_flayer(pm2
);
551 if (let1
== S_KOBOLD
|| pm1
== &mons
[PM_KOBOLD_ZOMBIE
]
552 || pm1
== &mons
[PM_KOBOLD_MUMMY
])
553 return (let2
== S_KOBOLD
|| pm2
== &mons
[PM_KOBOLD_ZOMBIE
]
554 || pm2
== &mons
[PM_KOBOLD_MUMMY
]);
556 return (let2
== S_OGRE
);
558 return (let2
== S_NYMPH
);
559 if (let1
== S_CENTAUR
)
560 return (let2
== S_CENTAUR
);
562 return is_unicorn(pm2
);
563 if (let1
== S_DRAGON
)
564 return (let2
== S_DRAGON
);
566 return (let2
== S_NAGA
);
567 /* other critters get steadily messier */
569 return is_rider(pm2
); /* debatable */
571 return is_minion(pm2
); /* [needs work?] */
572 /* tengu don't match imps (first test handled case of both being tengu) */
573 if (pm1
== &mons
[PM_TENGU
] || pm2
== &mons
[PM_TENGU
])
576 return (let2
== S_IMP
);
577 /* and minor demons (imps) don't match major demons */
578 else if (let2
== S_IMP
)
581 return is_demon(pm2
);
582 if (is_undead(pm1
)) {
583 if (let1
== S_ZOMBIE
)
584 return (let2
== S_ZOMBIE
);
586 return (let2
== S_MUMMY
);
587 if (let1
== S_VAMPIRE
)
588 return (let2
== S_VAMPIRE
);
590 return (let2
== S_LICH
);
591 if (let1
== S_WRAITH
)
592 return (let2
== S_WRAITH
);
594 return (let2
== S_GHOST
);
595 } else if (is_undead(pm2
))
598 /* check for monsters which grow into more mature forms */
600 int m1
= monsndx(pm1
), m2
= monsndx(pm2
), prv
, nxt
;
602 /* we know m1 != m2 (very first check above); test all smaller
603 forms of m1 against m2, then all larger ones; don't need to
604 make the corresponding tests for variants of m2 against m1 */
605 for (prv
= m1
, nxt
= big_to_little(m1
); nxt
!= prv
;
606 prv
= nxt
, nxt
= big_to_little(nxt
))
609 for (prv
= m1
, nxt
= little_to_big(m1
); nxt
!= prv
;
610 prv
= nxt
, nxt
= little_to_big(nxt
))
614 /* not caught by little/big handling */
615 if (pm1
== &mons
[PM_GARGOYLE
] || pm1
== &mons
[PM_WINGED_GARGOYLE
])
616 return (pm2
== &mons
[PM_GARGOYLE
]
617 || pm2
== &mons
[PM_WINGED_GARGOYLE
]);
618 if (pm1
== &mons
[PM_KILLER_BEE
] || pm1
== &mons
[PM_QUEEN_BEE
])
619 return (pm2
== &mons
[PM_KILLER_BEE
] || pm2
== &mons
[PM_QUEEN_BEE
]);
621 if (is_longworm(pm1
))
622 return is_longworm(pm2
); /* handles tail */
623 /* [currently there's no reason to bother matching up
624 assorted bugs and blobs with their closest variants] */
629 /* return an index into the mons array */
632 struct permonst
*ptr
;
636 i
= (int) (ptr
- &mons
[0]);
637 if (i
< LOW_PM
|| i
>= NUMMONS
) {
638 panic("monsndx - could not index monster (%s)",
639 fmt_ptr((genericptr_t
) ptr
));
640 return NON_PM
; /* will not get here */
645 /* for handling alternate spellings */
651 /* figure out what type of monster a user-supplied string is specifying */
656 /* Be careful. We must check the entire string in case it was
657 * something such as "ettin zombie corpse". The calling routine
658 * doesn't know about the "corpse" until the monster name has
659 * already been taken off the front, so we have to be able to
660 * read the name with extraneous stuff such as "corpse" stuck on
662 * This causes a problem for names which prefix other names such
663 * as "ettin" on "ettin zombie". In this case we want the _longest_
665 * This also permits plurals created by adding suffixes such as 's'
666 * or 'es'. Other plurals must still be handled explicitly.
669 register int mntmp
= NON_PM
;
670 register char *s
, *str
, *term
;
674 str
= strcpy(buf
, in_str
);
676 if (!strncmp(str
, "a ", 2))
678 else if (!strncmp(str
, "an ", 3))
680 else if (!strncmp(str
, "the ", 4))
686 if ((s
= strstri(str
, "vortices")) != 0)
688 /* be careful with "ies"; "priest", "zombies" */
689 else if (slen
> 3 && !strcmpi(term
- 3, "ies")
690 && (slen
< 7 || strcmpi(term
- 7, "zombies")))
691 Strcpy(term
- 3, "y");
692 /* luckily no monster names end in fe or ve with ves plurals */
693 else if (slen
> 3 && !strcmpi(term
- 3, "ves"))
694 Strcpy(term
- 3, "f");
696 slen
= strlen(str
); /* length possibly needs recomputing */
699 static const struct alt_spl names
[] = {
700 /* Alternate spellings */
701 { "grey dragon", PM_GRAY_DRAGON
},
702 { "baby grey dragon", PM_BABY_GRAY_DRAGON
},
703 { "grey unicorn", PM_GRAY_UNICORN
},
704 { "grey ooze", PM_GRAY_OOZE
},
705 { "gray-elf", PM_GREY_ELF
},
706 { "mindflayer", PM_MIND_FLAYER
},
707 { "master mindflayer", PM_MASTER_MIND_FLAYER
},
708 /* More alternates; priest and priestess are separate monster
709 types but that isn't the case for {aligned,high} priests */
710 { "aligned priestess", PM_ALIGNED_PRIEST
},
711 { "high priestess", PM_HIGH_PRIEST
},
712 /* Inappropriate singularization by -ves check above */
713 { "master of thief", PM_MASTER_OF_THIEVES
},
714 /* Potential misspellings where we want to avoid falling back
715 to the rank title prefix (input has been singularized) */
716 { "master thief", PM_MASTER_OF_THIEVES
},
717 { "master of assassin", PM_MASTER_ASSASSIN
},
719 { "invisible stalker", PM_STALKER
},
720 { "high-elf", PM_ELVENKING
}, /* PM_HIGH_ELF is obsolete */
721 { "halfling", PM_HOBBIT
}, /* potential guess for polyself */
722 /* Hyphenated names */
723 { "ki rin", PM_KI_RIN
},
724 { "uruk hai", PM_URUK_HAI
},
725 { "orc captain", PM_ORC_CAPTAIN
},
726 { "woodland elf", PM_WOODLAND_ELF
},
727 { "green elf", PM_GREEN_ELF
},
728 { "grey elf", PM_GREY_ELF
},
729 { "gray elf", PM_GREY_ELF
},
730 { "elf lord", PM_ELF_LORD
},
731 { "olog hai", PM_OLOG_HAI
},
732 { "arch lich", PM_ARCH_LICH
},
733 /* Some irregular plurals */
734 { "incubi", PM_INCUBUS
},
735 { "succubi", PM_SUCCUBUS
},
736 { "violet fungi", PM_VIOLET_FUNGUS
},
737 { "homunculi", PM_HOMUNCULUS
},
738 { "baluchitheria", PM_BALUCHITHERIUM
},
739 { "lurkers above", PM_LURKER_ABOVE
},
740 { "cavemen", PM_CAVEMAN
},
741 { "cavewomen", PM_CAVEWOMAN
},
742 { "djinn", PM_DJINNI
},
743 { "mumakil", PM_MUMAK
},
744 { "erinyes", PM_ERINYS
},
748 register const struct alt_spl
*namep
;
750 for (namep
= names
; namep
->name
; namep
++)
751 if (!strncmpi(str
, namep
->name
, (int) strlen(namep
->name
)))
752 return namep
->pm_val
;
755 for (len
= 0, i
= LOW_PM
; i
< NUMMONS
; i
++) {
756 register int m_i_len
= strlen(mons
[i
].mname
);
758 if (m_i_len
> len
&& !strncmpi(mons
[i
].mname
, str
, m_i_len
)) {
759 if (m_i_len
== slen
) {
760 return i
; /* exact match */
761 } else if (slen
> m_i_len
762 && (str
[m_i_len
] == ' '
763 || !strcmpi(&str
[m_i_len
], "s")
764 || !strncmpi(&str
[m_i_len
], "s ", 2)
765 || !strcmpi(&str
[m_i_len
], "'")
766 || !strncmpi(&str
[m_i_len
], "' ", 2)
767 || !strcmpi(&str
[m_i_len
], "'s")
768 || !strncmpi(&str
[m_i_len
], "'s ", 3)
769 || !strcmpi(&str
[m_i_len
], "es")
770 || !strncmpi(&str
[m_i_len
], "es ", 3))) {
777 mntmp
= title_to_mon(str
, (int *) 0, (int *) 0);
781 /* monster class from user input; used for genocide and controlled polymorph;
782 returns 0 rather than MAXMCLASSES if no match is found */
784 name_to_monclass(in_str
, mndx_p
)
788 /* Single letters are matched against def_monsyms[].sym; words
789 or phrases are first matched against def_monsyms[].explain
790 to check class description; if not found there, then against
791 mons[].mname to test individual monster types. Input can be a
792 substring of the full description or mname, but to be accepted,
793 such partial matches must start at beginning of a word. Some
794 class descriptions include "foo or bar" and "foo or other foo"
795 so we don't want to accept "or", "other", "or other" there. */
796 static NEARDATA
const char *const falsematch
[] = {
797 /* multiple-letter input which matches any of these gets rejected */
798 "an", "the", "or", "other", "or other", 0
800 /* positive pm_val => specific monster; negative => class */
801 static NEARDATA
const struct alt_spl truematch
[] = {
802 /* "long worm" won't match "worm" class but would accidentally match
803 "long worm tail" class before the comparison with monster types */
804 { "long worm", PM_LONG_WORM
},
805 /* matches wrong--or at least suboptimal--class */
806 { "demon", -S_DEMON
}, /* hits "imp or minor demon" */
807 /* matches specific monster (overly restrictive) */
808 { "devil", -S_DEMON
}, /* always "horned devil" */
809 /* some plausible guesses which need help */
810 { "bug", -S_XAN
}, /* would match bugbear... */
811 { "fish", -S_EEL
}, /* wouldn't match anything */
819 *mndx_p
= NON_PM
; /* haven't [yet] matched a specific type */
821 if (!in_str
|| !in_str
[0]) {
824 } else if (!in_str
[1]) {
825 /* single character */
826 i
= def_char_to_monclass(*in_str
);
827 if (i
== S_MIMIC_DEF
) { /* ']' -> 'm' */
829 } else if (i
== S_WORM_TAIL
) { /* '~' -> 'w' */
832 *mndx_p
= PM_LONG_WORM
;
833 } else if (i
== MAXMCLASSES
) /* maybe 'I' */
834 i
= (*in_str
== DEF_INVISIBLE
) ? S_invisible
: 0;
837 /* multiple characters */
838 in_str
= makesingular(in_str
);
839 /* check for special cases */
840 for (i
= 0; falsematch
[i
]; i
++)
841 if (!strcmpi(in_str
, falsematch
[i
]))
843 for (i
= 0; truematch
[i
].name
; i
++)
844 if (!strcmpi(in_str
, truematch
[i
].name
)) {
845 i
= truematch
[i
].pm_val
;
847 return -i
; /* class */
849 *mndx_p
= i
; /* monster */
852 /* check monster class descriptions */
853 for (i
= 1; i
< MAXMCLASSES
; i
++) {
854 x
= def_monsyms
[i
].explain
;
855 if ((p
= strstri(x
, in_str
)) != 0 && (p
== x
|| *(p
- 1) == ' '))
858 /* check individual species names */
859 i
= name_to_mon(in_str
);
869 /* returns 3 values (0=male, 1=female, 2=none) */
872 register struct monst
*mtmp
;
874 if (is_neuter(mtmp
->data
))
879 /* Like gender(), but lower animals and such are still "it".
880 This is the one we want to use when printing messages. */
883 register struct monst
*mtmp
;
885 if (is_neuter(mtmp
->data
) || !canspotmon(mtmp
))
887 return (humanoid(mtmp
->data
) || (mtmp
->data
->geno
& G_UNIQ
)
888 || type_is_pname(mtmp
->data
)) ? (int) mtmp
->female
: 2;
891 /* used for nearby monsters when you go to another level */
896 if (mtmp
== u
.usteed
)
899 /* Wizard with Amulet won't bother trying to follow across levels */
900 if (mtmp
->iswiz
&& mon_has_amulet(mtmp
))
902 /* some monsters will follow even while intending to flee from you */
903 if (mtmp
->mtame
|| mtmp
->iswiz
|| is_fshk(mtmp
))
905 /* stalking types follow, but won't when fleeing unless you hold
907 return (boolean
) ((mtmp
->data
->mflags2
& M2_STALK
)
908 && (!mtmp
->mflee
|| u
.uhave
.amulet
));
911 static const short grownups
[][2] = {
912 { PM_CHICKATRICE
, PM_COCKATRICE
},
913 { PM_LITTLE_DOG
, PM_DOG
},
914 { PM_DOG
, PM_LARGE_DOG
},
915 { PM_HELL_HOUND_PUP
, PM_HELL_HOUND
},
916 { PM_WINTER_WOLF_CUB
, PM_WINTER_WOLF
},
917 { PM_KITTEN
, PM_HOUSECAT
},
918 { PM_HOUSECAT
, PM_LARGE_CAT
},
919 { PM_PONY
, PM_HORSE
},
920 { PM_HORSE
, PM_WARHORSE
},
921 { PM_KOBOLD
, PM_LARGE_KOBOLD
},
922 { PM_LARGE_KOBOLD
, PM_KOBOLD_LORD
},
923 { PM_GNOME
, PM_GNOME_LORD
},
924 { PM_GNOME_LORD
, PM_GNOME_KING
},
925 { PM_DWARF
, PM_DWARF_LORD
},
926 { PM_DWARF_LORD
, PM_DWARF_KING
},
927 { PM_MIND_FLAYER
, PM_MASTER_MIND_FLAYER
},
928 { PM_ORC
, PM_ORC_CAPTAIN
},
929 { PM_HILL_ORC
, PM_ORC_CAPTAIN
},
930 { PM_MORDOR_ORC
, PM_ORC_CAPTAIN
},
931 { PM_URUK_HAI
, PM_ORC_CAPTAIN
},
932 { PM_SEWER_RAT
, PM_GIANT_RAT
},
933 { PM_CAVE_SPIDER
, PM_GIANT_SPIDER
},
934 { PM_OGRE
, PM_OGRE_LORD
},
935 { PM_OGRE_LORD
, PM_OGRE_KING
},
936 { PM_ELF
, PM_ELF_LORD
},
937 { PM_WOODLAND_ELF
, PM_ELF_LORD
},
938 { PM_GREEN_ELF
, PM_ELF_LORD
},
939 { PM_GREY_ELF
, PM_ELF_LORD
},
940 { PM_ELF_LORD
, PM_ELVENKING
},
941 { PM_LICH
, PM_DEMILICH
},
942 { PM_DEMILICH
, PM_MASTER_LICH
},
943 { PM_MASTER_LICH
, PM_ARCH_LICH
},
944 { PM_VAMPIRE
, PM_VAMPIRE_LORD
},
945 { PM_BAT
, PM_GIANT_BAT
},
946 { PM_BABY_GRAY_DRAGON
, PM_GRAY_DRAGON
},
947 { PM_BABY_SILVER_DRAGON
, PM_SILVER_DRAGON
},
949 {PM_BABY_SHIMMERING_DRAGON
, PM_SHIMMERING_DRAGON
},
951 { PM_BABY_RED_DRAGON
, PM_RED_DRAGON
},
952 { PM_BABY_WHITE_DRAGON
, PM_WHITE_DRAGON
},
953 { PM_BABY_ORANGE_DRAGON
, PM_ORANGE_DRAGON
},
954 { PM_BABY_BLACK_DRAGON
, PM_BLACK_DRAGON
},
955 { PM_BABY_BLUE_DRAGON
, PM_BLUE_DRAGON
},
956 { PM_BABY_GREEN_DRAGON
, PM_GREEN_DRAGON
},
957 { PM_BABY_YELLOW_DRAGON
, PM_YELLOW_DRAGON
},
958 { PM_RED_NAGA_HATCHLING
, PM_RED_NAGA
},
959 { PM_BLACK_NAGA_HATCHLING
, PM_BLACK_NAGA
},
960 { PM_GOLDEN_NAGA_HATCHLING
, PM_GOLDEN_NAGA
},
961 { PM_GUARDIAN_NAGA_HATCHLING
, PM_GUARDIAN_NAGA
},
962 { PM_SMALL_MIMIC
, PM_LARGE_MIMIC
},
963 { PM_LARGE_MIMIC
, PM_GIANT_MIMIC
},
964 { PM_BABY_LONG_WORM
, PM_LONG_WORM
},
965 { PM_BABY_PURPLE_WORM
, PM_PURPLE_WORM
},
966 { PM_BABY_CROCODILE
, PM_CROCODILE
},
967 { PM_SOLDIER
, PM_SERGEANT
},
968 { PM_SERGEANT
, PM_LIEUTENANT
},
969 { PM_LIEUTENANT
, PM_CAPTAIN
},
970 { PM_WATCHMAN
, PM_WATCH_CAPTAIN
},
971 { PM_ALIGNED_PRIEST
, PM_HIGH_PRIEST
},
972 { PM_STUDENT
, PM_ARCHEOLOGIST
},
973 { PM_ATTENDANT
, PM_HEALER
},
974 { PM_PAGE
, PM_KNIGHT
},
975 { PM_ACOLYTE
, PM_PRIEST
},
976 { PM_APPRENTICE
, PM_WIZARD
},
977 { PM_MANES
, PM_LEMURE
},
978 { PM_KEYSTONE_KOP
, PM_KOP_SERGEANT
},
979 { PM_KOP_SERGEANT
, PM_KOP_LIEUTENANT
},
980 { PM_KOP_LIEUTENANT
, PM_KOP_KAPTAIN
},
985 little_to_big(montype
)
990 for (i
= 0; grownups
[i
][0] >= LOW_PM
; i
++)
991 if (montype
== grownups
[i
][0]) {
992 montype
= grownups
[i
][1];
999 big_to_little(montype
)
1004 for (i
= 0; grownups
[i
][0] >= LOW_PM
; i
++)
1005 if (montype
== grownups
[i
][1]) {
1006 montype
= grownups
[i
][0];
1013 * Return the permonst ptr for the race of the monster.
1014 * Returns correct pointer for non-polymorphed and polymorphed
1015 * player. It does not return a pointer to player role character.
1017 const struct permonst
*
1021 if (mtmp
== &youmonst
&& !Upolyd
)
1022 return &mons
[urace
.malenum
];
1027 static const char *levitate
[4] = { "float", "Float", "wobble", "Wobble" };
1028 static const char *flys
[4] = { "fly", "Fly", "flutter", "Flutter" };
1029 static const char *flyl
[4] = { "fly", "Fly", "stagger", "Stagger" };
1030 static const char *slither
[4] = { "slither", "Slither", "falter", "Falter" };
1031 static const char *ooze
[4] = { "ooze", "Ooze", "tremble", "Tremble" };
1032 static const char *immobile
[4] = { "wiggle", "Wiggle", "pulsate", "Pulsate" };
1033 static const char *crawl
[4] = { "crawl", "Crawl", "falter", "Falter" };
1036 locomotion(ptr
, def
)
1037 const struct permonst
*ptr
;
1040 int capitalize
= (*def
== highc(*def
));
1042 return (is_floater(ptr
) ? levitate
[capitalize
]
1043 : (is_flyer(ptr
) && ptr
->msize
<= MZ_SMALL
) ? flys
[capitalize
]
1044 : (is_flyer(ptr
) && ptr
->msize
> MZ_SMALL
) ? flyl
[capitalize
]
1045 : slithy(ptr
) ? slither
[capitalize
]
1046 : amorphous(ptr
) ? ooze
[capitalize
]
1047 : !ptr
->mmove
? immobile
[capitalize
]
1048 : nolimbs(ptr
) ? crawl
[capitalize
]
1054 const struct permonst
*ptr
;
1057 int capitalize
= 2 + (*def
== highc(*def
));
1059 return (is_floater(ptr
) ? levitate
[capitalize
]
1060 : (is_flyer(ptr
) && ptr
->msize
<= MZ_SMALL
) ? flys
[capitalize
]
1061 : (is_flyer(ptr
) && ptr
->msize
> MZ_SMALL
) ? flyl
[capitalize
]
1062 : slithy(ptr
) ? slither
[capitalize
]
1063 : amorphous(ptr
) ? ooze
[capitalize
]
1064 : !ptr
->mmove
? immobile
[capitalize
]
1065 : nolimbs(ptr
) ? crawl
[capitalize
]
1069 /* return phrase describing the effect of fire attack on a type of monster */
1071 on_fire(mptr
, mattk
)
1072 struct permonst
*mptr
;
1073 struct attack
*mattk
;
1077 switch (monsndx(mptr
)) {
1078 case PM_FLAMING_SPHERE
:
1079 case PM_FIRE_VORTEX
:
1080 case PM_FIRE_ELEMENTAL
:
1082 what
= "already on fire";
1084 case PM_WATER_ELEMENTAL
:
1086 case PM_STEAM_VORTEX
:
1090 case PM_GLASS_GOLEM
:
1093 case PM_STONE_GOLEM
:
1096 case PM_AIR_ELEMENTAL
:
1097 case PM_EARTH_ELEMENTAL
:
1098 case PM_DUST_VORTEX
:
1099 case PM_ENERGY_VORTEX
:
1100 what
= "heating up";
1103 what
= (mattk
->aatyp
== AT_HUGS
) ? "being roasted" : "on fire";
1111 * True if monster is presumed to have a sense of smell.
1112 * False if monster definitely does not have a sense of smell.
1114 * Do not base this on presence of a head or nose, since many
1115 * creatures sense smells other ways (feelers, forked-tongues, etc.)
1116 * We're assuming all insects can smell at a distance too.
1120 struct permonst
*mdat
;
1123 || mdat
->mlet
== S_EYE
/* spheres */
1124 || mdat
->mlet
== S_JELLY
|| mdat
->mlet
== S_PUDDING
1125 || mdat
->mlet
== S_BLOB
|| mdat
->mlet
== S_VORTEX
1126 || mdat
->mlet
== S_ELEMENTAL
1127 || mdat
->mlet
== S_FUNGUS
/* mushrooms and fungi */
1128 || mdat
->mlet
== S_LIGHT
)