Source:NetHack 3.6.0/src/mon.c

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

Below is the full text to mon.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/mon.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	mon.c	$NHDT-Date: 1449269918 2015/12/04 22:58:38 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.199 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  /* If you're using precompiled headers, you don't want this either */
  6.  #ifdef MICROPORT_BUG
  7.  #define MKROOM_H
  8.  #endif
  9.  
  10.  #include "hack.h"
  11.  #include "mfndpos.h"
  12.  #include <ctype.h>
  13.  
  14.  STATIC_VAR boolean vamp_rise_msg;
  15.  
  16.  STATIC_DCL void FDECL(sanity_check_single_mon, (struct monst *, const char *));
  17.  STATIC_DCL boolean FDECL(restrap, (struct monst *));
  18.  STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *));
  19.  STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *));
  20.  STATIC_DCL int NDECL(pick_animal);
  21.  STATIC_DCL void FDECL(kill_eggs, (struct obj *));
  22.  STATIC_DCL int FDECL(pickvampshape, (struct monst *));
  23.  STATIC_DCL boolean FDECL(isspecmon, (struct monst *));
  24.  STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int));
  25.  STATIC_DCL boolean FDECL(validvamp, (struct monst *, int *, int));
  26.  STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int));
  27.  STATIC_DCL struct obj *FDECL(make_corpse, (struct monst *, unsigned));
  28.  STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *));
  29.  STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
  30.  
  31.  #define LEVEL_SPECIFIC_NOCORPSE(mdat) \
  32.      (Is_rogue_level(&u.uz)            \
  33.       || (level.flags.graveyard && is_undead(mdat) && rn2(3)))
  34.  
  35.  #if 0
  36.  /* part of the original warning code which was replaced in 3.3.1 */
  37.  const char *warnings[] = {
  38.      "white", "pink", "red", "ruby", "purple", "black"
  39.  };
  40.  #endif /* 0 */
  41.  
  42.  

sanity_check_single_mon

  1.  void
  2.  sanity_check_single_mon(mtmp, msg)
  3.  struct monst *mtmp;
  4.  const char *msg;
  5.  {
  6.      if (DEADMONSTER(mtmp))
  7.          return;
  8.      if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS])
  9.          impossible("illegal mon data (%s)", msg);
  10.  }
  11.  

mon_sanity_check

  1.  void
  2.  mon_sanity_check()
  3.  {
  4.      int x,y;
  5.      struct monst *mtmp = fmon;
  6.  
  7.      while (mtmp) {
  8.          sanity_check_single_mon(mtmp, "fmon");
  9.          mtmp = mtmp->nmon;
  10.      }
  11.      for (x = 0; x < COLNO; x++)
  12.          for (y = 0; y < ROWNO; y++)
  13.              if ((mtmp = m_at(x,y)) != 0)
  14.                  sanity_check_single_mon(mtmp, "m_at");
  15.  
  16.      mtmp = migrating_mons;
  17.      while (mtmp) {
  18.          sanity_check_single_mon(mtmp, "migr");
  19.          mtmp = mtmp->nmon;
  20.      }
  21.  }
  22.  
  23.  

undead_to_corpse

  1.  /* convert the monster index of an undead to its living counterpart */
  2.  int
  3.  undead_to_corpse(mndx)
  4.  int mndx;
  5.  {
  6.      switch (mndx) {
  7.      case PM_KOBOLD_ZOMBIE:
  8.      case PM_KOBOLD_MUMMY:
  9.          mndx = PM_KOBOLD;
  10.          break;
  11.      case PM_DWARF_ZOMBIE:
  12.      case PM_DWARF_MUMMY:
  13.          mndx = PM_DWARF;
  14.          break;
  15.      case PM_GNOME_ZOMBIE:
  16.      case PM_GNOME_MUMMY:
  17.          mndx = PM_GNOME;
  18.          break;
  19.      case PM_ORC_ZOMBIE:
  20.      case PM_ORC_MUMMY:
  21.          mndx = PM_ORC;
  22.          break;
  23.      case PM_ELF_ZOMBIE:
  24.      case PM_ELF_MUMMY:
  25.          mndx = PM_ELF;
  26.          break;
  27.      case PM_VAMPIRE:
  28.      case PM_VAMPIRE_LORD:
  29.  #if 0 /* DEFERRED */
  30.      case PM_VAMPIRE_MAGE:
  31.  #endif
  32.      case PM_HUMAN_ZOMBIE:
  33.      case PM_HUMAN_MUMMY:
  34.          mndx = PM_HUMAN;
  35.          break;
  36.      case PM_GIANT_ZOMBIE:
  37.      case PM_GIANT_MUMMY:
  38.          mndx = PM_GIANT;
  39.          break;
  40.      case PM_ETTIN_ZOMBIE:
  41.      case PM_ETTIN_MUMMY:
  42.          mndx = PM_ETTIN;
  43.          break;
  44.      default:
  45.          break;
  46.      }
  47.      return mndx;
  48.  }
  49.  

genus

  1.  /* Convert the monster index of some monsters (such as quest guardians)
  2.   * to their generic species type.
  3.   *
  4.   * Return associated character class monster, rather than species
  5.   * if mode is 1.
  6.   */
  7.  int
  8.  genus(mndx, mode)
  9.  int mndx, mode;
  10.  {
  11.      switch (mndx) {
  12.      /* Quest guardians */
  13.      case PM_STUDENT:
  14.          mndx = mode ? PM_ARCHEOLOGIST : PM_HUMAN;
  15.          break;
  16.      case PM_CHIEFTAIN:
  17.          mndx = mode ? PM_BARBARIAN : PM_HUMAN;
  18.          break;
  19.      case PM_NEANDERTHAL:
  20.          mndx = mode ? PM_CAVEMAN : PM_HUMAN;
  21.          break;
  22.      case PM_ATTENDANT:
  23.          mndx = mode ? PM_HEALER : PM_HUMAN;
  24.          break;
  25.      case PM_PAGE:
  26.          mndx = mode ? PM_KNIGHT : PM_HUMAN;
  27.          break;
  28.      case PM_ABBOT:
  29.          mndx = mode ? PM_MONK : PM_HUMAN;
  30.          break;
  31.      case PM_ACOLYTE:
  32.          mndx = mode ? PM_PRIEST : PM_HUMAN;
  33.          break;
  34.      case PM_HUNTER:
  35.          mndx = mode ? PM_RANGER : PM_HUMAN;
  36.          break;
  37.      case PM_THUG:
  38.          mndx = mode ? PM_ROGUE : PM_HUMAN;
  39.          break;
  40.      case PM_ROSHI:
  41.          mndx = mode ? PM_SAMURAI : PM_HUMAN;
  42.          break;
  43.      case PM_GUIDE:
  44.          mndx = mode ? PM_TOURIST : PM_HUMAN;
  45.          break;
  46.      case PM_APPRENTICE:
  47.          mndx = mode ? PM_WIZARD : PM_HUMAN;
  48.          break;
  49.      case PM_WARRIOR:
  50.          mndx = mode ? PM_VALKYRIE : PM_HUMAN;
  51.          break;
  52.      default:
  53.          if (mndx >= LOW_PM && mndx < NUMMONS) {
  54.              struct permonst *ptr = &mons[mndx];
  55.  
  56.              if (is_human(ptr))
  57.                  mndx = PM_HUMAN;
  58.              else if (is_elf(ptr))
  59.                  mndx = PM_ELF;
  60.              else if (is_dwarf(ptr))
  61.                  mndx = PM_DWARF;
  62.              else if (is_gnome(ptr))
  63.                  mndx = PM_GNOME;
  64.              else if (is_orc(ptr))
  65.                  mndx = PM_ORC;
  66.          }
  67.          break;
  68.      }
  69.      return mndx;
  70.  }
  71.  

pm_to_cham

  1.  /* return monster index if chameleon, or NON_PM if not */
  2.  int
  3.  pm_to_cham(mndx)
  4.  int mndx;
  5.  {
  6.      int mcham = NON_PM;
  7.  
  8.      /*
  9.       * As of 3.6.0 we just check M2_SHAPESHIFTER instead of having a
  10.       * big switch statement with hardcoded shapeshifter types here.
  11.       */
  12.      if (mndx >= LOW_PM && is_shapeshifter(&mons[mndx]))
  13.          mcham = mndx;
  14.      return mcham;
  15.  }
  16.  

make_corpse

  1.  /* for deciding whether corpse will carry along full monster data */
  2.  #define KEEPTRAITS(mon)                                                 \
  3.      ((mon)->isshk || (mon)->mtame || unique_corpstat((mon)->data)       \
  4.       || is_reviver((mon)->data)                                         \
  5.          /* normally quest leader will be unique, */                     \
  6.          /* but he or she might have been polymorphed  */                \
  7.       || (mon)->m_id == quest_status.leader_m_id                         \
  8.          /* special cancellation handling for these */                   \
  9.       || (dmgtype((mon)->data, AD_SEDU) || dmgtype((mon)->data, AD_SSEX)))
  10.  
  11.  /* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
  12.   * leave corpses.  Monsters which leave "special" corpses should have
  13.   * G_NOCORPSE set in order to prevent wishing for one, finding tins of one,
  14.   * etc....
  15.   */
  16.  STATIC_OVL struct obj *
  17.  make_corpse(mtmp, corpseflags)
  18.  register struct monst *mtmp;
  19.  unsigned corpseflags;
  20.  {
  21.      register struct permonst *mdat = mtmp->data;
  22.      int num;
  23.      struct obj *obj = (struct obj *) 0;
  24.      struct obj *otmp = (struct obj *) 0;
  25.      int x = mtmp->mx, y = mtmp->my;
  26.      int mndx = monsndx(mdat);
  27.      unsigned corpstatflags = corpseflags;
  28.      boolean burythem = ((corpstatflags & CORPSTAT_BURIED) != 0);
  29.  
  30.      switch (mndx) {
  31.      case PM_GRAY_DRAGON:
  32.      case PM_SILVER_DRAGON:
  33.  #if 0 /* DEFERRED */
  34.      case PM_SHIMMERING_DRAGON:
  35.  #endif
  36.      case PM_RED_DRAGON:
  37.      case PM_ORANGE_DRAGON:
  38.      case PM_WHITE_DRAGON:
  39.      case PM_BLACK_DRAGON:
  40.      case PM_BLUE_DRAGON:
  41.      case PM_GREEN_DRAGON:
  42.      case PM_YELLOW_DRAGON:
  43.          /* Make dragon scales.  This assumes that the order of the
  44.             dragons is the same as the order of the scales. */
  45.          if (!rn2(mtmp->mrevived ? 20 : 3)) {
  46.              num = GRAY_DRAGON_SCALES + monsndx(mdat) - PM_GRAY_DRAGON;
  47.              obj = mksobj_at(num, x, y, FALSE, FALSE);
  48.              obj->spe = 0;
  49.              obj->cursed = obj->blessed = FALSE;
  50.          }
  51.          goto default_1;
  52.      case PM_WHITE_UNICORN:
  53.      case PM_GRAY_UNICORN:
  54.      case PM_BLACK_UNICORN:
  55.          if (mtmp->mrevived && rn2(2)) {
  56.              if (canseemon(mtmp))
  57.                  pline("%s recently regrown horn crumbles to dust.",
  58.                        s_suffix(Monnam(mtmp)));
  59.          } else {
  60.              obj = mksobj_at(UNICORN_HORN, x, y, TRUE, FALSE);
  61.              if (obj && mtmp->mrevived)
  62.                  obj->degraded_horn = 1;
  63.          }
  64.          goto default_1;
  65.      case PM_LONG_WORM:
  66.          (void) mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE);
  67.          goto default_1;
  68.      case PM_VAMPIRE:
  69.      case PM_VAMPIRE_LORD:
  70.          /* include mtmp in the mkcorpstat() call */
  71.          num = undead_to_corpse(mndx);
  72.          corpstatflags |= CORPSTAT_INIT;
  73.          obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags);
  74.          obj->age -= 100; /* this is an *OLD* corpse */
  75.          break;
  76.      case PM_KOBOLD_MUMMY:
  77.      case PM_DWARF_MUMMY:
  78.      case PM_GNOME_MUMMY:
  79.      case PM_ORC_MUMMY:
  80.      case PM_ELF_MUMMY:
  81.      case PM_HUMAN_MUMMY:
  82.      case PM_GIANT_MUMMY:
  83.      case PM_ETTIN_MUMMY:
  84.      case PM_KOBOLD_ZOMBIE:
  85.      case PM_DWARF_ZOMBIE:
  86.      case PM_GNOME_ZOMBIE:
  87.      case PM_ORC_ZOMBIE:
  88.      case PM_ELF_ZOMBIE:
  89.      case PM_HUMAN_ZOMBIE:
  90.      case PM_GIANT_ZOMBIE:
  91.      case PM_ETTIN_ZOMBIE:
  92.          num = undead_to_corpse(mndx);
  93.          corpstatflags |= CORPSTAT_INIT;
  94.          obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags);
  95.          obj->age -= 100; /* this is an *OLD* corpse */
  96.          break;
  97.      case PM_IRON_GOLEM:
  98.          num = d(2, 6);
  99.          while (num--)
  100.              obj = mksobj_at(IRON_CHAIN, x, y, TRUE, FALSE);
  101.          free_mname(mtmp); /* don't christen obj */
  102.          break;
  103.      case PM_GLASS_GOLEM:
  104.          num = d(2, 4); /* very low chance of creating all glass gems */
  105.          while (num--)
  106.              obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE, FALSE);
  107.          free_mname(mtmp);
  108.          break;
  109.      case PM_CLAY_GOLEM:
  110.          obj = mksobj_at(ROCK, x, y, FALSE, FALSE);
  111.          obj->quan = (long) (rn2(20) + 50);
  112.          obj->owt = weight(obj);
  113.          free_mname(mtmp);
  114.          break;
  115.      case PM_STONE_GOLEM:
  116.          corpstatflags &= ~CORPSTAT_INIT;
  117.          obj =
  118.              mkcorpstat(STATUE, (struct monst *) 0, mdat, x, y, corpstatflags);
  119.          break;
  120.      case PM_WOOD_GOLEM:
  121.          num = d(2, 4);
  122.          while (num--) {
  123.              obj = mksobj_at(QUARTERSTAFF, x, y, TRUE, FALSE);
  124.          }
  125.          free_mname(mtmp);
  126.          break;
  127.      case PM_LEATHER_GOLEM:
  128.          num = d(2, 4);
  129.          while (num--)
  130.              obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE, FALSE);
  131.          free_mname(mtmp);
  132.          break;
  133.      case PM_GOLD_GOLEM:
  134.          /* Good luck gives more coins */
  135.          obj = mkgold((long) (200 - rnl(101)), x, y);
  136.          free_mname(mtmp);
  137.          break;
  138.      case PM_PAPER_GOLEM:
  139.          num = rnd(4);
  140.          while (num--)
  141.              obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE);
  142.          free_mname(mtmp);
  143.          break;
  144.      /* expired puddings will congeal into a large blob;
  145.         like dragons, relies on the order remaining consistent */
  146.      case PM_GRAY_OOZE:
  147.      case PM_BROWN_PUDDING:
  148.      case PM_GREEN_SLIME:
  149.      case PM_BLACK_PUDDING:
  150.          /* we have to do this here because most other places
  151.             expect there to be an object coming back; not this one */
  152.          obj = mksobj_at(GLOB_OF_BLACK_PUDDING - (PM_BLACK_PUDDING - mndx),
  153.                          x, y, TRUE, FALSE);
  154.  
  155.          while (obj && (otmp = obj_nexto(obj)) != (struct obj *) 0) {
  156.              pudding_merge_message(obj, otmp);
  157.              obj = obj_meld(&obj, &otmp);
  158.          }
  159.          free_mname(mtmp);
  160.          return obj;
  161.          break;
  162.      default_1:
  163.      default:
  164.          if (mvitals[mndx].mvflags & G_NOCORPSE) {
  165.              return (struct obj *) 0;
  166.          } else {
  167.              corpstatflags |= CORPSTAT_INIT;
  168.              /* preserve the unique traits of some creatures */
  169.              obj = mkcorpstat(CORPSE, KEEPTRAITS(mtmp) ? mtmp : 0,
  170.                               mdat, x, y, corpstatflags);
  171.              if (burythem) {
  172.                  boolean dealloc;
  173.  
  174.                  (void) bury_an_obj(obj, &dealloc);
  175.                  newsym(x, y);
  176.                  return dealloc ? (struct obj *) 0 : obj;
  177.              }
  178.          }
  179.          break;
  180.      }
  181.      /* All special cases should precede the G_NOCORPSE check */
  182.  
  183.      if (!obj) return NULL;
  184.  
  185.      /* if polymorph or undead turning has killed this monster,
  186.         prevent the same attack beam from hitting its corpse */
  187.      if (context.bypasses)
  188.          bypass_obj(obj);
  189.  
  190.      if (has_mname(mtmp))
  191.          obj = oname(obj, MNAME(mtmp));
  192.  
  193.      /*  Avoid "It was hidden under a green mold corpse!"
  194.       *  during Blind combat. An unseen monster referred to as "it"
  195.       *  could be killed and leave a corpse.  If a hider then hid
  196.       *  underneath it, you could be told the corpse type of a
  197.       *  monster that you never knew was there without this.
  198.       *  The code in hitmu() substitutes the word "something"
  199.       *  if the corpses obj->dknown is 0.
  200.       */
  201.      if (Blind && !sensemon(mtmp))
  202.          obj->dknown = 0;
  203.  
  204.      stackobj(obj);
  205.      newsym(x, y);
  206.      return obj;
  207.  }
  208.  

