Source:NetHack 3.6.0/src/mondata.c

From NetHackWiki
(Redirected from Mondata.c)
Jump to: navigation, search

Below is the full text to mondata.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/mondata.c#line123]], for example.

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

Top of file

  1.  /* NetHack 3.6	mondata.c	$NHDT-Date: 1446604115 2015/11/04 02:28:35 $  $NHDT-Branch: master $:$NHDT-Revision: 1.58 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  #include "hack.h"
  6.  
  7.  /*      These routines provide basic data for any type of monster. */
  8.  

set_mon_data

  1.  /* set up an individual monster's base type (initial creation, shapechange) */
  2.  void
  3.  set_mon_data(mon, ptr, flag)
  4.  struct monst *mon;
  5.  struct permonst *ptr;
  6.  int flag;
  7.  {
  8.      mon->data = ptr;
  9.      if (flag == -1)
  10.          return; /* "don't care" */
  11.  
  12.      if (flag == 1)
  13.          mon->mintrinsics |= (ptr->mresists & 0x00FF);
  14.      else
  15.          mon->mintrinsics = (ptr->mresists & 0x00FF);
  16.      return;
  17.  }
  18.  

attacktype_fordmg

  1.  /* does monster-type have any attack for a specific type of damage? */
  2.  struct attack *
  3.  attacktype_fordmg(ptr, atyp, dtyp)
  4.  struct permonst *ptr;
  5.  int atyp, dtyp;
  6.  {
  7.      struct attack *a;
  8.  
  9.      for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
  10.          if (a->aatyp == atyp && (dtyp == AD_ANY || a->adtyp == dtyp))
  11.              return a;
  12.      return (struct attack *) 0;
  13.  }
  14.  

attacktype

  1.  /* does monster-type have a particular type of attack */
  2.  boolean
  3.  attacktype(ptr, atyp)
  4.  struct permonst *ptr;
  5.  int atyp;
  6.  {
  7.      return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE;
  8.  }
  9.  

noattacks

  1.  /* returns True if monster doesn't attack, False if it does */
  2.  boolean
  3.  noattacks(ptr)
  4.  struct permonst *ptr;
  5.  {
  6.      int i;
  7.      struct attack *mattk = ptr->mattk;
  8.  
  9.      for (i = 0; i < NATTK; i++) {
  10.          /* AT_BOOM "passive attack" (gas spore's explosion upon death)
  11.             isn't an attack as far as our callers are concerned */
  12.          if (mattk[i].aatyp == AT_BOOM)
  13.              continue;
  14.  
  15.          if (mattk[i].aatyp)
  16.              return FALSE;
  17.      }
  18.      return TRUE;
  19.  }
  20.  

poly_when_stoned

  1.  /* does monster-type transform into something else when petrified? */
  2.  boolean
  3.  poly_when_stoned(ptr)
  4.  struct permonst *ptr;
  5.  {
  6.      /* non-stone golems turn into stone golems unless latter is genocided */
  7.      return (boolean) (is_golem(ptr) && ptr != &mons[PM_STONE_GOLEM]
  8.                        && !(mvitals[PM_STONE_GOLEM].mvflags & G_GENOD));
  9.      /* allow G_EXTINCT */
  10.  }
  11.  

resists_drli

  1.  /* returns True if monster is drain-life resistant */
  2.  boolean
  3.  resists_drli(mon)
  4.  struct monst *mon;
  5.  {
  6.      struct permonst *ptr = mon->data;
  7.      struct obj *wep;
  8.  
  9.      if (is_undead(ptr) || is_demon(ptr) || is_were(ptr)
  10.          /* is_were() doesn't handle hero in human form */
  11.          || (mon == &youmonst && u.ulycn >= LOW_PM)
  12.          || ptr == &mons[PM_DEATH] || is_vampshifter(mon))
  13.          return TRUE;
  14.      wep = (mon == &youmonst) ? uwep : MON_WEP(mon);
  15.      return (boolean) (wep && wep->oartifact && defends(AD_DRLI, wep));
  16.  }
  17.  

resists_magm

  1.  /* True if monster is magic-missile (actually, general magic) resistant */
  2.  boolean
  3.  resists_magm(mon)
  4.  struct monst *mon;
  5.  {
  6.      struct permonst *ptr = mon->data;
  7.      boolean is_you = (mon == &youmonst);
  8.      long slotmask;
  9.      struct obj *o;
  10.  
  11.      /* as of 3.2.0:  gray dragons, Angels, Oracle, Yeenoghu */
  12.      if (dmgtype(ptr, AD_MAGM) || ptr == &mons[PM_BABY_GRAY_DRAGON]
  13.          || dmgtype(ptr, AD_RBRE)) /* Chromatic Dragon */
  14.          return TRUE;
  15.      /* check for magic resistance granted by wielded weapon */
  16.      o = is_you ? uwep : MON_WEP(mon);
  17.      if (o && o->oartifact && defends(AD_MAGM, o))
  18.          return TRUE;
  19.      /* check for magic resistance granted by worn or carried items */
  20.      o = is_you ? invent : mon->minvent;
  21.      slotmask = W_ARMOR | W_ACCESSORY;
  22.      if (!is_you /* assumes monsters don't wield non-weapons */
  23.          || (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))))
  24.          slotmask |= W_WEP;
  25.      if (is_you && u.twoweap)
  26.          slotmask |= W_SWAPWEP;
  27.      for (; o; o = o->nobj)
  28.          if (((o->owornmask & slotmask) != 0L
  29.               && objects[o->otyp].oc_oprop == ANTIMAGIC)
  30.              || (o->oartifact && defends_when_carried(AD_MAGM, o)))
  31.              return TRUE;
  32.      return FALSE;
  33.  }
  34.  

