Source:NetHack 3.6.0/src/polyself.c

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

Below is the full text to polyself.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/polyself.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	polyself.c	$NHDT-Date: 1448496566 2015/11/26 00:09:26 $  $NHDT-Branch: master $:$NHDT-Revision: 1.104 $ */
  2.  /*      Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  /*
  6.   * Polymorph self routine.
  7.   *
  8.   * Note:  the light source handling code assumes that both youmonst.m_id
  9.   * and youmonst.mx will always remain 0 when it handles the case of the
  10.   * player polymorphed into a light-emitting monster.
  11.   *
  12.   * Transformation sequences:
  13.   *              /-> polymon                 poly into monster form
  14.   *    polyself =
  15.   *              \-> newman -> polyman       fail to poly, get human form
  16.   *
  17.   *    rehumanize -> polyman                 return to original form
  18.   *
  19.   *    polymon (called directly)             usually golem petrification
  20.   */
  21.  
  22.  #include "hack.h"
  23.  
  24.  STATIC_DCL void FDECL(check_strangling, (BOOLEAN_P));
  25.  STATIC_DCL void FDECL(polyman, (const char *, const char *));
  26.  STATIC_DCL void NDECL(break_armor);
  27.  STATIC_DCL void FDECL(drop_weapon, (int));
  28.  STATIC_DCL void NDECL(uunstick);
  29.  STATIC_DCL int FDECL(armor_to_dragon, (int));
  30.  STATIC_DCL void NDECL(newman);
  31.  STATIC_DCL boolean FDECL(polysense, (struct permonst *));
  32.  
  33.  STATIC_VAR const char no_longer_petrify_resistant[] =
  34.      "No longer petrify-resistant, you";
  35.  
  36.  /* controls whether taking on new form or becoming new man can also
  37.     change sex (ought to be an arg to polymon() and newman() instead) */
  38.  STATIC_VAR int sex_change_ok = 0;
  39.  

set_uasmon

  1.  /* update the youmonst.data structure pointer and intrinsics */
  2.  void
  3.  set_uasmon()
  4.  {
  5.      struct permonst *mdat = &mons[u.umonnum];
  6.  
  7.      set_mon_data(&youmonst, mdat, 0);
  8.  
  9.  #define PROPSET(PropIndx, ON)                          \
  10.      do {                                               \
  11.          if (ON)                                        \
  12.              u.uprops[PropIndx].intrinsic |= FROMFORM;  \
  13.          else                                           \
  14.              u.uprops[PropIndx].intrinsic &= ~FROMFORM; \
  15.      } while (0)
  16.  
  17.      PROPSET(FIRE_RES, resists_fire(&youmonst));
  18.      PROPSET(COLD_RES, resists_cold(&youmonst));
  19.      PROPSET(SLEEP_RES, resists_sleep(&youmonst));
  20.      PROPSET(DISINT_RES, resists_disint(&youmonst));
  21.      PROPSET(SHOCK_RES, resists_elec(&youmonst));
  22.      PROPSET(POISON_RES, resists_poison(&youmonst));
  23.      PROPSET(ACID_RES, resists_acid(&youmonst));
  24.      PROPSET(STONE_RES, resists_ston(&youmonst));
  25.      {
  26.          /* resists_drli() takes wielded weapon into account; suppress it */
  27.          struct obj *save_uwep = uwep;
  28.  
  29.          uwep = 0;
  30.          PROPSET(DRAIN_RES, resists_drli(&youmonst));
  31.          uwep = save_uwep;
  32.      }
  33.      /* resists_magm() takes wielded, worn, and carried equipment into
  34.         into account; cheat and duplicate its monster-specific part */
  35.      PROPSET(ANTIMAGIC, (dmgtype(mdat, AD_MAGM)
  36.                          || mdat == &mons[PM_BABY_GRAY_DRAGON]
  37.                          || dmgtype(mdat, AD_RBRE)));
  38.      PROPSET(SICK_RES, (mdat->mlet == S_FUNGUS || mdat == &mons[PM_GHOUL]));
  39.  
  40.      PROPSET(STUNNED, (mdat == &mons[PM_STALKER] || is_bat(mdat)));
  41.      PROPSET(HALLUC_RES, dmgtype(mdat, AD_HALU));
  42.      PROPSET(SEE_INVIS, perceives(mdat));
  43.      PROPSET(TELEPAT, telepathic(mdat));
  44.      PROPSET(INFRAVISION, infravision(mdat));
  45.      PROPSET(INVIS, pm_invisible(mdat));
  46.      PROPSET(TELEPORT, can_teleport(mdat));
  47.      PROPSET(TELEPORT_CONTROL, control_teleport(mdat));
  48.      PROPSET(LEVITATION, is_floater(mdat));
  49.      PROPSET(FLYING, is_flyer(mdat));
  50.      PROPSET(SWIMMING, is_swimmer(mdat));
  51.      /* [don't touch MAGICAL_BREATHING here; both Amphibious and Breathless
  52.         key off of it but include different monster forms...] */
  53.      PROPSET(PASSES_WALLS, passes_walls(mdat));
  54.      PROPSET(REGENERATION, regenerates(mdat));
  55.      PROPSET(REFLECTING, (mdat == &mons[PM_SILVER_DRAGON]));
  56.  
  57.      float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
  58.  
  59.  #undef PROPSET
  60.  
  61.  #ifdef STATUS_VIA_WINDOWPORT
  62.      status_initialize(REASSESS_ONLY);
  63.  #endif
  64.  }
  65.  

float_vs_flight

  1.  /* Levitation overrides Flying; set or clear BFlying|I_SPECIAL */
  2.  void
  3.  float_vs_flight()
  4.  {
  5.      /* floating overrides flight; normally float_up() and float_down()
  6.         handle this, but sometimes they're skipped */
  7.      if (HLevitation || ELevitation)
  8.          BFlying |= I_SPECIAL;
  9.      else
  10.          BFlying &= ~I_SPECIAL;
  11.  }
  12.  

check_strangling

  1.  /* for changing into form that's immune to strangulation */
  2.  STATIC_OVL void
  3.  check_strangling(on)
  4.  boolean on;
  5.  {
  6.      /* on -- maybe resume strangling */
  7.      if (on) {
  8.          /* when Strangled is already set, polymorphing from one
  9.             vulnerable form into another causes the counter to be reset */
  10.          if (uamul && uamul->otyp == AMULET_OF_STRANGULATION
  11.              && can_be_strangled(&youmonst)) {
  12.              Your("%s %s your %s!", simpleonames(uamul),
  13.                   Strangled ? "still constricts" : "begins constricting",
  14.                   body_part(NECK)); /* "throat" */
  15.              Strangled = 6L;
  16.              makeknown(AMULET_OF_STRANGULATION);
  17.          }
  18.  
  19.      /* off -- maybe block strangling */
  20.      } else {
  21.          if (Strangled && !can_be_strangled(&youmonst)) {
  22.              Strangled = 0L;
  23.              You("are no longer being strangled.");
  24.          }
  25.      }
  26.  }
  27.  

polyman

  1.  /* make a (new) human out of the player */
  2.  STATIC_OVL void
  3.  polyman(fmt, arg)
  4.  const char *fmt, *arg;
  5.  {
  6.      boolean sticky = (sticks(youmonst.data) && u.ustuck && !u.uswallow),
  7.              was_mimicking = (youmonst.m_ap_type == M_AP_OBJECT);
  8.      boolean was_blind = !!Blind;
  9.  
  10.      if (Upolyd) {
  11.          u.acurr = u.macurr; /* restore old attribs */
  12.          u.amax = u.mamax;
  13.          u.umonnum = u.umonster;
  14.          flags.female = u.mfemale;
  15.      }
  16.      set_uasmon();
  17.  
  18.      u.mh = u.mhmax = 0;
  19.      u.mtimedone = 0;
  20.      skinback(FALSE);
  21.      u.uundetected = 0;
  22.  
  23.      if (sticky)
  24.          uunstick();
  25.      find_ac();
  26.      if (was_mimicking) {
  27.          if (multi < 0)
  28.              unmul("");
  29.          youmonst.m_ap_type = M_AP_NOTHING;
  30.      }
  31.  
  32.      newsym(u.ux, u.uy);
  33.  
  34.      You(fmt, arg);
  35.      /* check whether player foolishly genocided self while poly'd */
  36.      if ((mvitals[urole.malenum].mvflags & G_GENOD)
  37.          || (urole.femalenum != NON_PM
  38.              && (mvitals[urole.femalenum].mvflags & G_GENOD))
  39.          || (mvitals[urace.malenum].mvflags & G_GENOD)
  40.          || (urace.femalenum != NON_PM
  41.              && (mvitals[urace.femalenum].mvflags & G_GENOD))) {
  42.          /* intervening activity might have clobbered genocide info */
  43.          struct kinfo *kptr = find_delayed_killer(POLYMORPH);
  44.  
  45.          if (kptr != (struct kinfo *) 0 && kptr->name[0]) {
  46.              killer.format = kptr->format;
  47.              Strcpy(killer.name, kptr->name);
  48.          } else {
  49.              killer.format = KILLED_BY;
  50.              Strcpy(killer.name, "self-genocide");
  51.          }
  52.          dealloc_killer(kptr);
  53.          done(GENOCIDED);
  54.      }
  55.  
  56.      if (u.twoweap && !could_twoweap(youmonst.data))
  57.          untwoweapon();
  58.  
  59.      if (u.utraptype == TT_PIT && u.utrap) {
  60.          u.utrap = rn1(6, 2); /* time to escape resets */
  61.      }
  62.      if (was_blind && !Blind) { /* reverting from eyeless */
  63.          Blinded = 1L;
  64.          make_blinded(0L, TRUE); /* remove blindness */
  65.      }
  66.      check_strangling(TRUE);
  67.  
  68.      if (!Levitation && !u.ustuck && is_pool_or_lava(u.ux, u.uy))
  69.          spoteffects(TRUE);
  70.  
  71.      see_monsters();
  72.  }
  73.  

