OSDN Git Service

no bone
[nethackexpress/trunk.git] / src / mondata.c
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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 *
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 *
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 *
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 *
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*/