resists_blnd

  1.  /* True iff monster is resistant to light-induced blindness */
  2.  boolean
  3.  resists_blnd(mon)
  4.  struct monst *mon;
  5.  {
  6.      struct permonst *ptr = mon->data;
  7.      boolean is_you = (mon == &youmonst);
  8.      long slotmask;
  9.      struct obj *o;
  10.  
  11.      if (is_you ? (Blind || Unaware)
  12.                 : (mon->mblinded || !mon->mcansee || !haseyes(ptr)
  13.                    /* BUG: temporary sleep sets mfrozen, but since
  14.                            paralysis does too, we can't check it */
  15.                    || mon->msleeping))
  16.          return TRUE;
  17.      /* yellow light, Archon; !dust vortex, !cobra, !raven */
  18.      if (dmgtype_fromattack(ptr, AD_BLND, AT_EXPL)
  19.          || dmgtype_fromattack(ptr, AD_BLND, AT_GAZE))
  20.          return TRUE;
  21.      o = is_you ? uwep : MON_WEP(mon);
  22.      if (o && o->oartifact && defends(AD_BLND, o))
  23.          return TRUE;
  24.      o = is_you ? invent : mon->minvent;
  25.      slotmask = W_ARMOR | W_ACCESSORY;
  26.      if (!is_you /* assumes monsters don't wield non-weapons */
  27.          || (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))))
  28.          slotmask |= W_WEP;
  29.      if (is_you && u.twoweap)
  30.          slotmask |= W_SWAPWEP;
  31.      for (; o; o = o->nobj)
  32.          if (((o->owornmask & slotmask) != 0L
  33.               && objects[o->otyp].oc_oprop == BLINDED)
  34.              || (o->oartifact && defends_when_carried(AD_BLND, o)))
  35.              return TRUE;
  36.      return FALSE;
  37.  }
  38.  

can_blnd

  1.  /* True iff monster can be blinded by the given attack;
  2.     note: may return True when mdef is blind (e.g. new cream-pie attack) */
  3.  boolean
  4.  can_blnd(magr, mdef, aatyp, obj)
  5.  struct monst *magr; /* NULL == no specific aggressor */
  6.  struct monst *mdef;
  7.  uchar aatyp;
  8.  struct obj *obj; /* aatyp == AT_WEAP, AT_SPIT */
  9.  {
  10.      boolean is_you = (mdef == &youmonst);
  11.      boolean check_visor = FALSE;
  12.      struct obj *o;
  13.      const char *s;
  14.  
  15.      /* no eyes protect against all attacks for now */
  16.      if (!haseyes(mdef->data))
  17.          return FALSE;
  18.  
  19.      switch (aatyp) {
  20.      case AT_EXPL:
  21.      case AT_BOOM:
  22.      case AT_GAZE:
  23.      case AT_MAGC:
  24.      case AT_BREA: /* assumed to be lightning */
  25.          /* light-based attacks may be cancelled or resisted */
  26.          if (magr && magr->mcan)
  27.              return FALSE;
  28.          return !resists_blnd(mdef);
  29.  
  30.      case AT_WEAP:
  31.      case AT_SPIT:
  32.      case AT_NONE:
  33.          /* an object is used (thrown/spit/other) */
  34.          if (obj && (obj->otyp == CREAM_PIE)) {
  35.              if (is_you && Blindfolded)
  36.                  return FALSE;
  37.          } else if (obj && (obj->otyp == BLINDING_VENOM)) {
  38.              /* all ublindf, including LENSES, protect, cream-pies too */
  39.              if (is_you && (ublindf || u.ucreamed))
  40.                  return FALSE;
  41.              check_visor = TRUE;
  42.          } else if (obj && (obj->otyp == POT_BLINDNESS)) {
  43.              return TRUE; /* no defense */
  44.          } else
  45.              return FALSE; /* other objects cannot cause blindness yet */
  46.          if ((magr == &youmonst) && u.uswallow)
  47.              return FALSE; /* can't affect eyes while inside monster */
  48.          break;
  49.  
  50.      case AT_ENGL:
  51.          if (is_you && (Blindfolded || Unaware || u.ucreamed))
  52.              return FALSE;
  53.          if (!is_you && mdef->msleeping)
  54.              return FALSE;
  55.          break;
  56.  
  57.      case AT_CLAW:
  58.          /* e.g. raven: all ublindf, including LENSES, protect */
  59.          if (is_you && ublindf)
  60.              return FALSE;
  61.          if ((magr == &youmonst) && u.uswallow)
  62.              return FALSE; /* can't affect eyes while inside monster */
  63.          check_visor = TRUE;
  64.          break;
  65.  
  66.      case AT_TUCH:
  67.      case AT_STNG:
  68.          /* some physical, blind-inducing attacks can be cancelled */
  69.          if (magr && magr->mcan)
  70.              return FALSE;
  71.          break;
  72.  
  73.      default:
  74.          break;
  75.      }
  76.  
  77.      /* check if wearing a visor (only checked if visor might help) */
  78.      if (check_visor) {
  79.          o = (mdef == &youmonst) ? invent : mdef->minvent;
  80.          for (; o; o = o->nobj)
  81.              if ((o->owornmask & W_ARMH)
  82.                  && (s = OBJ_DESCR(objects[o->otyp])) != (char *) 0
  83.                  && !strcmp(s, "visored helmet"))
  84.                  return FALSE;
  85.      }
  86.  
  87.      return TRUE;
  88.  }
  89.  

ranged_attk

  1.  /* returns True if monster can attack at range */
  2.  boolean
  3.  ranged_attk(ptr)
  4.  struct permonst *ptr;
  5.  {
  6.      register int i, atyp;
  7.      long atk_mask = (1L << AT_BREA) | (1L << AT_SPIT) | (1L << AT_GAZE);
  8.  
  9.      /* was: (attacktype(ptr, AT_BREA) || attacktype(ptr, AT_WEAP)
  10.       *       || attacktype(ptr, AT_SPIT) || attacktype(ptr, AT_GAZE)
  11.       *       || attacktype(ptr, AT_MAGC));
  12.       * but that's too slow -dlc
  13.       */
  14.      for (i = 0; i < NATTK; i++) {
  15.          atyp = ptr->mattk[i].aatyp;
  16.          if (atyp >= AT_WEAP)
  17.              return TRUE;
  18.          /* assert(atyp < 32); */
  19.          if ((atk_mask & (1L << atyp)) != 0L)
  20.              return TRUE;
  21.      }
  22.      return FALSE;
  23.  }
  24.  

mon_hates_silver

  1.  /* True if specific monster is especially affected by silver weapons */
  2.  boolean
  3.  mon_hates_silver(mon)
  4.  struct monst *mon;
  5.  {
  6.      return (boolean) (is_vampshifter(mon) || hates_silver(mon->data));
  7.  }
  8.  