change_sex

  1.  void
  2.  change_sex()
  3.  {
  4.      /* setting u.umonster for caveman/cavewoman or priest/priestess
  5.         swap unintentionally makes `Upolyd' appear to be true */
  6.      boolean already_polyd = (boolean) Upolyd;
  7.  
  8.      /* Some monsters are always of one sex and their sex can't be changed;
  9.       * Succubi/incubi can change, but are handled below.
  10.       *
  11.       * !already_polyd check necessary because is_male() and is_female()
  12.       * are true if the player is a priest/priestess.
  13.       */
  14.      if (!already_polyd
  15.          || (!is_male(youmonst.data) && !is_female(youmonst.data)
  16.              && !is_neuter(youmonst.data)))
  17.          flags.female = !flags.female;
  18.      if (already_polyd) /* poly'd: also change saved sex */
  19.          u.mfemale = !u.mfemale;
  20.      max_rank_sz(); /* [this appears to be superfluous] */
  21.      if ((already_polyd ? u.mfemale : flags.female) && urole.name.f)
  22.          Strcpy(pl_character, urole.name.f);
  23.      else
  24.          Strcpy(pl_character, urole.name.m);
  25.      u.umonster = ((already_polyd ? u.mfemale : flags.female)
  26.                    && urole.femalenum != NON_PM)
  27.                       ? urole.femalenum
  28.                       : urole.malenum;
  29.      if (!already_polyd) {
  30.          u.umonnum = u.umonster;
  31.      } else if (u.umonnum == PM_SUCCUBUS || u.umonnum == PM_INCUBUS) {
  32.          flags.female = !flags.female;
  33.          /* change monster type to match new sex */
  34.          u.umonnum = (u.umonnum == PM_SUCCUBUS) ? PM_INCUBUS : PM_SUCCUBUS;
  35.          set_uasmon();
  36.      }
  37.  }
  38.  

newman

  1.  STATIC_OVL void
  2.  newman()
  3.  {
  4.      int i, oldlvl, newlvl, hpmax, enmax;
  5.  
  6.      oldlvl = u.ulevel;
  7.      newlvl = oldlvl + rn1(5, -2);     /* new = old + {-2,-1,0,+1,+2} */
  8.      if (newlvl > 127 || newlvl < 1) { /* level went below 0? */
  9.          goto dead; /* old level is still intact (in case of lifesaving) */
  10.      }
  11.      if (newlvl > MAXULEV)
  12.          newlvl = MAXULEV;
  13.      /* If your level goes down, your peak level goes down by
  14.         the same amount so that you can't simply use blessed
  15.         full healing to undo the decrease.  But if your level
  16.         goes up, your peak level does *not* undergo the same
  17.         adjustment; you might end up losing out on the chance
  18.         to regain some levels previously lost to other causes. */
  19.      if (newlvl < oldlvl)
  20.          u.ulevelmax -= (oldlvl - newlvl);
  21.      if (u.ulevelmax < newlvl)
  22.          u.ulevelmax = newlvl;
  23.      u.ulevel = newlvl;
  24.  
  25.      if (sex_change_ok && !rn2(10))
  26.          change_sex();
  27.  
  28.      adjabil(oldlvl, (int) u.ulevel);
  29.      reset_rndmonst(NON_PM); /* new monster generation criteria */
  30.  
  31.      /* random experience points for the new experience level */
  32.      u.uexp = rndexp(FALSE);
  33.  
  34.      /* set up new attribute points (particularly Con) */
  35.      redist_attr();
  36.  
  37.      /*
  38.       * New hit points:
  39.       *  remove level-gain based HP from any extra HP accumulated
  40.       *  (the "extra" might actually be negative);
  41.       *  modify the extra, retaining {80%, 90%, 100%, or 110%};
  42.       *  add in newly generated set of level-gain HP.
  43.       *
  44.       * (This used to calculate new HP in direct proportion to old HP,
  45.       * but that was subject to abuse:  accumulate a large amount of
  46.       * extra HP, drain level down to 1, then polyself to level 2 or 3
  47.       * [lifesaving capability needed to handle level 0 and -1 cases]
  48.       * and the extra got multiplied by 2 or 3.  Repeat the level
  49.       * drain and polyself steps until out of lifesaving capability.)
  50.       */
  51.      hpmax = u.uhpmax;
  52.      for (i = 0; i < oldlvl; i++)
  53.          hpmax -= (int) u.uhpinc[i];
  54.      /* hpmax * rn1(4,8) / 10; 0.95*hpmax on average */
  55.      hpmax = rounddiv((long) hpmax * (long) rn1(4, 8), 10);
  56.      for (i = 0; (u.ulevel = i) < newlvl; i++)
  57.          hpmax += newhp();
  58.      if (hpmax < u.ulevel)
  59.          hpmax = u.ulevel; /* min of 1 HP per level */
  60.      /* retain same proportion for current HP; u.uhp * hpmax / u.uhpmax */
  61.      u.uhp = rounddiv((long) u.uhp * (long) hpmax, u.uhpmax);
  62.      u.uhpmax = hpmax;
  63.      /*
  64.       * Do the same for spell power.
  65.       */
  66.      enmax = u.uenmax;
  67.      for (i = 0; i < oldlvl; i++)
  68.          enmax -= (int) u.ueninc[i];
  69.      enmax = rounddiv((long) enmax * (long) rn1(4, 8), 10);
  70.      for (i = 0; (u.ulevel = i) < newlvl; i++)
  71.          enmax += newpw();
  72.      if (enmax < u.ulevel)
  73.          enmax = u.ulevel;
  74.      u.uen = rounddiv((long) u.uen * (long) enmax,
  75.                       ((u.uenmax < 1) ? 1 : u.uenmax));
  76.      u.uenmax = enmax;
  77.      /* [should alignment record be tweaked too?] */
  78.  
  79.      u.uhunger = rn1(500, 500);
  80.      if (Sick)
  81.          make_sick(0L, (char *) 0, FALSE, SICK_ALL);
  82.      if (Stoned)
  83.          make_stoned(0L, (char *) 0, 0, (char *) 0);
  84.      if (u.uhp <= 0) {
  85.          if (Polymorph_control) { /* even when Stunned || Unaware */
  86.              if (u.uhp <= 0)
  87.                  u.uhp = 1;
  88.          } else {
  89.          dead: /* we come directly here if their experience level went to 0 or
  90.                   less */
  91.              Your("new form doesn't seem healthy enough to survive.");
  92.              killer.format = KILLED_BY_AN;
  93.              Strcpy(killer.name, "unsuccessful polymorph");
  94.              done(DIED);
  95.              newuhs(FALSE);
  96.              (void) polysense(youmonst.data);
  97.              return; /* lifesaved */
  98.          }
  99.      }
  100.      newuhs(FALSE);
  101.      polyman("feel like a new %s!",
  102.              /* use saved gender we're about to revert to, not current */
  103.              (u.mfemale && urace.individual.f)
  104.                  ? urace.individual.f
  105.                  : (urace.individual.m) ? urace.individual.m : urace.noun);
  106.      if (Slimed) {
  107.          Your("body transforms, but there is still slime on you.");
  108.          make_slimed(10L, (const char *) 0);
  109.      }
  110.  
  111.      (void) polysense(youmonst.data);
  112.      context.botl = 1;
  113.      see_monsters();
  114.      (void) encumber_msg();
  115.  
  116.      retouch_equipment(2);
  117.      if (!uarmg)
  118.          selftouch(no_longer_petrify_resistant);
  119.  }
  120.  

