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. */
9 /* These routines provide basic data for any type of monster. */
14 set_mon_data(mon, ptr, flag)
20 if (flag == -1) return; /* "don't care" */
23 mon->mintrinsics |= (ptr->mresists & 0x00FF);
25 mon->mintrinsics = (ptr->mresists & 0x00FF);
33 attacktype_fordmg(ptr, atyp, dtyp)
39 for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
40 if (a->aatyp == atyp && (dtyp == AD_ANY || a->adtyp == dtyp))
43 return (struct attack *)0;
51 return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE;
61 return((boolean)(is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM] &&
62 !(mvitals[PM_STONE_GOLEM].mvflags & G_GENOD)));
67 resists_drli(mon) /* returns TRUE if monster is drain-life resistant */
70 struct permonst *ptr = mon->data;
71 struct obj *wep = ((mon == &youmonst) ? uwep : MON_WEP(mon));
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)));
79 resists_magm(mon) /* TRUE if monster is magic-missile resistant */
82 struct permonst *ptr = mon->data;
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 */
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))
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)))
102 /* TRUE iff monster is resistant to light-induced blindness */
107 struct permonst *ptr = mon->data;
108 boolean is_you = (mon == &youmonst);
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 */
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))
121 o = is_you ? uwep : MON_WEP(mon);
122 if (o && o->oartifact && defends(AD_BLND, o))
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)))
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) */
135 can_blnd(magr, mdef, aatyp, obj)
136 struct monst *magr; /* NULL == no specific aggressor */
139 struct obj *obj; /* aatyp == AT_WEAP, AT_SPIT */
141 boolean is_you = (mdef == &youmonst);
142 boolean check_visor = FALSE;
146 /* no eyes protect against all attacks for now */
147 if (!haseyes(mdef->data))
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)
156 return !resists_blnd(mdef);
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)
163 } else if (obj && (obj->otyp == BLINDING_VENOM)) {
164 /* all ublindf, including LENSES, protect, cream-pies too */
165 if (is_you && (ublindf || u.ucreamed))
168 } else if (obj && (obj->otyp == POT_BLINDNESS)) {
169 return TRUE; /* no defense */
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 */
177 if (is_you && (Blindfolded || u.usleep || u.ucreamed))
179 if (!is_you && mdef->msleeping)
184 /* e.g. raven: all ublindf, including LENSES, protect */
185 if (is_you && ublindf)
187 if ((magr == &youmonst) && u.uswallow)
188 return FALSE; /* can't affect eyes while inside monster */
192 case AT_TUCH: case AT_STNG:
193 /* some physical, blind-inducing attacks can be cancelled */
194 if (magr && magr->mcan)
202 /* check if wearing a visor (only checked if visor might help) */
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"))
219 ranged_attk(ptr) /* returns TRUE if monster can attack at range */
220 struct permonst *ptr;
222 register int i, atyp;
223 long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
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
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;
242 register struct permonst *ptr;
243 /* returns TRUE if monster is especially affected by silver weapons */
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])));
250 /* true iff the type of monster pass through iron bars */
253 struct permonst *mptr;
255 return (boolean) (passes_walls(mptr) || amorphous(mptr) ||
256 is_whirly(mptr) || verysmall(mptr) ||
257 (slithy(mptr) && !bigmonst(mptr)));
264 can_track(ptr) /* returns TRUE if monster can track well */
265 register struct permonst *ptr;
267 if (uwep && uwep->oartifact == ART_EXCALIBUR)
270 return((boolean)haseyes(ptr));
277 sliparm(ptr) /* creature will slide out of armor */
278 register struct permonst *ptr;
280 return((boolean)(is_whirly(ptr) || ptr->msize <= MZ_SMALL ||
285 breakarm(ptr) /* creature will break out of armor */
286 register struct permonst *ptr;
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])
297 sticks(ptr) /* creature sticks other creatures it hits */
298 register struct permonst *ptr;
300 return((boolean)(dmgtype(ptr,AD_STCK) || dmgtype(ptr,AD_WRAP) ||
301 attacktype(ptr,AT_HUGS)));
304 /* number of horns this type of monster has on its head */
307 struct permonst *ptr;
309 switch (monsndx(ptr)) {
310 case PM_HORNED_DEVIL: /* ? "more than one" */
315 case PM_WHITE_UNICORN:
316 case PM_GRAY_UNICORN:
317 case PM_BLACK_UNICORN:
327 dmgtype_fromattack(ptr, dtyp, atyp)
328 struct permonst *ptr;
333 for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
334 if (a->adtyp == dtyp && (atyp == AT_ANY || a->aatyp == atyp))
337 return (struct attack *)0;
342 struct permonst *ptr;
345 return dmgtype_fromattack(ptr, dtyp, AT_ANY) ? TRUE : FALSE;
348 /* returns the maximum damage a defender can do to the attacker via
349 * a passive defense */
351 max_passive_dmg(mdef, magr)
352 register struct monst *mdef, *magr;
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)) ||
366 dmg = mdef->data->mattk[i].damn;
367 if(!dmg) dmg = mdef->data->mlevel+1;
368 dmg *= mdef->data->mattk[i].damd;
380 monsndx(ptr) /* return an index into the mons array */
381 struct permonst *ptr;
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)",
390 return NON_PM; /* will not get here */
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
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_
413 * This also permits plurals created by adding suffixes such as 's'
414 * or 'es'. Other plurals must still be handled explicitly.
417 register int mntmp = NON_PM;
418 register char *s, *str, *term;
422 str = strcpy(buf, in_str);
424 if (!strncmp(str, "a ", 2)) str += 2;
425 else if (!strncmp(str, "an ", 3)) str += 3;
430 if ((s = strstri(str, "vortices")) != 0)
432 /* be careful with "ies"; "priest", "zombies" */
433 else if (slen > 3 && !strcmpi(term-3, "ies") &&
434 (slen < 7 || strcmpi(term-7, "zombies")))
436 /* luckily no monster names end in fe or ve with ves plurals */
437 else if (slen > 3 && !strcmpi(term-3, "ves"))
440 slen = strlen(str); /* length possibly needs recomputing */
443 static const struct alt_spl { const char* name; short pm_val; }
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 },
461 { "high elf", PM_HIGH_ELF },
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 },
482 register const struct alt_spl *namep;
484 for (namep = names; namep->name; namep++)
485 if (!strncmpi(str, namep->name, (int)strlen(namep->name)))
486 return namep->pm_val;
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))) {
508 if (mntmp == NON_PM) mntmp = title_to_mon(str, (int *)0, (int *)0);
515 /* returns 3 values (0=male, 1=female, 2=none) */
518 register struct monst *mtmp;
520 if (is_neuter(mtmp->data)) return 2;
524 /* Like gender(), but lower animals and such are still "it". */
525 /* This is the one we want to use when printing messages. */
528 register struct monst *mtmp;
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;
538 /* used for nearby monsters when you go to another level */
543 /* monsters with the Amulet--even pets--won't follow across levels */
544 if (mon_has_amulet(mtmp)) return FALSE;
546 /* some monsters will follow even while intending to flee from you */
547 if (mtmp->mtame || mtmp->iswiz || is_fshk(mtmp)) return TRUE;
549 /* stalking types follow, but won't when fleeing unless you hold
551 return (boolean)((mtmp->data->mflags2 & M2_STALK) &&
552 (!mtmp->mflee || u.uhave.amulet));
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},
580 {PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
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},
609 {PM_KEYSTONE_KOP, PM_KOP_SERGEANT},
610 {PM_KOP_SERGEANT, PM_KOP_LIEUTENANT},
611 {PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN},
617 little_to_big(montype)
623 for (i = 0; grownups[i][0] >= LOW_PM; i++)
624 if(montype == grownups[i][0]) return grownups[i][1];
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
636 for (i = 0; grownups[i][0] >= LOW_PM; i++)
637 if(montype == grownups[i][0]) monvalue = grownups[i][1];
644 big_to_little(montype)
649 for (i = 0; grownups[i][0] >= LOW_PM; i++)
650 if(montype == grownups[i][1]) return grownups[i][0];
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.
659 const struct permonst *
663 if (mtmp == &youmonst && !Upolyd) return(&mons[urace.malenum]);
664 else return(mtmp->data);
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" };
677 const struct permonst *ptr;
680 int capitalize = (*def == highc(*def));
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] :
697 const struct permonst *ptr;
700 int capitalize = 2 + (*def == highc(*def));
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] :
715 /* return a phrase describing the effect of fire attack on a type of monster */
718 struct permonst *mptr;
719 struct attack *mattk;
723 switch (monsndx(mptr)) {
724 case PM_FLAMING_SPHERE:
726 case PM_FIRE_ELEMENTAL:
728 what = "already on fire";
730 case PM_WATER_ELEMENTAL:
732 case PM_STEAM_VORTEX:
742 case PM_AIR_ELEMENTAL:
743 case PM_EARTH_ELEMENTAL:
745 case PM_ENERGY_VORTEX:
749 what = (mattk->aatyp == AT_HUGS) ? "being roasted" : "on fire";