minliquid

  1.  /* check mtmp and water/lava for compatibility, 0 (survived), 1 (died) */
  2.  int
  3.  minliquid(mtmp)
  4.  register struct monst *mtmp;
  5.  {
  6.      boolean inpool, inlava, infountain;
  7.  
  8.      /* [what about ceiling clingers?] */
  9.      inpool = (is_pool(mtmp->mx, mtmp->my)
  10.                && !(is_flyer(mtmp->data) || is_floater(mtmp->data)));
  11.      inlava = (is_lava(mtmp->mx, mtmp->my)
  12.                && !(is_flyer(mtmp->data) || is_floater(mtmp->data)));
  13.      infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
  14.  
  15.      /* Flying and levitation keeps our steed out of the liquid */
  16.      /* (but not water-walking or swimming) */
  17.      if (mtmp == u.usteed && (Flying || Levitation))
  18.          return 0;
  19.  
  20.      /* Gremlin multiplying won't go on forever since the hit points
  21.       * keep going down, and when it gets to 1 hit point the clone
  22.       * function will fail.
  23.       */
  24.      if (mtmp->data == &mons[PM_GREMLIN] && (inpool || infountain) && rn2(3)) {
  25.          if (split_mon(mtmp, (struct monst *) 0))
  26.              dryup(mtmp->mx, mtmp->my, FALSE);
  27.          if (inpool)
  28.              water_damage_chain(mtmp->minvent, FALSE);
  29.          return 0;
  30.      } else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) {
  31.          int dam = d(2, 6);
  32.  
  33.          if (cansee(mtmp->mx, mtmp->my))
  34.              pline("%s rusts.", Monnam(mtmp));
  35.          mtmp->mhp -= dam;
  36.          if (mtmp->mhpmax > dam)
  37.              mtmp->mhpmax -= dam;
  38.          if (mtmp->mhp < 1) {
  39.              mondead(mtmp);
  40.              if (mtmp->mhp < 1)
  41.                  return 1;
  42.          }
  43.          water_damage_chain(mtmp->minvent, FALSE);
  44.          return 0;
  45.      }
  46.  
  47.      if (inlava) {
  48.          /*
  49.           * Lava effects much as water effects. Lava likers are able to
  50.           * protect their stuff. Fire resistant monsters can only protect
  51.           * themselves  --ALI
  52.           */
  53.          if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
  54.              if (!resists_fire(mtmp)) {
  55.                  if (cansee(mtmp->mx, mtmp->my))
  56.                      pline("%s %s.", Monnam(mtmp),
  57.                            mtmp->data == &mons[PM_WATER_ELEMENTAL]
  58.                                ? "boils away"
  59.                                : "burns to a crisp");
  60.                  mondead(mtmp);
  61.              } else {
  62.                  if (--mtmp->mhp < 1) {
  63.                      if (cansee(mtmp->mx, mtmp->my))
  64.                          pline("%s surrenders to the fire.", Monnam(mtmp));
  65.                      mondead(mtmp);
  66.                  } else if (cansee(mtmp->mx, mtmp->my))
  67.                      pline("%s burns slightly.", Monnam(mtmp));
  68.              }
  69.              if (mtmp->mhp > 0) {
  70.                  (void) fire_damage_chain(mtmp->minvent, FALSE, FALSE,
  71.                                           mtmp->mx, mtmp->my);
  72.                  (void) rloc(mtmp, FALSE);
  73.                  return 0;
  74.              }
  75.              return 1;
  76.          }
  77.      } else if (inpool) {
  78.          /* Most monsters drown in pools.  flooreffects() will take care of
  79.           * water damage to dead monsters' inventory, but survivors need to
  80.           * be handled here.  Swimmers are able to protect their stuff...
  81.           */
  82.          if (!is_clinger(mtmp->data) && !is_swimmer(mtmp->data)
  83.              && !amphibious(mtmp->data)) {
  84.              if (cansee(mtmp->mx, mtmp->my)) {
  85.                  pline("%s drowns.", Monnam(mtmp));
  86.              }
  87.              if (u.ustuck && u.uswallow && u.ustuck == mtmp) {
  88.                  /* This can happen after a purple worm plucks you off a
  89.                  flying steed while you are over water. */
  90.                  pline("%s sinks as water rushes in and flushes you out.",
  91.                        Monnam(mtmp));
  92.              }
  93.              mondead(mtmp);
  94.              if (mtmp->mhp > 0) {
  95.                  water_damage_chain(mtmp->minvent, FALSE);
  96.                  (void) rloc(mtmp, FALSE);
  97.                  return 0;
  98.              }
  99.              return 1;
  100.          }
  101.      } else {
  102.          /* but eels have a difficult time outside */
  103.          if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) {
  104.              /* as mhp gets lower, the rate of further loss slows down */
  105.              if (mtmp->mhp > 1 && rn2(mtmp->mhp) > rn2(8))
  106.                  mtmp->mhp--;
  107.              monflee(mtmp, 2, FALSE, FALSE);
  108.          }
  109.      }
  110.      return 0;
  111.  }
  112.  

mcalcmove

  1.  int
  2.  mcalcmove(mon)
  3.  struct monst *mon;
  4.  {
  5.      int mmove = mon->data->mmove;
  6.  
  7.      /* Note: MSLOW's `+ 1' prevents slowed speed 1 getting reduced to 0;
  8.       *       MFAST's `+ 2' prevents hasted speed 1 from becoming a no-op;
  9.       *       both adjustments have negligible effect on higher speeds.
  10.       */
  11.      if (mon->mspeed == MSLOW)
  12.          mmove = (2 * mmove + 1) / 3;
  13.      else if (mon->mspeed == MFAST)
  14.          mmove = (4 * mmove + 2) / 3;
  15.  
  16.      if (mon == u.usteed) {
  17.          if (u.ugallop && context.mv) {
  18.              /* average movement is 1.50 times normal */
  19.              mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
  20.          }
  21.      } else if (mmove) {
  22.          /* vary movement points allocated to slightly reduce predictability;
  23.             random increment (avg +2) exceeds random decrement (avg +1) by
  24.             a small amount; normal speed monsters will occasionally get an
  25.             extra move and slow ones won't be quite as slow */
  26.          mmove += rn2(5) - rn2(3); /* + 0..4 - 0..2, average net +1 */
  27.          if (mmove < 1)
  28.              mmove = 1;
  29.      }
  30.  
  31.      return mmove;
  32.  }
  33.  

mcalcdistress

  1.  /* actions that happen once per ``turn'', regardless of each
  2.     individual monster's metabolism; some of these might need to
  3.     be reclassified to occur more in proportion with movement rate */
  4.  void
  5.  mcalcdistress()
  6.  {
  7.      struct monst *mtmp;
  8.  
  9.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  10.          if (DEADMONSTER(mtmp))
  11.              continue;
  12.  
  13.          /* must check non-moving monsters once/turn in case
  14.           * they managed to end up in liquid */
  15.          if (mtmp->data->mmove == 0) {
  16.              if (vision_full_recalc)
  17.                  vision_recalc(0);
  18.              if (minliquid(mtmp))
  19.                  continue;
  20.          }
  21.  
  22.          /* regenerate hit points */
  23.          mon_regen(mtmp, FALSE);
  24.  
  25.          /* possibly polymorph shapechangers and lycanthropes */
  26.          if (mtmp->cham >= LOW_PM) {
  27.              if (is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
  28.                  decide_to_shapeshift(mtmp, 0);
  29.              else if (!rn2(6))
  30.                  (void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE);
  31.          }
  32.          were_change(mtmp);
  33.  
  34.          /* gradually time out temporary problems */
  35.          if (mtmp->mblinded && !--mtmp->mblinded)
  36.              mtmp->mcansee = 1;
  37.          if (mtmp->mfrozen && !--mtmp->mfrozen)
  38.              mtmp->mcanmove = 1;
  39.          if (mtmp->mfleetim && !--mtmp->mfleetim)
  40.              mtmp->mflee = 0;
  41.  
  42.          /* FIXME: mtmp->mlstmv ought to be updated here */
  43.      }
  44.  }
  45.  

movemon

  1.  int
  2.  movemon()
  3.  {
  4.      register struct monst *mtmp, *nmtmp;
  5.      register boolean somebody_can_move = FALSE;
  6.  
  7.      /*
  8.       * Some of you may remember the former assertion here that
  9.       * because of deaths and other actions, a simple one-pass
  10.       * algorithm wasn't possible for movemon.  Deaths are no longer
  11.       * removed to the separate list fdmon; they are simply left in
  12.       * the chain with hit points <= 0, to be cleaned up at the end
  13.       * of the pass.
  14.       *
  15.       * The only other actions which cause monsters to be removed from
  16.       * the chain are level migrations and losedogs().  I believe losedogs()
  17.       * is a cleanup routine not associated with monster movements, and
  18.       * monsters can only affect level migrations on themselves, not others
  19.       * (hence the fetching of nmon before moving the monster).  Currently,
  20.       * monsters can jump into traps, read cursed scrolls of teleportation,
  21.       * and drink cursed potions of raise level to change levels.  These are
  22.       * all reflexive at this point.  Should one monster be able to level
  23.       * teleport another, this scheme would have problems.
  24.       */
  25.  
  26.      for (mtmp = fmon; mtmp; mtmp = nmtmp) {
  27.          /* end monster movement early if hero is flagged to leave the level */
  28.          if (u.utotype
  29.  #ifdef SAFERHANGUP
  30.              /* or if the program has lost contact with the user */
  31.              || program_state.done_hup
  32.  #endif
  33.              ) {
  34.              somebody_can_move = FALSE;
  35.              break;
  36.          }
  37.          nmtmp = mtmp->nmon;
  38.          /* one dead monster needs to perform a move after death:
  39.             vault guard whose temporary corridor is still on the map */
  40.          if (mtmp->isgd && !mtmp->mx && mtmp->mhp <= 0)
  41.              (void) gd_move(mtmp);
  42.          if (DEADMONSTER(mtmp))
  43.              continue;
  44.  
  45.          /* Find a monster that we have not treated yet. */
  46.          if (mtmp->movement < NORMAL_SPEED)
  47.              continue;
  48.  
  49.          mtmp->movement -= NORMAL_SPEED;
  50.          if (mtmp->movement >= NORMAL_SPEED)
  51.              somebody_can_move = TRUE;
  52.  
  53.          if (vision_full_recalc)
  54.              vision_recalc(0); /* vision! */
  55.  
  56.          /* reset obj bypasses before next monster moves */
  57.          if (context.bypasses)
  58.              clear_bypasses();
  59.          clear_splitobjs();
  60.          if (minliquid(mtmp))
  61.              continue;
  62.  
  63.          if (is_hider(mtmp->data)) {
  64.              /* unwatched mimics and piercers may hide again  [MRS] */
  65.              if (restrap(mtmp))
  66.                  continue;
  67.              if (mtmp->m_ap_type == M_AP_FURNITURE
  68.                  || mtmp->m_ap_type == M_AP_OBJECT)
  69.                  continue;
  70.              if (mtmp->mundetected)
  71.                  continue;
  72.          } else if (mtmp->data->mlet == S_EEL && !mtmp->mundetected
  73.                     && (mtmp->mflee || distu(mtmp->mx, mtmp->my) > 2)
  74.                     && !canseemon(mtmp) && !rn2(4)) {
  75.              /* some eels end up stuck in isolated pools, where they
  76.                 can't--or at least won't--move, so they never reach
  77.                 their post-move chance to re-hide */
  78.              if (hideunder(mtmp))
  79.                  continue;
  80.          }
  81.  
  82.          /* continue if the monster died fighting */
  83.          if (Conflict && !mtmp->iswiz && mtmp->mcansee) {
  84.              /* Note:
  85.               *  Conflict does not take effect in the first round.
  86.               *  Therefore, A monster when stepping into the area will
  87.               *  get to swing at you.
  88.               *
  89.               *  The call to fightm() must be _last_.  The monster might
  90.               *  have died if it returns 1.
  91.               */
  92.              if (couldsee(mtmp->mx, mtmp->my)
  93.                  && (distu(mtmp->mx, mtmp->my) <= BOLT_LIM * BOLT_LIM)
  94.                  && fightm(mtmp))
  95.                  continue; /* mon might have died */
  96.          }
  97.          if (dochugw(mtmp)) /* otherwise just move the monster */
  98.              continue;
  99.      }
  100.  
  101.      if (any_light_source())
  102.          vision_full_recalc = 1; /* in case a mon moved with a light source */
  103.      /* reset obj bypasses after last monster has moved */
  104.      if (context.bypasses)
  105.          clear_bypasses();
  106.      clear_splitobjs();
  107.      /* remove dead monsters; dead vault guard will be left at <0,0>
  108.         if temporary corridor out of vault hasn't been removed yet */
  109.      dmonsfree();
  110.  
  111.      /* a monster may have levteleported player -dlc */
  112.      if (u.utotype) {
  113.          deferred_goto();
  114.          /* changed levels, so these monsters are dormant */
  115.          somebody_can_move = FALSE;
  116.      }
  117.  
  118.      return somebody_can_move;
  119.  }
  120.  

meatmetal

  1.  #define mstoning(obj)                                       \
  2.      (ofood(obj) && (touch_petrifies(&mons[(obj)->corpsenm]) \
  3.                      || (obj)->corpsenm == PM_MEDUSA))
  4.  
  5.  /*
  6.   * Maybe eat a metallic object (not just gold).
  7.   * Return value: 0 => nothing happened, 1 => monster ate something,
  8.   * 2 => monster died (it must have grown into a genocided form, but
  9.   * that can't happen at present because nothing which eats objects
  10.   * has young and old forms).
  11.   */
  12.  int
  13.  meatmetal(mtmp)
  14.  register struct monst *mtmp;
  15.  {
  16.      register struct obj *otmp;
  17.      struct permonst *ptr;
  18.      int poly, grow, heal, mstone;
  19.  
  20.      /* If a pet, eating is handled separately, in dog.c */
  21.      if (mtmp->mtame)
  22.          return 0;
  23.  
  24.      /* Eats topmost metal object if it is there */
  25.      for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp;
  26.           otmp = otmp->nexthere) {
  27.          /* Don't eat indigestible/choking/inappropriate objects */
  28.          if ((mtmp->data == &mons[PM_RUST_MONSTER] && !is_rustprone(otmp))
  29.              || (otmp->otyp == AMULET_OF_STRANGULATION)
  30.              || (otmp->otyp == RIN_SLOW_DIGESTION))
  31.              continue;
  32.          if (is_metallic(otmp) && !obj_resists(otmp, 5, 95)
  33.              && touch_artifact(otmp, mtmp)) {
  34.              if (mtmp->data == &mons[PM_RUST_MONSTER] && otmp->oerodeproof) {
  35.                  if (canseemon(mtmp) && flags.verbose) {
  36.                      pline("%s eats %s!", Monnam(mtmp),
  37.                            distant_name(otmp, doname));
  38.                  }
  39.                  /* The object's rustproofing is gone now */
  40.                  otmp->oerodeproof = 0;
  41.                  mtmp->mstun = 1;
  42.                  if (canseemon(mtmp) && flags.verbose) {
  43.                      pline("%s spits %s out in disgust!", Monnam(mtmp),
  44.                            distant_name(otmp, doname));
  45.                  }
  46.              } else {
  47.                  if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
  48.                      pline("%s eats %s!", Monnam(mtmp),
  49.                            distant_name(otmp, doname));
  50.                  else if (flags.verbose)
  51.                      You_hear("a crunching sound.");
  52.                  mtmp->meating = otmp->owt / 2 + 1;
  53.                  /* Heal up to the object's weight in hp */
  54.                  if (mtmp->mhp < mtmp->mhpmax) {
  55.                      mtmp->mhp += objects[otmp->otyp].oc_weight;
  56.                      if (mtmp->mhp > mtmp->mhpmax)
  57.                          mtmp->mhp = mtmp->mhpmax;
  58.                  }
  59.                  if (otmp == uball) {
  60.                      unpunish();
  61.                      delobj(otmp);
  62.                  } else if (otmp == uchain) {
  63.                      unpunish(); /* frees uchain */
  64.                  } else {
  65.                      poly = polyfodder(otmp);
  66.                      grow = mlevelgain(otmp);
  67.                      heal = mhealup(otmp);
  68.                      mstone = mstoning(otmp);
  69.                      delobj(otmp);
  70.                      ptr = mtmp->data;
  71.                      if (poly) {
  72.                          if (newcham(mtmp, (struct permonst *) 0, FALSE, FALSE))
  73.                              ptr = mtmp->data;
  74.                      } else if (grow) {
  75.                          ptr = grow_up(mtmp, (struct monst *) 0);
  76.                      } else if (mstone) {
  77.                          if (poly_when_stoned(ptr)) {
  78.                              mon_to_stone(mtmp);
  79.                              ptr = mtmp->data;
  80.                          } else if (!resists_ston(mtmp)) {
  81.                              if (canseemon(mtmp))
  82.                                  pline("%s turns to stone!", Monnam(mtmp));
  83.                              monstone(mtmp);
  84.                              ptr = (struct permonst *) 0;
  85.                          }
  86.                      } else if (heal) {
  87.                          mtmp->mhp = mtmp->mhpmax;
  88.                      }
  89.                      if (!ptr)
  90.                          return 2; /* it died */
  91.                  }
  92.                  /* Left behind a pile? */
  93.                  if (rnd(25) < 3)
  94.                      (void) mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE, FALSE);
  95.                  newsym(mtmp->mx, mtmp->my);
  96.                  return 1;
  97.              }
  98.          }
  99.      }
  100.      return 0;
  101.  }
  102.  

meatobj

  1.  /* monster eats a pile of objects */
  2.  int
  3.  meatobj(mtmp) /* for gelatinous cubes */
  4.  struct monst *mtmp;
  5.  {
  6.      register struct obj *otmp, *otmp2;
  7.      struct permonst *ptr, *original_ptr = mtmp->data;
  8.      int poly, grow, heal, count = 0, ecount = 0;
  9.      char buf[BUFSZ];
  10.  
  11.      buf[0] = '\0';
  12.      /* If a pet, eating is handled separately, in dog.c */
  13.      if (mtmp->mtame)
  14.          return 0;
  15.  
  16.      /* eat organic objects, including cloth and wood, if present;
  17.         engulf others, except huge rocks and metal attached to player
  18.         [despite comment at top, doesn't assume that eater is a g.cube] */
  19.      for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
  20.          otmp2 = otmp->nexthere;
  21.  
  22.          /* touch sensitive items */
  23.          if (otmp->otyp == CORPSE && is_rider(&mons[otmp->corpsenm])) {
  24.              /* Rider corpse isn't just inedible; can't engulf it either */
  25.              (void) revive_corpse(otmp);
  26.  
  27.          /* untouchable (or inaccessible) items */
  28.          } else if ((otmp->otyp == CORPSE
  29.                      && touch_petrifies(&mons[otmp->corpsenm])
  30.                      && !resists_ston(mtmp))
  31.                     /* don't engulf boulders and statues or ball&chain */
  32.                     || otmp->oclass == ROCK_CLASS
  33.                     || otmp == uball || otmp == uchain) {
  34.              /* do nothing--neither eaten nor engulfed */
  35.              continue;
  36.  
  37.          /* inedible items -- engulf these */
  38.          } else if (!is_organic(otmp) || obj_resists(otmp, 5, 95)
  39.                     || !touch_artifact(otmp, mtmp)
  40.                     /* redundant due to non-organic composition but
  41.                        included for emphasis */
  42.                     || (otmp->otyp == AMULET_OF_STRANGULATION
  43.                         || otmp->otyp == RIN_SLOW_DIGESTION)
  44.                     /* cockatrice corpses handled above; this
  45.                        touch_petrifies() check catches eggs */
  46.                     || ((otmp->otyp == CORPSE || otmp->otyp == EGG)
  47.                         && ((touch_petrifies(&mons[otmp->corpsenm])
  48.                              && !resists_ston(mtmp))
  49.                             || (otmp->corpsenm == PM_GREEN_SLIME
  50.                                 && !slimeproof(mtmp->data))))) {
  51.              /* engulf */
  52.              ++ecount;
  53.              if (ecount == 1)
  54.                  Sprintf(buf, "%s engulfs %s.", Monnam(mtmp),
  55.                          distant_name(otmp, doname));
  56.              else if (ecount == 2)
  57.                  Sprintf(buf, "%s engulfs several objects.", Monnam(mtmp));
  58.              obj_extract_self(otmp);
  59.              (void) mpickobj(mtmp, otmp); /* slurp */
  60.  
  61.          /* lastly, edible items; yum! */
  62.          } else {
  63.              /* devour */
  64.              ++count;
  65.              if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
  66.                  pline("%s eats %s!", Monnam(mtmp),
  67.                        distant_name(otmp, doname));
  68.              else if (flags.verbose)
  69.                  You_hear("a slurping sound.");
  70.              /* Heal up to the object's weight in hp */
  71.              if (mtmp->mhp < mtmp->mhpmax) {
  72.                  mtmp->mhp += objects[otmp->otyp].oc_weight;
  73.                  if (mtmp->mhp > mtmp->mhpmax)
  74.                      mtmp->mhp = mtmp->mhpmax;
  75.              }
  76.              if (Has_contents(otmp)) {
  77.                  register struct obj *otmp3;
  78.  
  79.                  /* contents of eaten containers become engulfed; this
  80.                     is arbitrary, but otherwise g.cubes are too powerful */
  81.                  while ((otmp3 = otmp->cobj) != 0) {
  82.                      obj_extract_self(otmp3);
  83.                      if (otmp->otyp == ICE_BOX && otmp3->otyp == CORPSE) {
  84.                          otmp3->age = monstermoves - otmp3->age;
  85.                          start_corpse_timeout(otmp3);
  86.                      }
  87.                      (void) mpickobj(mtmp, otmp3);
  88.                  }
  89.              }
  90.              poly = polyfodder(otmp);
  91.              grow = mlevelgain(otmp);
  92.              heal = mhealup(otmp);
  93.              delobj(otmp); /* munch */
  94.              ptr = mtmp->data;
  95.              if (poly) {
  96.                  if (newcham(mtmp, (struct permonst *) 0, FALSE, FALSE))
  97.                      ptr = mtmp->data;
  98.              } else if (grow) {
  99.                  ptr = grow_up(mtmp, (struct monst *) 0);
  100.              } else if (heal) {
  101.                  mtmp->mhp = mtmp->mhpmax;
  102.              }
  103.              /* in case it polymorphed or died */
  104.              if (ptr != original_ptr)
  105.                  return !ptr ? 2 : 1;
  106.          }
  107.  
  108.          /* Engulf & devour is instant, so don't set meating */
  109.          if (mtmp->minvis)
  110.              newsym(mtmp->mx, mtmp->my);
  111.      }
  112.  
  113.      if (ecount > 0) {
  114.          if (cansee(mtmp->mx, mtmp->my) && flags.verbose && buf[0])
  115.              pline1(buf);
  116.          else if (flags.verbose)
  117.              You_hear("%s slurping sound%s.",
  118.                       (ecount == 1) ? "a" : "several", plur(ecount));
  119.      }
  120.      return (count > 0 || ecount > 0) ? 1 : 0;
  121.  }
  122.  