polyself

  1.  void
  2.  polyself(psflags)
  3.  int psflags;
  4.  {
  5.      char buf[BUFSZ];
  6.      int old_light, new_light, mntmp, class, tryct;
  7.      boolean forcecontrol = (psflags == 1), monsterpoly = (psflags == 2),
  8.              draconian = (uarm && Is_dragon_armor(uarm)),
  9.              iswere = (u.ulycn >= LOW_PM), isvamp = is_vampire(youmonst.data),
  10.              controllable_poly = Polymorph_control && !(Stunned || Unaware);
  11.  
  12.      if (Unchanging) {
  13.          pline("You fail to transform!");
  14.          return;
  15.      }
  16.      /* being Stunned|Unaware doesn't negate this aspect of Poly_control */
  17.      if (!Polymorph_control && !forcecontrol && !draconian && !iswere
  18.          && !isvamp) {
  19.          if (rn2(20) > ACURR(A_CON)) {
  20.              You1(shudder_for_moment);
  21.              losehp(rnd(30), "system shock", KILLED_BY_AN);
  22.              exercise(A_CON, FALSE);
  23.              return;
  24.          }
  25.      }
  26.      old_light = emits_light(youmonst.data);
  27.      mntmp = NON_PM;
  28.  
  29.      if (monsterpoly && isvamp)
  30.          goto do_vampyr;
  31.  
  32.      if (controllable_poly || forcecontrol) {
  33.          tryct = 5;
  34.          do {
  35.              mntmp = NON_PM;
  36.              getlin("Become what kind of monster? [type the name]", buf);
  37.              (void) mungspaces(buf);
  38.              if (*buf == '\033') {
  39.                  /* user is cancelling controlled poly */
  40.                  if (forcecontrol) { /* wizard mode #polyself */
  41.                      pline1(Never_mind);
  42.                      return;
  43.                  }
  44.                  Strcpy(buf, "*"); /* resort to random */
  45.              }
  46.              if (!strcmp(buf, "*") || !strcmp(buf, "random")) {
  47.                  /* explicitly requesting random result */
  48.                  tryct = 0; /* will skip thats_enough_tries */
  49.                  continue;  /* end do-while(--tryct > 0) loop */
  50.              }
  51.              class = 0;
  52.              mntmp = name_to_mon(buf);
  53.              if (mntmp < LOW_PM) {
  54.              by_class:
  55.                  class = name_to_monclass(buf, &mntmp);
  56.                  if (class && mntmp == NON_PM)
  57.                      mntmp = mkclass_poly(class);
  58.              }
  59.              if (mntmp < LOW_PM) {
  60.                  if (!class)
  61.                      pline("I've never heard of such monsters.");
  62.                  else
  63.                      You_cant("polymorph into any of those.");
  64.              } else if (iswere && (were_beastie(mntmp) == u.ulycn
  65.                                    || mntmp == counter_were(u.ulycn)
  66.                                    || (Upolyd && mntmp == PM_HUMAN))) {
  67.                  goto do_shift;
  68.                  /* Note:  humans are illegal as monsters, but an
  69.                   * illegal monster forces newman(), which is what we
  70.                   * want if they specified a human.... */
  71.              } else if (!polyok(&mons[mntmp])
  72.                         && !(mntmp == PM_HUMAN || your_race(&mons[mntmp])
  73.                              || mntmp == urole.malenum
  74.                              || mntmp == urole.femalenum)) {
  75.                  const char *pm_name;
  76.  
  77.                  /* mkclass_poly() can pick a !polyok()
  78.                     candidate; if so, usually try again */
  79.                  if (class) {
  80.                      if (rn2(3) || --tryct > 0)
  81.                          goto by_class;
  82.                      /* no retries left; put one back on counter
  83.                         so that end of loop decrement will yield
  84.                         0 and trigger thats_enough_tries message */
  85.                      ++tryct;
  86.                  }
  87.                  pm_name = mons[mntmp].mname;
  88.                  if (the_unique_pm(&mons[mntmp]))
  89.                      pm_name = the(pm_name);
  90.                  else if (!type_is_pname(&mons[mntmp]))
  91.                      pm_name = an(pm_name);
  92.                  You_cant("polymorph into %s.", pm_name);
  93.              } else
  94.                  break;
  95.          } while (--tryct > 0);
  96.          if (!tryct)
  97.              pline1(thats_enough_tries);
  98.          /* allow skin merging, even when polymorph is controlled */
  99.          if (draconian && (tryct <= 0 || mntmp == armor_to_dragon(uarm->otyp)))
  100.              goto do_merge;
  101.          if (isvamp && (tryct <= 0 || mntmp == PM_WOLF || mntmp == PM_FOG_CLOUD
  102.                         || is_bat(&mons[mntmp])))
  103.              goto do_vampyr;
  104.      } else if (draconian || iswere || isvamp) {
  105.          /* special changes that don't require polyok() */
  106.          if (draconian) {
  107.          do_merge:
  108.              mntmp = armor_to_dragon(uarm->otyp);
  109.              if (!(mvitals[mntmp].mvflags & G_GENOD)) {
  110.                  /* allow G_EXTINCT */
  111.                  if (Is_dragon_scales(uarm)) {
  112.                      /* dragon scales remain intact as uskin */
  113.                      You("merge with your scaly armor.");
  114.                  } else { /* dragon scale mail */
  115.                      /* d.scale mail first reverts to scales */
  116.                      char *p, *dsmail;
  117.  
  118.                      /* similar to noarmor(invent.c),
  119.                         shorten to "<color> scale mail" */
  120.                      dsmail = strcpy(buf, simpleonames(uarm));
  121.                      if ((p = strstri(dsmail, " dragon ")) != 0)
  122.                          while ((p[1] = p[8]) != '\0')
  123.                              ++p;
  124.                      /* tricky phrasing; dragon scale mail
  125.                         is singular, dragon scales are plural */
  126.                      Your("%s reverts to scales as you merge with them.",
  127.                           dsmail);
  128.                      /* uarm->spe enchantment remains unchanged;
  129.                         re-converting scales to mail poses risk
  130.                         of evaporation due to over enchanting */
  131.                      uarm->otyp += GRAY_DRAGON_SCALES - GRAY_DRAGON_SCALE_MAIL;
  132.                      uarm->dknown = 1;
  133.                      context.botl = 1; /* AC is changing */
  134.                  }
  135.                  uskin = uarm;
  136.                  uarm = (struct obj *) 0;
  137.                  /* save/restore hack */
  138.                  uskin->owornmask |= I_SPECIAL;
  139.                  update_inventory();
  140.              }
  141.          } else if (iswere) {
  142.          do_shift:
  143.              if (Upolyd && were_beastie(mntmp) != u.ulycn)
  144.                  mntmp = PM_HUMAN; /* Illegal; force newman() */
  145.              else
  146.                  mntmp = u.ulycn;
  147.          } else if (isvamp) {
  148.          do_vampyr:
  149.              if (mntmp < LOW_PM || (mons[mntmp].geno & G_UNIQ))
  150.                  mntmp = (youmonst.data != &mons[PM_VAMPIRE] && !rn2(10))
  151.                              ? PM_WOLF
  152.                              : !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
  153.              if (controllable_poly) {
  154.                  Sprintf(buf, "Become %s?", an(mons[mntmp].mname));
  155.                  if (yn(buf) != 'y')
  156.                      return;
  157.              }
  158.          }
  159.          /* if polymon fails, "you feel" message has been given
  160.             so don't follow up with another polymon or newman;
  161.             sex_change_ok left disabled here */
  162.          if (mntmp == PM_HUMAN)
  163.              newman(); /* werecritter */
  164.          else
  165.              (void) polymon(mntmp);
  166.          goto made_change; /* maybe not, but this is right anyway */
  167.      }
  168.  
  169.      if (mntmp < LOW_PM) {
  170.          tryct = 200;
  171.          do {
  172.              /* randomly pick an "ordinary" monster */
  173.              mntmp = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
  174.              if (polyok(&mons[mntmp]) && !is_placeholder(&mons[mntmp]))
  175.                  break;
  176.          } while (--tryct > 0);
  177.      }
  178.  
  179.      /* The below polyok() fails either if everything is genocided, or if
  180.       * we deliberately chose something illegal to force newman().
  181.       */
  182.      sex_change_ok++;
  183.      if (!polyok(&mons[mntmp]) || (!forcecontrol && !rn2(5))
  184.          || your_race(&mons[mntmp])) {
  185.          newman();
  186.      } else {
  187.          (void) polymon(mntmp);
  188.      }
  189.      sex_change_ok--; /* reset */
  190.  
  191.  made_change:
  192.      new_light = emits_light(youmonst.data);
  193.      if (old_light != new_light) {
  194.          if (old_light)
  195.              del_light_source(LS_MONSTER, monst_to_any(&youmonst));
  196.          if (new_light == 1)
  197.              ++new_light; /* otherwise it's undetectable */
  198.          if (new_light)
  199.              new_light_source(u.ux, u.uy, new_light, LS_MONSTER,
  200.                               monst_to_any(&youmonst));
  201.      }
  202.  }
  203.  

