1 /*	SCCS Id: @(#)mondata.c	3.4	2003/06/02	*/
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 #include "eshk.h"
7 #include "epri.h"
8 
9 /*	These routines provide basic data for any type of monster. */
10 
11 #ifdef OVLB
12 
13 void
set_mon_data(mon,ptr,flag)14 set_mon_data(mon, ptr, flag)
15 struct monst *mon;
16 struct permonst *ptr;
17 int flag;
18 {
19     mon->data = ptr;
20     if (flag == -1) return;		/* "don't care" */
21 
22     if (flag == 1)
23 	mon->mintrinsics |= (ptr->mresists & 0x00FF);
24     else
25 	mon->mintrinsics = (ptr->mresists & 0x00FF);
26     return;
27 }
28 
29 #endif /* OVLB */
30 #ifdef OVL0
31 
32 struct attack *
attacktype_fordmg(ptr,atyp,dtyp)33 attacktype_fordmg(ptr, atyp, dtyp)
34 struct permonst *ptr;
35 int atyp, dtyp;
36 {
37     struct attack *a;
38 
39     for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
40 	if (a->aatyp == atyp && (dtyp == AD_ANY || a->adtyp == dtyp))
41 	    return a;
42 
43     return (struct attack *)0;
44 }
45 
46 boolean
attacktype(ptr,atyp)47 attacktype(ptr, atyp)
48 struct permonst *ptr;
49 int atyp;
50 {
51     return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE;
52 }
53 
54 #endif /* OVL0 */
55 #ifdef OVLB
56 
57 boolean
poly_when_stoned(ptr)58 poly_when_stoned(ptr)
59     struct permonst *ptr;
60 {
61     return((boolean)(is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM] &&
62 	    !(mvitals[PM_STONE_GOLEM].mvflags & G_GENOD)));
63 	    /* allow G_EXTINCT */
64 }
65 
66 boolean
resists_drli(mon)67 resists_drli(mon)	/* returns TRUE if monster is drain-life resistant */
68 struct monst *mon;
69 {
70 	struct permonst *ptr = mon->data;
71 	struct obj *wep = ((mon == &youmonst) ? uwep : MON_WEP(mon));
72 
73 	return (boolean)(is_undead(ptr) || is_demon(ptr) || is_were(ptr) ||
74 			 ptr == &mons[PM_DEATH] ||
75 			 (wep && wep->oartifact && defends(AD_DRLI, wep)));
76 }
77 
78 boolean
resists_magm(mon)79 resists_magm(mon)	/* TRUE if monster is magic-missile resistant */
80 struct monst *mon;
81 {
82 	struct permonst *ptr = mon->data;
83 	struct obj *o;
84 
85 	/* as of 3.2.0:  gray dragons, Angels, Oracle, Yeenoghu */
86 	if (dmgtype(ptr, AD_MAGM) || ptr == &mons[PM_BABY_GRAY_DRAGON] ||
87 		dmgtype(ptr, AD_RBRE))	/* Chromatic Dragon */
88 	    return TRUE;
89 	/* check for magic resistance granted by wielded weapon */
90 	o = (mon == &youmonst) ? uwep : MON_WEP(mon);
91 	if (o && o->oartifact && defends(AD_MAGM, o))
92 	    return TRUE;
93 	/* check for magic resistance granted by worn or carried items */
94 	o = (mon == &youmonst) ? invent : mon->minvent;
95 	for ( ; o; o = o->nobj)
96 	    if ((o->owornmask && objects[o->otyp].oc_oprop == ANTIMAGIC) ||
97 		    (o->oartifact && protects(AD_MAGM, o)))
98 		return TRUE;
99 	return FALSE;
100 }
101 
102 /* TRUE iff monster is resistant to light-induced blindness */
103 boolean
resists_blnd(mon)104 resists_blnd(mon)
105 struct monst *mon;
106 {
107 	struct permonst *ptr = mon->data;
108 	boolean is_you = (mon == &youmonst);
109 	struct obj *o;
110 
111 	if (is_you ? (Blind || u.usleep) :
112 		(mon->mblinded || !mon->mcansee || !haseyes(ptr) ||
113 		    /* BUG: temporary sleep sets mfrozen, but since
114 			    paralysis does too, we can't check it */
115 		    mon->msleeping))
116 	    return TRUE;
117 	/* yellow light, Archon; !dust vortex, !cobra, !raven */
118 	if (dmgtype_fromattack(ptr, AD_BLND, AT_EXPL) ||
119 		dmgtype_fromattack(ptr, AD_BLND, AT_GAZE))
120 	    return TRUE;
121 	o = is_you ? uwep : MON_WEP(mon);
122 	if (o && o->oartifact && defends(AD_BLND, o))
123 	    return TRUE;
124 	o = is_you ? invent : mon->minvent;
125 	for ( ; o; o = o->nobj)
126 	    if ((o->owornmask && objects[o->otyp].oc_oprop == BLINDED) ||
127 		    (o->oartifact && protects(AD_BLND, o)))
128 		return TRUE;
129 	return FALSE;
130 }
131 
132 /* TRUE iff monster can be blinded by the given attack */
133 /* Note: may return TRUE when mdef is blind (e.g. new cream-pie attack) */
134 boolean
can_blnd(magr,mdef,aatyp,obj)135 can_blnd(magr, mdef, aatyp, obj)
136 struct monst *magr;		/* NULL == no specific aggressor */
137 struct monst *mdef;
138 uchar aatyp;
139 struct obj *obj;		/* aatyp == AT_WEAP, AT_SPIT */
140 {
141 	boolean is_you = (mdef == &youmonst);
142 	boolean check_visor = FALSE;
143 	struct obj *o;
144 	const char *s;
145 
146 	/* no eyes protect against all attacks for now */
147 	if (!haseyes(mdef->data))
148 	    return FALSE;
149 
150 	switch(aatyp) {
151 	case AT_EXPL: case AT_BOOM: case AT_GAZE: case AT_MAGC:
152 	case AT_BREA: /* assumed to be lightning */
153 	    /* light-based attacks may be cancelled or resisted */
154 	    if (magr && magr->mcan)
155 		return FALSE;
156 	    return !resists_blnd(mdef);
157 
158 	case AT_WEAP: case AT_SPIT: case AT_NONE:
159 	    /* an object is used (thrown/spit/other) */
160 	    if (obj && (obj->otyp == CREAM_PIE)) {
161 		if (is_you && Blindfolded)
162 		    return FALSE;
163 	    } else if (obj && (obj->otyp == BLINDING_VENOM)) {
164 		/* all ublindf, including LENSES, protect, cream-pies too */
165 		if (is_you && (ublindf || u.ucreamed))
166 		    return FALSE;
167 		check_visor = TRUE;
168 	    } else if (obj && (obj->otyp == POT_BLINDNESS)) {
169 		return TRUE;	/* no defense */
170 	    } else
171 		return FALSE;	/* other objects cannot cause blindness yet */
172 	    if ((magr == &youmonst) && u.uswallow)
173 		return FALSE;	/* can't affect eyes while inside monster */
174 	    break;
175 
176 	case AT_ENGL:
177 	    if (is_you && (Blindfolded || u.usleep || u.ucreamed))
178 		return FALSE;
179 	    if (!is_you && mdef->msleeping)
180 		return FALSE;
181 	    break;
182 
183 	case AT_CLAW:
184 	    /* e.g. raven: all ublindf, including LENSES, protect */
185 	    if (is_you && ublindf)
186 		return FALSE;
187 	    if ((magr == &youmonst) && u.uswallow)
188 		return FALSE;	/* can't affect eyes while inside monster */
189 	    check_visor = TRUE;
190 	    break;
191 
192 	case AT_TUCH: case AT_STNG:
193 	    /* some physical, blind-inducing attacks can be cancelled */
194 	    if (magr && magr->mcan)
195 		return FALSE;
196 	    break;
197 
198 	default:
199 	    break;
200 	}
201 
202 	/* check if wearing a visor (only checked if visor might help) */
203 	if (check_visor) {
204 	    o = (mdef == &youmonst) ? invent : mdef->minvent;
205 	    for ( ; o; o = o->nobj)
206 		if ((o->owornmask & W_ARMH) &&
207 		    (s = OBJ_DESCR(objects[o->otyp])) != (char *)0 &&
208 		    !strcmp(s, "visored helmet"))
209 		    return FALSE;
210 	}
211 
212 	return TRUE;
213 }
214 
215 #endif /* OVLB */
216 #ifdef OVL0
217 
218 boolean
ranged_attk(ptr)219 ranged_attk(ptr)	/* returns TRUE if monster can attack at range */
220 struct permonst *ptr;
221 {
222 	register int i, atyp;
223 	long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
224 
225 	/* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP) ||
226 		attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE) ||
227 		attacktype(ptr, AT_MAGC));
228 	   but that's too slow -dlc
229 	 */
230 	for (i = 0; i < NATTK; i++) {
231 	    atyp = ptr->mattk[i].aatyp;
232 	    if (atyp >= AT_WEAP) return TRUE;
233 	 /* assert(atyp < 32); */
234 	    if ((atk_mask & (1L << atyp)) != 0L) return TRUE;
235 	}
236 
237 	return FALSE;
238 }
239 
240 boolean
hates_silver(ptr)241 hates_silver(ptr)
242 register struct permonst *ptr;
243 /* returns TRUE if monster is especially affected by silver weapons */
244 {
245 	return((boolean)(is_were(ptr) || ptr->mlet==S_VAMPIRE || is_demon(ptr) ||
246 		ptr == &mons[PM_SHADE] ||
247 		(ptr->mlet==S_IMP && ptr != &mons[PM_TENGU])));
248 }
249 
250 /* true iff the type of monster pass through iron bars */
251 boolean
passes_bars(mptr)252 passes_bars(mptr)
253 struct permonst *mptr;
254 {
255     return (boolean) (passes_walls(mptr) || amorphous(mptr) ||
256 		      is_whirly(mptr) || verysmall(mptr) ||
257 		      (slithy(mptr) && !bigmonst(mptr)));
258 }
259 
260 #endif /* OVL0 */
261 #ifdef OVL1
262 
263 boolean
can_track(ptr)264 can_track(ptr)		/* returns TRUE if monster can track well */
265 	register struct permonst *ptr;
266 {
267 	if (uwep && uwep->oartifact == ART_EXCALIBUR)
268 		return TRUE;
269 	else
270 		return((boolean)haseyes(ptr));
271 }
272 
273 #endif /* OVL1 */
274 #ifdef OVLB
275 
276 boolean
sliparm(ptr)277 sliparm(ptr)	/* creature will slide out of armor */
278 	register struct permonst *ptr;
279 {
280 	return((boolean)(is_whirly(ptr) || ptr->msize <= MZ_SMALL ||
281 			 noncorporeal(ptr)));
282 }
283 
284 boolean
breakarm(ptr)285 breakarm(ptr)	/* creature will break out of armor */
286 	register struct permonst *ptr;
287 {
288 	return ((bigmonst(ptr) || (ptr->msize > MZ_SMALL && !humanoid(ptr)) ||
289 		/* special cases of humanoids that cannot wear body armor */
290 		ptr == &mons[PM_MARILITH] || ptr == &mons[PM_WINGED_GARGOYLE])
291 	      && !sliparm(ptr));
292 }
293 #endif /* OVLB */
294 #ifdef OVL1
295 
296 boolean
sticks(ptr)297 sticks(ptr)	/* creature sticks other creatures it hits */
298 	register struct permonst *ptr;
299 {
300 	return((boolean)(dmgtype(ptr,AD_STCK) || dmgtype(ptr,AD_WRAP) ||
301 		attacktype(ptr,AT_HUGS)));
302 }
303 
304 /* number of horns this type of monster has on its head */
305 int
num_horns(ptr)306 num_horns(ptr)
307 struct permonst *ptr;
308 {
309     switch (monsndx(ptr)) {
310     case PM_HORNED_DEVIL:	/* ? "more than one" */
311     case PM_MINOTAUR:
312     case PM_ASMODEUS:
313     case PM_BALROG:
314 	return 2;
315     case PM_WHITE_UNICORN:
316     case PM_GRAY_UNICORN:
317     case PM_BLACK_UNICORN:
318     case PM_KI_RIN:
319 	return 1;
320     default:
321 	break;
322     }
323     return 0;
324 }
325 
326 struct attack *
dmgtype_fromattack(ptr,dtyp,atyp)327 dmgtype_fromattack(ptr, dtyp, atyp)
328 struct permonst *ptr;
329 int dtyp, atyp;
330 {
331     struct attack *a;
332 
333     for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
334 	if (a->adtyp == dtyp && (atyp == AT_ANY || a->aatyp == atyp))
335 	    return a;
336 
337     return (struct attack *)0;
338 }
339 
340 boolean
dmgtype(ptr,dtyp)341 dmgtype(ptr, dtyp)
342 struct permonst *ptr;
343 int dtyp;
344 {
345     return dmgtype_fromattack(ptr, dtyp, AT_ANY) ? TRUE : FALSE;
346 }
347 
348 /* returns the maximum damage a defender can do to the attacker via
349  * a passive defense */
350 int
max_passive_dmg(mdef,magr)351 max_passive_dmg(mdef, magr)
352     register struct monst *mdef, *magr;
353 {
354     int	i, dmg = 0;
355     uchar adtyp;
356 
357     for(i = 0; i < NATTK; i++)
358 	if(mdef->data->mattk[i].aatyp == AT_NONE ||
359 		mdef->data->mattk[i].aatyp == AT_BOOM) {
360 	    adtyp = mdef->data->mattk[i].adtyp;
361 	    if ((adtyp == AD_ACID && !resists_acid(magr)) ||
362 		    (adtyp == AD_COLD && !resists_cold(magr)) ||
363 		    (adtyp == AD_FIRE && !resists_fire(magr)) ||
364 		    (adtyp == AD_ELEC && !resists_elec(magr)) ||
365 		    adtyp == AD_PHYS) {
366 		dmg = mdef->data->mattk[i].damn;
367 		if(!dmg) dmg = mdef->data->mlevel+1;
368 		dmg *= mdef->data->mattk[i].damd;
369 	    } else dmg = 0;
370 
371 	    return dmg;
372 	}
373     return 0;
374 }
375 
376 #endif /* OVL1 */
377 #ifdef OVL0
378 
379 int
monsndx(ptr)380 monsndx(ptr)		/* return an index into the mons array */
381 	struct	permonst	*ptr;
382 {
383 	register int	i;
384 
385 	i = (int)(ptr - &mons[0]);
386 	if (i < LOW_PM || i >= NUMMONS) {
387 		/* ought to switch this to use `fmt_ptr' */
388 	    panic("monsndx - could not index monster (%lx)",
389 		  (unsigned long)ptr);
390 	    return NON_PM;		/* will not get here */
391 	}
392 
393 	return(i);
394 }
395 
396 #endif /* OVL0 */
397 #ifdef OVL1
398 
399 
400 int
name_to_mon(in_str)401 name_to_mon(in_str)
402 const char *in_str;
403 {
404 	/* Be careful.  We must check the entire string in case it was
405 	 * something such as "ettin zombie corpse".  The calling routine
406 	 * doesn't know about the "corpse" until the monster name has
407 	 * already been taken off the front, so we have to be able to
408 	 * read the name with extraneous stuff such as "corpse" stuck on
409 	 * the end.
410 	 * This causes a problem for names which prefix other names such
411 	 * as "ettin" on "ettin zombie".  In this case we want the _longest_
412 	 * name which exists.
413 	 * This also permits plurals created by adding suffixes such as 's'
414 	 * or 'es'.  Other plurals must still be handled explicitly.
415 	 */
416 	register int i;
417 	register int mntmp = NON_PM;
418 	register char *s, *str, *term;
419 	char buf[BUFSZ];
420 	int len, slen;
421 
422 	str = strcpy(buf, in_str);
423 
424 	if (!strncmp(str, "a ", 2)) str += 2;
425 	else if (!strncmp(str, "an ", 3)) str += 3;
426 
427 	slen = strlen(str);
428 	term = str + slen;
429 
430 	if ((s = strstri(str, "vortices")) != 0)
431 	    Strcpy(s+4, "ex");
432 	/* be careful with "ies"; "priest", "zombies" */
433 	else if (slen > 3 && !strcmpi(term-3, "ies") &&
434 		    (slen < 7 || strcmpi(term-7, "zombies")))
435 	    Strcpy(term-3, "y");
436 	/* luckily no monster names end in fe or ve with ves plurals */
437 	else if (slen > 3 && !strcmpi(term-3, "ves"))
438 	    Strcpy(term-3, "f");
439 
440 	slen = strlen(str); /* length possibly needs recomputing */
441 
442     {
443 	static const struct alt_spl { const char* name; short pm_val; }
444 	    names[] = {
445 	    /* Alternate spellings */
446 		{ "grey dragon",	PM_GRAY_DRAGON },
447 		{ "baby grey dragon",	PM_BABY_GRAY_DRAGON },
448 		{ "grey unicorn",	PM_GRAY_UNICORN },
449 		{ "grey ooze",		PM_GRAY_OOZE },
450 		{ "gray-elf",		PM_GREY_ELF },
451 	    /* Hyphenated names */
452 		{ "ki rin",		PM_KI_RIN },
453 		{ "uruk hai",		PM_URUK_HAI },
454 		{ "orc captain",	PM_ORC_CAPTAIN },
455 		{ "woodland elf",	PM_WOODLAND_ELF },
456 		{ "green elf",		PM_GREEN_ELF },
457 		{ "grey elf",		PM_GREY_ELF },
458 		{ "gray elf",		PM_GREY_ELF },
459 		{ "elf lord",		PM_ELF_LORD },
460 #if 0	/* OBSOLETE */
461 		{ "high elf",		PM_HIGH_ELF },
462 #endif
463 		{ "olog hai",		PM_OLOG_HAI },
464 		{ "arch lich",		PM_ARCH_LICH },
465 	    /* Some irregular plurals */
466 		{ "incubi",		PM_INCUBUS },
467 		{ "succubi",		PM_SUCCUBUS },
468 		{ "violet fungi",	PM_VIOLET_FUNGUS },
469 		{ "homunculi",		PM_HOMUNCULUS },
470 		{ "baluchitheria",	PM_BALUCHITHERIUM },
471 		{ "lurkers above",	PM_LURKER_ABOVE },
472 		{ "cavemen",		PM_CAVEMAN },
473 		{ "cavewomen",		PM_CAVEWOMAN },
474 		{ "djinn",		PM_DJINNI },
475 		{ "mumakil",		PM_MUMAK },
476 		{ "erinyes",		PM_ERINYS },
477 	    /* falsely caught by -ves check above */
478 		{ "master of thief",	PM_MASTER_OF_THIEVES },
479 	    /* end of list */
480 		{ 0, 0 }
481 	};
482 	register const struct alt_spl *namep;
483 
484 	for (namep = names; namep->name; namep++)
485 	    if (!strncmpi(str, namep->name, (int)strlen(namep->name)))
486 		return namep->pm_val;
487     }
488 
489 	for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
490 	    register int m_i_len = strlen(mons[i].mname);
491 	    if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) {
492 		if (m_i_len == slen) return i;	/* exact match */
493 		else if (slen > m_i_len &&
494 			(str[m_i_len] == ' ' ||
495 			 !strcmpi(&str[m_i_len], "s") ||
496 			 !strncmpi(&str[m_i_len], "s ", 2) ||
497 			 !strcmpi(&str[m_i_len], "'") ||
498 			 !strncmpi(&str[m_i_len], "' ", 2) ||
499 			 !strcmpi(&str[m_i_len], "'s") ||
500 			 !strncmpi(&str[m_i_len], "'s ", 3) ||
501 			 !strcmpi(&str[m_i_len], "es") ||
502 			 !strncmpi(&str[m_i_len], "es ", 3))) {
503 		    mntmp = i;
504 		    len = m_i_len;
505 		}
506 	    }
507 	}
508 	if (mntmp == NON_PM) mntmp = title_to_mon(str, (int *)0, (int *)0);
509 	return mntmp;
510 }
511 
512 #endif /* OVL1 */
513 #ifdef OVL2
514 
515 /* returns 3 values (0=male, 1=female, 2=none) */
516 int
gender(mtmp)517 gender(mtmp)
518 register struct monst *mtmp;
519 {
520 	if (is_neuter(mtmp->data)) return 2;
521 	return mtmp->female;
522 }
523 
524 /* Like gender(), but lower animals and such are still "it". */
525 /* This is the one we want to use when printing messages. */
526 int
pronoun_gender(mtmp)527 pronoun_gender(mtmp)
528 register struct monst *mtmp;
529 {
530 	if (is_neuter(mtmp->data) || !canspotmon(mtmp)) return 2;
531 	return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ) ||
532 		type_is_pname(mtmp->data)) ? (int)mtmp->female : 2;
533 }
534 
535 #endif /* OVL2 */
536 #ifdef OVLB
537 
538 /* used for nearby monsters when you go to another level */
539 boolean
levl_follower(mtmp)540 levl_follower(mtmp)
541 struct monst *mtmp;
542 {
543 	/* monsters with the Amulet--even pets--won't follow across levels */
544 	if (mon_has_amulet(mtmp)) return FALSE;
545 
546 	/* some monsters will follow even while intending to flee from you */
547 	if (mtmp->mtame || mtmp->iswiz || is_fshk(mtmp)) return TRUE;
548 
549 	/* stalking types follow, but won't when fleeing unless you hold
550 	   the Amulet */
551 	return (boolean)((mtmp->data->mflags2 & M2_STALK) &&
552 				(!mtmp->mflee || u.uhave.amulet));
553 }
554 
555 static const short grownups[][2] = {
556 	{PM_CHICKATRICE, PM_COCKATRICE},
557 	{PM_LITTLE_DOG, PM_DOG}, {PM_DOG, PM_LARGE_DOG},
558 	{PM_HELL_HOUND_PUP, PM_HELL_HOUND},
559 	{PM_WINTER_WOLF_CUB, PM_WINTER_WOLF},
560 	{PM_KITTEN, PM_HOUSECAT}, {PM_HOUSECAT, PM_LARGE_CAT},
561 	{PM_PONY, PM_HORSE}, {PM_HORSE, PM_WARHORSE},
562 	{PM_KOBOLD, PM_LARGE_KOBOLD}, {PM_LARGE_KOBOLD, PM_KOBOLD_LORD},
563 	{PM_GNOME, PM_GNOME_LORD}, {PM_GNOME_LORD, PM_GNOME_KING},
564 	{PM_DWARF, PM_DWARF_LORD}, {PM_DWARF_LORD, PM_DWARF_KING},
565 	{PM_MIND_FLAYER, PM_MASTER_MIND_FLAYER},
566 	{PM_ORC, PM_ORC_CAPTAIN}, {PM_HILL_ORC, PM_ORC_CAPTAIN},
567 	{PM_MORDOR_ORC, PM_ORC_CAPTAIN}, {PM_URUK_HAI, PM_ORC_CAPTAIN},
568 	{PM_SEWER_RAT, PM_GIANT_RAT},
569 	{PM_CAVE_SPIDER, PM_GIANT_SPIDER},
570 	{PM_OGRE, PM_OGRE_LORD}, {PM_OGRE_LORD, PM_OGRE_KING},
571 	{PM_ELF, PM_ELF_LORD}, {PM_WOODLAND_ELF, PM_ELF_LORD},
572 	{PM_GREEN_ELF, PM_ELF_LORD}, {PM_GREY_ELF, PM_ELF_LORD},
573 	{PM_ELF_LORD, PM_ELVENKING},
574 	{PM_LICH, PM_DEMILICH}, {PM_DEMILICH, PM_MASTER_LICH},
575 	{PM_MASTER_LICH, PM_ARCH_LICH},
576 	{PM_VAMPIRE, PM_VAMPIRE_LORD}, {PM_BAT, PM_GIANT_BAT},
577 	{PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON},
578 	{PM_BABY_SILVER_DRAGON, PM_SILVER_DRAGON},
579 #if 0	/* DEFERRED */
580 	{PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
581 #endif
582 	{PM_BABY_RED_DRAGON, PM_RED_DRAGON},
583 	{PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON},
584 	{PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON},
585 	{PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON},
586 	{PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON},
587 	{PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON},
588 	{PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON},
589 	{PM_RED_NAGA_HATCHLING, PM_RED_NAGA},
590 	{PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA},
591 	{PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA},
592 	{PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA},
593 	{PM_SMALL_MIMIC, PM_LARGE_MIMIC}, {PM_LARGE_MIMIC, PM_GIANT_MIMIC},
594 	{PM_BABY_LONG_WORM, PM_LONG_WORM},
595 	{PM_BABY_PURPLE_WORM, PM_PURPLE_WORM},
596 	{PM_BABY_CROCODILE, PM_CROCODILE},
597 	{PM_SOLDIER, PM_SERGEANT},
598 	{PM_SERGEANT, PM_LIEUTENANT},
599 	{PM_LIEUTENANT, PM_CAPTAIN},
600 	{PM_WATCHMAN, PM_WATCH_CAPTAIN},
601 	{PM_ALIGNED_PRIEST, PM_HIGH_PRIEST},
602 	{PM_STUDENT, PM_ARCHEOLOGIST},
603 	{PM_ATTENDANT, PM_HEALER},
604 	{PM_PAGE, PM_KNIGHT},
605 	{PM_ACOLYTE, PM_PRIEST},
606 	{PM_APPRENTICE, PM_WIZARD},
607 	{PM_MANES,PM_LEMURE},
608 #ifdef KOPS
609 	{PM_KEYSTONE_KOP, PM_KOP_SERGEANT},
610 	{PM_KOP_SERGEANT, PM_KOP_LIEUTENANT},
611 	{PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN},
612 #endif
613 	{NON_PM,NON_PM}
614 };
615 
616 int
little_to_big(montype)617 little_to_big(montype)
618 int montype;
619 {
620 #ifndef AIXPS2_BUG
621 	register int i;
622 
623 	for (i = 0; grownups[i][0] >= LOW_PM; i++)
624 		if(montype == grownups[i][0]) return grownups[i][1];
625 	return montype;
626 #else
627 /* AIX PS/2 C-compiler 1.1.1 optimizer does not like the above for loop,
628  * and causes segmentation faults at runtime.  (The problem does not
629  * occur if -O is not used.)
630  * lehtonen@cs.Helsinki.FI (Tapio Lehtonen) 28031990
631  */
632 	int i;
633 	int monvalue;
634 
635 	monvalue = montype;
636 	for (i = 0; grownups[i][0] >= LOW_PM; i++)
637 		if(montype == grownups[i][0]) monvalue = grownups[i][1];
638 
639 	return monvalue;
640 #endif
641 }
642 
643 int
big_to_little(montype)644 big_to_little(montype)
645 int montype;
646 {
647 	register int i;
648 
649 	for (i = 0; grownups[i][0] >= LOW_PM; i++)
650 		if(montype == grownups[i][1]) return grownups[i][0];
651 	return montype;
652 }
653 
654 /*
655  * Return the permonst ptr for the race of the monster.
656  * Returns correct pointer for non-polymorphed and polymorphed
657  * player.  It does not return a pointer to player role character.
658  */
659 const struct permonst *
raceptr(mtmp)660 raceptr(mtmp)
661 struct monst *mtmp;
662 {
663     if (mtmp == &youmonst && !Upolyd) return(&mons[urace.malenum]);
664     else return(mtmp->data);
665 }
666 
667 static const char *levitate[4]	= { "float", "Float", "wobble", "Wobble" };
668 static const char *flys[4]	= { "fly", "Fly", "flutter", "Flutter" };
669 static const char *flyl[4]	= { "fly", "Fly", "stagger", "Stagger" };
670 static const char *slither[4]	= { "slither", "Slither", "falter", "Falter" };
671 static const char *ooze[4]	= { "ooze", "Ooze", "tremble", "Tremble" };
672 static const char *immobile[4]	= { "wiggle", "Wiggle", "pulsate", "Pulsate" };
673 static const char *crawl[4]	= { "crawl", "Crawl", "falter", "Falter" };
674 
675 const char *
locomotion(ptr,def)676 locomotion(ptr, def)
677 const struct permonst *ptr;
678 const char *def;
679 {
680 	int capitalize = (*def == highc(*def));
681 
682 	return (
683 		is_floater(ptr) ? levitate[capitalize] :
684 		(is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize] :
685 		(is_flyer(ptr) && ptr->msize > MZ_SMALL)  ? flyl[capitalize] :
686 		slithy(ptr)     ? slither[capitalize] :
687 		amorphous(ptr)  ? ooze[capitalize] :
688 		!ptr->mmove	? immobile[capitalize] :
689 		nolimbs(ptr)    ? crawl[capitalize] :
690 		def
691 	       );
692 
693 }
694 
695 const char *
stagger(ptr,def)696 stagger(ptr, def)
697 const struct permonst *ptr;
698 const char *def;
699 {
700 	int capitalize = 2 + (*def == highc(*def));
701 
702 	return (
703 		is_floater(ptr) ? levitate[capitalize] :
704 		(is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize] :
705 		(is_flyer(ptr) && ptr->msize > MZ_SMALL)  ? flyl[capitalize] :
706 		slithy(ptr)     ? slither[capitalize] :
707 		amorphous(ptr)  ? ooze[capitalize] :
708 		!ptr->mmove	? immobile[capitalize] :
709 		nolimbs(ptr)    ? crawl[capitalize] :
710 		def
711 	       );
712 
713 }
714 
715 /* return a phrase describing the effect of fire attack on a type of monster */
716 const char *
on_fire(mptr,mattk)717 on_fire(mptr, mattk)
718 struct permonst *mptr;
719 struct attack *mattk;
720 {
721     const char *what;
722 
723     switch (monsndx(mptr)) {
724     case PM_FLAMING_SPHERE:
725     case PM_FIRE_VORTEX:
726     case PM_FIRE_ELEMENTAL:
727     case PM_SALAMANDER:
728 	what = "already on fire";
729 	break;
730     case PM_WATER_ELEMENTAL:
731     case PM_FOG_CLOUD:
732     case PM_STEAM_VORTEX:
733 	what = "boiling";
734 	break;
735     case PM_ICE_VORTEX:
736     case PM_GLASS_GOLEM:
737 	what = "melting";
738 	break;
739     case PM_STONE_GOLEM:
740     case PM_CLAY_GOLEM:
741     case PM_GOLD_GOLEM:
742     case PM_AIR_ELEMENTAL:
743     case PM_EARTH_ELEMENTAL:
744     case PM_DUST_VORTEX:
745     case PM_ENERGY_VORTEX:
746 	what = "heating up";
747 	break;
748     default:
749 	what = (mattk->aatyp == AT_HUGS) ? "being roasted" : "on fire";
750 	break;
751     }
752     return what;
753 }
754 
755 #endif /* OVLB */
756 
757 /*mondata.c*/
758