mpickgold

  1.  void
  2.  mpickgold(mtmp)
  3.  register struct monst *mtmp;
  4.  {
  5.      register struct obj *gold;
  6.      int mat_idx;
  7.  
  8.      if ((gold = g_at(mtmp->mx, mtmp->my)) != 0) {
  9.          mat_idx = objects[gold->otyp].oc_material;
  10.          obj_extract_self(gold);
  11.          add_to_minv(mtmp, gold);
  12.          if (cansee(mtmp->mx, mtmp->my)) {
  13.              if (flags.verbose && !mtmp->isgd)
  14.                  pline("%s picks up some %s.", Monnam(mtmp),
  15.                        mat_idx == GOLD ? "gold" : "money");
  16.              newsym(mtmp->mx, mtmp->my);
  17.          }
  18.      }
  19.  }
  20.  

mpickstuff

  1.  boolean
  2.  mpickstuff(mtmp, str)
  3.  register struct monst *mtmp;
  4.  register const char *str;
  5.  {
  6.      register struct obj *otmp, *otmp2, *otmp3;
  7.      int carryamt = 0;
  8.  
  9.      /* prevent shopkeepers from leaving the door of their shop */
  10.      if (mtmp->isshk && inhishop(mtmp))
  11.          return FALSE;
  12.  
  13.      for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
  14.          otmp2 = otmp->nexthere;
  15.          /* Nymphs take everything.  Most monsters don't pick up corpses. */
  16.          if (!str ? searches_for_item(mtmp, otmp)
  17.                   : !!(index(str, otmp->oclass))) {
  18.              if (otmp->otyp == CORPSE && mtmp->data->mlet != S_NYMPH
  19.                  /* let a handful of corpse types thru to can_carry() */
  20.                  && !touch_petrifies(&mons[otmp->corpsenm])
  21.                  && otmp->corpsenm != PM_LIZARD
  22.                  && !acidic(&mons[otmp->corpsenm]))
  23.                  continue;
  24.              if (!touch_artifact(otmp, mtmp))
  25.                  continue;
  26.              carryamt = can_carry(mtmp, otmp);
  27.              if (carryamt == 0)
  28.                  continue;
  29.              if (is_pool(mtmp->mx, mtmp->my))
  30.                  continue;
  31.              /* handle cases where the critter can only get some */
  32.              otmp3 = otmp;
  33.              if (carryamt != otmp->quan) {
  34.                  otmp3 = splitobj(otmp, carryamt);
  35.              }
  36.              if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
  37.                  pline("%s picks up %s.", Monnam(mtmp),
  38.                        (distu(mtmp->mx, mtmp->my) <= 5)
  39.                            ? doname(otmp3)
  40.                            : distant_name(otmp3, doname));
  41.              obj_extract_self(otmp3);      /* remove from floor */
  42.              (void) mpickobj(mtmp, otmp3); /* may merge and free otmp3 */
  43.              m_dowear(mtmp, FALSE);
  44.              newsym(mtmp->mx, mtmp->my);
  45.              return TRUE; /* pick only one object */
  46.          }
  47.      }
  48.      return FALSE;
  49.  }
  50.  

curr_mon_load

  1.  int
  2.  curr_mon_load(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      int curload = 0;
  6.      struct obj *obj;
  7.  
  8.      for (obj = mtmp->minvent; obj; obj = obj->nobj) {
  9.          if (obj->otyp != BOULDER || !throws_rocks(mtmp->data))
  10.              curload += obj->owt;
  11.      }
  12.  
  13.      return curload;
  14.  }
  15.  

max_mon_load

  1.  int
  2.  max_mon_load(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      long maxload;
  6.  
  7.      /* Base monster carrying capacity is equal to human maximum
  8.       * carrying capacity, or half human maximum if not strong.
  9.       * (for a polymorphed player, the value used would be the
  10.       * non-polymorphed carrying capacity instead of max/half max).
  11.       * This is then modified by the ratio between the monster weights
  12.       * and human weights.  Corpseless monsters are given a capacity
  13.       * proportional to their size instead of weight.
  14.       */
  15.      if (!mtmp->data->cwt)
  16.          maxload = (MAX_CARR_CAP * (long) mtmp->data->msize) / MZ_HUMAN;
  17.      else if (!strongmonst(mtmp->data)
  18.               || (strongmonst(mtmp->data) && (mtmp->data->cwt > WT_HUMAN)))
  19.          maxload = (MAX_CARR_CAP * (long) mtmp->data->cwt) / WT_HUMAN;
  20.      else
  21.          maxload = MAX_CARR_CAP; /*strong monsters w/cwt <= WT_HUMAN*/
  22.  
  23.      if (!strongmonst(mtmp->data))
  24.          maxload /= 2;
  25.  
  26.      if (maxload < 1)
  27.          maxload = 1;
  28.  
  29.      return (int) maxload;
  30.  }
  31.  

can_carry

  1.  /* for restricting monsters' object-pickup.
  2.   *
  3.   * to support the new pet behavior, this now returns the max # of objects
  4.   * that a given monster could pick up from a pile. frequently this will be
  5.   * otmp->quan, but special cases for 'only one' now exist so.
  6.   *
  7.   * this will probably cause very amusing behavior with pets and gold coins.
  8.   *
  9.   * TODO: allow picking up 2-N objects from a pile of N based on weight.
  10.   *       Change from 'int' to 'long' to accomate big stacks of gold.
  11.   *       Right now we fake it by reporting a partial quantity, but the
  12.   *       likesgold handling m_move results in picking up the whole stack.
  13.   */
  14.  int
  15.  can_carry(mtmp, otmp)
  16.  struct monst *mtmp;
  17.  struct obj *otmp;
  18.  {
  19.      int iquan, otyp = otmp->otyp, newload = otmp->owt;
  20.      struct permonst *mdat = mtmp->data;
  21.      short nattk = 0;
  22.  
  23.      if (notake(mdat))
  24.          return 0; /* can't carry anything */
  25.  
  26.      if (otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])
  27.          && !(mtmp->misc_worn_check & W_ARMG) && !resists_ston(mtmp))
  28.          return 0;
  29.      if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm]))
  30.          return 0;
  31.      if (objects[otyp].oc_material == SILVER && mon_hates_silver(mtmp)
  32.          && (otyp != BELL_OF_OPENING || !is_covetous(mdat)))
  33.          return 0;
  34.  
  35.      /* hostile monsters who like gold will pick up the whole stack;
  36.         tame mosnters with hands will pick up the partial stack */
  37.      iquan = (otmp->quan > (long) LARGEST_INT)
  38.                 ? 20000 + rn2(LARGEST_INT - 20000 + 1)
  39.                 : (int) otmp->quan;
  40.  
  41.      /* monsters without hands can't pick up multiple objects at once
  42.       * unless they have an engulfing attack
  43.       *
  44.       * ...dragons, of course, can always carry gold pieces and gems somehow
  45.       */
  46.      if (iquan > 1) {
  47.          boolean glomper = FALSE;
  48.  
  49.          if (mtmp->data->mlet == S_DRAGON
  50.              && (otmp->oclass == COIN_CLASS
  51.                  || otmp->oclass == GEM_CLASS))
  52.              glomper = TRUE;
  53.          else
  54.              for (nattk = 0; nattk < NATTK; nattk++)
  55.                  if (mtmp->data->mattk[nattk].aatyp == AT_ENGL) {
  56.                      glomper = TRUE;
  57.                      break;
  58.                  }
  59.          if ((mtmp->data->mflags1 & M1_NOHANDS) && !glomper)
  60.              return 1;
  61.      }
  62.  
  63.      /* steeds don't pick up stuff (to avoid shop abuse) */
  64.      if (mtmp == u.usteed)
  65.          return 0;
  66.      if (mtmp->isshk)
  67.          return iquan; /* no limit */
  68.      if (mtmp->mpeaceful && !mtmp->mtame)
  69.          return 0;
  70.      /* otherwise players might find themselves obligated to violate
  71.       * their alignment if the monster takes something they need
  72.       */
  73.  
  74.      /* special--boulder throwers carry unlimited amounts of boulders */
  75.      if (throws_rocks(mdat) && otyp == BOULDER)
  76.          return iquan;
  77.  
  78.      /* nymphs deal in stolen merchandise, but not boulders or statues */
  79.      if (mdat->mlet == S_NYMPH)
  80.          return (otmp->oclass == ROCK_CLASS) ? 0 : iquan;
  81.  
  82.      if (curr_mon_load(mtmp) + newload > max_mon_load(mtmp))
  83.          return 0;
  84.  
  85.      return iquan;
  86.  }
  87.  

mfndpos

  1.  /* return number of acceptable neighbour positions */
  2.  int
  3.  mfndpos(mon, poss, info, flag)
  4.  struct monst *mon;
  5.  coord *poss; /* coord poss[9] */
  6.  long *info;  /* long info[9] */
  7.  long flag;
  8.  {
  9.      struct permonst *mdat = mon->data;
  10.      register struct trap *ttmp;
  11.      xchar x, y, nx, ny;
  12.      int cnt = 0;
  13.      uchar ntyp;
  14.      uchar nowtyp;
  15.      boolean wantpool, poolok, lavaok, nodiag;
  16.      boolean rockok = FALSE, treeok = FALSE, thrudoor;
  17.      int maxx, maxy;
  18.  
  19.      x = mon->mx;
  20.      y = mon->my;
  21.      nowtyp = levl[x][y].typ;
  22.  
  23.      nodiag = NODIAG(mdat - mons);
  24.      wantpool = mdat->mlet == S_EEL;
  25.      poolok = (is_flyer(mdat) || is_clinger(mdat)
  26.                || (is_swimmer(mdat) && !wantpool));
  27.      lavaok = (is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat));
  28.      thrudoor = ((flag & (ALLOW_WALL | BUSTDOOR)) != 0L);
  29.      if (flag & ALLOW_DIG) {
  30.          struct obj *mw_tmp;
  31.  
  32.          /* need to be specific about what can currently be dug */
  33.          if (!needspick(mdat)) {
  34.              rockok = treeok = TRUE;
  35.          } else if ((mw_tmp = MON_WEP(mon)) && mw_tmp->cursed
  36.                     && mon->weapon_check == NO_WEAPON_WANTED) {
  37.              rockok = is_pick(mw_tmp);
  38.              treeok = is_axe(mw_tmp);
  39.          } else {
  40.              rockok = (m_carrying(mon, PICK_AXE)
  41.                        || (m_carrying(mon, DWARVISH_MATTOCK)
  42.                            && !which_armor(mon, W_ARMS)));
  43.              treeok = (m_carrying(mon, AXE) || (m_carrying(mon, BATTLE_AXE)
  44.                                                 && !which_armor(mon, W_ARMS)));
  45.          }
  46.          if (rockok || treeok)
  47.              thrudoor = TRUE;
  48.      }
  49.  
  50.  nexttry: /* eels prefer the water, but if there is no water nearby,
  51.              they will crawl over land */
  52.      if (mon->mconf) {
  53.          flag |= ALLOW_ALL;
  54.          flag &= ~NOTONL;
  55.      }
  56.      if (!mon->mcansee)
  57.          flag |= ALLOW_SSM;
  58.      maxx = min(x + 1, COLNO - 1);
  59.      maxy = min(y + 1, ROWNO - 1);
  60.      for (nx = max(1, x - 1); nx <= maxx; nx++)
  61.          for (ny = max(0, y - 1); ny <= maxy; ny++) {
  62.              if (nx == x && ny == y)
  63.                  continue;
  64.              ntyp = levl[nx][ny].typ;
  65.              if (IS_ROCK(ntyp)
  66.                  && !((flag & ALLOW_WALL) && may_passwall(nx, ny))
  67.                  && !((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx, ny)))
  68.                  continue;
  69.              /* KMH -- Added iron bars */
  70.              if (ntyp == IRONBARS && !(flag & ALLOW_BARS))
  71.                  continue;
  72.              if (IS_DOOR(ntyp) && !(amorphous(mdat) || can_fog(mon))
  73.                  && (((levl[nx][ny].doormask & D_CLOSED) && !(flag & OPENDOOR))
  74.                      || ((levl[nx][ny].doormask & D_LOCKED)
  75.                          && !(flag & UNLOCKDOOR))) && !thrudoor)
  76.                  continue;
  77.              /* first diagonal checks (tight squeezes handled below) */
  78.              if (nx != x && ny != y
  79.                  && (nodiag
  80.                      || (IS_DOOR(nowtyp) && (levl[x][y].doormask & ~D_BROKEN))
  81.                      || (IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN))
  82.                      || ((IS_DOOR(nowtyp) || IS_DOOR(ntyp))
  83.                          && Is_rogue_level(&u.uz))
  84.                      /* mustn't pass between adjacent long worm segments,
  85.                         but can attack that way */
  86.                      || (m_at(x, ny) && m_at(nx, y) && worm_cross(x, y, nx, ny)
  87.                          && !m_at(nx, ny) && (nx != u.ux || ny != u.uy))))
  88.                  continue;
  89.              if ((is_pool(nx, ny) == wantpool || poolok)
  90.                  && (lavaok || !is_lava(nx, ny))) {
  91.                  int dispx, dispy;
  92.                  boolean monseeu = (mon->mcansee
  93.                                     && (!Invis || perceives(mdat)));
  94.                  boolean checkobj = OBJ_AT(nx, ny);
  95.  
  96.                  /* Displacement also displaces the Elbereth/scare monster,
  97.                   * as long as you are visible.
  98.                   */
  99.                  if (Displaced && monseeu && mon->mux == nx && mon->muy == ny) {
  100.                      dispx = u.ux;
  101.                      dispy = u.uy;
  102.                  } else {
  103.                      dispx = nx;
  104.                      dispy = ny;
  105.                  }
  106.  
  107.                  info[cnt] = 0;
  108.                  if (onscary(dispx, dispy, mon)) {
  109.                      if (!(flag & ALLOW_SSM))
  110.                          continue;
  111.                      info[cnt] |= ALLOW_SSM;
  112.                  }
  113.                  if ((nx == u.ux && ny == u.uy)
  114.                      || (nx == mon->mux && ny == mon->muy)) {
  115.                      if (nx == u.ux && ny == u.uy) {
  116.                          /* If it's right next to you, it found you,
  117.                           * displaced or no.  We must set mux and muy
  118.                           * right now, so when we return we can tell
  119.                           * that the ALLOW_U means to attack _you_ and
  120.                           * not the image.
  121.                           */
  122.                          mon->mux = u.ux;
  123.                          mon->muy = u.uy;
  124.                      }
  125.                      if (!(flag & ALLOW_U))
  126.                          continue;
  127.                      info[cnt] |= ALLOW_U;
  128.                  } else {
  129.                      if (MON_AT(nx, ny)) {
  130.                          struct monst *mtmp2 = m_at(nx, ny);
  131.                          long mmflag = flag | mm_aggression(mon, mtmp2);
  132.  
  133.                          if (mmflag & ALLOW_M) {
  134.                              info[cnt] |= ALLOW_M;
  135.                              if (mtmp2->mtame) {
  136.                                  if (!(mmflag & ALLOW_TM))
  137.                                      continue;
  138.                                  info[cnt] |= ALLOW_TM;
  139.                              }
  140.                          } else {
  141.                              mmflag = flag | mm_displacement(mon, mtmp2);
  142.                              if (!(mmflag & ALLOW_MDISP))
  143.                                  continue;
  144.                              info[cnt] |= ALLOW_MDISP;
  145.                          }
  146.                      }
  147.                      /* Note: ALLOW_SANCT only prevents movement, not
  148.                         attack, into a temple. */
  149.                      if (level.flags.has_temple && *in_rooms(nx, ny, TEMPLE)
  150.                          && !*in_rooms(x, y, TEMPLE)
  151.                          && in_your_sanctuary((struct monst *) 0, nx, ny)) {
  152.                          if (!(flag & ALLOW_SANCT))
  153.                              continue;
  154.                          info[cnt] |= ALLOW_SANCT;
  155.                      }
  156.                  }
  157.                  if (checkobj && sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
  158.                      if (flag & NOGARLIC)
  159.                          continue;
  160.                      info[cnt] |= NOGARLIC;
  161.                  }
  162.                  if (checkobj && sobj_at(BOULDER, nx, ny)) {
  163.                      if (!(flag & ALLOW_ROCK))
  164.                          continue;
  165.                      info[cnt] |= ALLOW_ROCK;
  166.                  }
  167.                  if (monseeu && onlineu(nx, ny)) {
  168.                      if (flag & NOTONL)
  169.                          continue;
  170.                      info[cnt] |= NOTONL;
  171.                  }
  172.                  /* check for diagonal tight squeeze */
  173.                  if (nx != x && ny != y && bad_rock(mdat, x, ny)
  174.                      && bad_rock(mdat, nx, y) && cant_squeeze_thru(mon))
  175.                      continue;
  176.                  /* The monster avoids a particular type of trap if it's
  177.                   * familiar with the trap type.  Pets get ALLOW_TRAPS
  178.                   * and checking is done in dogmove.c.  In either case,
  179.                   * "harmless" traps are neither avoided nor marked in info[].
  180.                   */
  181.                  if ((ttmp = t_at(nx, ny)) != 0) {
  182.                      if (ttmp->ttyp >= TRAPNUM || ttmp->ttyp == 0) {
  183.                          impossible(
  184.                           "A monster looked at a very strange trap of type %d.",
  185.                                     ttmp->ttyp);
  186.                              continue;
  187.                      }
  188.                      if ((ttmp->ttyp != RUST_TRAP
  189.                           || mdat == &mons[PM_IRON_GOLEM])
  190.                          && ttmp->ttyp != STATUE_TRAP
  191.                          && ((ttmp->ttyp != PIT && ttmp->ttyp != SPIKED_PIT
  192.                               && ttmp->ttyp != TRAPDOOR && ttmp->ttyp != HOLE)
  193.                              || (!is_flyer(mdat) && !is_floater(mdat)
  194.                                  && !is_clinger(mdat)) || Sokoban)
  195.                          && (ttmp->ttyp != SLP_GAS_TRAP || !resists_sleep(mon))
  196.                          && (ttmp->ttyp != BEAR_TRAP
  197.                              || (mdat->msize > MZ_SMALL && !amorphous(mdat)
  198.                                  && !is_flyer(mdat) && !is_floater(mdat)
  199.                                  && !is_whirly(mdat) && !unsolid(mdat)))
  200.                          && (ttmp->ttyp != FIRE_TRAP || !resists_fire(mon))
  201.                          && (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat))
  202.                          && (ttmp->ttyp != WEB
  203.                              || (!amorphous(mdat) && !webmaker(mdat)))
  204.                          && (ttmp->ttyp != ANTI_MAGIC || !resists_magm(mon))) {
  205.                          if (!(flag & ALLOW_TRAPS)) {
  206.                              if (mon->mtrapseen & (1L << (ttmp->ttyp - 1)))
  207.                                  continue;
  208.                          }
  209.                          info[cnt] |= ALLOW_TRAPS;
  210.                      }
  211.                  }
  212.                  poss[cnt].x = nx;
  213.                  poss[cnt].y = ny;
  214.                  cnt++;
  215.              }
  216.          }
  217.      if (!cnt && wantpool && !is_pool(x, y)) {
  218.          wantpool = FALSE;
  219.          goto nexttry;
  220.      }
  221.      return cnt;
  222.  }
  223.  