polymon

  1.  /* (try to) make a mntmp monster out of the player;
  2.     returns 1 if polymorph successful */
  3.  int
  4.  polymon(mntmp)
  5.  int mntmp;
  6.  {
  7.      boolean sticky = sticks(youmonst.data) && u.ustuck && !u.uswallow,
  8.              was_blind = !!Blind, dochange = FALSE;
  9.      int mlvl;
  10.  
  11.      if (mvitals[mntmp].mvflags & G_GENOD) { /* allow G_EXTINCT */
  12.          You_feel("rather %s-ish.", mons[mntmp].mname);
  13.          exercise(A_WIS, TRUE);
  14.          return 0;
  15.      }
  16.  
  17.      /* KMH, conduct */
  18.      u.uconduct.polyselfs++;
  19.  
  20.      /* exercise used to be at the very end but only Wis was affected
  21.         there since the polymorph was always in effect by then */
  22.      exercise(A_CON, FALSE);
  23.      exercise(A_WIS, TRUE);
  24.  
  25.      if (!Upolyd) {
  26.          /* Human to monster; save human stats */
  27.          u.macurr = u.acurr;
  28.          u.mamax = u.amax;
  29.          u.mfemale = flags.female;
  30.      } else {
  31.          /* Monster to monster; restore human stats, to be
  32.           * immediately changed to provide stats for the new monster
  33.           */
  34.          u.acurr = u.macurr;
  35.          u.amax = u.mamax;
  36.          flags.female = u.mfemale;
  37.      }
  38.  
  39.      /* if stuck mimicking gold, stop immediately */
  40.      if (multi < 0 && youmonst.m_ap_type == M_AP_OBJECT
  41.          && youmonst.data->mlet != S_MIMIC)
  42.          unmul("");
  43.      /* if becoming a non-mimic, stop mimicking anything */
  44.      if (mons[mntmp].mlet != S_MIMIC) {
  45.          /* as in polyman() */
  46.          youmonst.m_ap_type = M_AP_NOTHING;
  47.      }
  48.      if (is_male(&mons[mntmp])) {
  49.          if (flags.female)
  50.              dochange = TRUE;
  51.      } else if (is_female(&mons[mntmp])) {
  52.          if (!flags.female)
  53.              dochange = TRUE;
  54.      } else if (!is_neuter(&mons[mntmp]) && mntmp != u.ulycn) {
  55.          if (sex_change_ok && !rn2(10))
  56.              dochange = TRUE;
  57.      }
  58.      if (dochange) {
  59.          flags.female = !flags.female;
  60.          You("%s %s%s!",
  61.              (u.umonnum != mntmp) ? "turn into a" : "feel like a new",
  62.              (is_male(&mons[mntmp]) || is_female(&mons[mntmp]))
  63.                  ? ""
  64.                  : flags.female ? "female " : "male ",
  65.              mons[mntmp].mname);
  66.      } else {
  67.          if (u.umonnum != mntmp)
  68.              You("turn into %s!", an(mons[mntmp].mname));
  69.          else
  70.              You_feel("like a new %s!", mons[mntmp].mname);
  71.      }
  72.      if (Stoned && poly_when_stoned(&mons[mntmp])) {
  73.          /* poly_when_stoned already checked stone golem genocide */
  74.          mntmp = PM_STONE_GOLEM;
  75.          make_stoned(0L, "You turn to stone!", 0, (char *) 0);
  76.      }
  77.  
  78.      u.mtimedone = rn1(500, 500);
  79.      u.umonnum = mntmp;
  80.      set_uasmon();
  81.  
  82.      /* New stats for monster, to last only as long as polymorphed.
  83.       * Currently only strength gets changed.
  84.       */
  85.      if (strongmonst(&mons[mntmp]))
  86.          ABASE(A_STR) = AMAX(A_STR) = STR18(100);
  87.  
  88.      if (Stone_resistance && Stoned) { /* parnes@eniac.seas.upenn.edu */
  89.          make_stoned(0L, "You no longer seem to be petrifying.", 0,
  90.                      (char *) 0);
  91.      }
  92.      if (Sick_resistance && Sick) {
  93.          make_sick(0L, (char *) 0, FALSE, SICK_ALL);
  94.          You("no longer feel sick.");
  95.      }
  96.      if (Slimed) {
  97.          if (flaming(youmonst.data)) {
  98.              make_slimed(0L, "The slime burns away!");
  99.          } else if (mntmp == PM_GREEN_SLIME) {
  100.              /* do it silently */
  101.              make_slimed(0L, (char *) 0);
  102.          }
  103.      }
  104.      check_strangling(FALSE); /* maybe stop strangling */
  105.      if (nohands(youmonst.data))
  106.          Glib = 0;
  107.  
  108.      /*
  109.      mlvl = adj_lev(&mons[mntmp]);
  110.       * We can't do the above, since there's no such thing as an
  111.       * "experience level of you as a monster" for a polymorphed character.
  112.       */
  113.      mlvl = (int) mons[mntmp].mlevel;
  114.      if (youmonst.data->mlet == S_DRAGON && mntmp >= PM_GRAY_DRAGON) {
  115.          u.mhmax = In_endgame(&u.uz) ? (8 * mlvl) : (4 * mlvl + d(mlvl, 4));
  116.      } else if (is_golem(youmonst.data)) {
  117.          u.mhmax = golemhp(mntmp);
  118.      } else {
  119.          if (!mlvl)
  120.              u.mhmax = rnd(4);
  121.          else
  122.              u.mhmax = d(mlvl, 8);
  123.          if (is_home_elemental(&mons[mntmp]))
  124.              u.mhmax *= 3;
  125.      }
  126.      u.mh = u.mhmax;
  127.  
  128.      if (u.ulevel < mlvl) {
  129.          /* Low level characters can't become high level monsters for long */
  130.  #ifdef DUMB
  131.          /* DRS/NS 2.2.6 messes up -- Peter Kendell */
  132.          int mtd = u.mtimedone, ulv = u.ulevel;
  133.  
  134.          u.mtimedone = mtd * ulv / mlvl;
  135.  #else
  136.          u.mtimedone = u.mtimedone * u.ulevel / mlvl;
  137.  #endif
  138.      }
  139.  
  140.      if (uskin && mntmp != armor_to_dragon(uskin->otyp))
  141.          skinback(FALSE);
  142.      break_armor();
  143.      drop_weapon(1);
  144.      (void) hideunder(&youmonst);
  145.  
  146.      if (u.utraptype == TT_PIT && u.utrap) {
  147.          u.utrap = rn1(6, 2); /* time to escape resets */
  148.      }
  149.      if (was_blind && !Blind) { /* previous form was eyeless */
  150.          Blinded = 1L;
  151.          make_blinded(0L, TRUE); /* remove blindness */
  152.      }
  153.      newsym(u.ux, u.uy); /* Change symbol */
  154.  
  155.      if (!sticky && !u.uswallow && u.ustuck && sticks(youmonst.data))
  156.          u.ustuck = 0;
  157.      else if (sticky && !sticks(youmonst.data))
  158.          uunstick();
  159.      if (u.usteed) {
  160.          if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) {
  161.              char buf[BUFSZ];
  162.  
  163.              pline("%s touch %s.", no_longer_petrify_resistant,
  164.                    mon_nam(u.usteed));
  165.              Sprintf(buf, "riding %s", an(u.usteed->data->mname));
  166.              instapetrify(buf);
  167.          }
  168.          if (!can_ride(u.usteed))
  169.              dismount_steed(DISMOUNT_POLY);
  170.      }
  171.  
  172.      if (flags.verbose) {
  173.          static const char use_thec[] = "Use the command #%s to %s.";
  174.          static const char monsterc[] = "monster";
  175.  
  176.          if (can_breathe(youmonst.data))
  177.              pline(use_thec, monsterc, "use your breath weapon");
  178.          if (attacktype(youmonst.data, AT_SPIT))
  179.              pline(use_thec, monsterc, "spit venom");
  180.          if (youmonst.data->mlet == S_NYMPH)
  181.              pline(use_thec, monsterc, "remove an iron ball");
  182.          if (attacktype(youmonst.data, AT_GAZE))
  183.              pline(use_thec, monsterc, "gaze at monsters");
  184.          if (is_hider(youmonst.data))
  185.              pline(use_thec, monsterc, "hide");
  186.          if (is_were(youmonst.data))
  187.              pline(use_thec, monsterc, "summon help");
  188.          if (webmaker(youmonst.data))
  189.              pline(use_thec, monsterc, "spin a web");
  190.          if (u.umonnum == PM_GREMLIN)
  191.              pline(use_thec, monsterc, "multiply in a fountain");
  192.          if (is_unicorn(youmonst.data))
  193.              pline(use_thec, monsterc, "use your horn");
  194.          if (is_mind_flayer(youmonst.data))
  195.              pline(use_thec, monsterc, "emit a mental blast");
  196.          if (youmonst.data->msound == MS_SHRIEK) /* worthless, actually */
  197.              pline(use_thec, monsterc, "shriek");
  198.          if (is_vampire(youmonst.data))
  199.              pline(use_thec, monsterc, "change shape");
  200.  
  201.          if (lays_eggs(youmonst.data) && flags.female)
  202.              pline(use_thec, "sit", "lay an egg");
  203.      }
  204.  
  205.      /* you now know what an egg of your type looks like */
  206.      if (lays_eggs(youmonst.data)) {
  207.          learn_egg_type(u.umonnum);
  208.          /* make queen bees recognize killer bee eggs */
  209.          learn_egg_type(egg_type_from_parent(u.umonnum, TRUE));
  210.      }
  211.      find_ac();
  212.      if ((!Levitation && !u.ustuck && !Flying && is_pool_or_lava(u.ux, u.uy))
  213.          || (Underwater && !Swimming))
  214.          spoteffects(TRUE);
  215.      if (Passes_walls && u.utrap
  216.          && (u.utraptype == TT_INFLOOR || u.utraptype == TT_BURIEDBALL)) {
  217.          u.utrap = 0;
  218.          if (u.utraptype == TT_INFLOOR)
  219.              pline_The("rock seems to no longer trap you.");
  220.          else {
  221.              pline_The("buried ball is no longer bound to you.");
  222.              buried_ball_to_freedom();
  223.          }
  224.      } else if (likes_lava(youmonst.data) && u.utrap
  225.                 && u.utraptype == TT_LAVA) {
  226.          u.utrap = 0;
  227.          pline_The("lava now feels soothing.");
  228.      }
  229.      if (amorphous(youmonst.data) || is_whirly(youmonst.data)
  230.          || unsolid(youmonst.data)) {
  231.          if (Punished) {
  232.              You("slip out of the iron chain.");
  233.              unpunish();
  234.          } else if (u.utrap && u.utraptype == TT_BURIEDBALL) {
  235.              You("slip free of the buried ball and chain.");
  236.              buried_ball_to_freedom();
  237.          }
  238.      }
  239.      if (u.utrap && (u.utraptype == TT_WEB || u.utraptype == TT_BEARTRAP)
  240.          && (amorphous(youmonst.data) || is_whirly(youmonst.data)
  241.              || unsolid(youmonst.data) || (youmonst.data->msize <= MZ_SMALL
  242.                                            && u.utraptype == TT_BEARTRAP))) {
  243.          You("are no longer stuck in the %s.",
  244.              u.utraptype == TT_WEB ? "web" : "bear trap");
  245.          /* probably should burn webs too if PM_FIRE_ELEMENTAL */
  246.          u.utrap = 0;
  247.      }
  248.      if (webmaker(youmonst.data) && u.utrap && u.utraptype == TT_WEB) {
  249.          You("orient yourself on the web.");
  250.          u.utrap = 0;
  251.      }
  252.      check_strangling(TRUE); /* maybe start strangling */
  253.      (void) polysense(youmonst.data);
  254.  
  255.      context.botl = 1;
  256.      vision_full_recalc = 1;
  257.      see_monsters();
  258.      (void) encumber_msg();
  259.  
  260.      retouch_equipment(2);
  261.      /* this might trigger a recursive call to polymon() [stone golem
  262.         wielding cockatrice corpse and hit by stone-to-flesh, becomes
  263.         flesh golem above, now gets transformed back into stone golem] */
  264.      if (!uarmg)
  265.          selftouch(no_longer_petrify_resistant);
  266.      return 1;
  267.  }
  268.  

