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*/