mm_aggression

  1.  /* Monster against monster special attacks; for the specified monster
  2.     combinations, this allows one monster to attack another adjacent one
  3.     in the absence of Conflict.  There is no provision for targetting
  4.     other monsters; just hand to hand fighting when they happen to be
  5.     next to each other. */
  6.  STATIC_OVL long
  7.  mm_aggression(magr, mdef)
  8.  struct monst *magr, /* monster that is currently deciding where to move */
  9.               *mdef; /* another monster which is next to it */
  10.  {
  11.      /* supposedly purple worms are attracted to shrieking because they
  12.         like to eat shriekers, so attack the latter when feasible */
  13.      if (magr->data == &mons[PM_PURPLE_WORM]
  14.          && mdef->data == &mons[PM_SHRIEKER])
  15.          return ALLOW_M | ALLOW_TM;
  16.      /* Various other combinations such as dog vs cat, cat vs rat, and
  17.         elf vs orc have been suggested.  For the time being we don't
  18.         support those. */
  19.      return 0L;
  20.  }
  21.  

mm_displacement

  1.  /* Monster displacing another monster out of the way */
  2.  STATIC_OVL long
  3.  mm_displacement(magr, mdef)
  4.  struct monst *magr, /* monster that is currently deciding where to move */
  5.               *mdef; /* another monster which is next to it */
  6.  {
  7.      struct permonst *pa = magr->data, *pd = mdef->data;
  8.  
  9.      /* if attacker can't barge through, there's nothing to do;
  10.         or if defender can barge through too, don't let attacker
  11.         do so, otherwise they might just end up swapping places
  12.         again when defender gets its chance to move */
  13.      if ((pa->mflags3 & M3_DISPLACES) != 0 && (pd->mflags3 & M3_DISPLACES) == 0
  14.          /* no displacing grid bugs diagonally */
  15.          && !(magr->mx != mdef->mx && magr->my != mdef->my
  16.               && NODIAG(monsndx(pd)))
  17.          /* no displacing trapped monsters or multi-location longworms */
  18.          && !mdef->mtrapped && (!mdef->wormno || !count_wsegs(mdef))
  19.          /* riders can move anything; others, same size or smaller only */
  20.          && (is_rider(pa) || pa->msize >= pd->msize))
  21.          return ALLOW_MDISP;
  22.      return 0L;
  23.  }
  24.  

monnear

  1.  /* Is the square close enough for the monster to move or attack into? */
  2.  boolean
  3.  monnear(mon, x, y)
  4.  struct monst *mon;
  5.  int x, y;
  6.  {
  7.      int distance = dist2(mon->mx, mon->my, x, y);
  8.  
  9.      if (distance == 2 && NODIAG(mon->data - mons))
  10.          return 0;
  11.      return (boolean) (distance < 3);
  12.  }
  13.  

dmonsfree

  1.  /* really free dead monsters */
  2.  void
  3.  dmonsfree()
  4.  {
  5.      struct monst **mtmp, *freetmp;
  6.      int count = 0;
  7.  
  8.      for (mtmp = &fmon; *mtmp;) {
  9.          freetmp = *mtmp;
  10.          if (freetmp->mhp <= 0 && !freetmp->isgd) {
  11.              *mtmp = freetmp->nmon;
  12.              freetmp->nmon = NULL;
  13.              dealloc_monst(freetmp);
  14.              count++;
  15.          } else
  16.              mtmp = &(freetmp->nmon);
  17.      }
  18.  
  19.      if (count != iflags.purge_monsters)
  20.          impossible("dmonsfree: %d removed doesn't match %d pending",
  21.                     count, iflags.purge_monsters);
  22.      iflags.purge_monsters = 0;
  23.  }
  24.  

replmon

  1.  /* called when monster is moved to larger structure */
  2.  void
  3.  replmon(mtmp, mtmp2)
  4.  struct monst *mtmp, *mtmp2;
  5.  {
  6.      struct obj *otmp;
  7.  
  8.      /* transfer the monster's inventory */
  9.      for (otmp = mtmp2->minvent; otmp; otmp = otmp->nobj) {
  10.          if (otmp->where != OBJ_MINVENT || otmp->ocarry != mtmp)
  11.              impossible("replmon: minvent inconsistency");
  12.          otmp->ocarry = mtmp2;
  13.      }
  14.      mtmp->minvent = 0;
  15.  
  16.      /* remove the old monster from the map and from `fmon' list */
  17.      relmon(mtmp, (struct monst **) 0);
  18.  
  19.      /* finish adding its replacement */
  20.      if (mtmp != u.usteed) /* don't place steed onto the map */
  21.          place_monster(mtmp2, mtmp2->mx, mtmp2->my);
  22.      if (mtmp2->wormno)      /* update level.monsters[wseg->wx][wseg->wy] */
  23.          place_wsegs(mtmp2); /* locations to mtmp2 not mtmp. */
  24.      if (emits_light(mtmp2->data)) {
  25.          /* since this is so rare, we don't have any `mon_move_light_source' */
  26.          new_light_source(mtmp2->mx, mtmp2->my, emits_light(mtmp2->data),
  27.                           LS_MONSTER, monst_to_any(mtmp2));
  28.          /* here we rely on fact that `mtmp' hasn't actually been deleted */
  29.          del_light_source(LS_MONSTER, monst_to_any(mtmp));
  30.      }
  31.      mtmp2->nmon = fmon;
  32.      fmon = mtmp2;
  33.      if (u.ustuck == mtmp)
  34.          u.ustuck = mtmp2;
  35.      if (u.usteed == mtmp)
  36.          u.usteed = mtmp2;
  37.      if (mtmp2->isshk)
  38.          replshk(mtmp, mtmp2);
  39.  
  40.      /* discard the old monster */
  41.      dealloc_monst(mtmp);
  42.  }
  43.  

relmon

  1.  /* release mon from the display and the map's monster list,
  2.     maybe transfer it to one of the other monster lists */
  3.  void
  4.  relmon(mon, monst_list)
  5.  struct monst *mon;
  6.  struct monst **monst_list; /* &migrating_mons or &mydogs or null */
  7.  {
  8.      struct monst *mtmp;
  9.      boolean unhide = (monst_list != 0);
  10.      int mx = mon->mx, my = mon->my;
  11.  
  12.      if (!fmon)
  13.          panic("relmon: no fmon available.");
  14.  
  15.      if (unhide) {
  16.          /* can't remain hidden across level changes (exception: wizard
  17.             clone can continue imitating some other monster form); also,
  18.             might be imitating a boulder so need line-of-sight unblocking */
  19.          mon->mundetected = 0;
  20.          if (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER)
  21.              seemimic(mon);
  22.      }
  23.  
  24.      remove_monster(mx, my);
  25.  
  26.      if (mon == fmon) {
  27.          fmon = fmon->nmon;
  28.      } else {
  29.          for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  30.              if (mtmp->nmon == mon)
  31.                  break;
  32.  
  33.          if (mtmp)
  34.              mtmp->nmon = mon->nmon;
  35.          else
  36.              panic("relmon: mon not in list.");
  37.      }
  38.  
  39.      if (unhide) {
  40.          newsym(mx, my);
  41.          /* insert into mydogs or migrating_mons */
  42.          mon->nmon = *monst_list;
  43.          *monst_list = mon;
  44.      } else {
  45.          /* orphan has no next monster */
  46.          mon->nmon = 0;
  47.      }
  48.  }
  49.  

copy_mextra

  1.  void
  2.  copy_mextra(mtmp2, mtmp1)
  3.  struct monst *mtmp2, *mtmp1;
  4.  {
  5.      if (!mtmp2 || !mtmp1 || !mtmp1->mextra)
  6.          return;
  7.  
  8.      if (!mtmp2->mextra)
  9.          mtmp2->mextra = newmextra();
  10.      if (MNAME(mtmp1)) {
  11.          new_mname(mtmp2, (int) strlen(MNAME(mtmp1)) + 1);
  12.          Strcpy(MNAME(mtmp2), MNAME(mtmp1));
  13.      }
  14.      if (EGD(mtmp1)) {
  15.          if (!EGD(mtmp2))
  16.              newegd(mtmp2);
  17.          (void) memcpy((genericptr_t) EGD(mtmp2), (genericptr_t) EGD(mtmp1),
  18.                        sizeof (struct egd));
  19.      }
  20.      if (EPRI(mtmp1)) {
  21.          if (!EPRI(mtmp2))
  22.              newepri(mtmp2);
  23.          (void) memcpy((genericptr_t) EPRI(mtmp2), (genericptr_t) EPRI(mtmp1),
  24.                        sizeof (struct epri));
  25.      }
  26.      if (ESHK(mtmp1)) {
  27.          if (!ESHK(mtmp2))
  28.              neweshk(mtmp2);
  29.          (void) memcpy((genericptr_t) ESHK(mtmp2), (genericptr_t) ESHK(mtmp1),
  30.                        sizeof (struct eshk));
  31.      }
  32.      if (EMIN(mtmp1)) {
  33.          if (!EMIN(mtmp2))
  34.              newemin(mtmp2);
  35.          (void) memcpy((genericptr_t) EMIN(mtmp2), (genericptr_t) EMIN(mtmp1),
  36.                        sizeof (struct emin));
  37.      }
  38.      if (EDOG(mtmp1)) {
  39.          if (!EDOG(mtmp2))
  40.              newedog(mtmp2);
  41.          (void) memcpy((genericptr_t) EDOG(mtmp2), (genericptr_t) EDOG(mtmp1),
  42.                        sizeof (struct edog));
  43.      }
  44.      if (has_mcorpsenm(mtmp1))
  45.          MCORPSENM(mtmp2) = MCORPSENM(mtmp1);
  46.  }
  47.  

dealloc_mextra

  1.  void
  2.  dealloc_mextra(m)
  3.  struct monst *m;
  4.  {
  5.      struct mextra *x = m->mextra;
  6.  
  7.      if (x) {
  8.          if (x->mname)
  9.              free((genericptr_t) x->mname);
  10.          if (x->egd)
  11.              free((genericptr_t) x->egd);
  12.          if (x->epri)
  13.              free((genericptr_t) x->epri);
  14.          if (x->eshk)
  15.              free((genericptr_t) x->eshk);
  16.          if (x->emin)
  17.              free((genericptr_t) x->emin);
  18.          if (x->edog)
  19.              free((genericptr_t) x->edog);
  20.          /* [no action needed for x->mcorpsenm] */
  21.  
  22.          free((genericptr_t) x);
  23.          m->mextra = (struct mextra *) 0;
  24.      }
  25.  }
  26.  

dealloc_monst

  1.  void
  2.  dealloc_monst(mon)
  3.  struct monst *mon;
  4.  {
  5.      if (mon->nmon)
  6.          panic("dealloc_monst with nmon");
  7.      if (mon->mextra)
  8.          dealloc_mextra(mon);
  9.      free((genericptr_t) mon);
  10.  }
  11.  

m_detach

  1.  /* remove effects of mtmp from other data structures */
  2.  STATIC_OVL void
  3.  m_detach(mtmp, mptr)
  4.  struct monst *mtmp;
  5.  struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */
  6.  {
  7.      if (mtmp == context.polearm.hitmon)
  8.          context.polearm.hitmon = 0;
  9.      if (mtmp->mleashed)
  10.          m_unleash(mtmp, FALSE);
  11.      /* to prevent an infinite relobj-flooreffects-hmon-killed loop */
  12.      mtmp->mtrapped = 0;
  13.      mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */
  14.      relobj(mtmp, 0, FALSE);
  15.      remove_monster(mtmp->mx, mtmp->my);
  16.      if (emits_light(mptr))
  17.          del_light_source(LS_MONSTER, monst_to_any(mtmp));
  18.      newsym(mtmp->mx, mtmp->my);
  19.      unstuck(mtmp);
  20.      fill_pit(mtmp->mx, mtmp->my);
  21.  
  22.      if (mtmp->isshk)
  23.          shkgone(mtmp);
  24.      if (mtmp->wormno)
  25.          wormgone(mtmp);
  26.      iflags.purge_monsters++;
  27.  }
  28.  

mlifesaver

  1.  /* find the worn amulet of life saving which will save a monster */
  2.  struct obj *
  3.  mlifesaver(mon)
  4.  struct monst *mon;
  5.  {
  6.      if (!nonliving(mon->data) || is_vampshifter(mon)) {
  7.          struct obj *otmp = which_armor(mon, W_AMUL);
  8.  
  9.          if (otmp && otmp->otyp == AMULET_OF_LIFE_SAVING)
  10.              return otmp;
  11.      }
  12.      return (struct obj *) 0;
  13.  }
  14.  

lifesaved_monster

  1.  STATIC_OVL void
  2.  lifesaved_monster(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      boolean surviver;
  6.      struct obj *lifesave = mlifesaver(mtmp);
  7.  
  8.      if (lifesave) {
  9.          /* not canseemon; amulets are on the head, so you don't want
  10.           * to show this for a long worm with only a tail visible.
  11.           * Nor do you check invisibility, because glowing and
  12.           * disintegrating amulets are always visible. */
  13.          if (cansee(mtmp->mx, mtmp->my)) {
  14.              pline("But wait...");
  15.              pline("%s medallion begins to glow!", s_suffix(Monnam(mtmp)));
  16.              makeknown(AMULET_OF_LIFE_SAVING);
  17.              /* amulet is visible, but monster might not be */
  18.              if (canseemon(mtmp)) {
  19.                  if (attacktype(mtmp->data, AT_EXPL)
  20.                      || attacktype(mtmp->data, AT_BOOM))
  21.                      pline("%s reconstitutes!", Monnam(mtmp));
  22.                  else
  23.                      pline("%s looks much better!", Monnam(mtmp));
  24.              }
  25.              pline_The("medallion crumbles to dust!");
  26.          }
  27.          m_useup(mtmp, lifesave);
  28.  
  29.          surviver = !(mvitals[monsndx(mtmp->data)].mvflags & G_GENOD);
  30.          mtmp->mcanmove = 1;
  31.          mtmp->mfrozen = 0;
  32.          if (mtmp->mtame && !mtmp->isminion) {
  33.              wary_dog(mtmp, !surviver);
  34.          }
  35.          if (mtmp->mhpmax <= 0)
  36.              mtmp->mhpmax = 10;
  37.          mtmp->mhp = mtmp->mhpmax;
  38.          if (surviver)
  39.              return;
  40.  
  41.          /* genocided monster can't be life-saved */
  42.          if (cansee(mtmp->mx, mtmp->my))
  43.              pline("Unfortunately, %s is still genocided...", mon_nam(mtmp));
  44.      }
  45.      mtmp->mhp = 0;
  46.  }
  47.  