break_armor

  1.  STATIC_OVL void
  2.  break_armor()
  3.  {
  4.      register struct obj *otmp;
  5.  
  6.      if (breakarm(youmonst.data)) {
  7.          if ((otmp = uarm) != 0) {
  8.              if (donning(otmp))
  9.                  cancel_don();
  10.              You("break out of your armor!");
  11.              exercise(A_STR, FALSE);
  12.              (void) Armor_gone();
  13.              useup(otmp);
  14.          }
  15.          if ((otmp = uarmc) != 0) {
  16.              if (otmp->oartifact) {
  17.                  Your("%s falls off!", cloak_simple_name(otmp));
  18.                  (void) Cloak_off();
  19.                  dropx(otmp);
  20.              } else {
  21.                  Your("%s tears apart!", cloak_simple_name(otmp));
  22.                  (void) Cloak_off();
  23.                  useup(otmp);
  24.              }
  25.          }
  26.          if (uarmu) {
  27.              Your("shirt rips to shreds!");
  28.              useup(uarmu);
  29.          }
  30.      } else if (sliparm(youmonst.data)) {
  31.          if (((otmp = uarm) != 0) && (racial_exception(&youmonst, otmp) < 1)) {
  32.              if (donning(otmp))
  33.                  cancel_don();
  34.              Your("armor falls around you!");
  35.              (void) Armor_gone();
  36.              dropx(otmp);
  37.          }
  38.          if ((otmp = uarmc) != 0) {
  39.              if (is_whirly(youmonst.data))
  40.                  Your("%s falls, unsupported!", cloak_simple_name(otmp));
  41.              else
  42.                  You("shrink out of your %s!", cloak_simple_name(otmp));
  43.              (void) Cloak_off();
  44.              dropx(otmp);
  45.          }
  46.          if ((otmp = uarmu) != 0) {
  47.              if (is_whirly(youmonst.data))
  48.                  You("seep right through your shirt!");
  49.              else
  50.                  You("become much too small for your shirt!");
  51.              setworn((struct obj *) 0, otmp->owornmask & W_ARMU);
  52.              dropx(otmp);
  53.          }
  54.      }
  55.      if (has_horns(youmonst.data)) {
  56.          if ((otmp = uarmh) != 0) {
  57.              if (is_flimsy(otmp) && !donning(otmp)) {
  58.                  char hornbuf[BUFSZ];
  59.  
  60.                  /* Future possibilities: This could damage/destroy helmet */
  61.                  Sprintf(hornbuf, "horn%s", plur(num_horns(youmonst.data)));
  62.                  Your("%s %s through %s.", hornbuf, vtense(hornbuf, "pierce"),
  63.                       yname(otmp));
  64.              } else {
  65.                  if (donning(otmp))
  66.                      cancel_don();
  67.                  Your("%s falls to the %s!", helm_simple_name(otmp),
  68.                       surface(u.ux, u.uy));
  69.                  (void) Helmet_off();
  70.                  dropx(otmp);
  71.              }
  72.          }
  73.      }
  74.      if (nohands(youmonst.data) || verysmall(youmonst.data)) {
  75.          if ((otmp = uarmg) != 0) {
  76.              if (donning(otmp))
  77.                  cancel_don();
  78.              /* Drop weapon along with gloves */
  79.              You("drop your gloves%s!", uwep ? " and weapon" : "");
  80.              drop_weapon(0);
  81.              (void) Gloves_off();
  82.              dropx(otmp);
  83.          }
  84.          if ((otmp = uarms) != 0) {
  85.              You("can no longer hold your shield!");
  86.              (void) Shield_off();
  87.              dropx(otmp);
  88.          }
  89.          if ((otmp = uarmh) != 0) {
  90.              if (donning(otmp))
  91.                  cancel_don();
  92.              Your("%s falls to the %s!", helm_simple_name(otmp),
  93.                   surface(u.ux, u.uy));
  94.              (void) Helmet_off();
  95.              dropx(otmp);
  96.          }
  97.      }
  98.      if (nohands(youmonst.data) || verysmall(youmonst.data)
  99.          || slithy(youmonst.data) || youmonst.data->mlet == S_CENTAUR) {
  100.          if ((otmp = uarmf) != 0) {
  101.              if (donning(otmp))
  102.                  cancel_don();
  103.              if (is_whirly(youmonst.data))
  104.                  Your("boots fall away!");
  105.              else
  106.                  Your("boots %s off your feet!",
  107.                       verysmall(youmonst.data) ? "slide" : "are pushed");
  108.              (void) Boots_off();
  109.              dropx(otmp);
  110.          }
  111.      }
  112.  }
  113.  

drop_weapon

  1.  STATIC_OVL void
  2.  drop_weapon(alone)
  3.  int alone;
  4.  {
  5.      struct obj *otmp;
  6.      const char *what, *which, *whichtoo;
  7.      boolean candropwep, candropswapwep;
  8.  
  9.      if (uwep) {
  10.          /* !alone check below is currently superfluous but in the
  11.           * future it might not be so if there are monsters which cannot
  12.           * wear gloves but can wield weapons
  13.           */
  14.          if (!alone || cantwield(youmonst.data)) {
  15.              candropwep = canletgo(uwep, "");
  16.              candropswapwep = !u.twoweap || canletgo(uswapwep, "");
  17.              if (alone) {
  18.                  what = (candropwep && candropswapwep) ? "drop" : "release";
  19.                  which = is_sword(uwep) ? "sword" : weapon_descr(uwep);
  20.                  if (u.twoweap) {
  21.                      whichtoo =
  22.                          is_sword(uswapwep) ? "sword" : weapon_descr(uswapwep);
  23.                      if (strcmp(which, whichtoo))
  24.                          which = "weapon";
  25.                  }
  26.                  if (uwep->quan != 1L || u.twoweap)
  27.                      which = makeplural(which);
  28.  
  29.                  You("find you must %s %s %s!", what,
  30.                      the_your[!!strncmp(which, "corpse", 6)], which);
  31.              }
  32.              if (u.twoweap) {
  33.                  otmp = uswapwep;
  34.                  uswapwepgone();
  35.                  if (candropswapwep)
  36.                      dropx(otmp);
  37.              }
  38.              otmp = uwep;
  39.              uwepgone();
  40.              if (candropwep)
  41.                  dropx(otmp);
  42.              update_inventory();
  43.          } else if (!could_twoweap(youmonst.data)) {
  44.              untwoweapon();
  45.          }
  46.      }
  47.  }
  48.  

rehumanize

  1.  void
  2.  rehumanize()
  3.  {
  4.      /* You can't revert back while unchanging */
  5.      if (Unchanging && (u.mh < 1)) {
  6.          killer.format = NO_KILLER_PREFIX;
  7.          Strcpy(killer.name, "killed while stuck in creature form");
  8.          done(DIED);
  9.      }
  10.  
  11.      if (emits_light(youmonst.data))
  12.          del_light_source(LS_MONSTER, monst_to_any(&youmonst));
  13.      polyman("return to %s form!", urace.adj);
  14.  
  15.      if (u.uhp < 1) {
  16.          /* can only happen if some bit of code reduces u.uhp
  17.             instead of u.mh while poly'd */
  18.          Your("old form was not healthy enough to survive.");
  19.          Sprintf(killer.name, "reverting to unhealthy %s form", urace.adj);
  20.          killer.format = KILLED_BY;
  21.          done(DIED);
  22.      }
  23.      nomul(0);
  24.  
  25.      context.botl = 1;
  26.      vision_full_recalc = 1;
  27.      (void) encumber_msg();
  28.  
  29.      retouch_equipment(2);
  30.      if (!uarmg)
  31.          selftouch(no_longer_petrify_resistant);
  32.  }
  33.  

dobreathe

  1.  int
  2.  dobreathe()
  3.  {
  4.      struct attack *mattk;
  5.  
  6.      if (Strangled) {
  7.          You_cant("breathe.  Sorry.");
  8.          return 0;
  9.      }
  10.      if (u.uen < 15) {
  11.          You("don't have enough energy to breathe!");
  12.          return 0;
  13.      }
  14.      u.uen -= 15;
  15.      context.botl = 1;
  16.  
  17.      if (!getdir((char *) 0))
  18.          return 0;
  19.  
  20.      mattk = attacktype_fordmg(youmonst.data, AT_BREA, AD_ANY);
  21.      if (!mattk)
  22.          impossible("bad breath attack?"); /* mouthwash needed... */
  23.      else if (!u.dx && !u.dy && !u.dz)
  24.          ubreatheu(mattk);
  25.      else
  26.          buzz((int) (20 + mattk->adtyp - 1), (int) mattk->damn, u.ux, u.uy,
  27.               u.dx, u.dy);
  28.      return 1;
  29.  }
  30.  

dospit

  1.  int
  2.  dospit()
  3.  {
  4.      struct obj *otmp;
  5.      struct attack *mattk;
  6.  
  7.      if (!getdir((char *) 0))
  8.          return 0;
  9.      mattk = attacktype_fordmg(youmonst.data, AT_SPIT, AD_ANY);
  10.      if (!mattk) {
  11.          impossible("bad spit attack?");
  12.      } else {
  13.          switch (mattk->adtyp) {
  14.          case AD_BLND:
  15.          case AD_DRST:
  16.              otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
  17.              break;
  18.          default:
  19.              impossible("bad attack type in dospit");
  20.          /* fall through */
  21.          case AD_ACID:
  22.              otmp = mksobj(ACID_VENOM, TRUE, FALSE);
  23.              break;
  24.          }
  25.          otmp->spe = 1; /* to indicate it's yours */
  26.          throwit(otmp, 0L, FALSE);
  27.      }
  28.      return 1;
  29.  }
  30.  

doremove

  1.  int
  2.  doremove()
  3.  {
  4.      if (!Punished) {
  5.          if (u.utrap && u.utraptype == TT_BURIEDBALL) {
  6.              pline_The("ball and chain are buried firmly in the %s.",
  7.                        surface(u.ux, u.uy));
  8.              return 0;
  9.          }
  10.          You("are not chained to anything!");
  11.          return 0;
  12.      }
  13.      unpunish();
  14.      return 1;
  15.  }
  16.  