hates_silver

  1.  /* True if monster-type is especially affected by silver weapons */
  2.  boolean
  3.  hates_silver(ptr)
  4.  register struct permonst *ptr;
  5.  {
  6.      return (boolean) (is_were(ptr) || ptr->mlet == S_VAMPIRE || is_demon(ptr)
  7.                        || ptr == &mons[PM_SHADE]
  8.                        || (ptr->mlet == S_IMP && ptr != &mons[PM_TENGU]));
  9.  }
  10.  

passes_bars

  1.  /* True iff the type of monster pass through iron bars */
  2.  boolean
  3.  passes_bars(mptr)
  4.  struct permonst *mptr;
  5.  {
  6.      return (boolean) (passes_walls(mptr) || amorphous(mptr) || unsolid(mptr)
  7.                        || is_whirly(mptr) || verysmall(mptr)
  8.                        || dmgtype(mptr, AD_CORR) || dmgtype(mptr, AD_RUST)
  9.                        || (slithy(mptr) && !bigmonst(mptr)));
  10.  }
  11.  

can_blow

  1.  /* returns True if monster can blow (whistle, etc) */
  2.  boolean
  3.  can_blow(mtmp)
  4.  register struct monst *mtmp;
  5.  {
  6.      if ((is_silent(mtmp->data) || mtmp->data->msound == MS_BUZZ)
  7.          && (breathless(mtmp->data) || verysmall(mtmp->data)
  8.              || !has_head(mtmp->data) || mtmp->data->mlet == S_EEL))
  9.          return FALSE;
  10.      if ((mtmp == &youmonst) && Strangled)
  11.          return FALSE;
  12.      return TRUE;
  13.  }
  14.  

can_be_strangled

  1.  /* True if mon is vulnerable to strangulation */
  2.  boolean
  3.  can_be_strangled(mon)
  4.  struct monst *mon;
  5.  {
  6.      struct obj *mamul;
  7.      boolean nonbreathing, nobrainer;
  8.  
  9.      /* For amulet of strangulation support:  here we're considering
  10.         strangulation to be loss of blood flow to the brain due to
  11.         constriction of the arteries in the neck, so all headless
  12.         creatures are immune (no neck) as are mindless creatures
  13.         who don't need to breathe (brain, if any, doesn't care).
  14.         Mindless creatures who do need to breath are vulnerable, as
  15.         are non-breathing creatures which have higher brain function. */
  16.      if (!has_head(mon->data))
  17.          return FALSE;
  18.      if (mon == &youmonst) {
  19.          /* hero can't be mindless but poly'ing into mindless form can
  20.             confer strangulation protection */
  21.          nobrainer = mindless(youmonst.data);
  22.          nonbreathing = Breathless;
  23.      } else {
  24.          nobrainer = mindless(mon->data);
  25.          /* monsters don't wear amulets of magical breathing,
  26.             so second part doesn't achieve anything useful... */
  27.          nonbreathing = (breathless(mon->data)
  28.                          || ((mamul = which_armor(mon, W_AMUL)) != 0
  29.                              && (mamul->otyp == AMULET_OF_MAGICAL_BREATHING)));
  30.      }
  31.      return (boolean) (!nobrainer || !nonbreathing);
  32.  }
  33.  

can_track

  1.  /* returns True if monster can track well */
  2.  boolean
  3.  can_track(ptr)
  4.  register struct permonst *ptr;
  5.  {
  6.      if (uwep && uwep->oartifact == ART_EXCALIBUR)
  7.          return TRUE;
  8.      else
  9.          return (boolean) haseyes(ptr);
  10.  }
  11.  

sliparm

  1.  /* creature will slide out of armor */
  2.  boolean
  3.  sliparm(ptr)
  4.  register struct permonst *ptr;
  5.  {
  6.      return (boolean) (is_whirly(ptr) || ptr->msize <= MZ_SMALL
  7.                        || noncorporeal(ptr));
  8.  }
  9.  

breakarm

  1.  /* creature will break out of armor */
  2.  boolean
  3.  breakarm(ptr)
  4.  register struct permonst *ptr;
  5.  {
  6.      if (sliparm(ptr))
  7.          return FALSE;
  8.  
  9.      return (boolean) (bigmonst(ptr)
  10.                        || (ptr->msize > MZ_SMALL && !humanoid(ptr))
  11.                        /* special cases of humanoids that cannot wear suits */
  12.                        || ptr == &mons[PM_MARILITH]
  13.                        || ptr == &mons[PM_WINGED_GARGOYLE]);
  14.  }
  15.  

sticks

  1.  /* creature sticks other creatures it hits */
  2.  boolean
  3.  sticks(ptr)
  4.  register struct permonst *ptr;
  5.  {
  6.      return (boolean) (dmgtype(ptr, AD_STCK) || dmgtype(ptr, AD_WRAP)
  7.                        || attacktype(ptr, AT_HUGS));
  8.  }
  9.  

cantvomit

  1.  /* some monster-types can't vomit */
  2.  boolean
  3.  cantvomit(ptr)
  4.  struct permonst *ptr;
  5.  {
  6.      /* rats and mice are incapable of vomiting;
  7.         which other creatures have the same limitation? */
  8.      if (ptr->mlet == S_RODENT && ptr != &mons[PM_ROCK_MOLE]
  9.          && ptr != &mons[PM_WOODCHUCK])
  10.          return TRUE;
  11.      return FALSE;
  12.  }
  13.  

num_horns

  1.  /* number of horns this type of monster has on its head */
  2.  int
  3.  num_horns(ptr)
  4.  struct permonst *ptr;
  5.  {
  6.      switch (monsndx(ptr)) {
  7.      case PM_HORNED_DEVIL: /* ? "more than one" */
  8.      case PM_MINOTAUR:
  9.      case PM_ASMODEUS:
  10.      case PM_BALROG:
  11.          return 2;
  12.      case PM_WHITE_UNICORN:
  13.      case PM_GRAY_UNICORN:
  14.      case PM_BLACK_UNICORN:
  15.      case PM_KI_RIN:
  16.          return 1;
  17.      default:
  18.          break;
  19.      }
  20.      return 0;
  21.  }
  22.  

dmgtype_fromattack

  1.  /* does monster-type deal out a particular type of damage from a particular
  2.     type of attack? */
  3.  struct attack *
  4.  dmgtype_fromattack(ptr, dtyp, atyp)
  5.  struct permonst *ptr;
  6.  int dtyp, atyp;
  7.  {
  8.      struct attack *a;
  9.  
  10.      for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++)
  11.          if (a->adtyp == dtyp && (atyp == AT_ANY || a->aatyp == atyp))
  12.              return a;
  13.      return (struct attack *) 0;
  14.  }
  15.  