mondead

  1.  void
  2.  mondead(mtmp)
  3.  register struct monst *mtmp;
  4.  {
  5.      struct permonst *mptr;
  6.      int tmp;
  7.  
  8.      lifesaved_monster(mtmp);
  9.      if (mtmp->mhp > 0)
  10.          return;
  11.  
  12.      if (is_vampshifter(mtmp)) {
  13.          int mndx = mtmp->cham;
  14.          int x = mtmp->mx, y = mtmp->my;
  15.  
  16.          /* this only happens if shapeshifted */
  17.          if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
  18.              char buf[BUFSZ];
  19.              boolean in_door = (amorphous(mtmp->data)
  20.                                 && closed_door(mtmp->mx, mtmp->my)),
  21.                  /* alternate message phrasing for some monster types */
  22.                  spec_mon = (nonliving(mtmp->data)
  23.                              || noncorporeal(mtmp->data)
  24.                              || amorphous(mtmp->data));
  25.  
  26.              /* construct a format string before transformation */
  27.              Sprintf(buf, "The %s%s suddenly %s and rises as %%s!",
  28.                      spec_mon ? "" : "seemingly dead ",
  29.                      x_monnam(mtmp, ARTICLE_NONE, (char *) 0,
  30.                               SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION
  31.                                   | SUPPRESS_INVISIBLE | SUPPRESS_IT,
  32.                               FALSE),
  33.                      spec_mon ? "reconstitutes" : "transforms");
  34.              mtmp->mcanmove = 1;
  35.              mtmp->mfrozen = 0;
  36.              if (mtmp->mhpmax <= 0)
  37.                  mtmp->mhpmax = 10;
  38.              mtmp->mhp = mtmp->mhpmax;
  39.              /* this can happen if previously a fog cloud */
  40.              if (u.uswallow && (mtmp == u.ustuck))
  41.                  expels(mtmp, mtmp->data, FALSE);
  42.              if (in_door) {
  43.                  coord new_xy;
  44.  
  45.                  if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx])) {
  46.                      rloc_to(mtmp, new_xy.x, new_xy.y);
  47.                  }
  48.              }
  49.              newcham(mtmp, &mons[mndx], FALSE, FALSE);
  50.              if (mtmp->data == &mons[mndx])
  51.                  mtmp->cham = NON_PM;
  52.              else
  53.                  mtmp->cham = mndx;
  54.              if (canspotmon(mtmp)) {
  55.                  pline(buf, a_monnam(mtmp));
  56.                  vamp_rise_msg = TRUE;
  57.              }
  58.              newsym(x, y);
  59.              return;
  60.          }
  61.      }
  62.  
  63.      /* dead vault guard is actually kept at coordinate <0,0> until
  64.         his temporary corridor to/from the vault has been removed;
  65.         need to do this after life-saving and before m_detach() */
  66.      if (mtmp->isgd && !grddead(mtmp))
  67.          return;
  68.  
  69.      /* Player is thrown from his steed when it dies */
  70.      if (mtmp == u.usteed)
  71.          dismount_steed(DISMOUNT_GENERIC);
  72.  
  73.      mptr = mtmp->data; /* save this for m_detach() */
  74.      /* restore chameleon, lycanthropes to true form at death */
  75.      if (mtmp->cham >= LOW_PM) {
  76.          set_mon_data(mtmp, &mons[mtmp->cham], -1);
  77.          mtmp->cham = NON_PM;
  78.      } else if (mtmp->data == &mons[PM_WEREJACKAL])
  79.          set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
  80.      else if (mtmp->data == &mons[PM_WEREWOLF])
  81.          set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
  82.      else if (mtmp->data == &mons[PM_WERERAT])
  83.          set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
  84.  
  85.      /* if MAXMONNO monsters of a given type have died, and it
  86.       * can be done, extinguish that monster.
  87.       *
  88.       * mvitals[].died does double duty as total number of dead monsters
  89.       * and as experience factor for the player killing more monsters.
  90.       * this means that a dragon dying by other means reduces the
  91.       * experience the player gets for killing a dragon directly; this
  92.       * is probably not too bad, since the player likely finagled the
  93.       * first dead dragon via ring of conflict or pets, and extinguishing
  94.       * based on only player kills probably opens more avenues of abuse
  95.       * for rings of conflict and such.
  96.       */
  97.      tmp = monsndx(mtmp->data);
  98.      if (mvitals[tmp].died < 255)
  99.          mvitals[tmp].died++;
  100.  
  101.      /* if it's a (possibly polymorphed) quest leader, mark him as dead */
  102.      if (mtmp->m_id == quest_status.leader_m_id)
  103.          quest_status.leader_is_dead = TRUE;
  104.  #ifdef MAIL
  105.      /* if the mail daemon dies, no more mail delivery.  -3. */
  106.      if (tmp == PM_MAIL_DAEMON)
  107.          mvitals[tmp].mvflags |= G_GENOD;
  108.  #endif
  109.  
  110.      if (mtmp->data->mlet == S_KOP) {
  111.          /* Dead Kops may come back. */
  112.          switch (rnd(5)) {
  113.          case 1: /* returns near the stairs */
  114.              (void) makemon(mtmp->data, xdnstair, ydnstair, NO_MM_FLAGS);
  115.              break;
  116.          case 2: /* randomly */
  117.              (void) makemon(mtmp->data, 0, 0, NO_MM_FLAGS);
  118.              break;
  119.          default:
  120.              break;
  121.          }
  122.      }
  123.      if (mtmp->iswiz)
  124.          wizdead();
  125.      if (mtmp->data->msound == MS_NEMESIS)
  126.          nemdead();
  127.      if (mtmp->data == &mons[PM_MEDUSA])
  128.          u.uachieve.killed_medusa = 1;
  129.      if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
  130.          unmap_object(mtmp->mx, mtmp->my);
  131.      m_detach(mtmp, mptr);
  132.  }
  133.  

corpse_chance

  1.  /* TRUE if corpse might be dropped, magr may die if mon was swallowed */
  2.  boolean
  3.  corpse_chance(mon, magr, was_swallowed)
  4.  struct monst *mon;
  5.  struct monst *magr;    /* killer, if swallowed */
  6.  boolean was_swallowed; /* digestion */
  7.  {
  8.      struct permonst *mdat = mon->data;
  9.      int i, tmp;
  10.  
  11.      if (mdat == &mons[PM_VLAD_THE_IMPALER] || mdat->mlet == S_LICH) {
  12.          if (cansee(mon->mx, mon->my) && !was_swallowed)
  13.              pline("%s body crumbles into dust.", s_suffix(Monnam(mon)));
  14.          return FALSE;
  15.      }
  16.  
  17.      /* Gas spores always explode upon death */
  18.      for (i = 0; i < NATTK; i++) {
  19.          if (mdat->mattk[i].aatyp == AT_BOOM) {
  20.              if (mdat->mattk[i].damn)
  21.                  tmp = d((int) mdat->mattk[i].damn, (int) mdat->mattk[i].damd);
  22.              else if (mdat->mattk[i].damd)
  23.                  tmp = d((int) mdat->mlevel + 1, (int) mdat->mattk[i].damd);
  24.              else
  25.                  tmp = 0;
  26.              if (was_swallowed && magr) {
  27.                  if (magr == &youmonst) {
  28.                      There("is an explosion in your %s!", body_part(STOMACH));
  29.                      Sprintf(killer.name, "%s explosion",
  30.                              s_suffix(mdat->mname));
  31.                      losehp(Maybe_Half_Phys(tmp), killer.name, KILLED_BY_AN);
  32.                  } else {
  33.                      You_hear("an explosion.");
  34.                      magr->mhp -= tmp;
  35.                      if (magr->mhp < 1)
  36.                          mondied(magr);
  37.                      if (magr->mhp < 1) { /* maybe lifesaved */
  38.                          if (canspotmon(magr))
  39.                              pline("%s rips open!", Monnam(magr));
  40.                      } else if (canseemon(magr))
  41.                          pline("%s seems to have indigestion.", Monnam(magr));
  42.                  }
  43.  
  44.                  return FALSE;
  45.              }
  46.  
  47.              Sprintf(killer.name, "%s explosion", s_suffix(mdat->mname));
  48.              killer.format = KILLED_BY_AN;
  49.              explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE, EXPL_NOXIOUS);
  50.              return FALSE;
  51.          }
  52.      }
  53.  
  54.      /* must duplicate this below check in xkilled() since it results in
  55.       * creating no objects as well as no corpse
  56.       */
  57.      if (LEVEL_SPECIFIC_NOCORPSE(mdat))
  58.          return FALSE;
  59.  
  60.      if (((bigmonst(mdat) || mdat == &mons[PM_LIZARD]) && !mon->mcloned)
  61.          || is_golem(mdat) || is_mplayer(mdat) || is_rider(mdat))
  62.          return TRUE;
  63.      tmp = 2 + ((mdat->geno & G_FREQ) < 2) + verysmall(mdat);
  64.      return (boolean) !rn2(tmp);
  65.  }
  66.  

mondied

  1.  /* drop (perhaps) a cadaver and remove monster */
  2.  void
  3.  mondied(mdef)
  4.  register struct monst *mdef;
  5.  {
  6.      mondead(mdef);
  7.      if (mdef->mhp > 0)
  8.          return; /* lifesaved */
  9.  
  10.      if (corpse_chance(mdef, (struct monst *) 0, FALSE)
  11.          && (accessible(mdef->mx, mdef->my) || is_pool(mdef->mx, mdef->my)))
  12.          (void) make_corpse(mdef, CORPSTAT_NONE);
  13.  }
  14.  

mongone

  1.  /* monster disappears, not dies */
  2.  void
  3.  mongone(mdef)
  4.  struct monst *mdef;
  5.  {
  6.      mdef->mhp = 0; /* can skip some inventory bookkeeping */
  7.  
  8.      /* dead vault guard is actually kept at coordinate <0,0> until
  9.         his temporary corridor to/from the vault has been removed */
  10.      if (mdef->isgd && !grddead(mdef))
  11.          return;
  12.      /* hero is thrown from his steed when it disappears */
  13.      if (mdef == u.usteed)
  14.          dismount_steed(DISMOUNT_GENERIC);
  15.      /* drop special items like the Amulet so that a dismissed Kop or nurse
  16.         can't remove them from the game */
  17.      mdrop_special_objs(mdef);
  18.      /* release rest of monster's inventory--it is removed from game */
  19.      discard_minvent(mdef);
  20.      m_detach(mdef, mdef->data);
  21.  }
  22.  

monstone

  1.  /* drop a statue or rock and remove monster */
  2.  void
  3.  monstone(mdef)
  4.  struct monst *mdef;
  5.  {
  6.      struct obj *otmp, *obj, *oldminvent;
  7.      xchar x = mdef->mx, y = mdef->my;
  8.      boolean wasinside = FALSE;
  9.  
  10.      /* we have to make the statue before calling mondead, to be able to
  11.       * put inventory in it, and we have to check for lifesaving before
  12.       * making the statue....
  13.       */
  14.      lifesaved_monster(mdef);
  15.      if (mdef->mhp > 0)
  16.          return;
  17.  
  18.      mdef->mtrapped = 0; /* (see m_detach) */
  19.  
  20.      if ((int) mdef->data->msize > MZ_TINY
  21.          || !rn2(2 + ((int) (mdef->data->geno & G_FREQ) > 2))) {
  22.          oldminvent = 0;
  23.          /* some objects may end up outside the statue */
  24.          while ((obj = mdef->minvent) != 0) {
  25.              obj_extract_self(obj);
  26.              if (obj->owornmask)
  27.                  update_mon_intrinsics(mdef, obj, FALSE, TRUE);
  28.              obj_no_longer_held(obj);
  29.              if (obj->owornmask & W_WEP)
  30.                  setmnotwielded(mdef, obj);
  31.              obj->owornmask = 0L;
  32.              if (obj->otyp == BOULDER
  33.  #if 0 /* monsters don't carry statues */
  34.                  ||  (obj->otyp == STATUE
  35.                       && mons[obj->corpsenm].msize >= mdef->data->msize)
  36.  #endif
  37.                  /* invocation tools resist even with 0% resistance */
  38.                  || obj_resists(obj, 0, 0)) {
  39.                  if (flooreffects(obj, x, y, "fall"))
  40.                      continue;
  41.                  place_object(obj, x, y);
  42.              } else {
  43.                  if (obj->lamplit)
  44.                      end_burn(obj, TRUE);
  45.                  obj->nobj = oldminvent;
  46.                  oldminvent = obj;
  47.              }
  48.          }
  49.          /* defer statue creation until after inventory removal
  50.             so that saved monster traits won't retain any stale
  51.             item-conferred attributes */
  52.          otmp = mkcorpstat(STATUE, mdef, mdef->data, x, y, CORPSTAT_NONE);
  53.          if (has_mname(mdef))
  54.              otmp = oname(otmp, MNAME(mdef));
  55.          while ((obj = oldminvent) != 0) {
  56.              oldminvent = obj->nobj;
  57.              (void) add_to_container(otmp, obj);
  58.          }
  59.          /* Archeologists should not break unique statues */
  60.          if (mdef->data->geno & G_UNIQ)
  61.              otmp->spe = 1;
  62.          otmp->owt = weight(otmp);
  63.      } else
  64.          otmp = mksobj_at(ROCK, x, y, TRUE, FALSE);
  65.  
  66.      stackobj(otmp);
  67.      /* mondead() already does this, but we must do it before the newsym */
  68.      if (glyph_is_invisible(levl[x][y].glyph))
  69.          unmap_object(x, y);
  70.      if (cansee(x, y))
  71.          newsym(x, y);
  72.      /* We don't currently trap the hero in the statue in this case but we
  73.       * could */
  74.      if (u.uswallow && u.ustuck == mdef)
  75.          wasinside = TRUE;
  76.      mondead(mdef);
  77.      if (wasinside) {
  78.          if (is_animal(mdef->data))
  79.              You("%s through an opening in the new %s.",
  80.                  locomotion(youmonst.data, "jump"), xname(otmp));
  81.      }
  82.  }
  83.  

monkilled

  1.  /* another monster has killed the monster mdef */
  2.  void
  3.  monkilled(mdef, fltxt, how)
  4.  struct monst *mdef;
  5.  const char *fltxt;
  6.  int how;
  7.  {
  8.      boolean be_sad = FALSE; /* true if unseen pet is killed */
  9.  
  10.      if ((mdef->wormno ? worm_known(mdef) : cansee(mdef->mx, mdef->my))
  11.          && fltxt)
  12.          pline("%s is %s%s%s!", Monnam(mdef),
  13.                nonliving(mdef->data) ? "destroyed" : "killed",
  14.                *fltxt ? " by the " : "", fltxt);
  15.      else
  16.          be_sad = (mdef->mtame != 0);
  17.  
  18.      /* no corpses if digested or disintegrated */
  19.      if (how == AD_DGST || how == -AD_RBRE)
  20.          mondead(mdef);
  21.      else
  22.          mondied(mdef);
  23.  
  24.      if (be_sad && mdef->mhp <= 0)
  25.          You("have a sad feeling for a moment, then it passes.");
  26.  }
  27.  

unstuck

  1.  void
  2.  unstuck(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      if (u.ustuck == mtmp) {
  6.          if (u.uswallow) {
  7.              u.ux = mtmp->mx;
  8.              u.uy = mtmp->my;
  9.              u.uswallow = 0;
  10.              u.uswldtim = 0;
  11.              if (Punished && uchain->where != OBJ_FLOOR)
  12.                  placebc();
  13.              vision_full_recalc = 1;
  14.              docrt();
  15.          }
  16.          u.ustuck = 0;
  17.      }
  18.  }
  19.  

killed

  1.  void
  2.  killed(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      xkilled(mtmp, 1);
  6.  }
  7.  

