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 13void 14set_mon_data(mon, ptr, flag) 15struct monst *mon; 16struct permonst *ptr; 17int 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 32struct attack * 33attacktype_fordmg(ptr, atyp, dtyp) 34struct permonst *ptr; 35int 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 46boolean 47attacktype(ptr, atyp) 48struct permonst *ptr; 49int atyp; 50{ 51 return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE; 52} 53 54#endif /* OVL0 */ 55#ifdef OVLB 56 57boolean 58poly_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 66boolean 67resists_drli(mon) /* returns TRUE if monster is drain-life resistant */ 68struct 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 78boolean 79resists_magm(mon) /* TRUE if monster is magic-missile resistant */ 80struct 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 */ 103boolean 104resists_blnd(mon) 105struct 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) */ 134boolean 135can_blnd(magr, mdef, aatyp, obj) 136struct monst *magr; /* NULL == no specific aggressor */ 137struct monst *mdef; 138uchar aatyp; 139struct 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 218boolean 219ranged_attk(ptr) /* returns TRUE if monster can attack at range */ 220struct 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 240boolean 241hates_silver(ptr) 242register 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 */ 251boolean 252passes_bars(mptr) 253struct 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 263boolean 264can_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 276boolean 277sliparm(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 284boolean 285breakarm(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 296boolean 297sticks(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 */ 305int 306num_horns(ptr) 307struct 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 326struct attack * 327dmgtype_fromattack(ptr, dtyp, atyp) 328struct permonst *ptr; 329int 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 340boolean 341dmgtype(ptr, dtyp) 342struct permonst *ptr; 343int 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 */ 350int 351max_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 379int 380monsndx(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 400int 401name_to_mon(in_str) 402const 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) */ 516int 517gender(mtmp) 518register 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. */ 526int 527pronoun_gender(mtmp) 528register 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 */ 539boolean 540levl_follower(mtmp) 541struct 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 555static 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 616int 617little_to_big(montype) 618int 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 643int 644big_to_little(montype) 645int 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 */ 659const struct permonst * 660raceptr(mtmp) 661struct monst *mtmp; 662{ 663 if (mtmp == &youmonst && !Upolyd) return(&mons[urace.malenum]); 664 else return(mtmp->data); 665} 666 667static const char *levitate[4] = { "float", "Float", "wobble", "Wobble" }; 668static const char *flys[4] = { "fly", "Fly", "flutter", "Flutter" }; 669static const char *flyl[4] = { "fly", "Fly", "stagger", "Stagger" }; 670static const char *slither[4] = { "slither", "Slither", "falter", "Falter" }; 671static const char *ooze[4] = { "ooze", "Ooze", "tremble", "Tremble" }; 672static const char *immobile[4] = { "wiggle", "Wiggle", "pulsate", "Pulsate" }; 673static const char *crawl[4] = { "crawl", "Crawl", "falter", "Falter" }; 674 675const char * 676locomotion(ptr, def) 677const struct permonst *ptr; 678const 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 695const char * 696stagger(ptr, def) 697const struct permonst *ptr; 698const 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 */ 716const char * 717on_fire(mptr, mattk) 718struct permonst *mptr; 719struct 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