dmgtype

  1.  /* does monster-type deal out a particular type of damage from any attack */
  2.  boolean
  3.  dmgtype(ptr, dtyp)
  4.  struct permonst *ptr;
  5.  int dtyp;
  6.  {
  7.      return dmgtype_fromattack(ptr, dtyp, AT_ANY) ? TRUE : FALSE;
  8.  }
  9.  

max_passive_dmg

  1.  /* returns the maximum damage a defender can do to the attacker via
  2.     a passive defense */
  3.  int
  4.  max_passive_dmg(mdef, magr)
  5.  register struct monst *mdef, *magr;
  6.  {
  7.      int i, dmg = 0, multi2 = 0;
  8.      uchar adtyp;
  9.  
  10.      /* each attack by magr can result in passive damage */
  11.      for (i = 0; i < NATTK; i++)
  12.          switch (magr->data->mattk[i].aatyp) {
  13.          case AT_CLAW:
  14.          case AT_BITE:
  15.          case AT_KICK:
  16.          case AT_BUTT:
  17.          case AT_TUCH:
  18.          case AT_STNG:
  19.          case AT_HUGS:
  20.          case AT_ENGL:
  21.          case AT_TENT:
  22.          case AT_WEAP:
  23.              multi2++;
  24.              break;
  25.          default:
  26.              break;
  27.          }
  28.  
  29.      for (i = 0; i < NATTK; i++)
  30.          if (mdef->data->mattk[i].aatyp == AT_NONE
  31.              || mdef->data->mattk[i].aatyp == AT_BOOM) {
  32.              adtyp = mdef->data->mattk[i].adtyp;
  33.              if ((adtyp == AD_ACID && !resists_acid(magr))
  34.                  || (adtyp == AD_COLD && !resists_cold(magr))
  35.                  || (adtyp == AD_FIRE && !resists_fire(magr))
  36.                  || (adtyp == AD_ELEC && !resists_elec(magr))
  37.                  || adtyp == AD_PHYS) {
  38.                  dmg = mdef->data->mattk[i].damn;
  39.                  if (!dmg)
  40.                      dmg = mdef->data->mlevel + 1;
  41.                  dmg *= mdef->data->mattk[i].damd;
  42.              } else
  43.                  dmg = 0;
  44.  
  45.              return dmg * multi2;
  46.          }
  47.      return 0;
  48.  }
  49.  

same_race

  1.  /* determine whether two monster types are from the same species */
  2.  boolean
  3.  same_race(pm1, pm2)
  4.  struct permonst *pm1, *pm2;
  5.  {
  6.      char let1 = pm1->mlet, let2 = pm2->mlet;
  7.  
  8.      if (pm1 == pm2)
  9.          return TRUE; /* exact match */
  10.      /* player races have their own predicates */
  11.      if (is_human(pm1))
  12.          return is_human(pm2);
  13.      if (is_elf(pm1))
  14.          return is_elf(pm2);
  15.      if (is_dwarf(pm1))
  16.          return is_dwarf(pm2);
  17.      if (is_gnome(pm1))
  18.          return is_gnome(pm2);
  19.      if (is_orc(pm1))
  20.          return is_orc(pm2);
  21.      /* other creatures are less precise */
  22.      if (is_giant(pm1))
  23.          return is_giant(pm2); /* open to quibbling here */
  24.      if (is_golem(pm1))
  25.          return is_golem(pm2); /* even moreso... */
  26.      if (is_mind_flayer(pm1))
  27.          return is_mind_flayer(pm2);
  28.      if (let1 == S_KOBOLD || pm1 == &mons[PM_KOBOLD_ZOMBIE]
  29.          || pm1 == &mons[PM_KOBOLD_MUMMY])
  30.          return (let2 == S_KOBOLD || pm2 == &mons[PM_KOBOLD_ZOMBIE]
  31.                  || pm2 == &mons[PM_KOBOLD_MUMMY]);
  32.      if (let1 == S_OGRE)
  33.          return (let2 == S_OGRE);
  34.      if (let1 == S_NYMPH)
  35.          return (let2 == S_NYMPH);
  36.      if (let1 == S_CENTAUR)
  37.          return (let2 == S_CENTAUR);
  38.      if (is_unicorn(pm1))
  39.          return is_unicorn(pm2);
  40.      if (let1 == S_DRAGON)
  41.          return (let2 == S_DRAGON);
  42.      if (let1 == S_NAGA)
  43.          return (let2 == S_NAGA);
  44.      /* other critters get steadily messier */
  45.      if (is_rider(pm1))
  46.          return is_rider(pm2); /* debatable */
  47.      if (is_minion(pm1))
  48.          return is_minion(pm2); /* [needs work?] */
  49.      /* tengu don't match imps (first test handled case of both being tengu) */
  50.      if (pm1 == &mons[PM_TENGU] || pm2 == &mons[PM_TENGU])
  51.          return FALSE;
  52.      if (let1 == S_IMP)
  53.          return (let2 == S_IMP);
  54.      /* and minor demons (imps) don't match major demons */
  55.      else if (let2 == S_IMP)
  56.          return FALSE;
  57.      if (is_demon(pm1))
  58.          return is_demon(pm2);
  59.      if (is_undead(pm1)) {
  60.          if (let1 == S_ZOMBIE)
  61.              return (let2 == S_ZOMBIE);
  62.          if (let1 == S_MUMMY)
  63.              return (let2 == S_MUMMY);
  64.          if (let1 == S_VAMPIRE)
  65.              return (let2 == S_VAMPIRE);
  66.          if (let1 == S_LICH)
  67.              return (let2 == S_LICH);
  68.          if (let1 == S_WRAITH)
  69.              return (let2 == S_WRAITH);
  70.          if (let1 == S_GHOST)
  71.              return (let2 == S_GHOST);
  72.      } else if (is_undead(pm2))
  73.          return FALSE;
  74.  
  75.      /* check for monsters which grow into more mature forms */
  76.      if (let1 == let2) {
  77.          int m1 = monsndx(pm1), m2 = monsndx(pm2), prv, nxt;
  78.  
  79.          /* we know m1 != m2 (very first check above); test all smaller
  80.             forms of m1 against m2, then all larger ones; don't need to
  81.             make the corresponding tests for variants of m2 against m1 */
  82.          for (prv = m1, nxt = big_to_little(m1); nxt != prv;
  83.               prv = nxt, nxt = big_to_little(nxt))
  84.              if (nxt == m2)
  85.                  return TRUE;
  86.          for (prv = m1, nxt = little_to_big(m1); nxt != prv;
  87.               prv = nxt, nxt = little_to_big(nxt))
  88.              if (nxt == m2)
  89.                  return TRUE;
  90.      }
  91.      /* not caught by little/big handling */
  92.      if (pm1 == &mons[PM_GARGOYLE] || pm1 == &mons[PM_WINGED_GARGOYLE])
  93.          return (pm2 == &mons[PM_GARGOYLE]
  94.                  || pm2 == &mons[PM_WINGED_GARGOYLE]);
  95.      if (pm1 == &mons[PM_KILLER_BEE] || pm1 == &mons[PM_QUEEN_BEE])
  96.          return (pm2 == &mons[PM_KILLER_BEE] || pm2 == &mons[PM_QUEEN_BEE]);
  97.  
  98.      if (is_longworm(pm1))
  99.          return is_longworm(pm2); /* handles tail */
  100.      /* [currently there's no reason to bother matching up
  101.          assorted bugs and blobs with their closest variants] */
  102.      /* didn't match */
  103.      return FALSE;
  104.  }
  105.  