dospinweb

  1.  int
  2.  dospinweb()
  3.  {
  4.      register struct trap *ttmp = t_at(u.ux, u.uy);
  5.  
  6.      if (Levitation || Is_airlevel(&u.uz) || Underwater
  7.          || Is_waterlevel(&u.uz)) {
  8.          You("must be on the ground to spin a web.");
  9.          return 0;
  10.      }
  11.      if (u.uswallow) {
  12.          You("release web fluid inside %s.", mon_nam(u.ustuck));
  13.          if (is_animal(u.ustuck->data)) {
  14.              expels(u.ustuck, u.ustuck->data, TRUE);
  15.              return 0;
  16.          }
  17.          if (is_whirly(u.ustuck->data)) {
  18.              int i;
  19.  
  20.              for (i = 0; i < NATTK; i++)
  21.                  if (u.ustuck->data->mattk[i].aatyp == AT_ENGL)
  22.                      break;
  23.              if (i == NATTK)
  24.                  impossible("Swallower has no engulfing attack?");
  25.              else {
  26.                  char sweep[30];
  27.  
  28.                  sweep[0] = '\0';
  29.                  switch (u.ustuck->data->mattk[i].adtyp) {
  30.                  case AD_FIRE:
  31.                      Strcpy(sweep, "ignites and ");
  32.                      break;
  33.                  case AD_ELEC:
  34.                      Strcpy(sweep, "fries and ");
  35.                      break;
  36.                  case AD_COLD:
  37.                      Strcpy(sweep, "freezes, shatters and ");
  38.                      break;
  39.                  }
  40.                  pline_The("web %sis swept away!", sweep);
  41.              }
  42.              return 0;
  43.          } /* default: a nasty jelly-like creature */
  44.          pline_The("web dissolves into %s.", mon_nam(u.ustuck));
  45.          return 0;
  46.      }
  47.      if (u.utrap) {
  48.          You("cannot spin webs while stuck in a trap.");
  49.          return 0;
  50.      }
  51.      exercise(A_DEX, TRUE);
  52.      if (ttmp) {
  53.          switch (ttmp->ttyp) {
  54.          case PIT:
  55.          case SPIKED_PIT:
  56.              You("spin a web, covering up the pit.");
  57.              deltrap(ttmp);
  58.              bury_objs(u.ux, u.uy);
  59.              newsym(u.ux, u.uy);
  60.              return 1;
  61.          case SQKY_BOARD:
  62.              pline_The("squeaky board is muffled.");
  63.              deltrap(ttmp);
  64.              newsym(u.ux, u.uy);
  65.              return 1;
  66.          case TELEP_TRAP:
  67.          case LEVEL_TELEP:
  68.          case MAGIC_PORTAL:
  69.          case VIBRATING_SQUARE:
  70.              Your("webbing vanishes!");
  71.              return 0;
  72.          case WEB:
  73.              You("make the web thicker.");
  74.              return 1;
  75.          case HOLE:
  76.          case TRAPDOOR:
  77.              You("web over the %s.",
  78.                  (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole");
  79.              deltrap(ttmp);
  80.              newsym(u.ux, u.uy);
  81.              return 1;
  82.          case ROLLING_BOULDER_TRAP:
  83.              You("spin a web, jamming the trigger.");
  84.              deltrap(ttmp);
  85.              newsym(u.ux, u.uy);
  86.              return 1;
  87.          case ARROW_TRAP:
  88.          case DART_TRAP:
  89.          case BEAR_TRAP:
  90.          case ROCKTRAP:
  91.          case FIRE_TRAP:
  92.          case LANDMINE:
  93.          case SLP_GAS_TRAP:
  94.          case RUST_TRAP:
  95.          case MAGIC_TRAP:
  96.          case ANTI_MAGIC:
  97.          case POLY_TRAP:
  98.              You("have triggered a trap!");
  99.              dotrap(ttmp, 0);
  100.              return 1;
  101.          default:
  102.              impossible("Webbing over trap type %d?", ttmp->ttyp);
  103.              return 0;
  104.          }
  105.      } else if (On_stairs(u.ux, u.uy)) {
  106.          /* cop out: don't let them hide the stairs */
  107.          Your("web fails to impede access to the %s.",
  108.               (levl[u.ux][u.uy].typ == STAIRS) ? "stairs" : "ladder");
  109.          return 1;
  110.      }
  111.      ttmp = maketrap(u.ux, u.uy, WEB);
  112.      if (ttmp) {
  113.          ttmp->madeby_u = 1;
  114.          feeltrap(ttmp);
  115.      }
  116.      return 1;
  117.  }
  118.  

dosummon

  1.  int
  2.  dosummon()
  3.  {
  4.      int placeholder;
  5.      if (u.uen < 10) {
  6.          You("lack the energy to send forth a call for help!");
  7.          return 0;
  8.      }
  9.      u.uen -= 10;
  10.      context.botl = 1;
  11.  
  12.      You("call upon your brethren for help!");
  13.      exercise(A_WIS, TRUE);
  14.      if (!were_summon(youmonst.data, TRUE, &placeholder, (char *) 0))
  15.          pline("But none arrive.");
  16.      return 1;
  17.  }
  18.  

dogaze

  1.  int
  2.  dogaze()
  3.  {
  4.      register struct monst *mtmp;
  5.      int looked = 0;
  6.      char qbuf[QBUFSZ];
  7.      int i;
  8.      uchar adtyp = 0;
  9.  
  10.      for (i = 0; i < NATTK; i++) {
  11.          if (youmonst.data->mattk[i].aatyp == AT_GAZE) {
  12.              adtyp = youmonst.data->mattk[i].adtyp;
  13.              break;
  14.          }
  15.      }
  16.      if (adtyp != AD_CONF && adtyp != AD_FIRE) {
  17.          impossible("gaze attack %d?", adtyp);
  18.          return 0;
  19.      }
  20.  
  21.      if (Blind) {
  22.          You_cant("see anything to gaze at.");
  23.          return 0;
  24.      } else if (Hallucination) {
  25.          You_cant("gaze at anything you can see.");
  26.          return 0;
  27.      }
  28.      if (u.uen < 15) {
  29.          You("lack the energy to use your special gaze!");
  30.          return 0;
  31.      }
  32.      u.uen -= 15;
  33.      context.botl = 1;
  34.  
  35.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  36.          if (DEADMONSTER(mtmp))
  37.              continue;
  38.          if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) {
  39.              looked++;
  40.              if (Invis && !perceives(mtmp->data)) {
  41.                  pline("%s seems not to notice your gaze.", Monnam(mtmp));
  42.              } else if (mtmp->minvis && !See_invisible) {
  43.                  You_cant("see where to gaze at %s.", Monnam(mtmp));
  44.              } else if (mtmp->m_ap_type == M_AP_FURNITURE
  45.                         || mtmp->m_ap_type == M_AP_OBJECT) {
  46.                  looked--;
  47.                  continue;
  48.              } else if (flags.safe_dog && mtmp->mtame && !Confusion) {
  49.                  You("avoid gazing at %s.", y_monnam(mtmp));
  50.              } else {
  51.                  if (flags.confirm && mtmp->mpeaceful && !Confusion) {
  52.                      Sprintf(qbuf, "Really %s %s?",
  53.                              (adtyp == AD_CONF) ? "confuse" : "attack",
  54.                              mon_nam(mtmp));
  55.                      if (yn(qbuf) != 'y')
  56.                          continue;
  57.                      setmangry(mtmp);
  58.                  }
  59.                  if (!mtmp->mcanmove || mtmp->mstun || mtmp->msleeping
  60.                      || !mtmp->mcansee || !haseyes(mtmp->data)) {
  61.                      looked--;
  62.                      continue;
  63.                  }
  64.                  /* No reflection check for consistency with when a monster
  65.                   * gazes at *you*--only medusa gaze gets reflected then.
  66.                   */
  67.                  if (adtyp == AD_CONF) {
  68.                      if (!mtmp->mconf)
  69.                          Your("gaze confuses %s!", mon_nam(mtmp));
  70.                      else
  71.                          pline("%s is getting more and more confused.",
  72.                                Monnam(mtmp));
  73.                      mtmp->mconf = 1;
  74.                  } else if (adtyp == AD_FIRE) {
  75.                      int dmg = d(2, 6), lev = (int) u.ulevel;
  76.  
  77.                      You("attack %s with a fiery gaze!", mon_nam(mtmp));
  78.                      if (resists_fire(mtmp)) {
  79.                          pline_The("fire doesn't burn %s!", mon_nam(mtmp));
  80.                          dmg = 0;
  81.                      }
  82.                      if (lev > rn2(20))
  83.                          (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
  84.                      if (lev > rn2(20))
  85.                          (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
  86.                      if (lev > rn2(25))
  87.                          (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
  88.                      if (dmg)
  89.                          mtmp->mhp -= dmg;
  90.                      if (mtmp->mhp <= 0)
  91.                          killed(mtmp);
  92.                  }
  93.                  /* For consistency with passive() in uhitm.c, this only
  94.                   * affects you if the monster is still alive.
  95.                   */
  96.                  if (DEADMONSTER(mtmp))
  97.                      continue;
  98.  
  99.                  if (mtmp->data == &mons[PM_FLOATING_EYE] && !mtmp->mcan) {
  100.                      if (!Free_action) {
  101.                          You("are frozen by %s gaze!",
  102.                              s_suffix(mon_nam(mtmp)));
  103.                          nomul((u.ulevel > 6 || rn2(4))
  104.                                    ? -d((int) mtmp->m_lev + 1,
  105.                                         (int) mtmp->data->mattk[0].damd)
  106.                                    : -200);
  107.                          multi_reason = "frozen by a monster's gaze";
  108.                          nomovemsg = 0;
  109.                          return 1;
  110.                      } else
  111.                          You("stiffen momentarily under %s gaze.",
  112.                              s_suffix(mon_nam(mtmp)));
  113.                  }
  114.                  /* Technically this one shouldn't affect you at all because
  115.                   * the Medusa gaze is an active monster attack that only
  116.                   * works on the monster's turn, but for it to *not* have an
  117.                   * effect would be too weird.
  118.                   */
  119.                  if (mtmp->data == &mons[PM_MEDUSA] && !mtmp->mcan) {
  120.                      pline("Gazing at the awake %s is not a very good idea.",
  121.                            l_monnam(mtmp));
  122.                      /* as if gazing at a sleeping anything is fruitful... */
  123.                      You("turn to stone...");
  124.                      killer.format = KILLED_BY;
  125.                      Strcpy(killer.name, "deliberately meeting Medusa's gaze");
  126.                      done(STONING);
  127.                  }
  128.              }
  129.          }
  130.      }
  131.      if (!looked)
  132.          You("gaze at no place in particular.");
  133.      return 1;
  134.  }
  135.  

dohide

  1.  int
  2.  dohide()
  3.  {
  4.      boolean ismimic = youmonst.data->mlet == S_MIMIC,
  5.              on_ceiling = is_clinger(youmonst.data) || Flying;
  6.  
  7.      /* can't hide while being held (or holding) or while trapped
  8.         (except for floor hiders [trapper or mimic] in pits) */
  9.      if (u.ustuck || (u.utrap && (u.utraptype != TT_PIT || on_ceiling))) {
  10.          You_cant("hide while you're %s.",
  11.                   !u.ustuck ? "trapped" : !sticks(youmonst.data)
  12.                                               ? "being held"
  13.                                               : humanoid(u.ustuck->data)
  14.                                                     ? "holding someone"
  15.                                                     : "holding that creature");
  16.          if (u.uundetected
  17.              || (ismimic && youmonst.m_ap_type != M_AP_NOTHING)) {
  18.              u.uundetected = 0;
  19.              youmonst.m_ap_type = M_AP_NOTHING;
  20.              newsym(u.ux, u.uy);
  21.          }
  22.          return 0;
  23.      }
  24.      /* note: the eel and hides_under cases are hypothetical;
  25.         such critters aren't offered the option of hiding via #monster */
  26.      if (youmonst.data->mlet == S_EEL && !is_pool(u.ux, u.uy)) {
  27.          if (IS_FOUNTAIN(levl[u.ux][u.uy].typ))
  28.              The("fountain is not deep enough to hide in.");
  29.          else
  30.              There("is no water to hide in here.");
  31.          u.uundetected = 0;
  32.          return 0;
  33.      }
  34.      if (hides_under(youmonst.data) && !level.objects[u.ux][u.uy]) {
  35.          There("is nothing to hide under here.");
  36.          u.uundetected = 0;
  37.          return 0;
  38.      }
  39.      /* Planes of Air and Water */
  40.      if (on_ceiling && !has_ceiling(&u.uz)) {
  41.          There("is nowhere to hide above you.");
  42.          u.uundetected = 0;
  43.          return 0;
  44.      }
  45.      if ((is_hider(youmonst.data) && !Flying) /* floor hider */
  46.          && (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))) {
  47.          There("is nowhere to hide beneath you.");
  48.          u.uundetected = 0;
  49.          return 0;
  50.      }
  51.      /* TODO? inhibit floor hiding at furniture locations, or
  52.       * else make youhiding() give smarter messages at such spots.
  53.       */
  54.  
  55.      if (u.uundetected || (ismimic && youmonst.m_ap_type != M_AP_NOTHING)) {
  56.          youhiding(FALSE, 1); /* "you are already hiding" */
  57.          return 0;
  58.      }
  59.  
  60.      if (ismimic) {
  61.          /* should bring up a dialog "what would you like to imitate?" */
  62.          youmonst.m_ap_type = M_AP_OBJECT;
  63.          youmonst.mappearance = STRANGE_OBJECT;
  64.      } else
  65.          u.uundetected = 1;
  66.      newsym(u.ux, u.uy);
  67.      youhiding(FALSE, 0); /* "you are now hiding" */
  68.      return 1;
  69.  }
  70.  

dopoly

  1.  int
  2.  dopoly()
  3.  {
  4.      struct permonst *savedat = youmonst.data;
  5.  
  6.      if (is_vampire(youmonst.data)) {
  7.          polyself(2);
  8.          if (savedat != youmonst.data) {
  9.              You("transform into %s.", an(youmonst.data->mname));
  10.              newsym(u.ux, u.uy);
  11.          }
  12.      }
  13.      return 1;
  14.  }
  15.  

domindblast

  1.  int
  2.  domindblast()
  3.  {
  4.      struct monst *mtmp, *nmon;
  5.  
  6.      if (u.uen < 10) {
  7.          You("concentrate but lack the energy to maintain doing so.");
  8.          return 0;
  9.      }
  10.      u.uen -= 10;
  11.      context.botl = 1;
  12.  
  13.      You("concentrate.");
  14.      pline("A wave of psychic energy pours out.");
  15.      for (mtmp = fmon; mtmp; mtmp = nmon) {
  16.          int u_sen;
  17.  
  18.          nmon = mtmp->nmon;
  19.          if (DEADMONSTER(mtmp))
  20.              continue;
  21.          if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM)
  22.              continue;
  23.          if (mtmp->mpeaceful)
  24.              continue;
  25.          u_sen = telepathic(mtmp->data) && !mtmp->mcansee;
  26.          if (u_sen || (telepathic(mtmp->data) && rn2(2)) || !rn2(10)) {
  27.              You("lock in on %s %s.", s_suffix(mon_nam(mtmp)),
  28.                  u_sen ? "telepathy"
  29.                        : telepathic(mtmp->data) ? "latent telepathy" : "mind");
  30.              mtmp->mhp -= rnd(15);
  31.              if (mtmp->mhp <= 0)
  32.                  killed(mtmp);
  33.          }
  34.      }
  35.      return 1;
  36.  }
  37.  

uunstick

  1.  STATIC_OVL void
  2.  uunstick()
  3.  {
  4.      pline("%s is no longer in your clutches.", Monnam(u.ustuck));
  5.      u.ustuck = 0;
  6.  }
  7.  

skinback

  1.  void
  2.  skinback(silently)
  3.  boolean silently;
  4.  {
  5.      if (uskin) {
  6.          if (!silently)
  7.              Your("skin returns to its original form.");
  8.          uarm = uskin;
  9.          uskin = (struct obj *) 0;
  10.          /* undo save/restore hack */
  11.          uarm->owornmask &= ~I_SPECIAL;
  12.      }
  13.  }
  14.  

mbodypart

  1.  const char *
  2.  mbodypart(mon, part)
  3.  struct monst *mon;
  4.  int part;
  5.  {
  6.      static NEARDATA const char
  7.          *humanoid_parts[] = { "arm",       "eye",  "face",         "finger",
  8.                                "fingertip", "foot", "hand",         "handed",
  9.                                "head",      "leg",  "light headed", "neck",
  10.                                "spine",     "toe",  "hair",         "blood",
  11.                                "lung",      "nose", "stomach" },
  12.          *jelly_parts[] = { "pseudopod", "dark spot", "front",
  13.                             "pseudopod extension", "pseudopod extremity",
  14.                             "pseudopod root", "grasp", "grasped",
  15.                             "cerebral area", "lower pseudopod", "viscous",
  16.                             "middle", "surface", "pseudopod extremity",
  17.                             "ripples", "juices", "surface", "sensor",
  18.                             "stomach" },
  19.          *animal_parts[] = { "forelimb",  "eye",           "face",
  20.                              "foreclaw",  "claw tip",      "rear claw",
  21.                              "foreclaw",  "clawed",        "head",
  22.                              "rear limb", "light headed",  "neck",
  23.                              "spine",     "rear claw tip", "fur",
  24.                              "blood",     "lung",          "nose",
  25.                              "stomach" },
  26.          *bird_parts[] = { "wing",     "eye",  "face",         "wing",
  27.                            "wing tip", "foot", "wing",         "winged",
  28.                            "head",     "leg",  "light headed", "neck",
  29.                            "spine",    "toe",  "feathers",     "blood",
  30.                            "lung",     "bill", "stomach" },
  31.          *horse_parts[] = { "foreleg",  "eye",           "face",
  32.                             "forehoof", "hoof tip",      "rear hoof",
  33.                             "forehoof", "hooved",        "head",
  34.                             "rear leg", "light headed",  "neck",
  35.                             "backbone", "rear hoof tip", "mane",
  36.                             "blood",    "lung",          "nose",
  37.                             "stomach" },
  38.          *sphere_parts[] = { "appendage", "optic nerve", "body", "tentacle",
  39.                              "tentacle tip", "lower appendage", "tentacle",
  40.                              "tentacled", "body", "lower tentacle",
  41.                              "rotational", "equator", "body",
  42.                              "lower tentacle tip", "cilia", "life force",
  43.                              "retina", "olfactory nerve", "interior" },
  44.          *fungus_parts[] = { "mycelium", "visual area", "front",
  45.                              "hypha",    "hypha",       "root",
  46.                              "strand",   "stranded",    "cap area",
  47.                              "rhizome",  "sporulated",  "stalk",
  48.                              "root",     "rhizome tip", "spores",
  49.                              "juices",   "gill",        "gill",
  50.                              "interior" },
  51.          *vortex_parts[] = { "region",        "eye",           "front",
  52.                              "minor current", "minor current", "lower current",
  53.                              "swirl",         "swirled",       "central core",
  54.                              "lower current", "addled",        "center",
  55.                              "currents",      "edge",          "currents",
  56.                              "life force",    "center",        "leading edge",
  57.                              "interior" },
  58.          *snake_parts[] = { "vestigial limb", "eye", "face", "large scale",
  59.                             "large scale tip", "rear region", "scale gap",
  60.                             "scale gapped", "head", "rear region",
  61.                             "light headed", "neck", "length", "rear scale",
  62.                             "scales", "blood", "lung", "forked tongue",
  63.                             "stomach" },
  64.          *worm_parts[] = { "anterior segment", "light sensitive cell",
  65.                            "clitellum", "setae", "setae", "posterior segment",
  66.                            "segment", "segmented", "anterior segment",
  67.                            "posterior", "over stretched", "clitellum",
  68.                            "length", "posterior setae", "setae", "blood",
  69.                            "skin", "prostomium", "stomach" },
  70.          *fish_parts[] = { "fin", "eye", "premaxillary", "pelvic axillary",
  71.                            "pelvic fin", "anal fin", "pectoral fin", "finned",
  72.                            "head", "peduncle", "played out", "gills",
  73.                            "dorsal fin", "caudal fin", "scales", "blood",
  74.                            "gill", "nostril", "stomach" };
  75.      /* claw attacks are overloaded in mons[]; most humanoids with
  76.         such attacks should still reference hands rather than claws */
  77.      static const char not_claws[] = {
  78.          S_HUMAN,     S_MUMMY,   S_ZOMBIE, S_ANGEL, S_NYMPH, S_LEPRECHAUN,
  79.          S_QUANTMECH, S_VAMPIRE, S_ORC,    S_GIANT, /* quest nemeses */
  80.          '\0' /* string terminator; assert( S_xxx != 0 ); */
  81.      };
  82.      struct permonst *mptr = mon->data;
  83.  
  84.      /* some special cases */
  85.      if (mptr->mlet == S_DOG || mptr->mlet == S_FELINE
  86.          || mptr->mlet == S_RODENT || mptr == &mons[PM_OWLBEAR]) {
  87.          switch (part) {
  88.          case HAND:
  89.              return "paw";
  90.          case HANDED:
  91.              return "pawed";
  92.          case FOOT:
  93.              return "rear paw";
  94.          case ARM:
  95.          case LEG:
  96.              return horse_parts[part]; /* "foreleg", "rear leg" */
  97.          default:
  98.              break; /* for other parts, use animal_parts[] below */
  99.          }
  100.      } else if (mptr->mlet == S_YETI) { /* excl. owlbear due to 'if' above */
  101.          /* opposable thumbs, hence "hands", "arms", "legs", &c */
  102.          return humanoid_parts[part]; /* yeti/sasquatch, monkey/ape */
  103.      }
  104.      if ((part == HAND || part == HANDED)
  105.          && (humanoid(mptr) && attacktype(mptr, AT_CLAW)
  106.              && !index(not_claws, mptr->mlet) && mptr != &mons[PM_STONE_GOLEM]
  107.              && mptr != &mons[PM_INCUBUS] && mptr != &mons[PM_SUCCUBUS]))
  108.          return (part == HAND) ? "claw" : "clawed";
  109.      if ((mptr == &mons[PM_MUMAK] || mptr == &mons[PM_MASTODON])
  110.          && part == NOSE)
  111.          return "trunk";
  112.      if (mptr == &mons[PM_SHARK] && part == HAIR)
  113.          return "skin"; /* sharks don't have scales */
  114.      if ((mptr == &mons[PM_JELLYFISH] || mptr == &mons[PM_KRAKEN])
  115.          && (part == ARM || part == FINGER || part == HAND || part == FOOT
  116.              || part == TOE))
  117.          return "tentacle";
  118.      if (mptr == &mons[PM_FLOATING_EYE] && part == EYE)
  119.          return "cornea";
  120.      if (humanoid(mptr) && (part == ARM || part == FINGER || part == FINGERTIP
  121.                             || part == HAND || part == HANDED))
  122.          return humanoid_parts[part];
  123.      if (mptr == &mons[PM_RAVEN])
  124.          return bird_parts[part];
  125.      if (mptr->mlet == S_CENTAUR || mptr->mlet == S_UNICORN
  126.          || (mptr == &mons[PM_ROTHE] && part != HAIR))
  127.          return horse_parts[part];
  128.      if (mptr->mlet == S_LIGHT) {
  129.          if (part == HANDED)
  130.              return "rayed";
  131.          else if (part == ARM || part == FINGER || part == FINGERTIP
  132.                   || part == HAND)
  133.              return "ray";
  134.          else
  135.              return "beam";
  136.      }
  137.      if (mptr == &mons[PM_STALKER] && part == HEAD)
  138.          return "head";
  139.      if (mptr->mlet == S_EEL && mptr != &mons[PM_JELLYFISH])
  140.          return fish_parts[part];
  141.      if (mptr->mlet == S_WORM)
  142.          return worm_parts[part];
  143.      if (slithy(mptr) || (mptr->mlet == S_DRAGON && part == HAIR))
  144.          return snake_parts[part];
  145.      if (mptr->mlet == S_EYE)
  146.          return sphere_parts[part];
  147.      if (mptr->mlet == S_JELLY || mptr->mlet == S_PUDDING
  148.          || mptr->mlet == S_BLOB || mptr == &mons[PM_JELLYFISH])
  149.          return jelly_parts[part];
  150.      if (mptr->mlet == S_VORTEX || mptr->mlet == S_ELEMENTAL)
  151.          return vortex_parts[part];
  152.      if (mptr->mlet == S_FUNGUS)
  153.          return fungus_parts[part];
  154.      if (humanoid(mptr))
  155.          return humanoid_parts[part];
  156.      return animal_parts[part];
  157.  }
  158.  

body_part

  1.  const char *
  2.  body_part(part)
  3.  int part;
  4.  {
  5.      return mbodypart(&youmonst, part);
  6.  }
  7.  

poly_gender

  1.  int
  2.  poly_gender()
  3.  {
  4.      /* Returns gender of polymorphed player;
  5.       * 0/1=same meaning as flags.female, 2=none.
  6.       */
  7.      if (is_neuter(youmonst.data) || !humanoid(youmonst.data))
  8.          return 2;
  9.      return flags.female;
  10.  }
  11.  

ugolemeffects

  1.  void
  2.  ugolemeffects(damtype, dam)
  3.  int damtype, dam;
  4.  {
  5.      int heal = 0;
  6.  
  7.      /* We won't bother with "slow"/"haste" since players do not
  8.       * have a monster-specific slow/haste so there is no way to
  9.       * restore the old velocity once they are back to human.
  10.       */
  11.      if (u.umonnum != PM_FLESH_GOLEM && u.umonnum != PM_IRON_GOLEM)
  12.          return;
  13.      switch (damtype) {
  14.      case AD_ELEC:
  15.          if (u.umonnum == PM_FLESH_GOLEM)
  16.              heal = (dam + 5) / 6; /* Approx 1 per die */
  17.          break;
  18.      case AD_FIRE:
  19.          if (u.umonnum == PM_IRON_GOLEM)
  20.              heal = dam;
  21.          break;
  22.      }
  23.      if (heal && (u.mh < u.mhmax)) {
  24.          u.mh += heal;
  25.          if (u.mh > u.mhmax)
  26.              u.mh = u.mhmax;
  27.          context.botl = 1;
  28.          pline("Strangely, you feel better than before.");
  29.          exercise(A_STR, TRUE);
  30.      }
  31.  }
  32.  

armor_to_dragon

  1.  STATIC_OVL int
  2.  armor_to_dragon(atyp)
  3.  int atyp;
  4.  {
  5.      switch (atyp) {
  6.      case GRAY_DRAGON_SCALE_MAIL:
  7.      case GRAY_DRAGON_SCALES:
  8.          return PM_GRAY_DRAGON;
  9.      case SILVER_DRAGON_SCALE_MAIL:
  10.      case SILVER_DRAGON_SCALES:
  11.          return PM_SILVER_DRAGON;
  12.  #if 0 /* DEFERRED */
  13.      case SHIMMERING_DRAGON_SCALE_MAIL:
  14.      case SHIMMERING_DRAGON_SCALES:
  15.          return PM_SHIMMERING_DRAGON;
  16.  #endif
  17.      case RED_DRAGON_SCALE_MAIL:
  18.      case RED_DRAGON_SCALES:
  19.          return PM_RED_DRAGON;
  20.      case ORANGE_DRAGON_SCALE_MAIL:
  21.      case ORANGE_DRAGON_SCALES:
  22.          return PM_ORANGE_DRAGON;
  23.      case WHITE_DRAGON_SCALE_MAIL:
  24.      case WHITE_DRAGON_SCALES:
  25.          return PM_WHITE_DRAGON;
  26.      case BLACK_DRAGON_SCALE_MAIL:
  27.      case BLACK_DRAGON_SCALES:
  28.          return PM_BLACK_DRAGON;
  29.      case BLUE_DRAGON_SCALE_MAIL:
  30.      case BLUE_DRAGON_SCALES:
  31.          return PM_BLUE_DRAGON;
  32.      case GREEN_DRAGON_SCALE_MAIL:
  33.      case GREEN_DRAGON_SCALES:
  34.          return PM_GREEN_DRAGON;
  35.      case YELLOW_DRAGON_SCALE_MAIL:
  36.      case YELLOW_DRAGON_SCALES:
  37.          return PM_YELLOW_DRAGON;
  38.      default:
  39.          return -1;
  40.      }
  41.  }
  42.  

polysense

  1.  /*
  2.   * Some species have awareness of other species
  3.   */
  4.  static boolean
  5.  polysense(mptr)
  6.  struct permonst *mptr;
  7.  {
  8.      short warnidx = 0;
  9.  
  10.      context.warntype.speciesidx = 0;
  11.      context.warntype.species = 0;
  12.      context.warntype.polyd = 0;
  13.  
  14.      switch (monsndx(mptr)) {
  15.      case PM_PURPLE_WORM:
  16.          warnidx = PM_SHRIEKER;
  17.          break;
  18.      case PM_VAMPIRE:
  19.      case PM_VAMPIRE_LORD:
  20.          context.warntype.polyd = M2_HUMAN | M2_ELF;
  21.          HWarn_of_mon |= FROMRACE;
  22.          return TRUE;
  23.      }
  24.      if (warnidx) {
  25.          context.warntype.speciesidx = warnidx;
  26.          context.warntype.species = &mons[warnidx];
  27.          HWarn_of_mon |= FROMRACE;
  28.          return TRUE;
  29.      }
  30.      context.warntype.speciesidx = 0;
  31.      context.warntype.species = 0;
  32.      HWarn_of_mon &= ~FROMRACE;
  33.      return FALSE;
  34.  }
  35.  
  36.  /*polyself.c*/