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