monsndx

  1.  /* return an index into the mons array */
  2.  int
  3.  monsndx(ptr)
  4.  struct permonst *ptr;
  5.  {
  6.      register int i;
  7.  
  8.      i = (int) (ptr - &mons[0]);
  9.      if (i < LOW_PM || i >= NUMMONS) {
  10.          panic("monsndx - could not index monster (%s)",
  11.                fmt_ptr((genericptr_t) ptr));
  12.          return NON_PM; /* will not get here */
  13.      }
  14.      return i;
  15.  }
  16.  

name_to_mon

  1.  /* for handling alternate spellings */
  2.  struct alt_spl {
  3.      const char *name;
  4.      short pm_val;
  5.  };
  6.  
  7.  /* figure out what type of monster a user-supplied string is specifying */
  8.  int
  9.  name_to_mon(in_str)
  10.  const char *in_str;
  11.  {
  12.      /* Be careful.  We must check the entire string in case it was
  13.       * something such as "ettin zombie corpse".  The calling routine
  14.       * doesn't know about the "corpse" until the monster name has
  15.       * already been taken off the front, so we have to be able to
  16.       * read the name with extraneous stuff such as "corpse" stuck on
  17.       * the end.
  18.       * This causes a problem for names which prefix other names such
  19.       * as "ettin" on "ettin zombie".  In this case we want the _longest_
  20.       * name which exists.
  21.       * This also permits plurals created by adding suffixes such as 's'
  22.       * or 'es'.  Other plurals must still be handled explicitly.
  23.       */
  24.      register int i;
  25.      register int mntmp = NON_PM;
  26.      register char *s, *str, *term;
  27.      char buf[BUFSZ];
  28.      int len, slen;
  29.  
  30.      str = strcpy(buf, in_str);
  31.  
  32.      if (!strncmp(str, "a ", 2))
  33.          str += 2;
  34.      else if (!strncmp(str, "an ", 3))
  35.          str += 3;
  36.      else if (!strncmp(str, "the ", 4))
  37.          str += 4;
  38.  
  39.      slen = strlen(str);
  40.      term = str + slen;
  41.  
  42.      if ((s = strstri(str, "vortices")) != 0)
  43.          Strcpy(s + 4, "ex");
  44.      /* be careful with "ies"; "priest", "zombies" */
  45.      else if (slen > 3 && !strcmpi(term - 3, "ies")
  46.               && (slen < 7 || strcmpi(term - 7, "zombies")))
  47.          Strcpy(term - 3, "y");
  48.      /* luckily no monster names end in fe or ve with ves plurals */
  49.      else if (slen > 3 && !strcmpi(term - 3, "ves"))
  50.          Strcpy(term - 3, "f");
  51.  
  52.      slen = strlen(str); /* length possibly needs recomputing */
  53.  
  54.      {
  55.          static const struct alt_spl names[] = {
  56.              /* Alternate spellings */
  57.              { "grey dragon", PM_GRAY_DRAGON },
  58.              { "baby grey dragon", PM_BABY_GRAY_DRAGON },
  59.              { "grey unicorn", PM_GRAY_UNICORN },
  60.              { "grey ooze", PM_GRAY_OOZE },
  61.              { "gray-elf", PM_GREY_ELF },
  62.              { "mindflayer", PM_MIND_FLAYER },
  63.              { "master mindflayer", PM_MASTER_MIND_FLAYER },
  64.              /* More alternates; priest and priestess are separate monster
  65.                 types but that isn't the case for {aligned,high} priests */
  66.              { "aligned priestess", PM_ALIGNED_PRIEST },
  67.              { "high priestess", PM_HIGH_PRIEST },
  68.              /* Inappropriate singularization by -ves check above */
  69.              { "master of thief", PM_MASTER_OF_THIEVES },
  70.              /* Potential misspellings where we want to avoid falling back
  71.                 to the rank title prefix (input has been singularized) */
  72.              { "master thief", PM_MASTER_OF_THIEVES },
  73.              { "master of assassin", PM_MASTER_ASSASSIN },
  74.              /* Outdated names */
  75.              { "invisible stalker", PM_STALKER },
  76.              { "high-elf", PM_ELVENKING }, /* PM_HIGH_ELF is obsolete */
  77.              { "halfling", PM_HOBBIT },    /* potential guess for polyself */
  78.              /* Hyphenated names */
  79.              { "ki rin", PM_KI_RIN },
  80.              { "uruk hai", PM_URUK_HAI },
  81.              { "orc captain", PM_ORC_CAPTAIN },
  82.              { "woodland elf", PM_WOODLAND_ELF },
  83.              { "green elf", PM_GREEN_ELF },
  84.              { "grey elf", PM_GREY_ELF },
  85.              { "gray elf", PM_GREY_ELF },
  86.              { "elf lord", PM_ELF_LORD },
  87.              { "olog hai", PM_OLOG_HAI },
  88.              { "arch lich", PM_ARCH_LICH },
  89.              /* Some irregular plurals */
  90.              { "incubi", PM_INCUBUS },
  91.              { "succubi", PM_SUCCUBUS },
  92.              { "violet fungi", PM_VIOLET_FUNGUS },
  93.              { "homunculi", PM_HOMUNCULUS },
  94.              { "baluchitheria", PM_BALUCHITHERIUM },
  95.              { "lurkers above", PM_LURKER_ABOVE },
  96.              { "cavemen", PM_CAVEMAN },
  97.              { "cavewomen", PM_CAVEWOMAN },
  98.              { "djinn", PM_DJINNI },
  99.              { "mumakil", PM_MUMAK },
  100.              { "erinyes", PM_ERINYS },
  101.              /* end of list */
  102.              { 0, NON_PM }
  103.          };
  104.          register const struct alt_spl *namep;
  105.  
  106.          for (namep = names; namep->name; namep++)
  107.              if (!strncmpi(str, namep->name, (int) strlen(namep->name)))
  108.                  return namep->pm_val;
  109.      }
  110.  
  111.      for (len = 0, i = LOW_PM; i < NUMMONS; i++) {
  112.          register int m_i_len = strlen(mons[i].mname);
  113.  
  114.          if (m_i_len > len && !strncmpi(mons[i].mname, str, m_i_len)) {
  115.              if (m_i_len == slen) {
  116.                  return i; /* exact match */
  117.              } else if (slen > m_i_len
  118.                         && (str[m_i_len] == ' '
  119.                             || !strcmpi(&str[m_i_len], "s")
  120.                             || !strncmpi(&str[m_i_len], "s ", 2)
  121.                             || !strcmpi(&str[m_i_len], "'")
  122.                             || !strncmpi(&str[m_i_len], "' ", 2)
  123.                             || !strcmpi(&str[m_i_len], "'s")
  124.                             || !strncmpi(&str[m_i_len], "'s ", 3)
  125.                             || !strcmpi(&str[m_i_len], "es")
  126.                             || !strncmpi(&str[m_i_len], "es ", 3))) {
  127.                  mntmp = i;
  128.                  len = m_i_len;
  129.              }
  130.          }
  131.      }
  132.      if (mntmp == NON_PM)
  133.          mntmp = title_to_mon(str, (int *) 0, (int *) 0);
  134.      return mntmp;
  135.  }
  136.  