xkilled

  1.  /* the player has killed the monster mtmp */
  2.  void
  3.  xkilled(mtmp, dest)
  4.  struct monst *mtmp;
  5.  int dest; /* dest==1, normal; dest==0, don't print message; dest==2, don't
  6.               drop corpse either; dest==3, message but no corpse */
  7.  {
  8.      int tmp, mndx, x = mtmp->mx, y = mtmp->my;
  9.      struct permonst *mdat;
  10.      struct obj *otmp;
  11.      struct trap *t;
  12.      boolean wasinside = u.uswallow && (u.ustuck == mtmp);
  13.      boolean burycorpse = FALSE;
  14.  
  15.      /* KMH, conduct */
  16.      u.uconduct.killer++;
  17.  
  18.      if (dest & 1) {
  19.          const char *verb = nonliving(mtmp->data) ? "destroy" : "kill";
  20.  
  21.          if (!wasinside && !canspotmon(mtmp))
  22.              You("%s it!", verb);
  23.          else {
  24.              You("%s %s!", verb,
  25.                  !mtmp->mtame
  26.                      ? mon_nam(mtmp)
  27.                      : x_monnam(mtmp,
  28.                                 (has_mname(mtmp)) ? ARTICLE_NONE : ARTICLE_THE,
  29.                                 "poor",
  30.                                 (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0,
  31.                                 FALSE));
  32.          }
  33.      }
  34.  
  35.      if (mtmp->mtrapped && (t = t_at(x, y)) != 0
  36.          && (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
  37.          if (sobj_at(BOULDER, x, y))
  38.              dest |= 2; /*
  39.          * Prevent corpses/treasure being created "on top"
  40.          * of the boulder that is about to fall in. This is
  41.          * out of order, but cannot be helped unless this
  42.          * whole routine is rearranged.
  43.          */
  44.          if (m_carrying(mtmp, BOULDER))
  45.              burycorpse = TRUE;
  46.      }
  47.  
  48.      /* your pet knows who just killed it...watch out */
  49.      if (mtmp->mtame && !mtmp->isminion)
  50.          EDOG(mtmp)->killed_by_u = 1;
  51.  
  52.      if (wasinside && thrownobj && thrownobj != uball) {
  53.          /* thrown object has killed hero's engulfer; add it to mon's
  54.             inventory now so that it will be placed with mon's other
  55.             stuff prior to lookhere/autopickup when hero is expelled
  56.             below (as a side-effect, this missile has immunity from
  57.             being consumed [for this shot/throw only]) */
  58.          mpickobj(mtmp, thrownobj);
  59.          /* let throwing code know that missile has been disposed of */
  60.          thrownobj = 0;
  61.      }
  62.  
  63.      vamp_rise_msg = FALSE; /* might get set in mondead() */
  64.      /* dispose of monster and make cadaver */
  65.      if (stoned)
  66.          monstone(mtmp);
  67.      else
  68.          mondead(mtmp);
  69.  
  70.      if (mtmp->mhp > 0) { /* monster lifesaved */
  71.          /* Cannot put the non-visible lifesaving message in
  72.           * lifesaved_monster() since the message appears only when you
  73.           * kill it (as opposed to visible lifesaving which always
  74.           * appears).
  75.           */
  76.          stoned = FALSE;
  77.          if (!cansee(x, y) && !vamp_rise_msg)
  78.              pline("Maybe not...");
  79.          return;
  80.      }
  81.  
  82.      mdat = mtmp->data; /* note: mondead can change mtmp->data */
  83.      mndx = monsndx(mdat);
  84.  
  85.      if (stoned) {
  86.          stoned = FALSE;
  87.          goto cleanup;
  88.      }
  89.  
  90.      if ((dest & 2) || LEVEL_SPECIFIC_NOCORPSE(mdat))
  91.          goto cleanup;
  92.  
  93.  #ifdef MAIL
  94.      if (mdat == &mons[PM_MAIL_DAEMON]) {
  95.          stackobj(mksobj_at(SCR_MAIL, x, y, FALSE, FALSE));
  96.      }
  97.  #endif
  98.      if (accessible(x, y) || is_pool(x, y)) {
  99.          struct obj *cadaver;
  100.          int otyp;
  101.  
  102.          /* illogical but traditional "treasure drop" */
  103.          if (!rn2(6) && !(mvitals[mndx].mvflags & G_NOCORPSE)
  104.              /* no extra item from swallower or steed */
  105.              && (x != u.ux || y != u.uy)
  106.              /* no extra item from kops--too easy to abuse */
  107.              && mdat->mlet != S_KOP
  108.              /* no items from cloned monsters */
  109.              && !mtmp->mcloned) {
  110.              otmp = mkobj(RANDOM_CLASS, TRUE);
  111.              /* don't create large objects from small monsters */
  112.              otyp = otmp->otyp;
  113.              if (mdat->msize < MZ_HUMAN && otyp != FIGURINE
  114.                  /* oc_big is also oc_bimanual and oc_bulky */
  115.                  && (otmp->owt > 30 || objects[otyp].oc_big)) {
  116.                  delobj(otmp);
  117.              } else if (!flooreffects(otmp, x, y, (dest & 1) ? "fall" : "")) {
  118.                  place_object(otmp, x, y);
  119.                  stackobj(otmp);
  120.              }
  121.          }
  122.          /* corpse--none if hero was inside the monster */
  123.          if (!wasinside && corpse_chance(mtmp, (struct monst *) 0, FALSE)) {
  124.              cadaver = make_corpse(mtmp, burycorpse ? CORPSTAT_BURIED
  125.                                                     : CORPSTAT_NONE);
  126.              if (burycorpse && cadaver && cansee(x, y) && !mtmp->minvis
  127.                  && cadaver->where == OBJ_BURIED && (dest & 1)) {
  128.                  pline("%s corpse ends up buried.", s_suffix(Monnam(mtmp)));
  129.              }
  130.          }
  131.      }
  132.      if (wasinside)
  133.          spoteffects(TRUE); /* poor man's expels() */
  134.      /* monster is gone, corpse or other object might now be visible */
  135.      newsym(x, y);
  136.  
  137.  cleanup:
  138.      /* punish bad behaviour */
  139.      if (is_human(mdat) && (!always_hostile(mdat) && mtmp->malign <= 0)
  140.          && (mndx < PM_ARCHEOLOGIST || mndx > PM_WIZARD)
  141.          && u.ualign.type != A_CHAOTIC) {
  142.          HTelepat &= ~INTRINSIC;
  143.          change_luck(-2);
  144.          You("murderer!");
  145.          if (Blind && !Blind_telepat)
  146.              see_monsters(); /* Can't sense monsters any more. */
  147.      }
  148.      if ((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame)
  149.          change_luck(-1);
  150.      if (is_unicorn(mdat) && sgn(u.ualign.type) == sgn(mdat->maligntyp)) {
  151.          change_luck(-5);
  152.          You_feel("guilty...");
  153.      }
  154.  
  155.      /* give experience points */
  156.      tmp = experience(mtmp, (int) mvitals[mndx].died);
  157.      more_experienced(tmp, 0);
  158.      newexplevel(); /* will decide if you go up */
  159.  
  160.      /* adjust alignment points */
  161.      if (mtmp->m_id == quest_status.leader_m_id) { /* REAL BAD! */
  162.          adjalign(-(u.ualign.record + (int) ALIGNLIM / 2));
  163.          pline("That was %sa bad idea...",
  164.                u.uevent.qcompleted ? "probably " : "");
  165.      } else if (mdat->msound == MS_NEMESIS) { /* Real good! */
  166.          adjalign((int) (ALIGNLIM / 4));
  167.      } else if (mdat->msound == MS_GUARDIAN) { /* Bad */
  168.          adjalign(-(int) (ALIGNLIM / 8));
  169.          if (!Hallucination)
  170.              pline("That was probably a bad idea...");
  171.          else
  172.              pline("Whoopsie-daisy!");
  173.      } else if (mtmp->ispriest) {
  174.          adjalign((p_coaligned(mtmp)) ? -2 : 2);
  175.          /* cancel divine protection for killing your priest */
  176.          if (p_coaligned(mtmp))
  177.              u.ublessed = 0;
  178.          if (mdat->maligntyp == A_NONE)
  179.              adjalign((int) (ALIGNLIM / 4)); /* BIG bonus */
  180.      } else if (mtmp->mtame) {
  181.          adjalign(-15); /* bad!! */
  182.          /* your god is mighty displeased... */
  183.          if (!Hallucination)
  184.              You_hear("the rumble of distant thunder...");
  185.          else
  186.              You_hear("the studio audience applaud!");
  187.      } else if (mtmp->mpeaceful)
  188.          adjalign(-5);
  189.  
  190.      /* malign was already adjusted for u.ualign.type and randomization */
  191.      adjalign(mtmp->malign);
  192.  }
  193.  

mon_to_stone

  1.  /* changes the monster into a stone monster of the same type
  2.     this should only be called when poly_when_stoned() is true */
  3.  void
  4.  mon_to_stone(mtmp)
  5.  struct monst *mtmp;
  6.  {
  7.      if (mtmp->data->mlet == S_GOLEM) {
  8.          /* it's a golem, and not a stone golem */
  9.          if (canseemon(mtmp))
  10.              pline("%s solidifies...", Monnam(mtmp));
  11.          if (newcham(mtmp, &mons[PM_STONE_GOLEM], FALSE, FALSE)) {
  12.              if (canseemon(mtmp))
  13.                  pline("Now it's %s.", an(mtmp->data->mname));
  14.          } else {
  15.              if (canseemon(mtmp))
  16.                  pline("... and returns to normal.");
  17.          }
  18.      } else
  19.          impossible("Can't polystone %s!", a_monnam(mtmp));
  20.  }
  21.  

mnexto

  1.  /* make monster mtmp next to you (if possible);
  2.     might place monst on far side of a wall or boulder */
  3.  void
  4.  mnexto(mtmp)
  5.  struct monst *mtmp;
  6.  {
  7.      coord mm;
  8.      boolean couldspot = canspotmon(mtmp);
  9.  
  10.      if (mtmp == u.usteed) {
  11.          /* Keep your steed in sync with you instead */
  12.          mtmp->mx = u.ux;
  13.          mtmp->my = u.uy;
  14.          return;
  15.      }
  16.  
  17.      if (!enexto(&mm, u.ux, u.uy, mtmp->data))
  18.          return;
  19.      rloc_to(mtmp, mm.x, mm.y);
  20.      if (!in_mklev && (mtmp->mstrategy & STRAT_APPEARMSG)) {
  21.          mtmp->mstrategy &= ~STRAT_APPEARMSG; /* one chance only */
  22.          if (!couldspot && canspotmon(mtmp))
  23.              pline("%s suddenly %s!", Amonnam(mtmp),
  24.                    !Blind ? "appears" : "arrives");
  25.      }
  26.      return;
  27.  }
  28.  

maybe_mnexto

  1.  /* like mnexto() but requires destination to be directly accessible */
  2.  void
  3.  maybe_mnexto(mtmp)
  4.  struct monst *mtmp;
  5.  {
  6.      coord mm;
  7.      struct permonst *ptr = mtmp->data;
  8.      boolean diagok = !NODIAG(ptr - mons);
  9.      int tryct = 20;
  10.  
  11.      do {
  12.          if (!enexto(&mm, u.ux, u.uy, ptr))
  13.              return;
  14.          if (couldsee(mm.x, mm.y)
  15.              /* don't move grid bugs diagonally */
  16.              && (diagok || mm.x == mtmp->mx || mm.y == mtmp->my)) {
  17.              rloc_to(mtmp, mm.x, mm.y);
  18.              return;
  19.          }
  20.      } while (--tryct > 0);
  21.  }
  22.  

mnearto

  1.  /* mnearto()
  2.   * Put monster near (or at) location if possible.
  3.   * Returns:
  4.   *      1 - if a monster was moved from x, y to put mtmp at x, y.
  5.   *      0 - in most cases.
  6.   */
  7.  boolean
  8.  mnearto(mtmp, x, y, move_other)
  9.  register struct monst *mtmp;
  10.  xchar x, y;
  11.  boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
  12.  {
  13.      struct monst *othermon = (struct monst *) 0;
  14.      xchar newx, newy;
  15.      coord mm;
  16.  
  17.      if (mtmp->mx == x && mtmp->my == y)
  18.          return FALSE;
  19.  
  20.      if (move_other && (othermon = m_at(x, y)) != 0) {
  21.          if (othermon->wormno)
  22.              remove_worm(othermon);
  23.          else
  24.              remove_monster(x, y);
  25.      }
  26.  
  27.      newx = x;
  28.      newy = y;
  29.      if (!goodpos(newx, newy, mtmp, 0)) {
  30.          /* Actually we have real problems if enexto ever fails.
  31.           * Migrating_mons that need to be placed will cause
  32.           * no end of trouble.
  33.           */
  34.          if (!enexto(&mm, newx, newy, mtmp->data))
  35.              return FALSE;
  36.          newx = mm.x;
  37.          newy = mm.y;
  38.      }
  39.      rloc_to(mtmp, newx, newy);
  40.  
  41.      if (move_other && othermon) {
  42.          xchar oldx = othermon->mx, oldy = othermon->my;
  43.  
  44.          othermon->mx = othermon->my = 0;
  45.          (void) mnearto(othermon, x, y, FALSE);
  46.          if (othermon->mx == 0 && othermon->my == 0) {
  47.              /* reloc failed, dump monster into "limbo"
  48.                 (aka migrate to current level) */
  49.              othermon->mx = oldx;
  50.              othermon->my = oldy;
  51.              mdrop_special_objs(othermon);
  52.              migrate_to_level(othermon, ledger_no(&u.uz), MIGR_APPROX_XY, NULL);
  53.          }
  54.      }
  55.  
  56.      return FALSE;
  57.  }
  58.  

m_respond

  1.  /* monster responds to player action; not the same as a passive attack;
  2.     assumes reason for response has been tested, and response _must_ be made */
  3.  void
  4.  m_respond(mtmp)
  5.  struct monst *mtmp;
  6.  {
  7.      if (mtmp->data->msound == MS_SHRIEK) {
  8.          if (!Deaf) {
  9.              pline("%s shrieks.", Monnam(mtmp));
  10.              stop_occupation();
  11.          }
  12.          if (!rn2(10)) {
  13.              if (!rn2(13))
  14.                  (void) makemon(&mons[PM_PURPLE_WORM], 0, 0, NO_MM_FLAGS);
  15.              else
  16.                  (void) makemon((struct permonst *) 0, 0, 0, NO_MM_FLAGS);
  17.          }
  18.          aggravate();
  19.      }
  20.      if (mtmp->data == &mons[PM_MEDUSA]) {
  21.          register int i;
  22.  
  23.          for (i = 0; i < NATTK; i++)
  24.              if (mtmp->data->mattk[i].aatyp == AT_GAZE) {
  25.                  (void) gazemu(mtmp, &mtmp->data->mattk[i]);
  26.                  break;
  27.              }
  28.      }
  29.  }
  30.  

setmangry

  1.  void
  2.  setmangry(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      mtmp->mstrategy &= ~STRAT_WAITMASK;
  6.      if (!mtmp->mpeaceful)
  7.          return;
  8.      if (mtmp->mtame)
  9.          return;
  10.      mtmp->mpeaceful = 0;
  11.      if (mtmp->ispriest) {
  12.          if (p_coaligned(mtmp))
  13.              adjalign(-5); /* very bad */
  14.          else
  15.              adjalign(2);
  16.      } else
  17.          adjalign(-1); /* attacking peaceful monsters is bad */
  18.      if (couldsee(mtmp->mx, mtmp->my)) {
  19.          if (humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
  20.              pline("%s gets angry!", Monnam(mtmp));
  21.          else if (flags.verbose && !Deaf)
  22.              growl(mtmp);
  23.      }
  24.  
  25.      /* attacking your own quest leader will anger his or her guardians */
  26.      if (!context.mon_moving /* should always be the case here */
  27.          && mtmp->data == &mons[quest_info(MS_LEADER)]) {
  28.          struct monst *mon;
  29.          struct permonst *q_guardian = &mons[quest_info(MS_GUARDIAN)];
  30.          int got_mad = 0;
  31.  
  32.          /* guardians will sense this attack even if they can't see it */
  33.          for (mon = fmon; mon; mon = mon->nmon) {
  34.              if (DEADMONSTER(mon))
  35.                  continue;
  36.              if (mon->data == q_guardian && mon->mpeaceful) {
  37.                  mon->mpeaceful = 0;
  38.                  if (canseemon(mon))
  39.                      ++got_mad;
  40.              }
  41.          }
  42.          if (got_mad && !Hallucination)
  43.              pline_The("%s appear%s to be angry too...",
  44.                        got_mad == 1 ? q_guardian->mname
  45.                                     : makeplural(q_guardian->mname),
  46.                        got_mad == 1 ? "s" : "");
  47.      }
  48.  }
  49.  

wakeup

  1.  /* wake up a monster, usually making it angry in the process */
  2.  void
  3.  wakeup(mtmp)
  4.  register struct monst *mtmp;
  5.  {
  6.      mtmp->msleeping = 0;
  7.      finish_meating(mtmp);
  8.      setmangry(mtmp);
  9.      if (mtmp->m_ap_type) {
  10.          seemimic(mtmp);
  11.      } else if (context.forcefight && !context.mon_moving
  12.                 && mtmp->mundetected) {
  13.          mtmp->mundetected = 0;
  14.          newsym(mtmp->mx, mtmp->my);
  15.      }
  16.  }
  17.  

wake_nearby

  1.  /* Wake up nearby monsters without angering them. */
  2.  void
  3.  wake_nearby()
  4.  {
  5.      register struct monst *mtmp;
  6.  
  7.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  8.          if (DEADMONSTER(mtmp))
  9.              continue;
  10.          if (distu(mtmp->mx, mtmp->my) < u.ulevel * 20) {
  11.              mtmp->msleeping = 0;
  12.              if (!unique_corpstat(mtmp->data))
  13.                  mtmp->mstrategy &= ~STRAT_WAITMASK;
  14.              if (mtmp->mtame && !mtmp->isminion)
  15.                  EDOG(mtmp)->whistletime = moves;
  16.          }
  17.      }
  18.  }
  19.  

wake_nearto

  1.  /* Wake up monsters near some particular location. */
  2.  void
  3.  wake_nearto(x, y, distance)
  4.  register int x, y, distance;
  5.  {
  6.      register struct monst *mtmp;
  7.  
  8.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  9.          if (DEADMONSTER(mtmp))
  10.              continue;
  11.          if (distance == 0 || dist2(mtmp->mx, mtmp->my, x, y) < distance) {
  12.              mtmp->msleeping = 0;
  13.              if (!unique_corpstat(mtmp->data))
  14.                  mtmp->mstrategy &= ~STRAT_WAITMASK;
  15.          }
  16.      }
  17.  }
  18.  

seemimic

  1.  /* NOTE: we must check for mimicry before calling this routine */
  2.  void
  3.  seemimic(mtmp)
  4.  register struct monst *mtmp;
  5.  {
  6.      boolean is_blocker_appear = (is_door_mappear(mtmp)
  7.                                   || is_obj_mappear(mtmp, BOULDER));
  8.  
  9.      if (has_mcorpsenm(mtmp))
  10.          freemcorpsenm(mtmp);
  11.  
  12.      mtmp->m_ap_type = M_AP_NOTHING;
  13.      mtmp->mappearance = 0;
  14.  
  15.      /*
  16.       *  Discovered mimics don't block light.
  17.       */
  18.      if (is_blocker_appear
  19.          && !does_block(mtmp->mx, mtmp->my, &levl[mtmp->mx][mtmp->my]))
  20.          unblock_point(mtmp->mx, mtmp->my);
  21.  
  22.      newsym(mtmp->mx, mtmp->my);
  23.  }
  24.  

rescham

  1.  /* force all chameleons to become normal */
  2.  void
  3.  rescham()
  4.  {
  5.      register struct monst *mtmp;
  6.      int mcham;
  7.  
  8.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  9.          if (DEADMONSTER(mtmp))
  10.              continue;
  11.          mcham = (int) mtmp->cham;
  12.          if (mcham >= LOW_PM) {
  13.              (void) newcham(mtmp, &mons[mcham], FALSE, FALSE);
  14.              mtmp->cham = NON_PM;
  15.          }
  16.          if (is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
  17.              new_were(mtmp);
  18.          if (mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
  19.              seemimic(mtmp);
  20.              /* we pretend that the mimic doesn't
  21.                 know that it has been unmasked */
  22.              mtmp->msleeping = 1;
  23.          }
  24.      }
  25.  }
  26.  

restartcham

  1.  /* Let the chameleons change again -dgk */
  2.  void
  3.  restartcham()
  4.  {
  5.      register struct monst *mtmp;
  6.  
  7.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  8.          if (DEADMONSTER(mtmp))
  9.              continue;
  10.          mtmp->cham = pm_to_cham(monsndx(mtmp->data));
  11.          if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping
  12.              && cansee(mtmp->mx, mtmp->my)) {
  13.              set_mimic_sym(mtmp);
  14.              newsym(mtmp->mx, mtmp->my);
  15.          }
  16.      }
  17.  }
  18.  

restore_cham

  1.  /* called when restoring a monster from a saved level; protection
  2.     against shape-changing might be different now than it was at the
  3.     time the level was saved. */
  4.  void
  5.  restore_cham(mon)
  6.  struct monst *mon;
  7.  {
  8.      int mcham;
  9.  
  10.      if (Protection_from_shape_changers) {
  11.          mcham = (int) mon->cham;
  12.          if (mcham >= LOW_PM) {
  13.              mon->cham = NON_PM;
  14.              (void) newcham(mon, &mons[mcham], FALSE, FALSE);
  15.          } else if (is_were(mon->data) && !is_human(mon->data)) {
  16.              new_were(mon);
  17.          }
  18.      } else if (mon->cham == NON_PM) {
  19.          mon->cham = pm_to_cham(monsndx(mon->data));
  20.      }
  21.  }
  22.  

restrap

  1.  /* unwatched hiders may hide again; if so, returns True */
  2.  STATIC_OVL boolean
  3.  restrap(mtmp)
  4.  register struct monst *mtmp;
  5.  {
  6.      struct trap *t;
  7.  
  8.      if (mtmp->mcan || mtmp->m_ap_type || cansee(mtmp->mx, mtmp->my)
  9.          || rn2(3) || mtmp == u.ustuck
  10.          /* can't hide while trapped except in pits */
  11.          || (mtmp->mtrapped && (t = t_at(mtmp->mx, mtmp->my)) != 0
  12.              && !(t->ttyp == PIT || t->ttyp == SPIKED_PIT))
  13.          || (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2))
  14.          return FALSE;
  15.  
  16.      if (mtmp->data->mlet == S_MIMIC) {
  17.          set_mimic_sym(mtmp);
  18.          return TRUE;
  19.      } else if (levl[mtmp->mx][mtmp->my].typ == ROOM) {
  20.          mtmp->mundetected = 1;
  21.          return TRUE;
  22.      }
  23.  
  24.      return FALSE;
  25.  }
  26.  

hideunder

  1.  /* monster/hero tries to hide under something at the current location */
  2.  boolean
  3.  hideunder(mtmp)
  4.  struct monst *mtmp;
  5.  {
  6.      struct trap *t;
  7.      boolean undetected = FALSE, is_u = (mtmp == &youmonst);
  8.      xchar x = is_u ? u.ux : mtmp->mx, y = is_u ? u.uy : mtmp->my;
  9.  
  10.      if (mtmp == u.ustuck) {
  11.          ; /* can't hide if holding you or held by you */
  12.      } else if (is_u ? (u.utrap && u.utraptype != TT_PIT)
  13.                      : (mtmp->mtrapped && (t = t_at(x, y)) != 0
  14.                         && !(t->ttyp == PIT || t->ttyp == SPIKED_PIT))) {
  15.          ; /* can't hide while stuck in a non-pit trap */
  16.      } else if (mtmp->data->mlet == S_EEL) {
  17.          undetected = (is_pool(x, y) && !Is_waterlevel(&u.uz));
  18.      } else if (hides_under(mtmp->data) && OBJ_AT(x, y)) {
  19.          struct obj *otmp = level.objects[x][y];
  20.  
  21.          /* most monsters won't hide under cockatrice corpse */
  22.          if (otmp->nexthere || otmp->otyp != CORPSE
  23.              || (mtmp == &youmonst ? Stone_resistance : resists_ston(mtmp))
  24.              || !touch_petrifies(&mons[otmp->corpsenm]))
  25.              undetected = TRUE;
  26.      }
  27.  
  28.      if (is_u)
  29.          u.uundetected = undetected;
  30.      else
  31.          mtmp->mundetected = undetected;
  32.      return undetected;
  33.  }
  34.  

