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