name_to_monclass

  1.  /* monster class from user input; used for genocide and controlled polymorph;
  2.     returns 0 rather than MAXMCLASSES if no match is found */
  3.  int
  4.  name_to_monclass(in_str, mndx_p)
  5.  const char *in_str;
  6.  int *mndx_p;
  7.  {
  8.      /* Single letters are matched against def_monsyms[].sym; words
  9.         or phrases are first matched against def_monsyms[].explain
  10.         to check class description; if not found there, then against
  11.         mons[].mname to test individual monster types.  Input can be a
  12.         substring of the full description or mname, but to be accepted,
  13.         such partial matches must start at beginning of a word.  Some
  14.         class descriptions include "foo or bar" and "foo or other foo"
  15.         so we don't want to accept "or", "other", "or other" there. */
  16.      static NEARDATA const char *const falsematch[] = {
  17.          /* multiple-letter input which matches any of these gets rejected */
  18.          "an", "the", "or", "other", "or other", 0
  19.      };
  20.      /* positive pm_val => specific monster; negative => class */
  21.      static NEARDATA const struct alt_spl truematch[] = {
  22.          /* "long worm" won't match "worm" class but would accidentally match
  23.             "long worm tail" class before the comparison with monster types */
  24.          { "long worm", PM_LONG_WORM },
  25.          /* matches wrong--or at least suboptimal--class */
  26.          { "demon", -S_DEMON }, /* hits "imp or minor demon" */
  27.          /* matches specific monster (overly restrictive) */
  28.          { "devil", -S_DEMON }, /* always "horned devil" */
  29.          /* some plausible guesses which need help */
  30.          { "bug", -S_XAN },  /* would match bugbear... */
  31.          { "fish", -S_EEL }, /* wouldn't match anything */
  32.          /* end of list */
  33.          { 0, NON_PM }
  34.      };
  35.      const char *p, *x;
  36.      int i;
  37.  
  38.      if (mndx_p)
  39.          *mndx_p = NON_PM; /* haven't [yet] matched a specific type */
  40.  
  41.      if (!in_str || !in_str[0]) {
  42.          /* empty input */
  43.          return 0;
  44.      } else if (!in_str[1]) {
  45.          /* single character */
  46.          i = def_char_to_monclass(*in_str);
  47.          if (i == S_MIMIC_DEF) { /* ']' -> 'm' */
  48.              i = S_MIMIC;
  49.          } else if (i == S_WORM_TAIL) { /* '~' -> 'w' */
  50.              i = S_WORM;
  51.              if (mndx_p)
  52.                  *mndx_p = PM_LONG_WORM;
  53.          } else if (i == MAXMCLASSES) /* maybe 'I' */
  54.              i = (*in_str == DEF_INVISIBLE) ? S_invisible : 0;
  55.          return i;
  56.      } else {
  57.          /* multiple characters */
  58.          in_str = makesingular(in_str);
  59.          /* check for special cases */
  60.          for (i = 0; falsematch[i]; i++)
  61.              if (!strcmpi(in_str, falsematch[i]))
  62.                  return 0;
  63.          for (i = 0; truematch[i].name; i++)
  64.              if (!strcmpi(in_str, truematch[i].name)) {
  65.                  i = truematch[i].pm_val;
  66.                  if (i < 0)
  67.                      return -i; /* class */
  68.                  if (mndx_p)
  69.                      *mndx_p = i; /* monster */
  70.                  return mons[i].mlet;
  71.              }
  72.          /* check monster class descriptions */
  73.          for (i = 1; i < MAXMCLASSES; i++) {
  74.              x = def_monsyms[i].explain;
  75.              if ((p = strstri(x, in_str)) != 0 && (p == x || *(p - 1) == ' '))
  76.                  return i;
  77.          }
  78.          /* check individual species names; not as thorough as mon_to_name()
  79.             but our caller can call that directly if desired */
  80.          for (i = LOW_PM; i < NUMMONS; i++) {
  81.              x = mons[i].mname;
  82.              if ((p = strstri(x, in_str)) != 0
  83.                  && (p == x || *(p - 1) == ' ')) {
  84.                  if (mndx_p)
  85.                      *mndx_p = i;
  86.                  return mons[i].mlet;
  87.              }
  88.          }
  89.      }
  90.      return 0;
  91.  }
  92.  

