1    | /*	SCCS Id: @(#)mondata.c	3.3	2000/07/14	*/
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
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   | boolean
33   | attacktype(ptr, atyp)
34   | 	register struct	permonst	*ptr;
35   | 	register int atyp;
36   | {
37   | 	int	i;
38   | 
39   | 	for(i = 0; i < NATTK; i++)
40   | 	    if(ptr->mattk[i].aatyp == atyp) return(TRUE);
41   | 
42   | 	return(FALSE);
43   | }
44   | 
45   | #endif /* OVL0 */
46   | #ifdef OVLB
47   | 
48   | boolean
49   | poly_when_stoned(ptr)
50   |     struct permonst *ptr;
51   | {
52   |     return((boolean)(is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM] &&
53   | 	    !(mvitals[PM_STONE_GOLEM].mvflags & G_GENOD)));
54   | 	    /* allow G_EXTINCT */
55   | }
56   | 
57   | boolean
58   | resists_drli(mon)	/* returns TRUE if monster is drain-life resistant */
59   | struct monst *mon;
60   | {
61   | 	struct permonst *ptr = mon->data;
62   | 	struct obj *wep = ((mon == &youmonst) ? uwep : MON_WEP(mon));
63   | 
64   | 	return (boolean)(is_undead(ptr) || is_demon(ptr) || is_were(ptr) ||
65   | 			 ptr == &mons[PM_DEATH] ||
66   | 			 (wep && wep->oartifact && defends(AD_DRLI, wep)));
67   | }
68   | 
69   | boolean
70   | resists_magm(mon)	/* TRUE if monster is magic-missile resistant */
71   | struct monst *mon;
72   | {
73   | 	struct permonst *ptr = mon->data;
74   | 	struct obj *o;
75   | 
76   | 	/* as of 3.2.0:  gray dragons, Angels, Oracle, Yeenoghu */
77   | 	if (dmgtype(ptr, AD_MAGM) || ptr == &mons[PM_BABY_GRAY_DRAGON] ||
78   | 		dmgtype(ptr, AD_RBRE))	/* Chromatic Dragon */
79   | 	    return TRUE;
80   | 	/* check for magic resistance granted by wielded weapon */
81   | 	o = (mon == &youmonst) ? uwep : MON_WEP(mon);
82   | 	if (o && o->oartifact && defends(AD_MAGM, o))
83   | 	    return TRUE;
84   | 	/* check for magic resistance granted by worn or carried items */
85   | 	o = (mon == &youmonst) ? invent : mon->minvent;
86   | 	for ( ; o; o = o->nobj)
87   | 	    if ((o->owornmask && objects[o->otyp].oc_oprop == ANTIMAGIC) ||
88   | 		    (o->oartifact && protects(AD_MAGM, o)))
89   | 		return TRUE;
90   | 	return FALSE;
91   | }
92   | 
93   | /* TRUE iff monster is resistant to light-induced blindness */
94   | boolean
95   | resists_blnd(mon)
96   | struct monst *mon;
97   | {
98   | 	struct permonst *ptr = mon->data;
99   | 	boolean is_you = (mon == &youmonst);
100  | 	struct obj *o;
101  | 
102  | 	if (is_you ? (Blind || u.usleep) :
103  | 		(mon->mblinded || !mon->mcansee || !haseyes(ptr) ||
104  | 		    /* BUG: temporary sleep sets mfrozen, but since
105  | 			    paralysis does too, we can't check it */
106  | 		    mon->msleeping))
107  | 	    return TRUE;
108  | 	/* AD_BLND => yellow light, Archon, !cobra, !raven */
109  | 	if (dmgtype(ptr, AD_BLND) &&
110  | 	    !attacktype(ptr, AT_SPIT) && !attacktype(ptr, AT_CLAW))
111  | 	    return TRUE;
112  | 	o = is_you ? uwep : MON_WEP(mon);
113  | 	if (o && o->oartifact && defends(AD_BLND, o))
114  | 	    return TRUE;
115  | 	o = is_you ? invent : mon->minvent;
116  | 	for ( ; o; o = o->nobj)
117  | 	    if ((o->owornmask && objects[o->otyp].oc_oprop == BLINDED) ||
118  | 		    (o->oartifact && protects(AD_BLND, o)))
119  | 		return TRUE;
120  | 	return FALSE;
121  | }
122  | 
123  | /* TRUE iff monster can be blinded by the given attack */
124  | /* Note: may return TRUE when mdef is blind (e.g. new cream-pie attack) */
125  | boolean
126  | can_blnd(magr, mdef, aatyp, obj)
127  | struct monst *magr;		/* NULL == no specific aggressor */
128  | struct monst *mdef;
129  | uchar aatyp;
130  | struct obj *obj;		/* aatyp == AT_WEAP, AT_SPIT */
131  | {
132  | 	boolean is_you = (mdef == &youmonst);
133  | 	boolean check_visor = FALSE;
134  | 	struct obj *o;
135  | 	const char *s;
136  | 
137  | 	/* no eyes protect against all attacks for now */
138  | 	if (!haseyes(mdef->data))
139  | 	    return FALSE;
140  | 
141  | 	switch(aatyp) {
142  | 	case AT_EXPL: case AT_BOOM: case AT_GAZE: case AT_MAGC:
143  | 	case AT_BREA: /* assumed to be lightning */
144  | 	    /* light-based attacks may be cancelled or resisted */
145  | 	    if (magr && magr->mcan)
146  | 		return FALSE;
147  | 	    return !resists_blnd(mdef);
148  | 
149  | 	case AT_WEAP: case AT_SPIT: case AT_NONE:
150  | 	    /* an object is used (thrown/spit/other) */
151  | 	    if (obj && (obj->otyp == CREAM_PIE)) {
152  | 		if (is_you && Blindfolded)
153  | 		    return FALSE;
154  | 	    } else if (obj && (obj->otyp == BLINDING_VENOM)) {
155  | 		/* all ublindf, including LENSES, protect, cream-pies too */
156  | 		if (is_you && (ublindf || u.ucreamed))
157  | 		    return FALSE;
158  | 		check_visor = TRUE;
159  | 	    } else if (obj && (obj->otyp == POT_BLINDNESS)) {
160  | 		return TRUE;	/* no defense */
161  | 	    } else
162  | 		return FALSE;	/* other objects cannot cause blindness yet */
163  | 	    if ((magr == &youmonst) && u.uswallow)
164  | 		return FALSE;	/* can't affect eyes while inside monster */
165  | 	    break;
166  | 
167  | 	case AT_ENGL:
168  | 	    if (is_you && (Blindfolded || u.usleep || u.ucreamed))
169  | 		return FALSE;
170  | 	    if (!is_you && mdef->msleeping)
171  | 		return FALSE;
172  | 	    break;
173  | 
174  | 	case AT_CLAW:
175  | 	    /* e.g. raven: all ublindf, including LENSES, protect */
176  | 	    if (is_you && ublindf)
177  | 		return FALSE;
178  | 	    if ((magr == &youmonst) && u.uswallow)
179  | 		return FALSE;	/* can't affect eyes while inside monster */
180  | 	    check_visor = TRUE;
181  | 	    break;
182  | 
183  | 	case AT_TUCH: case AT_STNG:
184  | 	    /* some physical, blind-inducing attacks can be cancelled */
185  | 	    if (magr && magr->mcan)
186  | 		return FALSE;
187  | 	    break;
188  | 
189  | 	default:
190  | 	    break;
191  | 	}
192  | 
193  | 	/* check if wearing a visor (only checked if visor might help) */
194  | 	if (check_visor) {
195  | 	    o = (mdef == &youmonst) ? invent : mdef->minvent;
196  | 	    for ( ; o; o = o->nobj)
197  | 		if ((o->owornmask & W_ARMH) &&
198  | 		    (s = OBJ_DESCR(objects[o->otyp])) != (char *)0 &&
199  | 		    !strcmp(s, "visored helmet"))
200  | 		    return FALSE;
201  | 	}
202  | 
203  | 	return TRUE;
204  | }
205  | 
206  | #endif /* OVLB */
207  | #ifdef OVL0
208  | 
209  | boolean
210  | ranged_attk(ptr)	/* returns TRUE if monster can attack at range */
211  | struct permonst *ptr;
212  | {
213  | 	register int i, atyp;
214  | 	long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
215  | 
216  | 	/* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP) ||
217  | 		attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE) ||
218  | 		attacktype(ptr, AT_MAGC));
219  | 	   but that's too slow -dlc
220  | 	 */
221  | 	for (i = 0; i < NATTK; i++) {
222  | 	    atyp = ptr->mattk[i].aatyp;
223  | 	    if (atyp >= AT_WEAP) return TRUE;
224  | 	 /* assert(atyp < 32); */
225  | 	    if ((atk_mask & (1L << atyp)) != 0L) return TRUE;
226  | 	}
227  | 
228  | 	return FALSE;
229  | }
230  | 
231  | boolean
232  | hates_silver(ptr)
233  | register struct permonst *ptr;
234  | /* returns TRUE if monster is especially affected by silver weapons */
235  | {
236  | 	return((boolean)(is_were(ptr) || ptr->mlet==S_VAMPIRE || is_demon(ptr) ||
237  | 		ptr == &mons[PM_SHADE] ||
238  | 		(ptr->mlet==S_IMP && ptr != &mons[PM_TENGU])));
239  | }
240  | 
241  | #endif /* OVL0 */
242  | #ifdef OVL1
243  | 
244  | boolean
245  | can_track(ptr)		/* returns TRUE if monster can track well */
246  | 	register struct permonst *ptr;
247  | {
248  | 	if (uwep && uwep->oartifact == ART_EXCALIBUR)
249  | 		return TRUE;
250  | 	else
251  | 		return((boolean)haseyes(ptr));
252  | }
253  | 
254  | #endif /* OVL1 */
255  | #ifdef OVLB
256  | 
257  | boolean
258  | sliparm(ptr)	/* creature will slide out of armor */
259  | 	register struct permonst *ptr;
260  | {
261  | 	return((boolean)(is_whirly(ptr) || ptr->msize <= MZ_SMALL ||
262  | 			 noncorporeal(ptr)));
263  | }
264  | 
265  | boolean
266  | breakarm(ptr)	/* creature will break out of armor */
267  | 	register struct permonst *ptr;
268  | {
269  | 	return ((bigmonst(ptr) || (ptr->msize > MZ_SMALL && !humanoid(ptr)) ||
270  | 		/* special cases of humanoids that cannot wear body armor */
271  | 		ptr == &mons[PM_MARILITH] || ptr == &mons[PM_WINGED_GARGOYLE])
272  | 	      && !sliparm(ptr));
273  | }
274  | #endif /* OVLB */
275  | #ifdef OVL1
276  | 
277  | boolean
278  | sticks(ptr)	/* creature sticks other creatures it hits */
279  | 	register struct permonst *ptr;
280  | {
281  | 	return((boolean)(dmgtype(ptr,AD_STCK) || dmgtype(ptr,AD_WRAP) ||
282  | 		attacktype(ptr,AT_HUGS)));
283  | }
284  | 
285  | boolean
286  | dmgtype(ptr, dtyp)
287  | 	register struct	permonst	*ptr;
288  | 	register int dtyp;
289  | {
290  | 	int	i;
291  | 
292  | 	for(i = 0; i < NATTK; i++)
293  | 	    if(ptr->mattk[i].adtyp == dtyp) return TRUE;
294  | 
295  | 	return FALSE;
296  | }
297  | 
298  | /* returns the maximum damage a defender can do to the attacker via
299  |  * a passive defense */
300  | int
301  | max_passive_dmg(mdef, magr)
302  |     register struct monst *mdef, *magr;
303  | {
304  |     int	i, dmg = 0;
305  |     uchar adtyp;
306  | 
307  |     for(i = 0; i < NATTK; i++)
308  | 	if(mdef->data->mattk[i].aatyp == AT_NONE ||
309  | 		mdef->data->mattk[i].aatyp == AT_BOOM) {
310  | 	    adtyp = mdef->data->mattk[i].adtyp;
311  | 	    if ((adtyp == AD_ACID && !resists_acid(magr)) ||
312  | 		    (adtyp == AD_COLD && !resists_cold(magr)) ||
313  | 		    (adtyp == AD_FIRE && !resists_fire(magr)) ||
314  | 		    (adtyp == AD_ELEC && !resists_elec(magr)) ||
315  | 		    adtyp == AD_PHYS) {
316  | 		dmg = mdef->data->mattk[i].damn;
317  | 		if(!dmg) dmg = mdef->data->mlevel+1;
318  | 		dmg *= mdef->data->mattk[i].damd;
319  | 	    } else dmg = 0;
320  | 
321  | 	    return dmg;
322  | 	}
323  |     return 0;
324  | }
325  | 
326  | #endif /* OVL1 */
327  | #ifdef OVL0
328  | 
329  | int
330  | monsndx(ptr)		/* return an index into the mons array */
331  | 	struct	permonst	*ptr;
332  | {
333  | 	register int	i;
334  | 
335  | 	i = (int)(ptr - &mons[0]);
336  | 	if (i < LOW_PM || i >= NUMMONS) {
337  | 		/* ought to switch this to use `fmt_ptr' */
338  | 	    panic("monsndx - could not index monster (%lx)",
339  | 		  (unsigned long)ptr);
340  | 	    return FALSE;		/* will not get here */
341  | 	}
342  | 
343  | 	return(i);
344  | }
345  | 
346  | #endif /* OVL0 */
347  | #ifdef OVL1
348  | 
349  | 
350  | int
351  | name_to_mon(in_str)
352  | const char *in_str;
353  | {
354  | 	/* Be careful.  We must check the entire string in case it was
355  | 	 * something such as "ettin zombie corpse".  The calling routine
356  | 	 * doesn't know about the "corpse" until the monster name has
357  | 	 * already been taken off the front, so we have to be able to
358  | 	 * read the name with extraneous stuff such as "corpse" stuck on
359  | 	 * the end.
360  | 	 * This causes a problem for names which prefix other names such
361  | 	 * as "ettin" on "ettin zombie".  In this case we want the _longest_
362  | 	 * name which exists.
363  | 	 * This also permits plurals created by adding suffixes such as 's'
364  | 	 * or 'es'.  Other plurals must still be handled explicitly.
365  | 	 */
366  | 	register int i;
367  | 	register int mntmp = NON_PM;
368  | 	register char *s, *str, *term;
369  | 	char buf[BUFSZ];
370  | 	int len, slen;
371  | 
372  | 	str = strcpy(buf, in_str);
373  | 
374  | 	if (!strncmp(str, "a ", 2)) str += 2;
375  | 	else if (!strncmp(str, "an ", 3)) str += 3;
376  | 
377  | 	slen = strlen(str);
378  | 	term = str + slen;
379  | 
380  | 	if ((s = strstri(str, "vortices")) != 0)
381  | 	    Strcpy(s+4, "ex");
382  | 	/* be careful with "ies"; "priest", "zombies" */
383  | 	else if (slen > 3 && !strcmpi(term-3, "ies") &&
384  | 		    (slen < 7 || strcmpi(term-7, "zombies")))
385  | 	    Strcpy(term-3, "y");
386  | 	/* luckily no monster names end in fe or ve with ves plurals */
387  | 	else if (slen > 3 && !strcmpi(term-3, "ves"))
388  | 	    Strcpy(term-3, "f");
389  | 
390  | 	slen = strlen(str); /* length possibly needs recomputing */
391  | 
392  |     {
393  | 	static const struct alt_spl { const char* name; short pm_val; }
394  | 	    names[] = {
395  | 	    /* Alternate spellings */
396  | 		{ "grey dragon",	PM_GRAY_DRAGON },
397  | 		{ "baby grey dragon",	PM_BABY_GRAY_DRAGON },
398  | 		{ "grey unicorn",	PM_GRAY_UNICORN },
399  | 		{ "grey ooze",		PM_GRAY_OOZE },
400  | 		{ "gray-elf",		PM_GREY_ELF },
401  | 	    /* Hyphenated names */
402  | 		{ "ki rin",		PM_KI_RIN },
403  | 		{ "uruk hai",		PM_URUK_HAI },
404  | 		{ "orc captain",	PM_ORC_CAPTAIN },
405  | 		{ "woodland elf",	PM_WOODLAND_ELF },
406  | 		{ "green elf",		PM_GREEN_ELF },
407  | 		{ "grey elf",		PM_GREY_ELF },
408  | 		{ "gray elf",		PM_GREY_ELF },
409  | 		{ "elf lord",		PM_ELF_LORD },
410  | #if 0	/* OBSOLETE */
411  | 		{ "high elf",		PM_HIGH_ELF },
412  | #endif
413  | 		{ "olog hai",		PM_OLOG_HAI },
414  | 		{ "arch lich",		PM_ARCH_LICH },
415  | 	    /* Some irregular plurals */
416  | 		{ "incubi",		PM_INCUBUS },
417  | 		{ "succubi",		PM_SUCCUBUS },
418  | 		{ "violet fungi",	PM_VIOLET_FUNGUS },
419  | 		{ "homunculi",		PM_HOMUNCULUS },
420  | 		{ "baluchitheria",	PM_BALUCHITHERIUM },
421  | 		{ "lurkers above",	PM_LURKER_ABOVE },
422  | 		{ "cavemen",		PM_CAVEMAN },
423  | 		{ "cavewomen",		PM_CAVEWOMAN },
424  | 		{ "djinn",		PM_DJINNI },
425  | 		{ "mumakil",		PM_MUMAK },
426  | 		{ "erinyes",		PM_ERINYS },
427  | 	    /* falsely caught by -ves check above */
428  | 		{ "master of thief",	PM_MASTER_OF_THIEVES },
429  | 	    /* end of list */
430  | 		{ 0, 0 }
431  | 	};
432  | 	register const struct alt_spl *namep;
433  | 
434  | 	for (namep = names; namep->name; namep++)
435  | 	    if (!strncmpi(str, namep->name, (int)strlen(namep->name)))
436  | 		return namep->pm_val;
437  |     }
438  | 
439  | 	for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
440  | 	    register int m_i_len = strlen(mons[i].mname);
441  | 	    if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) {
442  | 		if (m_i_len == slen) return i;	/* exact match */
443  | 		else if (slen > m_i_len &&
444  | 			(str[m_i_len] == ' ' ||
445  | 			 !strcmpi(&str[m_i_len], "s") ||
446  | 			 !strncmpi(&str[m_i_len], "s ", 2) ||
447  | 			 !strcmpi(&str[m_i_len], "es") ||
448  | 			 !strncmpi(&str[m_i_len], "es ", 3))) {
449  | 		    mntmp = i;
450  | 		    len = m_i_len;
451  | 		}
452  | 	    }
453  | 	}
454  | 	if (mntmp == NON_PM) mntmp = title_to_mon(str, (int *)0, (int *)0);
455  | 	return mntmp;
456  | }
457  | 
458  | #endif /* OVL1 */
459  | #ifdef OVL2
460  | 
461  | /* returns 3 values (0=male, 1=female, 2=none) */
462  | int
463  | gender(mtmp)
464  | register struct monst *mtmp;
465  | {
466  | 	if (is_neuter(mtmp->data)) return 2;
467  | 	return mtmp->female;
468  | }
469  | 
470  | /* Like gender(), but lower animals and such are still "it". */
471  | /* This is the one we want to use when printing messages. */
472  | int
473  | pronoun_gender(mtmp)
474  | register struct monst *mtmp;
475  | {
476  | 	if (!canspotmon(mtmp) || !humanoid(mtmp->data))
477  | 		return 2;
478  | 	return mtmp->female;
479  | }
480  | 
481  | #endif /* OVL2 */
482  | #ifdef OVLB
483  | 
484  | boolean
485  | levl_follower(mtmp)
486  | register struct monst *mtmp;
487  | {
488  | 	return((boolean)(mtmp->mtame || (mtmp->data->mflags2 & M2_STALK) || is_fshk(mtmp)
489  | 		|| (mtmp->iswiz && !mon_has_amulet(mtmp))));
490  | }
491  | 
492  | static const short grownups[][2] = {
493  | 	{PM_CHICKATRICE, PM_COCKATRICE},
494  | 	{PM_LITTLE_DOG, PM_DOG}, {PM_DOG, PM_LARGE_DOG},
495  | 	{PM_HELL_HOUND_PUP, PM_HELL_HOUND},
496  | 	{PM_WINTER_WOLF_CUB, PM_WINTER_WOLF},
497  | 	{PM_KITTEN, PM_HOUSECAT}, {PM_HOUSECAT, PM_LARGE_CAT},
498  | 	{PM_PONY, PM_HORSE}, {PM_HORSE, PM_WARHORSE},
499  | 	{PM_KOBOLD, PM_LARGE_KOBOLD}, {PM_LARGE_KOBOLD, PM_KOBOLD_LORD},
500  | 	{PM_GNOME, PM_GNOME_LORD}, {PM_GNOME_LORD, PM_GNOME_KING},
501  | 	{PM_DWARF, PM_DWARF_LORD}, {PM_DWARF_LORD, PM_DWARF_KING},
502  | 	{PM_OGRE, PM_OGRE_LORD}, {PM_OGRE_LORD, PM_OGRE_KING},
503  | 	{PM_ELF, PM_ELF_LORD}, {PM_WOODLAND_ELF, PM_ELF_LORD},
504  | 	{PM_GREEN_ELF, PM_ELF_LORD}, {PM_GREY_ELF, PM_ELF_LORD},
505  | 	{PM_ELF_LORD, PM_ELVENKING},
506  | 	{PM_LICH, PM_DEMILICH}, {PM_DEMILICH, PM_MASTER_LICH},
507  | 	{PM_MASTER_LICH, PM_ARCH_LICH},
508  | 	{PM_VAMPIRE, PM_VAMPIRE_LORD}, {PM_BAT, PM_GIANT_BAT},
509  | 	{PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON},
510  | 	{PM_BABY_SILVER_DRAGON, PM_SILVER_DRAGON},
511  | #if 0	/* DEFERRED */
512  | 	{PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
513  | #endif
514  | 	{PM_BABY_RED_DRAGON, PM_RED_DRAGON},
515  | 	{PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON},
516  | 	{PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON},
517  | 	{PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON},
518  | 	{PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON},
519  | 	{PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON},
520  | 	{PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON},
521  | 	{PM_RED_NAGA_HATCHLING, PM_RED_NAGA},
522  | 	{PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA},
523  | 	{PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA},
524  | 	{PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA},
525  | 	{PM_SMALL_MIMIC, PM_LARGE_MIMIC}, {PM_LARGE_MIMIC, PM_GIANT_MIMIC},
526  | 	{PM_BABY_LONG_WORM, PM_LONG_WORM},
527  | 	{PM_BABY_PURPLE_WORM, PM_PURPLE_WORM},
528  | 	{PM_BABY_CROCODILE, PM_CROCODILE},
529  | 	{PM_SOLDIER, PM_SERGEANT},
530  | 	{PM_SERGEANT, PM_LIEUTENANT},
531  | 	{PM_LIEUTENANT, PM_CAPTAIN},
532  | 	{PM_WATCHMAN, PM_WATCH_CAPTAIN},
533  | 	{PM_ALIGNED_PRIEST, PM_HIGH_PRIEST},
534  | 	{PM_STUDENT, PM_ARCHEOLOGIST},
535  | 	{PM_ATTENDANT, PM_HEALER},
536  | 	{PM_PAGE, PM_KNIGHT},
537  | 	{PM_ACOLYTE, PM_PRIEST},
538  | 	{PM_APPRENTICE, PM_WIZARD},
539  | 	{PM_MANES,PM_LEMURE},
540  | #ifdef KOPS
541  | 	{PM_KEYSTONE_KOP, PM_KOP_SERGEANT},
542  | 	{PM_KOP_SERGEANT, PM_KOP_LIEUTENANT},
543  | 	{PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN},
544  | #endif
545  | 	{NON_PM,NON_PM}
546  | };
547  | 
548  | int
549  | little_to_big(montype)
550  | int montype;
551  | {
552  | #ifndef AIXPS2_BUG
553  | 	register int i;
554  | 
555  | 	for (i = 0; grownups[i][0] >= LOW_PM; i++)
556  | 		if(montype == grownups[i][0]) return grownups[i][1];
557  | 	return montype;
558  | #else
559  | /* AIX PS/2 C-compiler 1.1.1 optimizer does not like the above for loop,
560  |  * and causes segmentation faults at runtime.  (The problem does not
561  |  * occur if -O is not used.)
562  |  * lehtonen@cs.Helsinki.FI (Tapio Lehtonen) 28031990
563  |  */
564  | 	int i;
565  | 	int monvalue;
566  | 
567  | 	monvalue = montype;
568  | 	for (i = 0; grownups[i][0] >= LOW_PM; i++)
569  | 		if(montype == grownups[i][0]) monvalue = grownups[i][1];
570  | 
571  | 	return monvalue;
572  | #endif
573  | }
574  | 
575  | int
576  | big_to_little(montype)
577  | int montype;
578  | {
579  | 	register int i;
580  | 
581  | 	for (i = 0; grownups[i][0] >= LOW_PM; i++)
582  | 		if(montype == grownups[i][1]) return grownups[i][0];
583  | 	return montype;
584  | }
585  | 
586  | static const char *levitate[2]	= { "float", "Float" };
587  | static const char *fly[2]	= { "fly", "Fly" };
588  | static const char *slither[2]	= { "slither", "Slither" };
589  | static const char *ooze[2]	= { "ooze", "Ooze" };
590  | static const char *crawl[2]	= { "crawl", "Crawl" };
591  | 
592  | const char *
593  | locomotion(ptr, def)
594  | const struct permonst *ptr;
595  | const char *def;
596  | {
597  | 	int capitalize = (*def == highc(*def));
598  | 
599  | 	return (
600  | 		is_floater(ptr) ? levitate[capitalize] :
601  | 		is_flyer(ptr)   ? fly[capitalize] :
602  | 		slithy(ptr)     ? slither[capitalize] :
603  | 		amorphous(ptr)  ? ooze[capitalize] :
604  | 		nolimbs(ptr)    ? crawl[capitalize] :
605  | 		def
606  | 	       );
607  | 
608  | }
609  | 
610  | #endif /* OVLB */
611  | 
612  | /*mondata.c*/