hide_monst

  1.  /* called when returning to a previously visited level */
  2.  void
  3.  hide_monst(mon)
  4.  struct monst *mon;
  5.  {
  6.      boolean hider_under = hides_under(mon->data) || mon->data->mlet == S_EEL;
  7.  
  8.      if ((is_hider(mon->data) || hider_under)
  9.          && !(mon->mundetected || mon->m_ap_type)) {
  10.          xchar x = mon->mx, y = mon->my;
  11.          char save_viz = viz_array[y][x];
  12.  
  13.          /* override vision, forcing hero to be unable to see monster's spot */
  14.          viz_array[y][x] &= ~(IN_SIGHT | COULD_SEE);
  15.          if (is_hider(mon->data))
  16.              (void) restrap(mon);
  17.          /* try again if mimic missed its 1/3 chance to hide */
  18.          if (mon->data->mlet == S_MIMIC && !mon->m_ap_type)
  19.              (void) restrap(mon);
  20.          if (hider_under)
  21.              (void) hideunder(mon);
  22.          viz_array[y][x] = save_viz;
  23.      }
  24.  }
  25.  

mon_animal_list

  1.  static short *animal_list = 0; /* list of PM values for animal monsters */
  2.  static int animal_list_count;
  3.  
  4.  void
  5.  mon_animal_list(construct)
  6.  boolean construct;
  7.  {
  8.      if (construct) {
  9.          short animal_temp[SPECIAL_PM];
  10.          int i, n;
  11.  
  12.          /* if (animal_list) impossible("animal_list already exists"); */
  13.  
  14.          for (n = 0, i = LOW_PM; i < SPECIAL_PM; i++)
  15.              if (is_animal(&mons[i]))
  16.                  animal_temp[n++] = i;
  17.          /* if (n == 0) animal_temp[n++] = NON_PM; */
  18.  
  19.          animal_list = (short *) alloc(n * sizeof *animal_list);
  20.          (void) memcpy((genericptr_t) animal_list, (genericptr_t) animal_temp,
  21.                        n * sizeof *animal_list);
  22.          animal_list_count = n;
  23.      } else { /* release */
  24.          if (animal_list)
  25.              free((genericptr_t) animal_list), animal_list = 0;
  26.          animal_list_count = 0;
  27.      }
  28.  }
  29.  

pick_animal

  1.  STATIC_OVL int
  2.  pick_animal()
  3.  {
  4.      int res;
  5.  
  6.      if (!animal_list)
  7.          mon_animal_list(TRUE);
  8.  
  9.      res = animal_list[rn2(animal_list_count)];
  10.      /* rogue level should use monsters represented by uppercase letters
  11.         only, but since chameleons aren't generated there (not uppercase!)
  12.         we don't perform a lot of retries */
  13.      if (Is_rogue_level(&u.uz) && !isupper((uchar) mons[res].mlet))
  14.          res = animal_list[rn2(animal_list_count)];
  15.      return res;
  16.  }
  17.  

decide_to_shapeshift

  1.  void
  2.  decide_to_shapeshift(mon, shiftflags)
  3.  struct monst *mon;
  4.  int shiftflags;
  5.  {
  6.      struct permonst *ptr;
  7.      unsigned was_female = mon->female;
  8.      boolean msg = FALSE;
  9.  
  10.      if ((shiftflags & SHIFT_MSG)
  11.          || ((shiftflags & SHIFT_SEENMSG) && sensemon(mon)))
  12.          msg = TRUE;
  13.  
  14.      if (is_vampshifter(mon)) {
  15.          /* The vampire has to be in good health (mhp) to maintain
  16.           * its shifted form.
  17.               *
  18.           * If we're shifted and getting low on hp, maybe shift back.
  19.           * If we're not already shifted and in good health, maybe shift.
  20.           */
  21.          if ((mon->mhp <= mon->mhpmax / 6) && rn2(4) && (mon->cham >= LOW_PM))
  22.              (void) newcham(mon, &mons[mon->cham], FALSE, msg);
  23.      } else if (mon->data->mlet == S_VAMPIRE && mon->cham == NON_PM && !rn2(6)
  24.                 && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
  25.          (void) newcham(mon, (struct permonst *) 0, FALSE, msg);
  26.      }
  27.      /* override the 10% chance for sex change */
  28.      ptr = mon->data;
  29.      if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
  30.          mon->female = was_female;
  31.  }
  32.  

pickvampshape

  1.  STATIC_OVL int
  2.  pickvampshape(mon)
  3.  struct monst *mon;
  4.  {
  5.      int mndx = mon->cham;
  6.      /* avoid picking monsters with lowercase display symbols ('d' for wolf
  7.         and 'v' for fog cloud) on rogue level*/
  8.      boolean uppercase_only = Is_rogue_level(&u.uz);
  9.  
  10.      switch (mndx) {
  11.      case PM_VLAD_THE_IMPALER:
  12.          /* ensure Vlad can keep carrying the Candelabrum */
  13.          if (mon_has_special(mon))
  14.              break; /* leave mndx as is */
  15.      /*FALLTHRU*/
  16.      case PM_VAMPIRE_LORD: /* vampire lord or Vlad can become wolf */
  17.          if (!rn2(10) && !uppercase_only) {
  18.              mndx = PM_WOLF;
  19.              break;
  20.          }
  21.      /*FALLTHRU*/
  22.      case PM_VAMPIRE: /* any vampire can become fog or bat */
  23.          mndx = (!rn2(4) && !uppercase_only) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
  24.          break;
  25.      }
  26.      return mndx;
  27.  }
  28.  

isspecmon

  1.  /* nonshapechangers who warrant special polymorph handling */
  2.  STATIC_OVL boolean
  3.  isspecmon(mon)
  4.  struct monst *mon;
  5.  {
  6.      return (mon->isshk || mon->ispriest || mon->isgd
  7.              || mon->m_id == quest_status.leader_m_id);
  8.  }
  9.  

validspecmon

  1.  /* restrict certain special monsters (shopkeepers, aligned priests,
  2.     vault guards) to forms that allow them to behave sensibly (catching
  3.     gold, speaking?) so that they don't need too much extra code */
  4.  STATIC_OVL boolean
  5.  validspecmon(mon, mndx)
  6.  struct monst *mon;
  7.  int mndx;
  8.  {
  9.      if (mndx == NON_PM)
  10.          return TRUE; /* caller wants random */
  11.  
  12.      if (!accept_newcham_form(mndx))
  13.          return FALSE; /* geno'd or !polyok */
  14.  
  15.      if (isspecmon(mon)) {
  16.          struct permonst *ptr = &mons[mndx];
  17.  
  18.          /* reject notake because object manipulation is expected
  19.             and nohead because speech capability is expected */
  20.          if (notake(ptr) || !has_head(ptr))
  21.              return FALSE;
  22.          /* [should we check ptr->msound here too?] */
  23.      }
  24.      return TRUE; /* potential new form is ok */
  25.  }
  26.  

validvamp

  1.  /* prevent wizard mode user from specifying invalid vampshifter shape */
  2.  STATIC_OVL boolean
  3.  validvamp(mon, mndx_p, monclass)
  4.  struct monst *mon;
  5.  int *mndx_p, monclass;
  6.  {
  7.      /* simplify caller's usage */
  8.      if (!is_vampshifter(mon))
  9.          return validspecmon(mon, *mndx_p);
  10.  
  11.      if (*mndx_p == PM_VAMPIRE || *mndx_p == PM_VAMPIRE_LORD
  12.          || *mndx_p == PM_VLAD_THE_IMPALER) {
  13.          /* player picked some type of vampire; use mon's self */
  14.          *mndx_p = mon->cham;
  15.          return TRUE;
  16.      }
  17.      if (mon->cham == PM_VLAD_THE_IMPALER && mon_has_special(mon)) {
  18.          /* Vlad with Candelabrum; override choice, then accept it */
  19.          *mndx_p = PM_VLAD_THE_IMPALER;
  20.          return TRUE;
  21.      }
  22.      /* basic vampires can't become wolves; any can become fog or bat
  23.         (we don't enforce upper-case only for rogue level here) */
  24.      if (*mndx_p == PM_WOLF)
  25.          return (boolean) (mon->cham != PM_VAMPIRE);
  26.      if (*mndx_p == PM_FOG_CLOUD || *mndx_p == PM_VAMPIRE_BAT)
  27.          return TRUE;
  28.  
  29.      /* if we get here, specific type was no good; try by class */
  30.      switch (monclass) {
  31.      case S_VAMPIRE:
  32.          *mndx_p = mon->cham;
  33.          break;
  34.      case S_BAT:
  35.          *mndx_p = PM_VAMPIRE_BAT;
  36.          break;
  37.      case S_VORTEX:
  38.          *mndx_p = PM_FOG_CLOUD;
  39.          break;
  40.      case S_DOG:
  41.          if (mon->cham != PM_VAMPIRE) {
  42.              *mndx_p = PM_WOLF;
  43.              break;
  44.          }
  45.      /*FALLTHRU*/
  46.      default:
  47.          *mndx_p = NON_PM;
  48.          break;
  49.      }
  50.      return (boolean) (*mndx_p != NON_PM);
  51.  }
  52.  

select_newcham_form

  1.  int
  2.  select_newcham_form(mon)
  3.  struct monst *mon;
  4.  {
  5.      int mndx = NON_PM, tryct;
  6.  
  7.      switch (mon->cham) {
  8.      case PM_SANDESTIN:
  9.          if (rn2(7))
  10.              mndx = pick_nasty();
  11.          break;
  12.      case PM_DOPPELGANGER:
  13.          if (!rn2(7)) {
  14.              mndx = pick_nasty();
  15.          } else if (rn2(3)) { /* role monsters */
  16.              mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1, PM_ARCHEOLOGIST);
  17.          } else if (!rn2(3)) { /* quest guardians */
  18.              mndx = rn1(PM_APPRENTICE - PM_STUDENT + 1, PM_STUDENT);
  19.              /* avoid own role's guardian */
  20.              if (mndx == urole.guardnum)
  21.                  mndx = NON_PM;
  22.          } else { /* general humanoids */
  23.              tryct = 5;
  24.              do {
  25.                  mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
  26.                  if (humanoid(&mons[mndx]) && polyok(&mons[mndx]))
  27.                      break;
  28.              } while (--tryct > 0);
  29.              if (!tryct)
  30.                  mndx = NON_PM;
  31.          }
  32.          break;
  33.      case PM_CHAMELEON:
  34.          if (!rn2(3))
  35.              mndx = pick_animal();
  36.          break;
  37.      case PM_VLAD_THE_IMPALER:
  38.      case PM_VAMPIRE_LORD:
  39.      case PM_VAMPIRE:
  40.          mndx = pickvampshape(mon);
  41.          break;
  42.      case NON_PM: /* ordinary */
  43.        {
  44.          struct obj *m_armr = which_armor(mon, W_ARM);
  45.  
  46.          if (m_armr && Is_dragon_scales(m_armr))
  47.              mndx = (int) (Dragon_scales_to_pm(m_armr) - mons);
  48.          else if (m_armr && Is_dragon_mail(m_armr))
  49.              mndx = (int) (Dragon_mail_to_pm(m_armr) - mons);
  50.        }
  51.          break;
  52.      }
  53.      /* for debugging: allow control of polymorphed monster */
  54.      if (wizard && iflags.mon_polycontrol) {
  55.          char pprompt[BUFSZ], buf[BUFSZ];
  56.          int monclass;
  57.  
  58.          Sprintf(pprompt, "Change %s @ <%d,%d> into what kind of monster?",
  59.                  noit_mon_nam(mon), (int) mon->mx, (int) mon->my);
  60.          tryct = 5;
  61.          do {
  62.              monclass = 0;
  63.              getlin(pprompt, buf);
  64.              mungspaces(buf);
  65.              /* for ESC, take form selected above (might be NON_PM) */
  66.              if (*buf == '\033')
  67.                  break;
  68.              /* for "*", use NON_PM to pick an arbitrary shape below */
  69.              if (!strcmp(buf, "*") || !strcmp(buf, "random")) {
  70.                  mndx = NON_PM;
  71.                  break;
  72.              }
  73.              mndx = name_to_mon(buf);
  74.              if (mndx == NON_PM) {
  75.                  /* didn't get a type, so check whether it's a class
  76.                     (single letter or text match with def_monsyms[]) */
  77.                  monclass = name_to_monclass(buf, &mndx);
  78.                  if (monclass && mndx == NON_PM)
  79.                      mndx = mkclass_poly(monclass);
  80.              }
  81.              if (mndx >= LOW_PM) {
  82.                  /* got a specific type of monster; use it if we can */
  83.                  if (validvamp(mon, &mndx, monclass))
  84.                      break;
  85.                  /* can't; revert to random in case we exhaust tryct */
  86.                  mndx = NON_PM;
  87.              }
  88.  
  89.              pline("It can't become that.");
  90.          } while (--tryct > 0);
  91.          if (!tryct)
  92.              pline1(thats_enough_tries);
  93.          if (is_vampshifter(mon) && !validvamp(mon, &mndx, monclass))
  94.              mndx = pickvampshape(mon); /* don't resort to arbitrary */
  95.      }
  96.  
  97.      /* if no form was specified above, pick one at random now */
  98.      if (mndx == NON_PM) {
  99.          tryct = 50;
  100.          do {
  101.              mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
  102.          } while (--tryct > 0 && !validspecmon(mon, mndx)
  103.                   /* try harder to select uppercase monster on rogue level */
  104.                   && (tryct > 40 && Is_rogue_level(&u.uz)
  105.                       && !isupper((uchar) mons[mndx].mlet)));
  106.      }
  107.      return mndx;
  108.  }
  109.  

accept_newcham_form

  1.  /* this used to be inline within newcham() but monpolycontrol needs it too */
  2.  STATIC_OVL struct permonst *
  3.  accept_newcham_form(mndx)
  4.  int mndx;
  5.  {
  6.      struct permonst *mdat;
  7.  
  8.      if (mndx == NON_PM)
  9.          return 0;
  10.      mdat = &mons[mndx];
  11.      if ((mvitals[mndx].mvflags & G_GENOD) != 0)
  12.          return 0;
  13.      if (is_placeholder(mdat))
  14.          return 0;
  15.      /* select_newcham_form() might deliberately pick a player
  16.         character type (random selection never does) which
  17.         polyok() rejects, so we need a special case here */
  18.      if (is_mplayer(mdat))
  19.          return mdat;
  20.      /* polyok() rules out M2_PNAME, M2_WERE, and all humans except Kops */
  21.      return polyok(mdat) ? mdat : 0;
  22.  }
  23.  

mgender_from_permonst

  1.  void
  2.  mgender_from_permonst(mtmp, mdat)
  3.  struct monst *mtmp;
  4.  struct permonst *mdat;
  5.  {
  6.      if (is_male(mdat)) {
  7.          if (mtmp->female)
  8.              mtmp->female = FALSE;
  9.      } else if (is_female(mdat)) {
  10.          if (!mtmp->female)
  11.              mtmp->female = TRUE;
  12.      } else if (!is_neuter(mdat)) {
  13.          if (!rn2(10))
  14.              mtmp->female = !mtmp->female;
  15.      }
  16.  }
  17.  