gender

  1.  /* returns 3 values (0=male, 1=female, 2=none) */
  2.  int
  3.  gender(mtmp)
  4.  register struct monst *mtmp;
  5.  {
  6.      if (is_neuter(mtmp->data))
  7.          return 2;
  8.      return mtmp->female;
  9.  }
  10.  

pronoun_gender

  1.  /* Like gender(), but lower animals and such are still "it".
  2.     This is the one we want to use when printing messages. */
  3.  int
  4.  pronoun_gender(mtmp)
  5.  register struct monst *mtmp;
  6.  {
  7.      if (is_neuter(mtmp->data) || !canspotmon(mtmp))
  8.          return 2;
  9.      return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ)
  10.              || type_is_pname(mtmp->data)) ? (int) mtmp->female : 2;
  11.  }
  12.  

levl_follower

  1.  /* used for nearby monsters when you go to another level */
  2.  boolean
  3.  levl_follower(mtmp)
  4.  struct monst *mtmp;
  5.  {
  6.      if (mtmp == u.usteed)
  7.          return TRUE;
  8.  
  9.      /* Wizard with Amulet won't bother trying to follow across levels */
  10.      if (mtmp->iswiz && mon_has_amulet(mtmp))
  11.          return FALSE;
  12.      /* some monsters will follow even while intending to flee from you */
  13.      if (mtmp->mtame || mtmp->iswiz || is_fshk(mtmp))
  14.          return TRUE;
  15.      /* stalking types follow, but won't when fleeing unless you hold
  16.         the Amulet */
  17.      return (boolean) ((mtmp->data->mflags2 & M2_STALK)
  18.                        && (!mtmp->mflee || u.uhave.amulet));
  19.  }
  20.  

grownups data structure

  1.  static const short grownups[][2] = {
  2.      { PM_CHICKATRICE, PM_COCKATRICE },
  3.      { PM_LITTLE_DOG, PM_DOG },
  4.      { PM_DOG, PM_LARGE_DOG },
  5.      { PM_HELL_HOUND_PUP, PM_HELL_HOUND },
  6.      { PM_WINTER_WOLF_CUB, PM_WINTER_WOLF },
  7.      { PM_KITTEN, PM_HOUSECAT },
  8.      { PM_HOUSECAT, PM_LARGE_CAT },
  9.      { PM_PONY, PM_HORSE },
  10.      { PM_HORSE, PM_WARHORSE },
  11.      { PM_KOBOLD, PM_LARGE_KOBOLD },
  12.      { PM_LARGE_KOBOLD, PM_KOBOLD_LORD },
  13.      { PM_GNOME, PM_GNOME_LORD },
  14.      { PM_GNOME_LORD, PM_GNOME_KING },
  15.      { PM_DWARF, PM_DWARF_LORD },
  16.      { PM_DWARF_LORD, PM_DWARF_KING },
  17.      { PM_MIND_FLAYER, PM_MASTER_MIND_FLAYER },
  18.      { PM_ORC, PM_ORC_CAPTAIN },
  19.      { PM_HILL_ORC, PM_ORC_CAPTAIN },
  20.      { PM_MORDOR_ORC, PM_ORC_CAPTAIN },
  21.      { PM_URUK_HAI, PM_ORC_CAPTAIN },
  22.      { PM_SEWER_RAT, PM_GIANT_RAT },
  23.      { PM_CAVE_SPIDER, PM_GIANT_SPIDER },
  24.      { PM_OGRE, PM_OGRE_LORD },
  25.      { PM_OGRE_LORD, PM_OGRE_KING },
  26.      { PM_ELF, PM_ELF_LORD },
  27.      { PM_WOODLAND_ELF, PM_ELF_LORD },
  28.      { PM_GREEN_ELF, PM_ELF_LORD },
  29.      { PM_GREY_ELF, PM_ELF_LORD },
  30.      { PM_ELF_LORD, PM_ELVENKING },
  31.      { PM_LICH, PM_DEMILICH },
  32.      { PM_DEMILICH, PM_MASTER_LICH },
  33.      { PM_MASTER_LICH, PM_ARCH_LICH },
  34.      { PM_VAMPIRE, PM_VAMPIRE_LORD },
  35.      { PM_BAT, PM_GIANT_BAT },
  36.      { PM_BABY_GRAY_DRAGON, PM_GRAY_DRAGON },
  37.      { PM_BABY_SILVER_DRAGON, PM_SILVER_DRAGON },
  38.  #if 0 /* DEFERRED */
  39.      {PM_BABY_SHIMMERING_DRAGON, PM_SHIMMERING_DRAGON},
  40.  #endif
  41.      { PM_BABY_RED_DRAGON, PM_RED_DRAGON },
  42.      { PM_BABY_WHITE_DRAGON, PM_WHITE_DRAGON },
  43.      { PM_BABY_ORANGE_DRAGON, PM_ORANGE_DRAGON },
  44.      { PM_BABY_BLACK_DRAGON, PM_BLACK_DRAGON },
  45.      { PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON },
  46.      { PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON },
  47.      { PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON },
  48.      { PM_RED_NAGA_HATCHLING, PM_RED_NAGA },
  49.      { PM_BLACK_NAGA_HATCHLING, PM_BLACK_NAGA },
  50.      { PM_GOLDEN_NAGA_HATCHLING, PM_GOLDEN_NAGA },
  51.      { PM_GUARDIAN_NAGA_HATCHLING, PM_GUARDIAN_NAGA },
  52.      { PM_SMALL_MIMIC, PM_LARGE_MIMIC },
  53.      { PM_LARGE_MIMIC, PM_GIANT_MIMIC },
  54.      { PM_BABY_LONG_WORM, PM_LONG_WORM },
  55.      { PM_BABY_PURPLE_WORM, PM_PURPLE_WORM },
  56.      { PM_BABY_CROCODILE, PM_CROCODILE },
  57.      { PM_SOLDIER, PM_SERGEANT },
  58.      { PM_SERGEANT, PM_LIEUTENANT },
  59.      { PM_LIEUTENANT, PM_CAPTAIN },
  60.      { PM_WATCHMAN, PM_WATCH_CAPTAIN },
  61.      { PM_ALIGNED_PRIEST, PM_HIGH_PRIEST },
  62.      { PM_STUDENT, PM_ARCHEOLOGIST },
  63.      { PM_ATTENDANT, PM_HEALER },
  64.      { PM_PAGE, PM_KNIGHT },
  65.      { PM_ACOLYTE, PM_PRIEST },
  66.      { PM_APPRENTICE, PM_WIZARD },
  67.      { PM_MANES, PM_LEMURE },
  68.      { PM_KEYSTONE_KOP, PM_KOP_SERGEANT },
  69.      { PM_KOP_SERGEANT, PM_KOP_LIEUTENANT },
  70.      { PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN },
  71.      { NON_PM, NON_PM }
  72.  };
  73.  

little_to_big

  1.  int
  2.  little_to_big(montype)
  3.  int montype;
  4.  {
  5.      register int i;
  6.  
  7.      for (i = 0; grownups[i][0] >= LOW_PM; i++)
  8.          if (montype == grownups[i][0]) {
  9.              montype = grownups[i][1];
  10.              break;
  11.          }
  12.      return montype;
  13.  }
  14.  

big_to_little

  1.  int
  2.  big_to_little(montype)
  3.  int montype;
  4.  {
  5.      register int i;
  6.  
  7.      for (i = 0; grownups[i][0] >= LOW_PM; i++)
  8.          if (montype == grownups[i][1]) {
  9.              montype = grownups[i][0];
  10.              break;
  11.          }
  12.      return montype;
  13.  }
  14.  

raceptr

  1.  /*
  2.   * Return the permonst ptr for the race of the monster.
  3.   * Returns correct pointer for non-polymorphed and polymorphed
  4.   * player.  It does not return a pointer to player role character.
  5.   */
  6.  const struct permonst *
  7.  raceptr(mtmp)
  8.  struct monst *mtmp;
  9.  {
  10.      if (mtmp == &youmonst && !Upolyd)
  11.          return &mons[urace.malenum];
  12.      else
  13.          return mtmp->data;
  14.  }
  15.  

locomotion

  1.  static const char *levitate[4] = { "float", "Float", "wobble", "Wobble" };
  2.  static const char *flys[4] = { "fly", "Fly", "flutter", "Flutter" };
  3.  static const char *flyl[4] = { "fly", "Fly", "stagger", "Stagger" };
  4.  static const char *slither[4] = { "slither", "Slither", "falter", "Falter" };
  5.  static const char *ooze[4] = { "ooze", "Ooze", "tremble", "Tremble" };
  6.  static const char *immobile[4] = { "wiggle", "Wiggle", "pulsate", "Pulsate" };
  7.  static const char *crawl[4] = { "crawl", "Crawl", "falter", "Falter" };
  8.  
  9.  const char *
  10.  locomotion(ptr, def)
  11.  const struct permonst *ptr;
  12.  const char *def;
  13.  {
  14.      int capitalize = (*def == highc(*def));
  15.  
  16.      return (is_floater(ptr) ? levitate[capitalize]
  17.              : (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize]
  18.                : (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize]
  19.                  : slithy(ptr) ? slither[capitalize]
  20.                    : amorphous(ptr) ? ooze[capitalize]
  21.                      : !ptr->mmove ? immobile[capitalize]
  22.                        : nolimbs(ptr) ? crawl[capitalize]
  23.                          : def);
  24.  }
  25.  

stagger

  1.  const char *
  2.  stagger(ptr, def)
  3.  const struct permonst *ptr;
  4.  const char *def;
  5.  {
  6.      int capitalize = 2 + (*def == highc(*def));
  7.  
  8.      return (is_floater(ptr) ? levitate[capitalize]
  9.              : (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize]
  10.                : (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize]
  11.                  : slithy(ptr) ? slither[capitalize]
  12.                    : amorphous(ptr) ? ooze[capitalize]
  13.                      : !ptr->mmove ? immobile[capitalize]
  14.                        : nolimbs(ptr) ? crawl[capitalize]
  15.                          : def);
  16.  }
  17.  

on_fire

  1.  /* return phrase describing the effect of fire attack on a type of monster */
  2.  const char *
  3.  on_fire(mptr, mattk)
  4.  struct permonst *mptr;
  5.  struct attack *mattk;
  6.  {
  7.      const char *what;
  8.  
  9.      switch (monsndx(mptr)) {
  10.      case PM_FLAMING_SPHERE:
  11.      case PM_FIRE_VORTEX:
  12.      case PM_FIRE_ELEMENTAL:
  13.      case PM_SALAMANDER:
  14.          what = "already on fire";
  15.          break;
  16.      case PM_WATER_ELEMENTAL:
  17.      case PM_FOG_CLOUD:
  18.      case PM_STEAM_VORTEX:
  19.          what = "boiling";
  20.          break;
  21.      case PM_ICE_VORTEX:
  22.      case PM_GLASS_GOLEM:
  23.          what = "melting";
  24.          break;
  25.      case PM_STONE_GOLEM:
  26.      case PM_CLAY_GOLEM:
  27.      case PM_GOLD_GOLEM:
  28.      case PM_AIR_ELEMENTAL:
  29.      case PM_EARTH_ELEMENTAL:
  30.      case PM_DUST_VORTEX:
  31.      case PM_ENERGY_VORTEX:
  32.          what = "heating up";
  33.          break;
  34.      default:
  35.          what = (mattk->aatyp == AT_HUGS) ? "being roasted" : "on fire";
  36.          break;
  37.      }
  38.      return what;
  39.  }
  40.  

olfaction

  1.  /*
  2.   * Returns:
  3.   *      True if monster is presumed to have a sense of smell.
  4.   *      False if monster definitely does not have a sense of smell.
  5.   *
  6.   * Do not base this on presence of a head or nose, since many
  7.   * creatures sense smells other ways (feelers, forked-tongues, etc.)
  8.   * We're assuming all insects can smell at a distance too.
  9.   */
  10.  boolean
  11.  olfaction(mdat)
  12.  struct permonst *mdat;
  13.  {
  14.      if (is_golem(mdat)
  15.          || mdat->mlet == S_EYE /* spheres  */
  16.          || mdat->mlet == S_JELLY || mdat->mlet == S_PUDDING
  17.          || mdat->mlet == S_BLOB || mdat->mlet == S_VORTEX
  18.          || mdat->mlet == S_ELEMENTAL
  19.          || mdat->mlet == S_FUNGUS /* mushrooms and fungi */
  20.          || mdat->mlet == S_LIGHT)
  21.          return FALSE;
  22.      return TRUE;
  23.  }
  24.  
  25.  /*mondata.c*/