newcham

  1.  /* make a chameleon take on another shape, or a polymorph target
  2.     (possibly self-inflicted) become a different monster;
  3.     returns 1 if it actually changes form */
  4.  int
  5.  newcham(mtmp, mdat, polyspot, msg)
  6.  struct monst *mtmp;
  7.  struct permonst *mdat;
  8.  boolean polyspot; /* change is the result of wand or spell of polymorph */
  9.  boolean msg;      /* "The oldmon turns into a newmon!" */
  10.  {
  11.      int hpn, hpd;
  12.      int mndx, tryct;
  13.      struct permonst *olddata = mtmp->data;
  14.      char oldname[BUFSZ], newname[BUFSZ];
  15.  
  16.      /* Riders are immune to polymorph and green slime */
  17.      if (is_rider(mtmp->data))
  18.          return 0;
  19.  
  20.      if (msg) {
  21.          /* like Monnam() but never mention saddle */
  22.          Strcpy(oldname, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
  23.                                   SUPPRESS_SADDLE, FALSE));
  24.          oldname[0] = highc(oldname[0]);
  25.      }
  26.  
  27.      /* mdat = 0 -> caller wants a random monster shape */
  28.      if (mdat == 0) {
  29.          /* select_newcham_form() loops when resorting to random but
  30.             it doesn't always pick that so we still retry here too */
  31.          tryct = 20;
  32.          do {
  33.              mndx = select_newcham_form(mtmp);
  34.              mdat = accept_newcham_form(mndx);
  35.              /* for the first several tries we require upper-case on
  36.                 the rogue level (after that, we take whatever we get) */
  37.              if (tryct > 15 && Is_rogue_level(&u.uz)
  38.                  && mdat && !isupper((uchar) mdat->mlet))
  39.                  mdat = 0;
  40.              if (mdat)
  41.                  break;
  42.          } while (--tryct > 0);
  43.          if (!tryct)
  44.              return 0;
  45.      } else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
  46.          return 0; /* passed in mdat is genocided */
  47.  
  48.      mgender_from_permonst(mtmp, mdat);
  49.  
  50.      if (In_endgame(&u.uz) && is_mplayer(olddata) && has_mname(mtmp)) {
  51.          /* mplayers start out as "Foo the Bar", but some of the
  52.           * titles are inappropriate when polymorphed, particularly
  53.           * into the opposite sex.  players don't use ranks when
  54.           * polymorphed, so dropping the rank for mplayers seems
  55.           * reasonable.
  56.           */
  57.          char *p = index(MNAME(mtmp), ' ');
  58.  
  59.          if (p)
  60.              *p = '\0';
  61.      }
  62.  
  63.      if (mdat == mtmp->data)
  64.          return 0; /* still the same monster */
  65.  
  66.      if (mtmp->wormno) { /* throw tail away */
  67.          wormgone(mtmp);
  68.          place_monster(mtmp, mtmp->mx, mtmp->my);
  69.      }
  70.      if (mtmp->m_ap_type && mdat->mlet != S_MIMIC)
  71.          seemimic(mtmp); /* revert to normal monster */
  72.  
  73.      /* (this code used to try to adjust the monster's health based on
  74.         a normal one of its type but there are too many special cases
  75.         which need to handled in order to do that correctly, so just
  76.         give the new form the same proportion of HP as its old one had) */
  77.      hpn = mtmp->mhp;
  78.      hpd = mtmp->mhpmax;
  79.      /* set level and hit points */
  80.      newmonhp(mtmp, monsndx(mdat));
  81.      /* new hp: same fraction of max as before */
  82.  #ifndef LINT
  83.      mtmp->mhp = (int) (((long) hpn * (long) mtmp->mhp) / (long) hpd);
  84.  #endif
  85.      /* sanity check (potential overflow) */
  86.      if (mtmp->mhp < 0 || mtmp->mhp > mtmp->mhpmax)
  87.          mtmp->mhp = mtmp->mhpmax;
  88.      /* unlikely but not impossible; a 1HD creature with 1HP that changes
  89.         into a 0HD creature will require this statement */
  90.      if (!mtmp->mhp)
  91.          mtmp->mhp = 1;
  92.  
  93.      /* take on the new form... */
  94.      set_mon_data(mtmp, mdat, 0);
  95.  
  96.      if (emits_light(olddata) != emits_light(mtmp->data)) {
  97.          /* used to give light, now doesn't, or vice versa,
  98.             or light's range has changed */
  99.          if (emits_light(olddata))
  100.              del_light_source(LS_MONSTER, monst_to_any(mtmp));
  101.          if (emits_light(mtmp->data))
  102.              new_light_source(mtmp->mx, mtmp->my, emits_light(mtmp->data),
  103.                               LS_MONSTER, monst_to_any(mtmp));
  104.      }
  105.      if (!mtmp->perminvis || pm_invisible(olddata))
  106.          mtmp->perminvis = pm_invisible(mdat);
  107.      mtmp->minvis = mtmp->invis_blkd ? 0 : mtmp->perminvis;
  108.      if (mtmp->mundetected)
  109.          (void) hideunder(mtmp);
  110.      if (u.ustuck == mtmp) {
  111.          if (u.uswallow) {
  112.              if (!attacktype(mdat, AT_ENGL)) {
  113.                  /* Does mdat care? */
  114.                  if (!noncorporeal(mdat) && !amorphous(mdat)
  115.                      && !is_whirly(mdat) && (mdat != &mons[PM_YELLOW_LIGHT])) {
  116.                      You("break out of %s%s!", mon_nam(mtmp),
  117.                          (is_animal(mdat) ? "'s stomach" : ""));
  118.                      mtmp->mhp = 1; /* almost dead */
  119.                  }
  120.                  expels(mtmp, olddata, FALSE);
  121.              } else {
  122.                  /* update swallow glyphs for new monster */
  123.                  swallowed(0);
  124.              }
  125.          } else if (!sticks(mdat) && !sticks(youmonst.data))
  126.              unstuck(mtmp);
  127.      }
  128.  
  129.  #ifndef DCC30_BUG
  130.      if (mdat == &mons[PM_LONG_WORM] && (mtmp->wormno = get_wormno()) != 0) {
  131.  #else
  132.      /* DICE 3.0 doesn't like assigning and comparing mtmp->wormno in the
  133.       * same expression.
  134.       */
  135.      if (mdat == &mons[PM_LONG_WORM]
  136.          && (mtmp->wormno = get_wormno(), mtmp->wormno != 0)) {
  137.  #endif
  138.          /* we can now create worms with tails - 11/91 */
  139.          initworm(mtmp, rn2(5));
  140.          if (count_wsegs(mtmp))
  141.              place_worm_tail_randomly(mtmp, mtmp->mx, mtmp->my);
  142.      }
  143.  
  144.      newsym(mtmp->mx, mtmp->my);
  145.  
  146.      if (msg) {
  147.          char *save_mname = 0;
  148.  
  149.          if (has_mname(mtmp)) {
  150.              save_mname = MNAME(mtmp);
  151.              MNAME(mtmp) = (char *) 0;
  152.          }
  153.          Strcpy(newname, (mdat == &mons[PM_GREEN_SLIME])
  154.                              ? "slime"
  155.                              : x_monnam(mtmp, ARTICLE_A, (char *) 0,
  156.                                         SUPPRESS_SADDLE, FALSE));
  157.          if (!strcmpi(oldname, "it") && !strcmpi(newname, "it"))
  158.              (void) usmellmon(mdat);
  159.          else
  160.              pline("%s turns into %s!", oldname, newname);
  161.          if (save_mname)
  162.              MNAME(mtmp) = save_mname;
  163.      }
  164.  
  165.      possibly_unwield(mtmp, polyspot); /* might lose use of weapon */
  166.      mon_break_armor(mtmp, polyspot);
  167.      if (!(mtmp->misc_worn_check & W_ARMG))
  168.          mselftouch(mtmp, "No longer petrify-resistant, ",
  169.                     !context.mon_moving);
  170.      m_dowear(mtmp, FALSE);
  171.  
  172.      /* This ought to re-test can_carry() on each item in the inventory
  173.       * rather than just checking ex-giants & boulders, but that'd be
  174.       * pretty expensive to perform.  If implemented, then perhaps
  175.       * minvent should be sorted in order to drop heaviest items first.
  176.       */
  177.      /* former giants can't continue carrying boulders */
  178.      if (mtmp->minvent && !throws_rocks(mdat)) {
  179.          register struct obj *otmp, *otmp2;
  180.  
  181.          for (otmp = mtmp->minvent; otmp; otmp = otmp2) {
  182.              otmp2 = otmp->nobj;
  183.              if (otmp->otyp == BOULDER) {
  184.                  /* this keeps otmp from being polymorphed in the
  185.                     same zap that the monster that held it is polymorphed */
  186.                  if (polyspot)
  187.                      bypass_obj(otmp);
  188.                  obj_extract_self(otmp);
  189.                  /* probably ought to give some "drop" message here */
  190.                  if (flooreffects(otmp, mtmp->mx, mtmp->my, ""))
  191.                      continue;
  192.                  place_object(otmp, mtmp->mx, mtmp->my);
  193.              }
  194.          }
  195.      }
  196.  
  197.      return 1;
  198.  }
  199.  

can_be_hatched

  1.  /* sometimes an egg will be special */
  2.  #define BREEDER_EGG (!rn2(77))
  3.  
  4.  /*
  5.   * Determine if the given monster number can be hatched from an egg.
  6.   * Return the monster number to use as the egg's corpsenm.  Return
  7.   * NON_PM if the given monster can't be hatched.
  8.   */
  9.  int
  10.  can_be_hatched(mnum)
  11.  int mnum;
  12.  {
  13.      /* ranger quest nemesis has the oviparous bit set, making it
  14.         be possible to wish for eggs of that unique monster; turn
  15.         such into ordinary eggs rather than forbidding them outright */
  16.      if (mnum == PM_SCORPIUS)
  17.          mnum = PM_SCORPION;
  18.  
  19.      mnum = little_to_big(mnum);
  20.      /*
  21.       * Queen bees lay killer bee eggs (usually), but killer bees don't
  22.       * grow into queen bees.  Ditto for [winged-]gargoyles.
  23.       */
  24.      if (mnum == PM_KILLER_BEE || mnum == PM_GARGOYLE
  25.          || (lays_eggs(&mons[mnum])
  26.              && (BREEDER_EGG
  27.                  || (mnum != PM_QUEEN_BEE && mnum != PM_WINGED_GARGOYLE))))
  28.          return mnum;
  29.      return NON_PM;
  30.  }
  31.  

egg_type_from_parent

  1.  /* type of egg laid by #sit; usually matches parent */
  2.  int
  3.  egg_type_from_parent(mnum, force_ordinary)
  4.  int mnum; /* parent monster; caller must handle lays_eggs() check */
  5.  boolean force_ordinary;
  6.  {
  7.      if (force_ordinary || !BREEDER_EGG) {
  8.          if (mnum == PM_QUEEN_BEE)
  9.              mnum = PM_KILLER_BEE;
  10.          else if (mnum == PM_WINGED_GARGOYLE)
  11.              mnum = PM_GARGOYLE;
  12.      }
  13.      return mnum;
  14.  }
  15.  

dead_species

  1.  /* decide whether an egg of the indicated monster type is viable;
  2.     also used to determine whether an egg or tin can be created... */
  3.  boolean
  4.  dead_species(m_idx, egg)
  5.  int m_idx;
  6.  boolean egg;
  7.  {
  8.      int alt_idx;
  9.  
  10.      /* generic eggs are unhatchable and have corpsenm of NON_PM */
  11.      if (m_idx < LOW_PM)
  12.          return TRUE;
  13.      /*
  14.       * For monsters with both baby and adult forms, genociding either
  15.       * form kills all eggs of that monster.  Monsters with more than
  16.       * two forms (small->large->giant mimics) are more or less ignored;
  17.       * fortunately, none of them have eggs.  Species extinction due to
  18.       * overpopulation does not kill eggs.
  19.       */
  20.      alt_idx = egg ? big_to_little(m_idx) : m_idx;
  21.      return (boolean) ((mvitals[m_idx].mvflags & G_GENOD) != 0
  22.                        || (mvitals[alt_idx].mvflags & G_GENOD) != 0);
  23.  }
  24.  

kill_eggs

  1.  /* kill off any eggs of genocided monsters */
  2.  STATIC_OVL void
  3.  kill_eggs(obj_list)
  4.  struct obj *obj_list;
  5.  {
  6.      struct obj *otmp;
  7.  
  8.      for (otmp = obj_list; otmp; otmp = otmp->nobj)
  9.          if (otmp->otyp == EGG) {
  10.              if (dead_species(otmp->corpsenm, TRUE)) {
  11.                  /*
  12.                   * It seems we could also just catch this when
  13.                   * it attempted to hatch, so we wouldn't have to
  14.                   * search all of the objlists.. or stop all
  15.                   * hatch timers based on a corpsenm.
  16.                   */
  17.                  kill_egg(otmp);
  18.              }
  19.  #if 0 /* not used */
  20.          } else if (otmp->otyp == TIN) {
  21.              if (dead_species(otmp->corpsenm, FALSE))
  22.                  otmp->corpsenm = NON_PM; /* empty tin */
  23.          } else if (otmp->otyp == CORPSE) {
  24.              if (dead_species(otmp->corpsenm, FALSE))
  25.                  ; /* not yet implemented... */
  26.  #endif
  27.          } else if (Has_contents(otmp)) {
  28.              kill_eggs(otmp->cobj);
  29.          }
  30.  }
  31.  

kill_genocided_monsters

  1.  /* kill all members of genocided species */
  2.  void
  3.  kill_genocided_monsters()
  4.  {
  5.      struct monst *mtmp, *mtmp2;
  6.      boolean kill_cham;
  7.      int mndx;
  8.  
  9.      /*
  10.       * Called during genocide, and again upon level change.  The latter
  11.       * catches up with any migrating monsters as they finally arrive at
  12.       * their intended destinations, so possessions get deposited there.
  13.       *
  14.       * Chameleon handling:
  15.       *  1) if chameleons have been genocided, destroy them
  16.       *     regardless of current form;
  17.       *  2) otherwise, force every chameleon which is imitating
  18.       *     any genocided species to take on a new form.
  19.       */
  20.      for (mtmp = fmon; mtmp; mtmp = mtmp2) {
  21.          mtmp2 = mtmp->nmon;
  22.          if (DEADMONSTER(mtmp))
  23.              continue;
  24.          mndx = monsndx(mtmp->data);
  25.          kill_cham = (mtmp->cham >= LOW_PM
  26.                       && (mvitals[mtmp->cham].mvflags & G_GENOD));
  27.          if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
  28.              if (mtmp->cham >= LOW_PM && !kill_cham)
  29.                  (void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE);
  30.              else
  31.                  mondead(mtmp);
  32.          }
  33.          if (mtmp->minvent)
  34.              kill_eggs(mtmp->minvent);
  35.      }
  36.  
  37.      kill_eggs(invent);
  38.      kill_eggs(fobj);
  39.      kill_eggs(migrating_objs);
  40.      kill_eggs(level.buriedobjlist);
  41.  }
  42.  

golemeffects

  1.  void
  2.  golemeffects(mon, damtype, dam)
  3.  register struct monst *mon;
  4.  int damtype, dam;
  5.  {
  6.      int heal = 0, slow = 0;
  7.  
  8.      if (mon->data == &mons[PM_FLESH_GOLEM]) {
  9.          if (damtype == AD_ELEC)
  10.              heal = (dam + 5) / 6;
  11.          else if (damtype == AD_FIRE || damtype == AD_COLD)
  12.              slow = 1;
  13.      } else if (mon->data == &mons[PM_IRON_GOLEM]) {
  14.          if (damtype == AD_ELEC)
  15.              slow = 1;
  16.          else if (damtype == AD_FIRE)
  17.              heal = dam;
  18.      } else {
  19.          return;
  20.      }
  21.      if (slow) {
  22.          if (mon->mspeed != MSLOW)
  23.              mon_adjust_speed(mon, -1, (struct obj *) 0);
  24.      }
  25.      if (heal) {
  26.          if (mon->mhp < mon->mhpmax) {
  27.              mon->mhp += heal;
  28.              if (mon->mhp > mon->mhpmax)
  29.                  mon->mhp = mon->mhpmax;
  30.              if (cansee(mon->mx, mon->my))
  31.                  pline("%s seems healthier.", Monnam(mon));
  32.          }
  33.      }
  34.  }
  35.  

angry_guards

  1.  boolean
  2.  angry_guards(silent)
  3.  boolean silent;
  4.  {
  5.      struct monst *mtmp;
  6.      int ct = 0, nct = 0, sct = 0, slct = 0;
  7.  
  8.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  9.          if (DEADMONSTER(mtmp))
  10.              continue;
  11.          if (is_watch(mtmp->data) && mtmp->mpeaceful) {
  12.              ct++;
  13.              if (cansee(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
  14.                  if (distu(mtmp->mx, mtmp->my) == 2)
  15.                      nct++;
  16.                  else
  17.                      sct++;
  18.              }
  19.              if (mtmp->msleeping || mtmp->mfrozen) {
  20.                  slct++;
  21.                  mtmp->msleeping = mtmp->mfrozen = 0;
  22.              }
  23.              mtmp->mpeaceful = 0;
  24.          }
  25.      }
  26.      if (ct) {
  27.          if (!silent) { /* do we want pline msgs? */
  28.              if (slct)
  29.                  pline_The("guard%s wake%s up!", slct > 1 ? "s" : "",
  30.                            slct == 1 ? "s" : "");
  31.              if (nct || sct) {
  32.                  if (nct)
  33.                      pline_The("guard%s get%s angry!", nct == 1 ? "" : "s",
  34.                                nct == 1 ? "s" : "");
  35.                  else if (!Blind)
  36.                      You_see("%sangry guard%s approaching!",
  37.                              sct == 1 ? "an " : "", sct > 1 ? "s" : "");
  38.              } else
  39.                  You_hear("the shrill sound of a guard's whistle.");
  40.          }
  41.          return TRUE;
  42.      }
  43.      return FALSE;
  44.  }
  45.  

pacify_guards

  1.  void
  2.  pacify_guards()
  3.  {
  4.      struct monst *mtmp;
  5.  
  6.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  7.          if (DEADMONSTER(mtmp))
  8.              continue;
  9.          if (is_watch(mtmp->data))
  10.              mtmp->mpeaceful = 1;
  11.      }
  12.  }
  13.  

mimic_hit_msg

  1.  void
  2.  mimic_hit_msg(mtmp, otyp)
  3.  struct monst *mtmp;
  4.  short otyp;
  5.  {
  6.      short ap = mtmp->mappearance;
  7.  
  8.      switch (mtmp->m_ap_type) {
  9.      case M_AP_NOTHING:
  10.      case M_AP_FURNITURE:
  11.      case M_AP_MONSTER:
  12.          break;
  13.      case M_AP_OBJECT:
  14.          if (otyp == SPE_HEALING || otyp == SPE_EXTRA_HEALING) {
  15.              pline("%s seems a more vivid %s than before.",
  16.                    The(simple_typename(ap)),
  17.                    c_obj_colors[objects[ap].oc_color]);
  18.          }
  19.          break;
  20.      }
  21.  }
  22.  

usmellmon

  1.  boolean
  2.  usmellmon(mdat)
  3.  struct permonst *mdat;
  4.  {
  5.      int mndx;
  6.      boolean nonspecific = FALSE;
  7.      boolean msg_given = FALSE;
  8.  
  9.      if (mdat) {
  10.          if (!olfaction(youmonst.data))
  11.              return FALSE;
  12.          mndx = monsndx(mdat);
  13.          switch (mndx) {
  14.          case PM_ROTHE:
  15.          case PM_MINOTAUR:
  16.              You("notice a bovine smell.");
  17.              msg_given = TRUE;
  18.              break;
  19.          case PM_CAVEMAN:
  20.          case PM_CAVEWOMAN:
  21.          case PM_BARBARIAN:
  22.          case PM_NEANDERTHAL:
  23.              You("smell body odor.");
  24.              msg_given = TRUE;
  25.              break;
  26.          /*
  27.          case PM_PESTILENCE:
  28.          case PM_FAMINE:
  29.          case PM_DEATH:
  30.              break;
  31.          */
  32.          case PM_HORNED_DEVIL:
  33.          case PM_BALROG:
  34.          case PM_ASMODEUS:
  35.          case PM_DISPATER:
  36.          case PM_YEENOGHU:
  37.          case PM_ORCUS:
  38.              break;
  39.          case PM_HUMAN_WEREJACKAL:
  40.          case PM_HUMAN_WERERAT:
  41.          case PM_HUMAN_WEREWOLF:
  42.          case PM_WEREJACKAL:
  43.          case PM_WERERAT:
  44.          case PM_WEREWOLF:
  45.          case PM_OWLBEAR:
  46.              You("detect an odor reminiscent of an animal's den.");
  47.              msg_given = TRUE;
  48.              break;
  49.          /*
  50.          case PM_PURPLE_WORM:
  51.              break;
  52.          */
  53.          case PM_STEAM_VORTEX:
  54.              You("smell steam.");
  55.              msg_given = TRUE;
  56.              break;
  57.          case PM_GREEN_SLIME:
  58.              pline("%s stinks.", Something);
  59.              msg_given = TRUE;
  60.              break;
  61.          case PM_VIOLET_FUNGUS:
  62.          case PM_SHRIEKER:
  63.              You("smell mushrooms.");
  64.              msg_given = TRUE;
  65.              break;
  66.          /* These are here to avoid triggering the
  67.             nonspecific treatment through the default case below*/
  68.          case PM_WHITE_UNICORN:
  69.          case PM_GRAY_UNICORN:
  70.          case PM_BLACK_UNICORN:
  71.          case PM_JELLYFISH:
  72.              break;
  73.          default:
  74.              nonspecific = TRUE;
  75.              break;
  76.          }
  77.  
  78.          if (nonspecific)
  79.              switch (mdat->mlet) {
  80.              case S_DOG:
  81.                  You("notice a dog smell.");
  82.                  msg_given = TRUE;
  83.                  break;
  84.              case S_DRAGON:
  85.                  You("smell a dragon!");
  86.                  msg_given = TRUE;
  87.                  break;
  88.              case S_FUNGUS:
  89.                  pline("%s smells moldy.", Something);
  90.                  msg_given = TRUE;
  91.                  break;
  92.              case S_UNICORN:
  93.                  You("detect a%s odor reminiscent of a stable.",
  94.                      (mndx == PM_PONY) ? "n" : " strong");
  95.                  msg_given = TRUE;
  96.                  break;
  97.              case S_ZOMBIE:
  98.                  You("smell rotting flesh.");
  99.                  msg_given = TRUE;
  100.                  break;
  101.              case S_EEL:
  102.                  You("smell fish.");
  103.                  msg_given = TRUE;
  104.                  break;
  105.              case S_ORC:
  106.                  if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC)))
  107.                      You("notice an attractive smell.");
  108.                  else
  109.                      pline("A foul stench makes you feel a little nauseated.");
  110.                  msg_given = TRUE;
  111.                  break;
  112.              default:
  113.                  break;
  114.              }
  115.      }
  116.      return msg_given ? TRUE : FALSE;
  117.  }
  118.  
  119.  /*mon.c*/