Source:NetHack 3.6.0/src/apply.c

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

Below is the full text to apply.c from the source code of NetHack 3.6.0. To link to a particular line, write [[Source:NetHack 3.6.0/src/apply.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	apply.c	$NHDT-Date: 1446808436 2015/11/06 11:13:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.210 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  #include "hack.h"
  6.  
  7.  extern boolean notonhead; /* for long worms */
  8.  
  9.  STATIC_DCL int FDECL(use_camera, (struct obj *));
  10.  STATIC_DCL int FDECL(use_towel, (struct obj *));
  11.  STATIC_DCL boolean FDECL(its_dead, (int, int, int *));
  12.  STATIC_DCL int FDECL(use_stethoscope, (struct obj *));
  13.  STATIC_DCL void FDECL(use_whistle, (struct obj *));
  14.  STATIC_DCL void FDECL(use_magic_whistle, (struct obj *));
  15.  STATIC_DCL void FDECL(use_leash, (struct obj *));
  16.  STATIC_DCL int FDECL(use_mirror, (struct obj *));
  17.  STATIC_DCL void FDECL(use_bell, (struct obj **));
  18.  STATIC_DCL void FDECL(use_candelabrum, (struct obj *));
  19.  STATIC_DCL void FDECL(use_candle, (struct obj **));
  20.  STATIC_DCL void FDECL(use_lamp, (struct obj *));
  21.  STATIC_DCL void FDECL(light_cocktail, (struct obj *));
  22.  STATIC_PTR void FDECL(display_jump_positions, (int));
  23.  STATIC_DCL void FDECL(use_tinning_kit, (struct obj *));
  24.  STATIC_DCL void FDECL(use_figurine, (struct obj **));
  25.  STATIC_DCL void FDECL(use_grease, (struct obj *));
  26.  STATIC_DCL void FDECL(use_trap, (struct obj *));
  27.  STATIC_DCL void FDECL(use_stone, (struct obj *));
  28.  STATIC_PTR int NDECL(set_trap); /* occupation callback */
  29.  STATIC_DCL int FDECL(use_whip, (struct obj *));
  30.  STATIC_PTR void FDECL(display_polearm_positions, (int));
  31.  STATIC_DCL int FDECL(use_pole, (struct obj *));
  32.  STATIC_DCL int FDECL(use_cream_pie, (struct obj *));
  33.  STATIC_DCL int FDECL(use_grapple, (struct obj *));
  34.  STATIC_DCL int FDECL(do_break_wand, (struct obj *));
  35.  STATIC_DCL boolean FDECL(figurine_location_checks, (struct obj *,
  36.                                                      coord *, BOOLEAN_P));
  37.  STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
  38.  STATIC_DCL void FDECL(setapplyclasses, (char *));
  39.  STATIC_DCL boolean FDECL(is_valid_jump_pos, (int, int, int, BOOLEAN_P));
  40.  STATIC_DCL boolean FDECL(find_poleable_mon, (coord *, int, int));
  41.  
  42.  #ifdef AMIGA
  43.  void FDECL(amii_speaker, (struct obj *, char *, int));
  44.  #endif
  45.  
  46.  static const char no_elbow_room[] =
  47.      "don't have enough elbow-room to maneuver.";
  48.  

use_camera

  1.  STATIC_OVL int
  2.  use_camera(obj)
  3.  struct obj *obj;
  4.  {
  5.      struct monst *mtmp;
  6.  
  7.      if (Underwater) {
  8.          pline("Using your camera underwater would void the warranty.");
  9.          return 0;
  10.      }
  11.      if (!getdir((char *) 0))
  12.          return 0;
  13.  
  14.      if (obj->spe <= 0) {
  15.          pline1(nothing_happens);
  16.          return 1;
  17.      }
  18.      consume_obj_charge(obj, TRUE);
  19.  
  20.      if (obj->cursed && !rn2(2)) {
  21.          (void) zapyourself(obj, TRUE);
  22.      } else if (u.uswallow) {
  23.          You("take a picture of %s %s.", s_suffix(mon_nam(u.ustuck)),
  24.              mbodypart(u.ustuck, STOMACH));
  25.      } else if (u.dz) {
  26.          You("take a picture of the %s.",
  27.              (u.dz > 0) ? surface(u.ux, u.uy) : ceiling(u.ux, u.uy));
  28.      } else if (!u.dx && !u.dy) {
  29.          (void) zapyourself(obj, TRUE);
  30.      } else if ((mtmp = bhit(u.dx, u.dy, COLNO, FLASHED_LIGHT,
  31.                              (int FDECL((*), (MONST_P, OBJ_P))) 0,
  32.                              (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj)) != 0) {
  33.          obj->ox = u.ux, obj->oy = u.uy;
  34.          (void) flash_hits_mon(mtmp, obj);
  35.      }
  36.      return 1;
  37.  }
  38.  

use_towel

  1.  STATIC_OVL int
  2.  use_towel(obj)
  3.  struct obj *obj;
  4.  {
  5.      boolean drying_feedback = (obj == uwep);
  6.  
  7.      if (!freehand()) {
  8.          You("have no free %s!", body_part(HAND));
  9.          return 0;
  10.      } else if (obj == ublindf) {
  11.          You("cannot use it while you're wearing it!");
  12.          return 0;
  13.      } else if (obj->cursed) {
  14.          long old;
  15.  
  16.          switch (rn2(3)) {
  17.          case 2:
  18.              old = Glib;
  19.              incr_itimeout(&Glib, rn1(10, 3));
  20.              Your("%s %s!", makeplural(body_part(HAND)),
  21.                   (old ? "are filthier than ever" : "get slimy"));
  22.              if (is_wet_towel(obj))
  23.                  dry_a_towel(obj, -1, drying_feedback);
  24.              return 1;
  25.          case 1:
  26.              if (!ublindf) {
  27.                  old = u.ucreamed;
  28.                  u.ucreamed += rn1(10, 3);
  29.                  pline("Yecch! Your %s %s gunk on it!", body_part(FACE),
  30.                        (old ? "has more" : "now has"));
  31.                  make_blinded(Blinded + (long) u.ucreamed - old, TRUE);
  32.              } else {
  33.                  const char *what;
  34.  
  35.                  what = (ublindf->otyp == LENSES)
  36.                             ? "lenses"
  37.                             : (obj->otyp == ublindf->otyp) ? "other towel"
  38.                                                            : "blindfold";
  39.                  if (ublindf->cursed) {
  40.                      You("push your %s %s.", what,
  41.                          rn2(2) ? "cock-eyed" : "crooked");
  42.                  } else {
  43.                      struct obj *saved_ublindf = ublindf;
  44.                      You("push your %s off.", what);
  45.                      Blindf_off(ublindf);
  46.                      dropx(saved_ublindf);
  47.                  }
  48.              }
  49.              if (is_wet_towel(obj))
  50.                  dry_a_towel(obj, -1, drying_feedback);
  51.              return 1;
  52.          case 0:
  53.              break;
  54.          }
  55.      }
  56.  
  57.      if (Glib) {
  58.          Glib = 0;
  59.          You("wipe off your %s.", makeplural(body_part(HAND)));
  60.          if (is_wet_towel(obj))
  61.              dry_a_towel(obj, -1, drying_feedback);
  62.          return 1;
  63.      } else if (u.ucreamed) {
  64.          Blinded -= u.ucreamed;
  65.          u.ucreamed = 0;
  66.          if (!Blinded) {
  67.              pline("You've got the glop off.");
  68.              if (!gulp_blnd_check()) {
  69.                  Blinded = 1;
  70.                  make_blinded(0L, TRUE);
  71.              }
  72.          } else {
  73.              Your("%s feels clean now.", body_part(FACE));
  74.          }
  75.          if (is_wet_towel(obj))
  76.              dry_a_towel(obj, -1, drying_feedback);
  77.          return 1;
  78.      }
  79.  
  80.      Your("%s and %s are already clean.", body_part(FACE),
  81.           makeplural(body_part(HAND)));
  82.  
  83.      return 0;
  84.  }
  85.  

its_dead

  1.  /* maybe give a stethoscope message based on floor objects */
  2.  STATIC_OVL boolean
  3.  its_dead(rx, ry, resp)
  4.  int rx, ry, *resp;
  5.  {
  6.      char buf[BUFSZ];
  7.      boolean more_corpses;
  8.      struct permonst *mptr;
  9.      struct obj *corpse = sobj_at(CORPSE, rx, ry),
  10.                 *statue = sobj_at(STATUE, rx, ry);
  11.  
  12.      if (!can_reach_floor(TRUE)) { /* levitation or unskilled riding */
  13.          corpse = 0;               /* can't reach corpse on floor */
  14.          /* you can't reach tiny statues (even though you can fight
  15.             tiny monsters while levitating--consistency, what's that?) */
  16.          while (statue && mons[statue->corpsenm].msize == MZ_TINY)
  17.              statue = nxtobj(statue, STATUE, TRUE);
  18.      }
  19.      /* when both corpse and statue are present, pick the uppermost one */
  20.      if (corpse && statue) {
  21.          if (nxtobj(statue, CORPSE, TRUE) == corpse)
  22.              corpse = 0; /* corpse follows statue; ignore it */
  23.          else
  24.              statue = 0; /* corpse precedes statue; ignore statue */
  25.      }
  26.      more_corpses = (corpse && nxtobj(corpse, CORPSE, TRUE));
  27.  
  28.      /* additional stethoscope messages from jyoung@apanix.apana.org.au */
  29.      if (!corpse && !statue) {
  30.          ; /* nothing to do */
  31.  
  32.      } else if (Hallucination) {
  33.          if (!corpse) {
  34.              /* it's a statue */
  35.              Strcpy(buf, "You're both stoned");
  36.          } else if (corpse->quan == 1L && !more_corpses) {
  37.              int gndr = 2; /* neuter: "it" */
  38.              struct monst *mtmp = get_mtraits(corpse, FALSE);
  39.  
  40.              /* (most corpses don't retain the monster's sex, so
  41.                 we're usually forced to use generic pronoun here) */
  42.              if (mtmp) {
  43.                  mptr = &mons[mtmp->mnum];
  44.                  /* can't use mhe() here; it calls pronoun_gender() which
  45.                     expects monster to be on the map (visibility check) */
  46.                  if ((humanoid(mptr) || (mptr->geno & G_UNIQ)
  47.                       || type_is_pname(mptr)) && !is_neuter(mptr))
  48.                      gndr = (int) mtmp->female;
  49.              } else {
  50.                  mptr = &mons[corpse->corpsenm];
  51.                  if (is_female(mptr))
  52.                      gndr = 1;
  53.                  else if (is_male(mptr))
  54.                      gndr = 0;
  55.              }
  56.              Sprintf(buf, "%s's dead", genders[gndr].he); /* "he"/"she"/"it" */
  57.              buf[0] = highc(buf[0]);
  58.          } else { /* plural */
  59.              Strcpy(buf, "They're dead");
  60.          }
  61.          /* variations on "He's dead, Jim." (Star Trek's Dr McCoy) */
  62.          You_hear("a voice say, \"%s, Jim.\"", buf);
  63.          *resp = 1;
  64.          return TRUE;
  65.  
  66.      } else if (corpse) {
  67.          boolean here = (rx == u.ux && ry == u.uy),
  68.                  one = (corpse->quan == 1L && !more_corpses), reviver = FALSE;
  69.  
  70.          if (Role_if(PM_HEALER)) {
  71.              /* ok to reset `corpse' here; we're done with it */
  72.              do {
  73.                  if (obj_has_timer(corpse, REVIVE_MON))
  74.                      reviver = TRUE;
  75.                  else
  76.                      corpse = nxtobj(corpse, CORPSE, TRUE);
  77.              } while (corpse && !reviver);
  78.          }
  79.          You("determine that %s unfortunate being%s %s%s dead.",
  80.              one ? (here ? "this" : "that") : (here ? "these" : "those"),
  81.              one ? "" : "s", one ? "is" : "are", reviver ? " mostly" : "");
  82.          return TRUE;
  83.  
  84.      } else { /* statue */
  85.          const char *what, *how;
  86.  
  87.          mptr = &mons[statue->corpsenm];
  88.          if (Blind) { /* ignore statue->dknown; it'll always be set */
  89.              Sprintf(buf, "%s %s",
  90.                      (rx == u.ux && ry == u.uy) ? "This" : "That",
  91.                      humanoid(mptr) ? "person" : "creature");
  92.              what = buf;
  93.          } else {
  94.              what = mptr->mname;
  95.              if (!type_is_pname(mptr))
  96.                  what = The(what);
  97.          }
  98.          how = "fine";
  99.          if (Role_if(PM_HEALER)) {
  100.              struct trap *ttmp = t_at(rx, ry);
  101.  
  102.              if (ttmp && ttmp->ttyp == STATUE_TRAP)
  103.                  how = "extraordinary";
  104.              else if (Has_contents(statue))
  105.                  how = "remarkable";
  106.          }
  107.  
  108.          pline("%s is in %s health for a statue.", what, how);
  109.          return TRUE;
  110.      }
  111.      return FALSE; /* no corpse or statue */
  112.  }
  113.  

use_stethoscope

  1.  static const char hollow_str[] = "a hollow sound.  This must be a secret %s!";
  2.  
  3.  /* Strictly speaking it makes no sense for usage of a stethoscope to
  4.     not take any time; however, unless it did, the stethoscope would be
  5.     almost useless.  As a compromise, one use per turn is free, another
  6.     uses up the turn; this makes curse status have a tangible effect. */
  7.  STATIC_OVL int
  8.  use_stethoscope(obj)
  9.  register struct obj *obj;
  10.  {
  11.      struct monst *mtmp;
  12.      struct rm *lev;
  13.      int rx, ry, res;
  14.      boolean interference = (u.uswallow && is_whirly(u.ustuck->data)
  15.                              && !rn2(Role_if(PM_HEALER) ? 10 : 3));
  16.  
  17.      if (nohands(youmonst.data)) {
  18.          You("have no hands!"); /* not `body_part(HAND)' */
  19.          return 0;
  20.      } else if (Deaf) {
  21.          You_cant("hear anything!");
  22.          return 0;
  23.      } else if (!freehand()) {
  24.          You("have no free %s.", body_part(HAND));
  25.          return 0;
  26.      }
  27.      if (!getdir((char *) 0))
  28.          return 0;
  29.  
  30.      res = (moves == context.stethoscope_move)
  31.            && (youmonst.movement == context.stethoscope_movement);
  32.      context.stethoscope_move = moves;
  33.      context.stethoscope_movement = youmonst.movement;
  34.  
  35.      if (u.usteed && u.dz > 0) {
  36.          if (interference) {
  37.              pline("%s interferes.", Monnam(u.ustuck));
  38.              mstatusline(u.ustuck);
  39.          } else
  40.              mstatusline(u.usteed);
  41.          return res;
  42.      } else if (u.uswallow && (u.dx || u.dy || u.dz)) {
  43.          mstatusline(u.ustuck);
  44.          return res;
  45.      } else if (u.uswallow && interference) {
  46.          pline("%s interferes.", Monnam(u.ustuck));
  47.          mstatusline(u.ustuck);
  48.          return res;
  49.      } else if (u.dz) {
  50.          if (Underwater)
  51.              You_hear("faint splashing.");
  52.          else if (u.dz < 0 || !can_reach_floor(TRUE))
  53.              cant_reach_floor(u.ux, u.uy, (u.dz < 0), TRUE);
  54.          else if (its_dead(u.ux, u.uy, &res))
  55.              ; /* message already given */
  56.          else if (Is_stronghold(&u.uz))
  57.              You_hear("the crackling of hellfire.");
  58.          else
  59.              pline_The("%s seems healthy enough.", surface(u.ux, u.uy));
  60.          return res;
  61.      } else if (obj->cursed && !rn2(2)) {
  62.          You_hear("your heart beat.");
  63.          return res;
  64.      }
  65.      if (Stunned || (Confusion && !rn2(5)))
  66.          confdir();
  67.      if (!u.dx && !u.dy) {
  68.          ustatusline();
  69.          return res;
  70.      }
  71.      rx = u.ux + u.dx;
  72.      ry = u.uy + u.dy;
  73.      if (!isok(rx, ry)) {
  74.          You_hear("a faint typing noise.");
  75.          return 0;
  76.      }
  77.      if ((mtmp = m_at(rx, ry)) != 0) {
  78.          const char *mnm = x_monnam(mtmp, ARTICLE_A, (const char *) 0,
  79.                                     SUPPRESS_IT | SUPPRESS_INVISIBLE, FALSE);
  80.  
  81.          if (mtmp->mundetected) {
  82.              if (!canspotmon(mtmp))
  83.                  There("is %s hidden there.", mnm);
  84.              mtmp->mundetected = 0;
  85.              newsym(mtmp->mx, mtmp->my);
  86.          } else if (mtmp->mappearance) {
  87.              const char *what = "thing";
  88.  
  89.              switch (mtmp->m_ap_type) {
  90.              case M_AP_OBJECT:
  91.                  what = simple_typename(mtmp->mappearance);
  92.                  break;
  93.              case M_AP_MONSTER: /* ignore Hallucination here */
  94.                  what = mons[mtmp->mappearance].mname;
  95.                  break;
  96.              case M_AP_FURNITURE:
  97.                  what = defsyms[mtmp->mappearance].explanation;
  98.                  break;
  99.              }
  100.              seemimic(mtmp);
  101.              pline("That %s is really %s", what, mnm);
  102.          } else if (flags.verbose && !canspotmon(mtmp)) {
  103.              There("is %s there.", mnm);
  104.          }
  105.          mstatusline(mtmp);
  106.          if (!canspotmon(mtmp))
  107.              map_invisible(rx, ry);
  108.          return res;
  109.      }
  110.      if (glyph_is_invisible(levl[rx][ry].glyph)) {
  111.          unmap_object(rx, ry);
  112.          newsym(rx, ry);
  113.          pline_The("invisible monster must have moved.");
  114.      }
  115.      lev = &levl[rx][ry];
  116.      switch (lev->typ) {
  117.      case SDOOR:
  118.          You_hear(hollow_str, "door");
  119.          cvt_sdoor_to_door(lev); /* ->typ = DOOR */
  120.          feel_newsym(rx, ry);
  121.          return res;
  122.      case SCORR:
  123.          You_hear(hollow_str, "passage");
  124.          lev->typ = CORR;
  125.          unblock_point(rx, ry);
  126.          feel_newsym(rx, ry);
  127.          return res;
  128.      }
  129.  
  130.      if (!its_dead(rx, ry, &res))
  131.          You("hear nothing special."); /* not You_hear()  */
  132.      return res;
  133.  }
  134.  

use_whistle

  1.  static const char whistle_str[] = "produce a %s whistling sound.";
  2.  
  3.  STATIC_OVL void
  4.  use_whistle(obj)
  5.  struct obj *obj;
  6.  {
  7.      if (!can_blow(&youmonst)) {
  8.          You("are incapable of using the whistle.");
  9.      } else if (Underwater) {
  10.          You("blow bubbles through %s.", yname(obj));
  11.      } else {
  12.          You(whistle_str, obj->cursed ? "shrill" : "high");
  13.          wake_nearby();
  14.      }
  15.  }
  16.  

use_magic_whistle

  1.  STATIC_OVL void
  2.  use_magic_whistle(obj)
  3.  struct obj *obj;
  4.  {
  5.      register struct monst *mtmp, *nextmon;
  6.  
  7.      if (!can_blow(&youmonst)) {
  8.          You("are incapable of using the whistle.");
  9.      } else if (obj->cursed && !rn2(2)) {
  10.          You("produce a %shigh-pitched humming noise.",
  11.              Underwater ? "very " : "");
  12.          wake_nearby();
  13.      } else {
  14.          int pet_cnt = 0, omx, omy;
  15.  
  16.          /* it's magic!  it works underwater too (at a higher pitch) */
  17.          You(whistle_str,
  18.              Hallucination ? "normal" : Underwater ? "strange, high-pitched"
  19.                                                    : "strange");
  20.          for (mtmp = fmon; mtmp; mtmp = nextmon) {
  21.              nextmon = mtmp->nmon; /* trap might kill mon */
  22.              if (DEADMONSTER(mtmp))
  23.                  continue;
  24.              /* steed is already at your location, so not affected;
  25.                 this avoids trap issues if you're on a trap location */
  26.              if (mtmp == u.usteed)
  27.                  continue;
  28.              if (mtmp->mtame) {
  29.                  if (mtmp->mtrapped) {
  30.                      /* no longer in previous trap (affects mintrap) */
  31.                      mtmp->mtrapped = 0;
  32.                      fill_pit(mtmp->mx, mtmp->my);
  33.                  }
  34.                  /* mimic must be revealed before we know whether it
  35.                     actually moves because line-of-sight may change */
  36.                  if (mtmp->m_ap_type)
  37.                      seemimic(mtmp);
  38.                  omx = mtmp->mx, omy = mtmp->my;
  39.                  mnexto(mtmp);
  40.                  if (mtmp->mx != omx || mtmp->my != omy) {
  41.                      mtmp->mundetected = 0; /* reveal non-mimic hider */
  42.                      if (canspotmon(mtmp))
  43.                          ++pet_cnt;
  44.                      if (mintrap(mtmp) == 2)
  45.                          change_luck(-1);
  46.                  }
  47.              }
  48.          }
  49.          if (pet_cnt > 0)
  50.              makeknown(obj->otyp);
  51.      }
  52.  }
  53.  

um_dist

  1.  boolean
  2.  um_dist(x, y, n)
  3.  xchar x, y, n;
  4.  {
  5.      return (boolean) (abs(u.ux - x) > n || abs(u.uy - y) > n);
  6.  }
  7.  

number_leashed

  1.  int
  2.  number_leashed()
  3.  {
  4.      int i = 0;
  5.      struct obj *obj;
  6.  
  7.      for (obj = invent; obj; obj = obj->nobj)
  8.          if (obj->otyp == LEASH && obj->leashmon != 0)
  9.              i++;
  10.      return i;
  11.  }
  12.  

o_unleash

  1.  /* otmp is about to be destroyed or stolen */
  2.  void
  3.  o_unleash(otmp)
  4.  register struct obj *otmp;
  5.  {
  6.      register struct monst *mtmp;
  7.  
  8.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  9.          if (mtmp->m_id == (unsigned) otmp->leashmon)
  10.              mtmp->mleashed = 0;
  11.      otmp->leashmon = 0;
  12.  }
  13.  

m_unleash

  1.  /* mtmp is about to die, or become untame */
  2.  void
  3.  m_unleash(mtmp, feedback)
  4.  register struct monst *mtmp;
  5.  boolean feedback;
  6.  {
  7.      register struct obj *otmp;
  8.  
  9.      if (feedback) {
  10.          if (canseemon(mtmp))
  11.              pline("%s pulls free of %s leash!", Monnam(mtmp), mhis(mtmp));
  12.          else
  13.              Your("leash falls slack.");
  14.      }
  15.      for (otmp = invent; otmp; otmp = otmp->nobj)
  16.          if (otmp->otyp == LEASH && otmp->leashmon == (int) mtmp->m_id)
  17.              otmp->leashmon = 0;
  18.      mtmp->mleashed = 0;
  19.  }
  20.  

unleash_all

  1.  /* player is about to die (for bones) */
  2.  void
  3.  unleash_all()
  4.  {
  5.      register struct obj *otmp;
  6.      register struct monst *mtmp;
  7.  
  8.      for (otmp = invent; otmp; otmp = otmp->nobj)
  9.          if (otmp->otyp == LEASH)
  10.              otmp->leashmon = 0;
  11.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  12.          mtmp->mleashed = 0;
  13.  }
  14.  

leashable

  1.  #define MAXLEASHED 2
  2.  
  3.  static boolean
  4.  leashable(mtmp)
  5.  struct monst *mtmp;
  6.  {
  7.      return (boolean) (mtmp->mnum != PM_LONG_WORM);
  8.  }
  9.  

use_leash

  1.  /* ARGSUSED */
  2.  STATIC_OVL void
  3.  use_leash(obj)
  4.  struct obj *obj;
  5.  {
  6.      coord cc;
  7.      register struct monst *mtmp;
  8.      int spotmon;
  9.  
  10.      if (!obj->leashmon && number_leashed() >= MAXLEASHED) {
  11.          You("cannot leash any more pets.");
  12.          return;
  13.      }
  14.  
  15.      if (!get_adjacent_loc((char *) 0, (char *) 0, u.ux, u.uy, &cc))
  16.          return;
  17.  
  18.      if ((cc.x == u.ux) && (cc.y == u.uy)) {
  19.          if (u.usteed && u.dz > 0) {
  20.              mtmp = u.usteed;
  21.              spotmon = 1;
  22.              goto got_target;
  23.          }
  24.          pline("Leash yourself?  Very funny...");
  25.          return;
  26.      }
  27.  
  28.      if (!(mtmp = m_at(cc.x, cc.y))) {
  29.          There("is no creature there.");
  30.          return;
  31.      }
  32.  
  33.      spotmon = canspotmon(mtmp);
  34.  got_target:
  35.  
  36.      if (!mtmp->mtame) {
  37.          if (!spotmon)
  38.              There("is no creature there.");
  39.          else
  40.              pline("%s %s leashed!", Monnam(mtmp),
  41.                    (!obj->leashmon) ? "cannot be" : "is not");
  42.          return;
  43.      }
  44.      if (!obj->leashmon) {
  45.          if (mtmp->mleashed) {
  46.              pline("This %s is already leashed.",
  47.                    spotmon ? l_monnam(mtmp) : "monster");
  48.              return;
  49.          }
  50.          if (!leashable(mtmp)) {
  51.              pline("The leash won't fit onto %s%s.", spotmon ? "your " : "",
  52.                    l_monnam(mtmp));
  53.              return;
  54.          }
  55.  
  56.          You("slip the leash around %s%s.", spotmon ? "your " : "",
  57.              l_monnam(mtmp));
  58.          mtmp->mleashed = 1;
  59.          obj->leashmon = (int) mtmp->m_id;
  60.          mtmp->msleeping = 0;
  61.          return;
  62.      }
  63.      if (obj->leashmon != (int) mtmp->m_id) {
  64.          pline("This leash is not attached to that creature.");
  65.          return;
  66.      } else {
  67.          if (obj->cursed) {
  68.              pline_The("leash would not come off!");
  69.              obj->bknown = TRUE;
  70.              return;
  71.          }
  72.          mtmp->mleashed = 0;
  73.          obj->leashmon = 0;
  74.          You("remove the leash from %s%s.", spotmon ? "your " : "",
  75.              l_monnam(mtmp));
  76.      }
  77.      return;
  78.  }
  79.  

get_mleash

  1.  /* assuming mtmp->mleashed has been checked */
  2.  struct obj *
  3.  get_mleash(mtmp)
  4.  struct monst *mtmp;
  5.  {
  6.      struct obj *otmp;
  7.  
  8.      otmp = invent;
  9.      while (otmp) {
  10.          if (otmp->otyp == LEASH && otmp->leashmon == (int) mtmp->m_id)
  11.              return otmp;
  12.          otmp = otmp->nobj;
  13.      }
  14.      return (struct obj *) 0;
  15.  }
  16.  

next_to_u

  1.  boolean
  2.  next_to_u()
  3.  {
  4.      register struct monst *mtmp;
  5.      register struct obj *otmp;
  6.  
  7.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  8.          if (DEADMONSTER(mtmp))
  9.              continue;
  10.          if (mtmp->mleashed) {
  11.              if (distu(mtmp->mx, mtmp->my) > 2)
  12.                  mnexto(mtmp);
  13.              if (distu(mtmp->mx, mtmp->my) > 2) {
  14.                  for (otmp = invent; otmp; otmp = otmp->nobj)
  15.                      if (otmp->otyp == LEASH
  16.                          && otmp->leashmon == (int) mtmp->m_id) {
  17.                          if (otmp->cursed)
  18.                              return FALSE;
  19.                          You_feel("%s leash go slack.",
  20.                                   (number_leashed() > 1) ? "a" : "the");
  21.                          mtmp->mleashed = 0;
  22.                          otmp->leashmon = 0;
  23.                      }
  24.              }
  25.          }
  26.      }
  27.      /* no pack mules for the Amulet */
  28.      if (u.usteed && mon_has_amulet(u.usteed))
  29.          return FALSE;
  30.      return TRUE;
  31.  }
  32.  

check_leash

  1.  void
  2.  check_leash(x, y)
  3.  register xchar x, y;
  4.  {
  5.      register struct obj *otmp;
  6.      register struct monst *mtmp;
  7.  
  8.      for (otmp = invent; otmp; otmp = otmp->nobj) {
  9.          if (otmp->otyp != LEASH || otmp->leashmon == 0)
  10.              continue;
  11.          for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  12.              if (DEADMONSTER(mtmp))
  13.                  continue;
  14.              if ((int) mtmp->m_id == otmp->leashmon)
  15.                  break;
  16.          }
  17.          if (!mtmp) {
  18.              impossible("leash in use isn't attached to anything?");
  19.              otmp->leashmon = 0;
  20.              continue;
  21.          }
  22.          if (dist2(u.ux, u.uy, mtmp->mx, mtmp->my)
  23.              > dist2(x, y, mtmp->mx, mtmp->my)) {
  24.              if (!um_dist(mtmp->mx, mtmp->my, 3)) {
  25.                  ; /* still close enough */
  26.              } else if (otmp->cursed && !breathless(mtmp->data)) {
  27.                  if (um_dist(mtmp->mx, mtmp->my, 5)
  28.                      || (mtmp->mhp -= rnd(2)) <= 0) {
  29.                      long save_pacifism = u.uconduct.killer;
  30.  
  31.                      Your("leash chokes %s to death!", mon_nam(mtmp));
  32.                      /* hero might not have intended to kill pet, but
  33.                         that's the result of his actions; gain experience,
  34.                         lose pacifism, take alignment and luck hit, make
  35.                         corpse less likely to remain tame after revival */
  36.                      xkilled(mtmp, 0); /* no "you kill it" message */
  37.                      /* life-saving doesn't ordinarily reset this */
  38.                      if (mtmp->mhp > 0)
  39.                          u.uconduct.killer = save_pacifism;
  40.                  } else {
  41.                      pline("%s is choked by the leash!", Monnam(mtmp));
  42.                      /* tameness eventually drops to 1 here (never 0) */
  43.                      if (mtmp->mtame && rn2(mtmp->mtame))
  44.                          mtmp->mtame--;
  45.                  }
  46.              } else {
  47.                  if (um_dist(mtmp->mx, mtmp->my, 5)) {
  48.                      pline("%s leash snaps loose!", s_suffix(Monnam(mtmp)));
  49.                      m_unleash(mtmp, FALSE);
  50.                  } else {
  51.                      You("pull on the leash.");
  52.                      if (mtmp->data->msound != MS_SILENT)
  53.                          switch (rn2(3)) {
  54.                          case 0:
  55.                              growl(mtmp);
  56.                              break;
  57.                          case 1:
  58.                              yelp(mtmp);
  59.                              break;
  60.                          default:
  61.                              whimper(mtmp);
  62.                              break;
  63.                          }
  64.                  }
  65.              }
  66.          }
  67.      }
  68.  }
  69.  

beautiful

  1.  const char *
  2.  beautiful()
  3.  {
  4.      return ((ACURR(A_CHA) > 14)
  5.                 ? ((poly_gender() == 1)
  6.                       ? "beautiful"
  7.                       : "handsome")
  8.                 : "ugly");
  9.  }
  10.  

use_mirror

  1.  #define WEAK 3 /* from eat.c */
  2.  
  3.  static const char look_str[] = "look %s.";
  4.  
  5.  STATIC_OVL int
  6.  use_mirror(obj)
  7.  struct obj *obj;
  8.  {
  9.      const char *mirror, *uvisage;
  10.      struct monst *mtmp;
  11.      unsigned how_seen;
  12.      char mlet;
  13.      boolean vis, invis_mirror, useeit, monable;
  14.  
  15.      if (!getdir((char *) 0))
  16.          return 0;
  17.      invis_mirror = Invis;
  18.      useeit = !Blind && (!invis_mirror || See_invisible);
  19.      uvisage = beautiful();
  20.      mirror = simpleonames(obj); /* "mirror" or "looking glass" */
  21.      if (obj->cursed && !rn2(2)) {
  22.          if (!Blind)
  23.              pline_The("%s fogs up and doesn't reflect!", mirror);
  24.          return 1;
  25.      }
  26.      if (!u.dx && !u.dy && !u.dz) {
  27.          if (!useeit) {
  28.              You_cant("see your %s %s.", uvisage, body_part(FACE));
  29.          } else {
  30.              if (u.umonnum == PM_FLOATING_EYE) {
  31.                  if (Free_action) {
  32.                      You("stiffen momentarily under your gaze.");
  33.                  } else {
  34.                      if (Hallucination)
  35.                          pline("Yow!  The %s stares back!", mirror);
  36.                      else
  37.                          pline("Yikes!  You've frozen yourself!");
  38.                      if (!Hallucination || !rn2(4)) {
  39.                          nomul(-rnd(MAXULEV + 6 - u.ulevel));
  40.                          multi_reason = "gazing into a mirror";
  41.                      }
  42.                      nomovemsg = 0; /* default, "you can move again" */
  43.                  }
  44.              } else if (youmonst.data->mlet == S_VAMPIRE)
  45.                  You("don't have a reflection.");
  46.              else if (u.umonnum == PM_UMBER_HULK) {
  47.                  pline("Huh?  That doesn't look like you!");
  48.                  make_confused(HConfusion + d(3, 4), FALSE);
  49.              } else if (Hallucination)
  50.                  You(look_str, hcolor((char *) 0));
  51.              else if (Sick)
  52.                  You(look_str, "peaked");
  53.              else if (u.uhs >= WEAK)
  54.                  You(look_str, "undernourished");
  55.              else
  56.                  You("look as %s as ever.", uvisage);
  57.          }
  58.          return 1;
  59.      }
  60.      if (u.uswallow) {
  61.          if (useeit)
  62.              You("reflect %s %s.", s_suffix(mon_nam(u.ustuck)),
  63.                  mbodypart(u.ustuck, STOMACH));
  64.          return 1;
  65.      }
  66.      if (Underwater) {
  67.          if (useeit)
  68.              You(Hallucination ? "give the fish a chance to fix their makeup."
  69.                                : "reflect the murky water.");
  70.          return 1;
  71.      }
  72.      if (u.dz) {
  73.          if (useeit)
  74.              You("reflect the %s.",
  75.                  (u.dz > 0) ? surface(u.ux, u.uy) : ceiling(u.ux, u.uy));
  76.          return 1;
  77.      }
  78.      mtmp = bhit(u.dx, u.dy, COLNO, INVIS_BEAM,
  79.                  (int FDECL((*), (MONST_P, OBJ_P))) 0,
  80.                  (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj);
  81.      if (!mtmp || !haseyes(mtmp->data) || notonhead)
  82.          return 1;
  83.  
  84.      /* couldsee(mtmp->mx, mtmp->my) is implied by the fact that bhit()
  85.         targetted it, so we can ignore possibility of X-ray vision */
  86.      vis = canseemon(mtmp);
  87.  /* ways to directly see monster (excludes X-ray vision, telepathy,
  88.     extended detection, type-specific warning) */
  89.  #define SEENMON (MONSEEN_NORMAL | MONSEEN_SEEINVIS | MONSEEN_INFRAVIS)
  90.      how_seen = vis ? howmonseen(mtmp) : 0;
  91.      /* whether monster is able to use its vision-based capabilities */
  92.      monable = !mtmp->mcan && (!mtmp->minvis || perceives(mtmp->data));
  93.      mlet = mtmp->data->mlet;
  94.      if (mtmp->msleeping) {
  95.          if (vis)
  96.              pline("%s is too tired to look at your %s.", Monnam(mtmp),
  97.                    mirror);
  98.      } else if (!mtmp->mcansee) {
  99.          if (vis)
  100.              pline("%s can't see anything right now.", Monnam(mtmp));
  101.      } else if (invis_mirror && !perceives(mtmp->data)) {
  102.          if (vis)
  103.              pline("%s fails to notice your %s.", Monnam(mtmp), mirror);
  104.          /* infravision doesn't produce an image in the mirror */
  105.      } else if ((how_seen & SEENMON) == MONSEEN_INFRAVIS) {
  106.          if (vis) /* (redundant) */
  107.              pline("%s is too far away to see %sself in the dark.",
  108.                    Monnam(mtmp), mhim(mtmp));
  109.          /* some monsters do special things */
  110.      } else if (mlet == S_VAMPIRE || mlet == S_GHOST || is_vampshifter(mtmp)) {
  111.          if (vis)
  112.              pline("%s doesn't have a reflection.", Monnam(mtmp));
  113.      } else if (monable && mtmp->data == &mons[PM_MEDUSA]) {
  114.          if (mon_reflects(mtmp, "The gaze is reflected away by %s %s!"))
  115.              return 1;
  116.          if (vis)
  117.              pline("%s is turned to stone!", Monnam(mtmp));
  118.          stoned = TRUE;
  119.          killed(mtmp);
  120.      } else if (monable && mtmp->data == &mons[PM_FLOATING_EYE]) {
  121.          int tmp = d((int) mtmp->m_lev, (int) mtmp->data->mattk[0].damd);
  122.          if (!rn2(4))
  123.              tmp = 120;
  124.          if (vis)
  125.              pline("%s is frozen by its reflection.", Monnam(mtmp));
  126.          else
  127.              You_hear("%s stop moving.", something);
  128.          paralyze_monst(mtmp, (int) mtmp->mfrozen + tmp);
  129.      } else if (monable && mtmp->data == &mons[PM_UMBER_HULK]) {
  130.          if (vis)
  131.              pline("%s confuses itself!", Monnam(mtmp));
  132.          mtmp->mconf = 1;
  133.      } else if (monable && (mlet == S_NYMPH || mtmp->data == &mons[PM_SUCCUBUS]
  134.                             || mtmp->data == &mons[PM_INCUBUS])) {
  135.          if (vis) {
  136.              char buf[BUFSZ]; /* "She" or "He" */
  137.  
  138.              pline("%s admires %sself in your %s.", Monnam(mtmp), mhim(mtmp),
  139.                    mirror);
  140.              pline("%s takes it!", upstart(strcpy(buf, mhe(mtmp))));
  141.          } else
  142.              pline("It steals your %s!", mirror);
  143.          setnotworn(obj); /* in case mirror was wielded */
  144.          freeinv(obj);
  145.          (void) mpickobj(mtmp, obj);
  146.          if (!tele_restrict(mtmp))
  147.              (void) rloc(mtmp, TRUE);
  148.      } else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data)
  149.                 && (!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) {
  150.          if (vis)
  151.              pline("%s is frightened by its reflection.", Monnam(mtmp));
  152.          monflee(mtmp, d(2, 4), FALSE, FALSE);
  153.      } else if (!Blind) {
  154.          if (mtmp->minvis && !See_invisible)
  155.              ;
  156.          else if ((mtmp->minvis && !perceives(mtmp->data))
  157.                   /* redundant: can't get here if these are true */
  158.                   || !haseyes(mtmp->data) || notonhead || !mtmp->mcansee)
  159.              pline("%s doesn't seem to notice %s reflection.", Monnam(mtmp),
  160.                    mhis(mtmp));
  161.          else
  162.              pline("%s ignores %s reflection.", Monnam(mtmp), mhis(mtmp));
  163.      }
  164.      return 1;
  165.  }
  166.  

use_bell

  1.  STATIC_OVL void
  2.  use_bell(optr)
  3.  struct obj **optr;
  4.  {
  5.      register struct obj *obj = *optr;
  6.      struct monst *mtmp;
  7.      boolean wakem = FALSE, learno = FALSE,
  8.              ordinary = (obj->otyp != BELL_OF_OPENING || !obj->spe),
  9.              invoking =
  10.                  (obj->otyp == BELL_OF_OPENING && invocation_pos(u.ux, u.uy)
  11.                   && !On_stairs(u.ux, u.uy));
  12.  
  13.      You("ring %s.", the(xname(obj)));
  14.  
  15.      if (Underwater || (u.uswallow && ordinary)) {
  16.  #ifdef AMIGA
  17.          amii_speaker(obj, "AhDhGqEqDhEhAqDqFhGw", AMII_MUFFLED_VOLUME);
  18.  #endif
  19.          pline("But the sound is muffled.");
  20.  
  21.      } else if (invoking && ordinary) {
  22.          /* needs to be recharged... */
  23.          pline("But it makes no sound.");
  24.          learno = TRUE; /* help player figure out why */
  25.  
  26.      } else if (ordinary) {
  27.  #ifdef AMIGA
  28.          amii_speaker(obj, "ahdhgqeqdhehaqdqfhgw", AMII_MUFFLED_VOLUME);
  29.  #endif
  30.          if (obj->cursed && !rn2(4)
  31.              /* note: once any of them are gone, we stop all of them */
  32.              && !(mvitals[PM_WOOD_NYMPH].mvflags & G_GONE)
  33.              && !(mvitals[PM_WATER_NYMPH].mvflags & G_GONE)
  34.              && !(mvitals[PM_MOUNTAIN_NYMPH].mvflags & G_GONE)
  35.              && (mtmp = makemon(mkclass(S_NYMPH, 0), u.ux, u.uy, NO_MINVENT))
  36.                     != 0) {
  37.              You("summon %s!", a_monnam(mtmp));
  38.              if (!obj_resists(obj, 93, 100)) {
  39.                  pline("%s shattered!", Tobjnam(obj, "have"));
  40.                  useup(obj);
  41.                  *optr = 0;
  42.              } else
  43.                  switch (rn2(3)) {
  44.                  default:
  45.                      break;
  46.                  case 1:
  47.                      mon_adjust_speed(mtmp, 2, (struct obj *) 0);
  48.                      break;
  49.                  case 2: /* no explanation; it just happens... */
  50.                      nomovemsg = "";
  51.                      multi_reason = NULL;
  52.                      nomul(-rnd(2));
  53.                      break;
  54.                  }
  55.          }
  56.          wakem = TRUE;
  57.  
  58.      } else {
  59.          /* charged Bell of Opening */
  60.          consume_obj_charge(obj, TRUE);
  61.  
  62.          if (u.uswallow) {
  63.              if (!obj->cursed)
  64.                  (void) openit();
  65.              else
  66.                  pline1(nothing_happens);
  67.  
  68.          } else if (obj->cursed) {
  69.              coord mm;
  70.  
  71.              mm.x = u.ux;
  72.              mm.y = u.uy;
  73.              mkundead(&mm, FALSE, NO_MINVENT);
  74.              wakem = TRUE;
  75.  
  76.          } else if (invoking) {
  77.              pline("%s an unsettling shrill sound...", Tobjnam(obj, "issue"));
  78.  #ifdef AMIGA
  79.              amii_speaker(obj, "aefeaefeaefeaefeaefe", AMII_LOUDER_VOLUME);
  80.  #endif
  81.              obj->age = moves;
  82.              learno = TRUE;
  83.              wakem = TRUE;
  84.  
  85.          } else if (obj->blessed) {
  86.              int res = 0;
  87.  
  88.  #ifdef AMIGA
  89.              amii_speaker(obj, "ahahahDhEhCw", AMII_SOFT_VOLUME);
  90.  #endif
  91.              if (uchain) {
  92.                  unpunish();
  93.                  res = 1;
  94.              } else if (u.utrap && u.utraptype == TT_BURIEDBALL) {
  95.                  buried_ball_to_freedom();
  96.                  res = 1;
  97.              }
  98.              res += openit();
  99.              switch (res) {
  100.              case 0:
  101.                  pline1(nothing_happens);
  102.                  break;
  103.              case 1:
  104.                  pline("%s opens...", Something);
  105.                  learno = TRUE;
  106.                  break;
  107.              default:
  108.                  pline("Things open around you...");
  109.                  learno = TRUE;
  110.                  break;
  111.              }
  112.  
  113.          } else { /* uncursed */
  114.  #ifdef AMIGA
  115.              amii_speaker(obj, "AeFeaeFeAefegw", AMII_OKAY_VOLUME);
  116.  #endif
  117.              if (findit() != 0)
  118.                  learno = TRUE;
  119.              else
  120.                  pline1(nothing_happens);
  121.          }
  122.  
  123.      } /* charged BofO */
  124.  
  125.      if (learno) {
  126.          makeknown(BELL_OF_OPENING);
  127.          obj->known = 1;
  128.      }
  129.      if (wakem)
  130.          wake_nearby();
  131.  }
  132.  

use_candelabrum

  1.  STATIC_OVL void
  2.  use_candelabrum(obj)
  3.  register struct obj *obj;
  4.  {
  5.      const char *s = (obj->spe != 1) ? "candles" : "candle";
  6.  
  7.      if (obj->lamplit) {
  8.          You("snuff the %s.", s);
  9.          end_burn(obj, TRUE);
  10.          return;
  11.      }
  12.      if (obj->spe <= 0) {
  13.          pline("This %s has no %s.", xname(obj), s);
  14.          return;
  15.      }
  16.      if (Underwater) {
  17.          You("cannot make fire under water.");
  18.          return;
  19.      }
  20.      if (u.uswallow || obj->cursed) {
  21.          if (!Blind)
  22.              pline_The("%s %s for a moment, then %s.", s, vtense(s, "flicker"),
  23.                        vtense(s, "die"));
  24.          return;
  25.      }
  26.      if (obj->spe < 7) {
  27.          There("%s only %d %s in %s.", vtense(s, "are"), obj->spe, s,
  28.                the(xname(obj)));
  29.          if (!Blind)
  30.              pline("%s lit.  %s dimly.", obj->spe == 1 ? "It is" : "They are",
  31.                    Tobjnam(obj, "shine"));
  32.      } else {
  33.          pline("%s's %s burn%s", The(xname(obj)), s,
  34.                (Blind ? "." : " brightly!"));
  35.      }
  36.      if (!invocation_pos(u.ux, u.uy) || On_stairs(u.ux, u.uy)) {
  37.          pline_The("%s %s being rapidly consumed!", s, vtense(s, "are"));
  38.          /* this used to be obj->age /= 2, rounding down; an age of
  39.             1 would yield 0, confusing begin_burn() and producing an
  40.             unlightable, unrefillable candelabrum; round up instead */
  41.          obj->age = (obj->age + 1L) / 2L;
  42.      } else {
  43.          if (obj->spe == 7) {
  44.              if (Blind)
  45.                  pline("%s a strange warmth!", Tobjnam(obj, "radiate"));
  46.              else
  47.                  pline("%s with a strange light!", Tobjnam(obj, "glow"));
  48.          }
  49.          obj->known = 1;
  50.      }
  51.      begin_burn(obj, FALSE);
  52.  }
== use_candle ==

  1.  
  2.  STATIC_OVL void
  3.  use_candle(optr)
  4.  struct obj **optr;
  5.  {
  6.      register struct obj *obj = *optr;
  7.      register struct obj *otmp;
  8.      const char *s = (obj->quan != 1) ? "candles" : "candle";
  9.      char qbuf[QBUFSZ], qsfx[QBUFSZ], *q;
  10.  
  11.      if (u.uswallow) {
  12.          You(no_elbow_room);
  13.          return;
  14.      }
  15.  
  16.      otmp = carrying(CANDELABRUM_OF_INVOCATION);
  17.      if (!otmp || otmp->spe == 7) {
  18.          use_lamp(obj);
  19.          return;
  20.      }
  21.  
  22.      /* first, minimal candelabrum suffix for formatting candles */
  23.      Sprintf(qsfx, " to\033%s?", thesimpleoname(otmp));
  24.      /* next, format the candles as a prefix for the candelabrum */
  25.      (void) safe_qbuf(qbuf, "Attach ", qsfx, obj, yname, thesimpleoname, s);
  26.      /* strip temporary candelabrum suffix */
  27.      if ((q = strstri(qbuf, " to\033")) != 0)
  28.          Strcpy(q, " to ");
  29.      /* last, format final "attach candles to candelabrum?" query */
  30.      if (yn(safe_qbuf(qbuf, qbuf, "?", otmp, yname, thesimpleoname, "it"))
  31.          == 'n') {
  32.          use_lamp(obj);
  33.          return;
  34.      } else {
  35.          if ((long) otmp->spe + obj->quan > 7L) {
  36.              obj = splitobj(obj, 7L - (long) otmp->spe);
  37.              /* avoid a grammatical error if obj->quan gets
  38.                 reduced to 1 candle from more than one */
  39.              s = (obj->quan != 1) ? "candles" : "candle";
  40.          } else
  41.              *optr = 0;
  42.          You("attach %ld%s %s to %s.", obj->quan, !otmp->spe ? "" : " more", s,
  43.              the(xname(otmp)));
  44.          if (!otmp->spe || otmp->age > obj->age)
  45.              otmp->age = obj->age;
  46.          otmp->spe += (int) obj->quan;
  47.          if (otmp->lamplit && !obj->lamplit)
  48.              pline_The("new %s magically %s!", s, vtense(s, "ignite"));
  49.          else if (!otmp->lamplit && obj->lamplit)
  50.              pline("%s out.", (obj->quan > 1L) ? "They go" : "It goes");
  51.          if (obj->unpaid)
  52.              verbalize("You %s %s, you bought %s!",
  53.                        otmp->lamplit ? "burn" : "use",
  54.                        (obj->quan > 1L) ? "them" : "it",
  55.                        (obj->quan > 1L) ? "them" : "it");
  56.          if (obj->quan < 7L && otmp->spe == 7)
  57.              pline("%s now has seven%s candles attached.", The(xname(otmp)),
  58.                    otmp->lamplit ? " lit" : "");
  59.          /* candelabrum's light range might increase */
  60.          if (otmp->lamplit)
  61.              obj_merge_light_sources(otmp, otmp);
  62.          /* candles are no longer a separate light source */
  63.          if (obj->lamplit)
  64.              end_burn(obj, TRUE);
  65.          /* candles are now gone */
  66.          useupall(obj);
  67.      }
  68.  }
  69.  

snuff_candle

  1.  /* call in drop, throw, and put in box, etc. */
  2.  boolean
  3.  snuff_candle(otmp)
  4.  struct obj *otmp;
  5.  {
  6.      boolean candle = Is_candle(otmp);
  7.  
  8.      if ((candle || otmp->otyp == CANDELABRUM_OF_INVOCATION)
  9.          && otmp->lamplit) {
  10.          char buf[BUFSZ];
  11.          xchar x, y;
  12.          boolean many = candle ? (otmp->quan > 1L) : (otmp->spe > 1);
  13.  
  14.          (void) get_obj_location(otmp, &x, &y, 0);
  15.          if (otmp->where == OBJ_MINVENT ? cansee(x, y) : !Blind)
  16.              pline("%s%scandle%s flame%s extinguished.", Shk_Your(buf, otmp),
  17.                    (candle ? "" : "candelabrum's "), (many ? "s'" : "'s"),
  18.                    (many ? "s are" : " is"));
  19.          end_burn(otmp, TRUE);
  20.          return TRUE;
  21.      }
  22.      return FALSE;
  23.  }
  24.  

snuff_lit

  1.  /* called when lit lamp is hit by water or put into a container or
  2.     you've been swallowed by a monster; obj might be in transit while
  3.     being thrown or dropped so don't assume that its location is valid */
  4.  boolean
  5.  snuff_lit(obj)
  6.  struct obj *obj;
  7.  {
  8.      xchar x, y;
  9.  
  10.      if (obj->lamplit) {
  11.          if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
  12.              || obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL) {
  13.              (void) get_obj_location(obj, &x, &y, 0);
  14.              if (obj->where == OBJ_MINVENT ? cansee(x, y) : !Blind)
  15.                  pline("%s %s out!", Yname2(obj), otense(obj, "go"));
  16.              end_burn(obj, TRUE);
  17.              return TRUE;
  18.          }
  19.          if (snuff_candle(obj))
  20.              return TRUE;
  21.      }
  22.      return FALSE;
  23.  }
  24.  

catch_lit

  1.  /* Called when potentially lightable object is affected by fire_damage().
  2.     Return TRUE if object was lit and FALSE otherwise --ALI */
  3.  boolean
  4.  catch_lit(obj)
  5.  struct obj *obj;
  6.  {
  7.      xchar x, y;
  8.  
  9.      if (!obj->lamplit && (obj->otyp == MAGIC_LAMP || ignitable(obj))) {
  10.          if ((obj->otyp == MAGIC_LAMP
  11.               || obj->otyp == CANDELABRUM_OF_INVOCATION) && obj->spe == 0)
  12.              return FALSE;
  13.          else if (obj->otyp != MAGIC_LAMP && obj->age == 0)
  14.              return FALSE;
  15.          if (!get_obj_location(obj, &x, &y, 0))
  16.              return FALSE;
  17.          if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->cursed)
  18.              return FALSE;
  19.          if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
  20.               || obj->otyp == BRASS_LANTERN) && obj->cursed && !rn2(2))
  21.              return FALSE;
  22.          if (obj->where == OBJ_MINVENT ? cansee(x, y) : !Blind)
  23.              pline("%s %s light!", Yname2(obj), otense(obj, "catch"));
  24.          if (obj->otyp == POT_OIL)
  25.              makeknown(obj->otyp);
  26.          if (carried(obj) && obj->unpaid && costly_spot(u.ux, u.uy)) {
  27.              /* if it catches while you have it, then it's your tough luck */
  28.              check_unpaid(obj);
  29.              verbalize("That's in addition to the cost of %s %s, of course.",
  30.                        yname(obj), obj->quan == 1L ? "itself" : "themselves");
  31.              bill_dummy_object(obj);
  32.          }
  33.          begin_burn(obj, FALSE);
  34.          return TRUE;
  35.      }
  36.      return FALSE;
  37.  }
  38.  

use_lamp

  1.  STATIC_OVL void
  2.  use_lamp(obj)
  3.  struct obj *obj;
  4.  {
  5.      char buf[BUFSZ];
  6.  
  7.      if (obj->lamplit) {
  8.          if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
  9.              || obj->otyp == BRASS_LANTERN)
  10.              pline("%slamp is now off.", Shk_Your(buf, obj));
  11.          else
  12.              You("snuff out %s.", yname(obj));
  13.          end_burn(obj, TRUE);
  14.          return;
  15.      }
  16.      if (Underwater) {
  17.          pline(!Is_candle(obj) ? "This is not a diving lamp"
  18.                                : "Sorry, fire and water don't mix.");
  19.          return;
  20.      }
  21.      /* magic lamps with an spe == 0 (wished for) cannot be lit */
  22.      if ((!Is_candle(obj) && obj->age == 0)
  23.          || (obj->otyp == MAGIC_LAMP && obj->spe == 0)) {
  24.          if (obj->otyp == BRASS_LANTERN)
  25.              Your("lamp has run out of power.");
  26.          else
  27.              pline("This %s has no oil.", xname(obj));
  28.          return;
  29.      }
  30.      if (obj->cursed && !rn2(2)) {
  31.          if (!Blind)
  32.              pline("%s for a moment, then %s.", Tobjnam(obj, "flicker"),
  33.                    otense(obj, "die"));
  34.      } else {
  35.          if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP
  36.              || obj->otyp == BRASS_LANTERN) {
  37.              check_unpaid(obj);
  38.              pline("%slamp is now on.", Shk_Your(buf, obj));
  39.          } else { /* candle(s) */
  40.              pline("%s flame%s %s%s", s_suffix(Yname2(obj)), plur(obj->quan),
  41.                    otense(obj, "burn"), Blind ? "." : " brightly!");
  42.              if (obj->unpaid && costly_spot(u.ux, u.uy)
  43.                  && obj->age == 20L * (long) objects[obj->otyp].oc_cost) {
  44.                  const char *ithem = (obj->quan > 1L) ? "them" : "it";
  45.  
  46.                  verbalize("You burn %s, you bought %s!", ithem, ithem);
  47.                  bill_dummy_object(obj);
  48.              }
  49.          }
  50.          begin_burn(obj, FALSE);
  51.      }
  52.  }
  53.  

light_cocktail

  1.  STATIC_OVL void
  2.  light_cocktail(obj)
  3.  struct obj *obj; /* obj is a potion of oil */
  4.  {
  5.      char buf[BUFSZ];
  6.      boolean split1off;
  7.  
  8.      if (u.uswallow) {
  9.          You(no_elbow_room);
  10.          return;
  11.      }
  12.  
  13.      if (obj->lamplit) {
  14.          You("snuff the lit potion.");
  15.          end_burn(obj, TRUE);
  16.          /*
  17.           * Free & add to re-merge potion.  This will average the
  18.           * age of the potions.  Not exactly the best solution,
  19.           * but its easy.
  20.           */
  21.          freeinv(obj);
  22.          (void) addinv(obj);
  23.          return;
  24.      } else if (Underwater) {
  25.          There("is not enough oxygen to sustain a fire.");
  26.          return;
  27.      }
  28.  
  29.      split1off = (obj->quan > 1L);
  30.      if (split1off)
  31.          obj = splitobj(obj, 1L);
  32.  
  33.      You("light %spotion.%s", shk_your(buf, obj),
  34.          Blind ? "" : "  It gives off a dim light.");
  35.  
  36.      if (obj->unpaid && costly_spot(u.ux, u.uy)) {
  37.          /* Normally, we shouldn't both partially and fully charge
  38.           * for an item, but (Yendorian Fuel) Taxes are inevitable...
  39.           */
  40.          check_unpaid(obj);
  41.          verbalize("That's in addition to the cost of the potion, of course.");
  42.          bill_dummy_object(obj);
  43.      }
  44.      makeknown(obj->otyp);
  45.  
  46.      begin_burn(obj, FALSE); /* after shop billing */
  47.      if (split1off) {
  48.          obj_extract_self(obj); /* free from inv */
  49.          obj->nomerge = 1;
  50.          obj = hold_another_object(obj, "You drop %s!", doname(obj),
  51.                                    (const char *) 0);
  52.          if (obj)
  53.              obj->nomerge = 0;
  54.      }
  55.  }
  56.  

dorub

  1.  static NEARDATA const char cuddly[] = { TOOL_CLASS, GEM_CLASS, 0 };
  2.  
  3.  int
  4.  dorub()
  5.  {
  6.      struct obj *obj = getobj(cuddly, "rub");
  7.  
  8.      if (obj && obj->oclass == GEM_CLASS) {
  9.          if (is_graystone(obj)) {
  10.              use_stone(obj);
  11.              return 1;
  12.          } else {
  13.              pline("Sorry, I don't know how to use that.");
  14.              return 0;
  15.          }
  16.      }
  17.  
  18.      if (!obj || !wield_tool(obj, "rub"))
  19.          return 0;
  20.  
  21.      /* now uwep is obj */
  22.      if (uwep->otyp == MAGIC_LAMP) {
  23.          if (uwep->spe > 0 && !rn2(3)) {
  24.              check_unpaid_usage(uwep, TRUE); /* unusual item use */
  25.              /* bones preparation:  perform the lamp transformation
  26.                 before releasing the djinni in case the latter turns out
  27.                 to be fatal (a hostile djinni has no chance to attack yet,
  28.                 but an indebted one who grants a wish might bestow an
  29.                 artifact which blasts the hero with lethal results) */
  30.              uwep->otyp = OIL_LAMP;
  31.              uwep->spe = 0; /* for safety */
  32.              uwep->age = rn1(500, 1000);
  33.              if (uwep->lamplit)
  34.                  begin_burn(uwep, TRUE);
  35.              djinni_from_bottle(uwep);
  36.              makeknown(MAGIC_LAMP);
  37.              update_inventory();
  38.          } else if (rn2(2)) {
  39.              You("%s smoke.", !Blind ? "see a puff of" : "smell");
  40.          } else
  41.              pline1(nothing_happens);
  42.      } else if (obj->otyp == BRASS_LANTERN) {
  43.          /* message from Adventure */
  44.          pline("Rubbing the electric lamp is not particularly rewarding.");
  45.          pline("Anyway, nothing exciting happens.");
  46.      } else
  47.          pline1(nothing_happens);
  48.      return 1;
  49.  }
  50.  

dojump

  1.  int
  2.  dojump()
  3.  {
  4.      /* Physical jump */
  5.      return jump(0);
  6.  }
  7.  

is_valid_jump_pos

  1.  boolean
  2.  is_valid_jump_pos(x, y, magic, showmsg)
  3.  int x, y, magic;
  4.  boolean showmsg;
  5.  {
  6.      if (!magic && !(HJumping & ~INTRINSIC) && !EJumping && distu(x, y) != 5) {
  7.          /* The Knight jumping restriction still applies when riding a
  8.           * horse.  After all, what shape is the knight piece in chess?
  9.           */
  10.          if (showmsg)
  11.              pline("Illegal move!");
  12.          return FALSE;
  13.      } else if (distu(x, y) > (magic ? 6 + magic * 3 : 9)) {
  14.          if (showmsg)
  15.              pline("Too far!");
  16.          return FALSE;
  17.      } else if (!cansee(x, y)) {
  18.          if (showmsg)
  19.              You("cannot see where to land!");
  20.          return FALSE;
  21.      } else if (!isok(x, y)) {
  22.          if (showmsg)
  23.              You("cannot jump there!");
  24.          return FALSE;
  25.      }
  26.      return TRUE;
  27.  }
  28.  

display_jump_positions

  1.  static int jumping_is_magic;
  2.  
  3.  void
  4.  display_jump_positions(state)
  5.  int state;
  6.  {
  7.      if (state == 0) {
  8.          tmp_at(DISP_BEAM, cmap_to_glyph(S_goodpos));
  9.      } else if (state == 1) {
  10.          int x, y, dx, dy;
  11.  
  12.          for (dx = -4; dx <= 4; dx++)
  13.              for (dy = -4; dy <= 4; dy++) {
  14.                  x = dx + (int) u.ux;
  15.                  y = dy + (int) u.uy;
  16.                  if (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
  17.                      && is_valid_jump_pos(x, y, jumping_is_magic, FALSE))
  18.                      tmp_at(x, y);
  19.              }
  20.      } else {
  21.          tmp_at(DISP_END, 0);
  22.      }
  23.  }
  24.  

jump

  1.  int
  2.  jump(magic)
  3.  int magic; /* 0=Physical, otherwise skill level */
  4.  {
  5.      coord cc;
  6.  
  7.      if (!magic && (nolimbs(youmonst.data) || slithy(youmonst.data))) {
  8.          /* normally (nolimbs || slithy) implies !Jumping,
  9.             but that isn't necessarily the case for knights */
  10.          You_cant("jump; you have no legs!");
  11.          return 0;
  12.      } else if (!magic && !Jumping) {
  13.          You_cant("jump very far.");
  14.          return 0;
  15.      /* if steed is immobile, can't do physical jump but can do spell one */
  16.      } else if (!magic && u.usteed && stucksteed(FALSE)) {
  17.          /* stucksteed gave "<steed> won't move" message */
  18.          return 0;
  19.      } else if (u.uswallow) {
  20.          if (magic) {
  21.              You("bounce around a little.");
  22.              return 1;
  23.          }
  24.          pline("You've got to be kidding!");
  25.          return 0;
  26.      } else if (u.uinwater) {
  27.          if (magic) {
  28.              You("swish around a little.");
  29.              return 1;
  30.          }
  31.          pline("This calls for swimming, not jumping!");
  32.          return 0;
  33.      } else if (u.ustuck) {
  34.          if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf) {
  35.              You("pull free from %s.", mon_nam(u.ustuck));
  36.              u.ustuck = 0;
  37.              return 1;
  38.          }
  39.          if (magic) {
  40.              You("writhe a little in the grasp of %s!", mon_nam(u.ustuck));
  41.              return 1;
  42.          }
  43.          You("cannot escape from %s!", mon_nam(u.ustuck));
  44.          return 0;
  45.      } else if (Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
  46.          if (magic) {
  47.              You("flail around a little.");
  48.              return 1;
  49.          }
  50.          You("don't have enough traction to jump.");
  51.          return 0;
  52.      } else if (!magic && near_capacity() > UNENCUMBERED) {
  53.          You("are carrying too much to jump!");
  54.          return 0;
  55.      } else if (!magic && (u.uhunger <= 100 || ACURR(A_STR) < 6)) {
  56.          You("lack the strength to jump!");
  57.          return 0;
  58.      } else if (!magic && Wounded_legs) {
  59.          long wl = (Wounded_legs & BOTH_SIDES);
  60.          const char *bp = body_part(LEG);
  61.  
  62.          if (wl == BOTH_SIDES)
  63.              bp = makeplural(bp);
  64.          if (u.usteed)
  65.              pline("%s is in no shape for jumping.", Monnam(u.usteed));
  66.          else
  67.              Your("%s%s %s in no shape for jumping.",
  68.                   (wl == LEFT_SIDE) ? "left " : (wl == RIGHT_SIDE) ? "right "
  69.                                                                    : "",
  70.                   bp, (wl == BOTH_SIDES) ? "are" : "is");
  71.          return 0;
  72.      } else if (u.usteed && u.utrap) {
  73.          pline("%s is stuck in a trap.", Monnam(u.usteed));
  74.          return 0;
  75.      }
  76.  
  77.      pline("Where do you want to jump?");
  78.      cc.x = u.ux;
  79.      cc.y = u.uy;
  80.      jumping_is_magic = magic;
  81.      getpos_sethilite(display_jump_positions);
  82.      if (getpos(&cc, TRUE, "the desired position") < 0)
  83.          return 0; /* user pressed ESC */
  84.      if (!is_valid_jump_pos(cc.x, cc.y, magic, TRUE)) {
  85.          return 0;
  86.      } else {
  87.          coord uc;
  88.          int range, temp;
  89.  
  90.          if (u.utrap)
  91.              switch (u.utraptype) {
  92.              case TT_BEARTRAP: {
  93.                  long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
  94.  
  95.                  You("rip yourself free of the bear trap!  Ouch!");
  96.                  losehp(Maybe_Half_Phys(rnd(10)), "jumping out of a bear trap",
  97.                         KILLED_BY);
  98.                  set_wounded_legs(side, rn1(1000, 500));
  99.                  break;
  100.              }
  101.              case TT_PIT:
  102.                  You("leap from the pit!");
  103.                  break;
  104.              case TT_WEB:
  105.                  You("tear the web apart as you pull yourself free!");
  106.                  deltrap(t_at(u.ux, u.uy));
  107.                  break;
  108.              case TT_LAVA:
  109.                  You("pull yourself above the lava!");
  110.                  u.utrap = 0;
  111.                  return 1;
  112.              case TT_BURIEDBALL:
  113.              case TT_INFLOOR:
  114.                  You("strain your %s, but you're still %s.",
  115.                      makeplural(body_part(LEG)),
  116.                      (u.utraptype == TT_INFLOOR)
  117.                          ? "stuck in the floor"
  118.                          : "attached to the buried ball");
  119.                  set_wounded_legs(LEFT_SIDE, rn1(10, 11));
  120.                  set_wounded_legs(RIGHT_SIDE, rn1(10, 11));
  121.                  return 1;
  122.              }
  123.  
  124.          /*
  125.           * Check the path from uc to cc, calling hurtle_step at each
  126.           * location.  The final position actually reached will be
  127.           * in cc.
  128.           */
  129.          uc.x = u.ux;
  130.          uc.y = u.uy;
  131.          /* calculate max(abs(dx), abs(dy)) as the range */
  132.          range = cc.x - uc.x;
  133.          if (range < 0)
  134.              range = -range;
  135.          temp = cc.y - uc.y;
  136.          if (temp < 0)
  137.              temp = -temp;
  138.          if (range < temp)
  139.              range = temp;
  140.          (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range);
  141.          teleds(cc.x, cc.y, TRUE);
  142.          sokoban_guilt();
  143.          nomul(-1);
  144.          multi_reason = "jumping around";
  145.          nomovemsg = "";
  146.          morehungry(rnd(25));
  147.          return 1;
  148.      }
  149.  }
  150.  

tinnable

  1.  boolean
  2.  tinnable(corpse)
  3.  struct obj *corpse;
  4.  {
  5.      if (corpse->oeaten)
  6.          return 0;
  7.      if (!mons[corpse->corpsenm].cnutrit)
  8.          return 0;
  9.      return 1;
  10.  }
  11.  

use_tinning_kit

  1.  STATIC_OVL void
  2.  use_tinning_kit(obj)
  3.  struct obj *obj;
  4.  {
  5.      struct obj *corpse, *can;
  6.  
  7.      /* This takes only 1 move.  If this is to be changed to take many
  8.       * moves, we've got to deal with decaying corpses...
  9.       */
  10.      if (obj->spe <= 0) {
  11.          You("seem to be out of tins.");
  12.          return;
  13.      }
  14.      if (!(corpse = floorfood("tin", 2)))
  15.          return;
  16.      if (corpse->oeaten) {
  17.          You("cannot tin %s which is partly eaten.", something);
  18.          return;
  19.      }
  20.      if (touch_petrifies(&mons[corpse->corpsenm]) && !Stone_resistance
  21.          && !uarmg) {
  22.          char kbuf[BUFSZ];
  23.  
  24.          if (poly_when_stoned(youmonst.data))
  25.              You("tin %s without wearing gloves.",
  26.                  an(mons[corpse->corpsenm].mname));
  27.          else {
  28.              pline("Tinning %s without wearing gloves is a fatal mistake...",
  29.                    an(mons[corpse->corpsenm].mname));
  30.              Sprintf(kbuf, "trying to tin %s without gloves",
  31.                      an(mons[corpse->corpsenm].mname));
  32.          }
  33.          instapetrify(kbuf);
  34.      }
  35.      if (is_rider(&mons[corpse->corpsenm])) {
  36.          if (revive_corpse(corpse))
  37.              verbalize("Yes...  But War does not preserve its enemies...");
  38.          else
  39.              pline_The("corpse evades your grasp.");
  40.          return;
  41.      }
  42.      if (mons[corpse->corpsenm].cnutrit == 0) {
  43.          pline("That's too insubstantial to tin.");
  44.          return;
  45.      }
  46.      consume_obj_charge(obj, TRUE);
  47.  
  48.      if ((can = mksobj(TIN, FALSE, FALSE)) != 0) {
  49.          static const char you_buy_it[] = "You tin it, you bought it!";
  50.  
  51.          can->corpsenm = corpse->corpsenm;
  52.          can->cursed = obj->cursed;
  53.          can->blessed = obj->blessed;
  54.          can->owt = weight(can);
  55.          can->known = 1;
  56.          /* Mark tinned tins. No spinach allowed... */
  57.          set_tin_variety(can, HOMEMADE_TIN);
  58.          if (carried(corpse)) {
  59.              if (corpse->unpaid)
  60.                  verbalize(you_buy_it);
  61.              useup(corpse);
  62.          } else {
  63.              if (costly_spot(corpse->ox, corpse->oy) && !corpse->no_charge)
  64.                  verbalize(you_buy_it);
  65.              useupf(corpse, 1L);
  66.          }
  67.          can = hold_another_object(can, "You make, but cannot pick up, %s.",
  68.                                    doname(can), (const char *) 0);
  69.      } else
  70.          impossible("Tinning failed.");
  71.  }
  72.  

use_unicorn_horn

  1.  void
  2.  use_unicorn_horn(obj)
  3.  struct obj *obj;
  4.  {
  5.  #define PROP_COUNT 7           /* number of properties we're dealing with */
  6.  #define ATTR_COUNT (A_MAX * 3) /* number of attribute points we might fix */
  7.      int idx, val, val_limit, trouble_count, unfixable_trbl, did_prop,
  8.          did_attr;
  9.      int trouble_list[PROP_COUNT + ATTR_COUNT];
  10.  
  11.      if (obj && obj->cursed) {
  12.          long lcount = (long) rn1(90, 10);
  13.  
  14.          switch (rn2(13) / 2) { /* case 6 is half as likely as the others */
  15.          case 0:
  16.              make_sick((Sick & TIMEOUT) ? (Sick & TIMEOUT) / 3L + 1L
  17.                                         : (long) rn1(ACURR(A_CON), 20),
  18.                        xname(obj), TRUE, SICK_NONVOMITABLE);
  19.              break;
  20.          case 1:
  21.              make_blinded((Blinded & TIMEOUT) + lcount, TRUE);
  22.              break;
  23.          case 2:
  24.              if (!Confusion)
  25.                  You("suddenly feel %s.",
  26.                      Hallucination ? "trippy" : "confused");
  27.              make_confused((HConfusion & TIMEOUT) + lcount, TRUE);
  28.              break;
  29.          case 3:
  30.              make_stunned((HStun & TIMEOUT) + lcount, TRUE);
  31.              break;
  32.          case 4:
  33.              (void) adjattrib(rn2(A_MAX), -1, FALSE);
  34.              break;
  35.          case 5:
  36.              (void) make_hallucinated((HHallucination & TIMEOUT) + lcount,
  37.                                       TRUE, 0L);
  38.              break;
  39.          case 6:
  40.              if (Deaf) /* make_deaf() won't give feedback when already deaf */
  41.                  pline("Nothing seems to happen.");
  42.              make_deaf((HDeaf & TIMEOUT) + lcount, TRUE);
  43.              break;
  44.          }
  45.          return;
  46.      }
  47.  
  48.  /*
  49.   * Entries in the trouble list use a very simple encoding scheme.
  50.   */
  51.  #define prop2trbl(X) ((X) + A_MAX)
  52.  #define attr2trbl(Y) (Y)
  53.  #define prop_trouble(X) trouble_list[trouble_count++] = prop2trbl(X)
  54.  #define attr_trouble(Y) trouble_list[trouble_count++] = attr2trbl(Y)
  55.  #define TimedTrouble(P) (((P) && !((P) & ~TIMEOUT)) ? ((P) & TIMEOUT) : 0L)
  56.  
  57.      trouble_count = unfixable_trbl = did_prop = did_attr = 0;
  58.  
  59.      /* collect property troubles */
  60.      if (TimedTrouble(Sick))
  61.          prop_trouble(SICK);
  62.      if (TimedTrouble(Blinded) > (long) u.ucreamed
  63.          && !(u.uswallow
  64.               && attacktype_fordmg(u.ustuck->data, AT_ENGL, AD_BLND)))
  65.          prop_trouble(BLINDED);
  66.      if (TimedTrouble(HHallucination))
  67.          prop_trouble(HALLUC);
  68.      if (TimedTrouble(Vomiting))
  69.          prop_trouble(VOMITING);
  70.      if (TimedTrouble(HConfusion))
  71.          prop_trouble(CONFUSION);
  72.      if (TimedTrouble(HStun))
  73.          prop_trouble(STUNNED);
  74.      if (TimedTrouble(HDeaf))
  75.          prop_trouble(DEAF);
  76.  
  77.      unfixable_trbl = unfixable_trouble_count(TRUE);
  78.  
  79.      /* collect attribute troubles */
  80.      for (idx = 0; idx < A_MAX; idx++) {
  81.          if (ABASE(idx) >= AMAX(idx))
  82.              continue;
  83.          val_limit = AMAX(idx);
  84.          /* don't recover strength lost from hunger */
  85.          if (idx == A_STR && u.uhs >= WEAK)
  86.              val_limit--;
  87.          if (Fixed_abil) {
  88.              /* potion/spell of restore ability override sustain ability
  89.                 intrinsic but unicorn horn usage doesn't */
  90.              unfixable_trbl += val_limit - ABASE(idx);
  91.              continue;
  92.          }
  93.          /* don't recover more than 3 points worth of any attribute */
  94.          if (val_limit > ABASE(idx) + 3)
  95.              val_limit = ABASE(idx) + 3;
  96.  
  97.          for (val = ABASE(idx); val < val_limit; val++)
  98.              attr_trouble(idx);
  99.          /* keep track of unfixed trouble, for message adjustment below */
  100.          unfixable_trbl += (AMAX(idx) - val_limit);
  101.      }
  102.  
  103.      if (trouble_count == 0) {
  104.          pline1(nothing_happens);
  105.          return;
  106.      } else if (trouble_count > 1) { /* shuffle */
  107.          int i, j, k;
  108.  
  109.          for (i = trouble_count - 1; i > 0; i--)
  110.              if ((j = rn2(i + 1)) != i) {
  111.                  k = trouble_list[j];
  112.                  trouble_list[j] = trouble_list[i];
  113.                  trouble_list[i] = k;
  114.              }
  115.      }
  116.  
  117.      /*
  118.       *  Chances for number of troubles to be fixed
  119.       *               0      1      2      3      4      5      6      7
  120.       *   blessed:  22.7%  22.7%  19.5%  15.4%  10.7%   5.7%   2.6%   0.8%
  121.       *  uncursed:  35.4%  35.4%  22.9%   6.3%    0      0      0      0
  122.       */
  123.      val_limit = rn2(d(2, (obj && obj->blessed) ? 4 : 2));
  124.      if (val_limit > trouble_count)
  125.          val_limit = trouble_count;
  126.  
  127.      /* fix [some of] the troubles */
  128.      for (val = 0; val < val_limit; val++) {
  129.          idx = trouble_list[val];
  130.  
  131.          switch (idx) {
  132.          case prop2trbl(SICK):
  133.              make_sick(0L, (char *) 0, TRUE, SICK_ALL);
  134.              did_prop++;
  135.              break;
  136.          case prop2trbl(BLINDED):
  137.              make_blinded((long) u.ucreamed, TRUE);
  138.              did_prop++;
  139.              break;
  140.          case prop2trbl(HALLUC):
  141.              (void) make_hallucinated(0L, TRUE, 0L);
  142.              did_prop++;
  143.              break;
  144.          case prop2trbl(VOMITING):
  145.              make_vomiting(0L, TRUE);
  146.              did_prop++;
  147.              break;
  148.          case prop2trbl(CONFUSION):
  149.              make_confused(0L, TRUE);
  150.              did_prop++;
  151.              break;
  152.          case prop2trbl(STUNNED):
  153.              make_stunned(0L, TRUE);
  154.              did_prop++;
  155.              break;
  156.          case prop2trbl(DEAF):
  157.              make_deaf(0L, TRUE);
  158.              did_prop++;
  159.              break;
  160.          default:
  161.              if (idx >= 0 && idx < A_MAX) {
  162.                  ABASE(idx) += 1;
  163.                  did_attr++;
  164.              } else
  165.                  panic("use_unicorn_horn: bad trouble? (%d)", idx);
  166.              break;
  167.          }
  168.      }
  169.  
  170.      if (did_attr)
  171.          pline("This makes you feel %s!",
  172.                (did_prop + did_attr) == (trouble_count + unfixable_trbl)
  173.                    ? "great"
  174.                    : "better");
  175.      else if (!did_prop)
  176.          pline("Nothing seems to happen.");
  177.  
  178.      context.botl = (did_attr || did_prop);
  179.  #undef PROP_COUNT
  180.  #undef ATTR_COUNT
  181.  #undef prop2trbl
  182.  #undef attr2trbl
  183.  #undef prop_trouble
  184.  #undef attr_trouble
  185.  #undef TimedTrouble
  186.  }
  187.  

fig_transform

  1.  /*
  2.   * Timer callback routine: turn figurine into monster
  3.   */
  4.  void
  5.  fig_transform(arg, timeout)
  6.  anything *arg;
  7.  long timeout;
  8.  {
  9.      struct obj *figurine = arg->a_obj;
  10.      struct monst *mtmp;
  11.      coord cc;
  12.      boolean cansee_spot, silent, okay_spot;
  13.      boolean redraw = FALSE;
  14.      boolean suppress_see = FALSE;
  15.      char monnambuf[BUFSZ], carriedby[BUFSZ];
  16.  
  17.      if (!figurine) {
  18.          debugpline0("null figurine in fig_transform()");
  19.          return;
  20.      }
  21.      silent = (timeout != monstermoves); /* happened while away */
  22.      okay_spot = get_obj_location(figurine, &cc.x, &cc.y, 0);
  23.      if (figurine->where == OBJ_INVENT || figurine->where == OBJ_MINVENT)
  24.          okay_spot = enexto(&cc, cc.x, cc.y, &mons[figurine->corpsenm]);
  25.      if (!okay_spot || !figurine_location_checks(figurine, &cc, TRUE)) {
  26.          /* reset the timer to try again later */
  27.          (void) start_timer((long) rnd(5000), TIMER_OBJECT, FIG_TRANSFORM,
  28.                             obj_to_any(figurine));
  29.          return;
  30.      }
  31.  
  32.      cansee_spot = cansee(cc.x, cc.y);
  33.      mtmp = make_familiar(figurine, cc.x, cc.y, TRUE);
  34.      if (mtmp) {
  35.          char and_vanish[BUFSZ];
  36.          struct obj *mshelter = level.objects[mtmp->mx][mtmp->my];
  37.          Sprintf(monnambuf, "%s", an(m_monnam(mtmp)));
  38.  
  39.          and_vanish[0] = '\0';
  40.          if ((mtmp->minvis && !See_invisible)
  41.              || (mtmp->data->mlet == S_MIMIC
  42.                  && mtmp->m_ap_type != M_AP_NOTHING))
  43.              suppress_see = TRUE;
  44.  
  45.          if (mtmp->mundetected) {
  46.              if (hides_under(mtmp->data) && mshelter) {
  47.                  Sprintf(and_vanish, " and %s under %s",
  48.                          locomotion(mtmp->data, "crawl"), doname(mshelter));
  49.              } else if (mtmp->data->mlet == S_MIMIC
  50.                         || mtmp->data->mlet == S_EEL) {
  51.                  suppress_see = TRUE;
  52.              } else
  53.                  Strcpy(and_vanish, " and vanish");
  54.          }
  55.  
  56.          switch (figurine->where) {
  57.          case OBJ_INVENT:
  58.              if (Blind || suppress_see)
  59.                  You_feel("%s %s from your pack!", something,
  60.                           locomotion(mtmp->data, "drop"));
  61.              else
  62.                  You_see("%s %s out of your pack%s!", monnambuf,
  63.                          locomotion(mtmp->data, "drop"), and_vanish);
  64.              break;
  65.  
  66.          case OBJ_FLOOR:
  67.              if (cansee_spot && !silent) {
  68.                  if (suppress_see)
  69.                      pline("%s suddenly vanishes!", an(xname(figurine)));
  70.                  else
  71.                      You_see("a figurine transform into %s%s!", monnambuf,
  72.                              and_vanish);
  73.                  redraw = TRUE; /* update figurine's map location */
  74.              }
  75.              break;
  76.  
  77.          case OBJ_MINVENT:
  78.              if (cansee_spot && !silent && !suppress_see) {
  79.                  struct monst *mon;
  80.                  mon = figurine->ocarry;
  81.                  /* figurine carrying monster might be invisible */
  82.                  if (canseemon(figurine->ocarry)) {
  83.                      Sprintf(carriedby, "%s pack", s_suffix(a_monnam(mon)));
  84.                  } else if (is_pool(mon->mx, mon->my))
  85.                      Strcpy(carriedby, "empty water");
  86.                  else
  87.                      Strcpy(carriedby, "thin air");
  88.                  You_see("%s %s out of %s%s!", monnambuf,
  89.                          locomotion(mtmp->data, "drop"), carriedby,
  90.                          and_vanish);
  91.              }
  92.              break;
  93.  #if 0
  94.          case OBJ_MIGRATING:
  95.              break;
  96.  #endif
  97.  
  98.          default:
  99.              impossible("figurine came to life where? (%d)",
  100.                         (int) figurine->where);
  101.              break;
  102.          }
  103.      }
  104.      /* free figurine now */
  105.      if (carried(figurine)) {
  106.          useup(figurine);
  107.      } else {
  108.          obj_extract_self(figurine);
  109.          obfree(figurine, (struct obj *) 0);
  110.      }
  111.      if (redraw)
  112.          newsym(cc.x, cc.y);
  113.  }
  114.  

figurine_location_checks

  1.  STATIC_OVL boolean
  2.  figurine_location_checks(obj, cc, quietly)
  3.  struct obj *obj;
  4.  coord *cc;
  5.  boolean quietly;
  6.  {
  7.      xchar x, y;
  8.  
  9.      if (carried(obj) && u.uswallow) {
  10.          if (!quietly)
  11.              You("don't have enough room in here.");
  12.          return FALSE;
  13.      }
  14.      x = cc ? cc->x : u.ux;
  15.      y = cc ? cc->y : u.uy;
  16.      if (!isok(x, y)) {
  17.          if (!quietly)
  18.              You("cannot put the figurine there.");
  19.          return FALSE;
  20.      }
  21.      if (IS_ROCK(levl[x][y].typ)
  22.          && !(passes_walls(&mons[obj->corpsenm]) && may_passwall(x, y))) {
  23.          if (!quietly)
  24.              You("cannot place a figurine in %s!",
  25.                  IS_TREE(levl[x][y].typ) ? "a tree" : "solid rock");
  26.          return FALSE;
  27.      }
  28.      if (sobj_at(BOULDER, x, y) && !passes_walls(&mons[obj->corpsenm])
  29.          && !throws_rocks(&mons[obj->corpsenm])) {
  30.          if (!quietly)
  31.              You("cannot fit the figurine on the boulder.");
  32.          return FALSE;
  33.      }
  34.      return TRUE;
  35.  }
  36.  

use_figurine

  1.  STATIC_OVL void
  2.  use_figurine(optr)
  3.  struct obj **optr;
  4.  {
  5.      register struct obj *obj = *optr;
  6.      xchar x, y;
  7.      coord cc;
  8.  
  9.      if (u.uswallow) {
  10.          /* can't activate a figurine while swallowed */
  11.          if (!figurine_location_checks(obj, (coord *) 0, FALSE))
  12.              return;
  13.      }
  14.      if (!getdir((char *) 0)) {
  15.          context.move = multi = 0;
  16.          return;
  17.      }
  18.      x = u.ux + u.dx;
  19.      y = u.uy + u.dy;
  20.      cc.x = x;
  21.      cc.y = y;
  22.      /* Passing FALSE arg here will result in messages displayed */
  23.      if (!figurine_location_checks(obj, &cc, FALSE))
  24.          return;
  25.      You("%s and it transforms.",
  26.          (u.dx || u.dy) ? "set the figurine beside you"
  27.                         : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
  28.                            || is_pool(cc.x, cc.y))
  29.                               ? "release the figurine"
  30.                               : (u.dz < 0 ? "toss the figurine into the air"
  31.                                           : "set the figurine on the ground"));
  32.      (void) make_familiar(obj, cc.x, cc.y, FALSE);
  33.      (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
  34.      useup(obj);
  35.      *optr = 0;
  36.  }
  37.  

use_grease

  1.  static NEARDATA const char lubricables[] = { ALL_CLASSES, ALLOW_NONE, 0 };
  2.  
  3.  STATIC_OVL void
  4.  use_grease(obj)
  5.  struct obj *obj;
  6.  {
  7.      struct obj *otmp;
  8.  
  9.      if (Glib) {
  10.          pline("%s from your %s.", Tobjnam(obj, "slip"),
  11.                makeplural(body_part(FINGER)));
  12.          dropx(obj);
  13.          return;
  14.      }
  15.  
  16.      if (obj->spe > 0) {
  17.          if ((obj->cursed || Fumbling) && !rn2(2)) {
  18.              consume_obj_charge(obj, TRUE);
  19.  
  20.              pline("%s from your %s.", Tobjnam(obj, "slip"),
  21.                    makeplural(body_part(FINGER)));
  22.              dropx(obj);
  23.              return;
  24.          }
  25.          otmp = getobj(lubricables, "grease");
  26.          if (!otmp)
  27.              return;
  28.          if (inaccessible_equipment(otmp, "grease", FALSE))
  29.              return;
  30.          consume_obj_charge(obj, TRUE);
  31.  
  32.          if (otmp != &zeroobj) {
  33.              You("cover %s with a thick layer of grease.", yname(otmp));
  34.              otmp->greased = 1;
  35.              if (obj->cursed && !nohands(youmonst.data)) {
  36.                  incr_itimeout(&Glib, rnd(15));
  37.                  pline("Some of the grease gets all over your %s.",
  38.                        makeplural(body_part(HAND)));
  39.              }
  40.          } else {
  41.              incr_itimeout(&Glib, rnd(15));
  42.              You("coat your %s with grease.", makeplural(body_part(FINGER)));
  43.          }
  44.      } else {
  45.          if (obj->known)
  46.              pline("%s empty.", Tobjnam(obj, "are"));
  47.          else
  48.              pline("%s to be empty.", Tobjnam(obj, "seem"));
  49.      }
  50.      update_inventory();
  51.  }
  52.  

reset_trapset

  1.  static struct trapinfo {
  2.      struct obj *tobj;
  3.      xchar tx, ty;
  4.      int time_needed;
  5.      boolean force_bungle;
  6.  } trapinfo;
  7.  
  8.  void
  9.  reset_trapset()
  10.  {
  11.      trapinfo.tobj = 0;
  12.      trapinfo.force_bungle = 0;
  13.  }
  14.  

use_stone

  1.  /* touchstones - by Ken Arnold */
  2.  STATIC_OVL void
  3.  use_stone(tstone)
  4.  struct obj *tstone;
  5.  {
  6.      struct obj *obj;
  7.      boolean do_scratch;
  8.      const char *streak_color, *choices;
  9.      char stonebuf[QBUFSZ];
  10.      static const char scritch[] = "\"scritch, scritch\"";
  11.      static const char allowall[3] = { COIN_CLASS, ALL_CLASSES, 0 };
  12.      static const char coins_gems[3] = { COIN_CLASS, GEM_CLASS, 0 };
  13.  
  14.      /* in case it was acquired while blinded */
  15.      if (!Blind)
  16.          tstone->dknown = 1;
  17.      /* when the touchstone is fully known, don't bother listing extra
  18.         junk as likely candidates for rubbing */
  19.      choices = (tstone->otyp == TOUCHSTONE && tstone->dknown
  20.                 && objects[TOUCHSTONE].oc_name_known)
  21.                    ? coins_gems
  22.                    : allowall;
  23.      Sprintf(stonebuf, "rub on the stone%s", plur(tstone->quan));
  24.      if ((obj = getobj(choices, stonebuf)) == 0)
  25.          return;
  26.  
  27.      if (obj == tstone && obj->quan == 1L) {
  28.          You_cant("rub %s on itself.", the(xname(obj)));
  29.          return;
  30.      }
  31.  
  32.      if (tstone->otyp == TOUCHSTONE && tstone->cursed
  33.          && obj->oclass == GEM_CLASS && !is_graystone(obj)
  34.          && !obj_resists(obj, 80, 100)) {
  35.          if (Blind)
  36.              pline("You feel something shatter.");
  37.          else if (Hallucination)
  38.              pline("Oh, wow, look at the pretty shards.");
  39.          else
  40.              pline("A sharp crack shatters %s%s.",
  41.                    (obj->quan > 1L) ? "one of " : "", the(xname(obj)));
  42.          useup(obj);
  43.          return;
  44.      }
  45.  
  46.      if (Blind) {
  47.          pline(scritch);
  48.          return;
  49.      } else if (Hallucination) {
  50.          pline("Oh wow, man: Fractals!");
  51.          return;
  52.      }
  53.  
  54.      do_scratch = FALSE;
  55.      streak_color = 0;
  56.  
  57.      switch (obj->oclass) {
  58.      case GEM_CLASS: /* these have class-specific handling below */
  59.      case RING_CLASS:
  60.          if (tstone->otyp != TOUCHSTONE) {
  61.              do_scratch = TRUE;
  62.          } else if (obj->oclass == GEM_CLASS
  63.                     && (tstone->blessed
  64.                         || (!tstone->cursed && (Role_if(PM_ARCHEOLOGIST)
  65.                                                 || Race_if(PM_GNOME))))) {
  66.              makeknown(TOUCHSTONE);
  67.              makeknown(obj->otyp);
  68.              prinv((char *) 0, obj, 0L);
  69.              return;
  70.          } else {
  71.              /* either a ring or the touchstone was not effective */
  72.              if (objects[obj->otyp].oc_material == GLASS) {
  73.                  do_scratch = TRUE;
  74.                  break;
  75.              }
  76.          }
  77.          streak_color = c_obj_colors[objects[obj->otyp].oc_color];
  78.          break; /* gem or ring */
  79.  
  80.      default:
  81.          switch (objects[obj->otyp].oc_material) {
  82.          case CLOTH:
  83.              pline("%s a little more polished now.", Tobjnam(tstone, "look"));
  84.              return;
  85.          case LIQUID:
  86.              if (!obj->known) /* note: not "whetstone" */
  87.                  You("must think this is a wetstone, do you?");
  88.              else
  89.                  pline("%s a little wetter now.", Tobjnam(tstone, "are"));
  90.              return;
  91.          case WAX:
  92.              streak_color = "waxy";
  93.              break; /* okay even if not touchstone */
  94.          case WOOD:
  95.              streak_color = "wooden";
  96.              break; /* okay even if not touchstone */
  97.          case GOLD:
  98.              do_scratch = TRUE; /* scratching and streaks */
  99.              streak_color = "golden";
  100.              break;
  101.          case SILVER:
  102.              do_scratch = TRUE; /* scratching and streaks */
  103.              streak_color = "silvery";
  104.              break;
  105.          default:
  106.              /* Objects passing the is_flimsy() test will not
  107.                 scratch a stone.  They will leave streaks on
  108.                 non-touchstones and touchstones alike. */
  109.              if (is_flimsy(obj))
  110.                  streak_color = c_obj_colors[objects[obj->otyp].oc_color];
  111.              else
  112.                  do_scratch = (tstone->otyp != TOUCHSTONE);
  113.              break;
  114.          }
  115.          break; /* default oclass */
  116.      }
  117.  
  118.      Sprintf(stonebuf, "stone%s", plur(tstone->quan));
  119.      if (do_scratch)
  120.          You("make %s%sscratch marks on the %s.",
  121.              streak_color ? streak_color : (const char *) "",
  122.              streak_color ? " " : "", stonebuf);
  123.      else if (streak_color)
  124.          You_see("%s streaks on the %s.", streak_color, stonebuf);
  125.      else
  126.          pline(scritch);
  127.      return;
  128.  }
  129.  

use_trap

  1.  /* Place a landmine/bear trap.  Helge Hafting */
  2.  STATIC_OVL void
  3.  use_trap(otmp)
  4.  struct obj *otmp;
  5.  {
  6.      int ttyp, tmp;
  7.      const char *what = (char *) 0;
  8.      char buf[BUFSZ];
  9.      int levtyp = levl[u.ux][u.uy].typ;
  10.      const char *occutext = "setting the trap";
  11.  
  12.      if (nohands(youmonst.data))
  13.          what = "without hands";
  14.      else if (Stunned)
  15.          what = "while stunned";
  16.      else if (u.uswallow)
  17.          what =
  18.              is_animal(u.ustuck->data) ? "while swallowed" : "while engulfed";
  19.      else if (Underwater)
  20.          what = "underwater";
  21.      else if (Levitation)
  22.          what = "while levitating";
  23.      else if (is_pool(u.ux, u.uy))
  24.          what = "in water";
  25.      else if (is_lava(u.ux, u.uy))
  26.          what = "in lava";
  27.      else if (On_stairs(u.ux, u.uy))
  28.          what = (u.ux == xdnladder || u.ux == xupladder) ? "on the ladder"
  29.                                                          : "on the stairs";
  30.      else if (IS_FURNITURE(levtyp) || IS_ROCK(levtyp)
  31.               || closed_door(u.ux, u.uy) || t_at(u.ux, u.uy))
  32.          what = "here";
  33.      else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
  34.          what = (levtyp == AIR)
  35.                     ? "in midair"
  36.                     : (levtyp == CLOUD)
  37.                           ? "in a cloud"
  38.                           : "in this place"; /* Air/Water Plane catch-all */
  39.      if (what) {
  40.          You_cant("set a trap %s!", what);
  41.          reset_trapset();
  42.          return;
  43.      }
  44.      ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP;
  45.      if (otmp == trapinfo.tobj && u.ux == trapinfo.tx && u.uy == trapinfo.ty) {
  46.          You("resume setting %s%s.", shk_your(buf, otmp),
  47.              defsyms[trap_to_defsym(what_trap(ttyp))].explanation);
  48.          set_occupation(set_trap, occutext, 0);
  49.          return;
  50.      }
  51.      trapinfo.tobj = otmp;
  52.      trapinfo.tx = u.ux, trapinfo.ty = u.uy;
  53.      tmp = ACURR(A_DEX);
  54.      trapinfo.time_needed =
  55.          (tmp > 17) ? 2 : (tmp > 12) ? 3 : (tmp > 7) ? 4 : 5;
  56.      if (Blind)
  57.          trapinfo.time_needed *= 2;
  58.      tmp = ACURR(A_STR);
  59.      if (ttyp == BEAR_TRAP && tmp < 18)
  60.          trapinfo.time_needed += (tmp > 12) ? 1 : (tmp > 7) ? 2 : 4;
  61.      /*[fumbling and/or confusion and/or cursed object check(s)
  62.         should be incorporated here instead of in set_trap]*/
  63.      if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
  64.          boolean chance;
  65.  
  66.          if (Fumbling || otmp->cursed)
  67.              chance = (rnl(10) > 3);
  68.          else
  69.              chance = (rnl(10) > 5);
  70.          You("aren't very skilled at reaching from %s.", mon_nam(u.usteed));
  71.          Sprintf(buf, "Continue your attempt to set %s?",
  72.                  the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
  73.          if (yn(buf) == 'y') {
  74.              if (chance) {
  75.                  switch (ttyp) {
  76.                  case LANDMINE: /* set it off */
  77.                      trapinfo.time_needed = 0;
  78.                      trapinfo.force_bungle = TRUE;
  79.                      break;
  80.                  case BEAR_TRAP: /* drop it without arming it */
  81.                      reset_trapset();
  82.                      You("drop %s!",
  83.                          the(defsyms[trap_to_defsym(what_trap(ttyp))]
  84.                                  .explanation));
  85.                      dropx(otmp);
  86.                      return;
  87.                  }
  88.              }
  89.          } else {
  90.              reset_trapset();
  91.              return;
  92.          }
  93.      }
  94.      You("begin setting %s%s.", shk_your(buf, otmp),
  95.          defsyms[trap_to_defsym(what_trap(ttyp))].explanation);
  96.      set_occupation(set_trap, occutext, 0);
  97.      return;
  98.  }
  99.  

set_trap

  1.  STATIC_PTR
  2.  int
  3.  set_trap()
  4.  {
  5.      struct obj *otmp = trapinfo.tobj;
  6.      struct trap *ttmp;
  7.      int ttyp;
  8.  
  9.      if (!otmp || !carried(otmp) || u.ux != trapinfo.tx
  10.          || u.uy != trapinfo.ty) {
  11.          /* ?? */
  12.          reset_trapset();
  13.          return 0;
  14.      }
  15.  
  16.      if (--trapinfo.time_needed > 0)
  17.          return 1; /* still busy */
  18.  
  19.      ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP;
  20.      ttmp = maketrap(u.ux, u.uy, ttyp);
  21.      if (ttmp) {
  22.          ttmp->madeby_u = 1;
  23.          feeltrap(ttmp);
  24.          if (*in_rooms(u.ux, u.uy, SHOPBASE)) {
  25.              add_damage(u.ux, u.uy, 0L); /* schedule removal */
  26.          }
  27.          if (!trapinfo.force_bungle)
  28.              You("finish arming %s.",
  29.                  the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
  30.          if (((otmp->cursed || Fumbling) && (rnl(10) > 5))
  31.              || trapinfo.force_bungle)
  32.              dotrap(ttmp,
  33.                     (unsigned) (trapinfo.force_bungle ? FORCEBUNGLE : 0));
  34.      } else {
  35.          /* this shouldn't happen */
  36.          Your("trap setting attempt fails.");
  37.      }
  38.      useup(otmp);
  39.      reset_trapset();
  40.      return 0;
  41.  }
  42.  

use_whip

  1.  STATIC_OVL int
  2.  use_whip(obj)
  3.  struct obj *obj;
  4.  {
  5.      char buf[BUFSZ];
  6.      struct monst *mtmp;
  7.      struct obj *otmp;
  8.      int rx, ry, proficient, res = 0;
  9.      const char *msg_slipsfree = "The bullwhip slips free.";
  10.      const char *msg_snap = "Snap!";
  11.  
  12.      if (obj != uwep) {
  13.          if (!wield_tool(obj, "lash"))
  14.              return 0;
  15.          else
  16.              res = 1;
  17.      }
  18.      if (!getdir((char *) 0))
  19.          return res;
  20.  
  21.      if (u.uswallow) {
  22.          mtmp = u.ustuck;
  23.          rx = mtmp->mx;
  24.          ry = mtmp->my;
  25.      } else {
  26.          if (Stunned || (Confusion && !rn2(5)))
  27.              confdir();
  28.          rx = u.ux + u.dx;
  29.          ry = u.uy + u.dy;
  30.          if (!isok(rx, ry)) {
  31.              You("miss.");
  32.              return res;
  33.          }
  34.          mtmp = m_at(rx, ry);
  35.      }
  36.  
  37.      /* fake some proficiency checks */
  38.      proficient = 0;
  39.      if (Role_if(PM_ARCHEOLOGIST))
  40.          ++proficient;
  41.      if (ACURR(A_DEX) < 6)
  42.          proficient--;
  43.      else if (ACURR(A_DEX) >= 14)
  44.          proficient += (ACURR(A_DEX) - 14);
  45.      if (Fumbling)
  46.          --proficient;
  47.      if (proficient > 3)
  48.          proficient = 3;
  49.      if (proficient < 0)
  50.          proficient = 0;
  51.  
  52.      if (u.uswallow && attack(u.ustuck)) {
  53.          There("is not enough room to flick your bullwhip.");
  54.  
  55.      } else if (Underwater) {
  56.          There("is too much resistance to flick your bullwhip.");
  57.  
  58.      } else if (u.dz < 0) {
  59.          You("flick a bug off of the %s.", ceiling(u.ux, u.uy));
  60.  
  61.      } else if ((!u.dx && !u.dy) || (u.dz > 0)) {
  62.          int dam;
  63.  
  64.          /* Sometimes you hit your steed by mistake */
  65.          if (u.usteed && !rn2(proficient + 2)) {
  66.              You("whip %s!", mon_nam(u.usteed));
  67.              kick_steed();
  68.              return 1;
  69.          }
  70.          if (Levitation || u.usteed) {
  71.              /* Have a shot at snaring something on the floor */
  72.              otmp = level.objects[u.ux][u.uy];
  73.              if (otmp && otmp->otyp == CORPSE && otmp->corpsenm == PM_HORSE) {
  74.                  pline("Why beat a dead horse?");
  75.                  return 1;
  76.              }
  77.              if (otmp && proficient) {
  78.                  You("wrap your bullwhip around %s on the %s.",
  79.                      an(singular(otmp, xname)), surface(u.ux, u.uy));
  80.                  if (rnl(6) || pickup_object(otmp, 1L, TRUE) < 1)
  81.                      pline1(msg_slipsfree);
  82.                  return 1;
  83.              }
  84.          }
  85.          dam = rnd(2) + dbon() + obj->spe;
  86.          if (dam <= 0)
  87.              dam = 1;
  88.          You("hit your %s with your bullwhip.", body_part(FOOT));
  89.          Sprintf(buf, "killed %sself with %s bullwhip", uhim(), uhis());
  90.          losehp(Maybe_Half_Phys(dam), buf, NO_KILLER_PREFIX);
  91.          context.botl = 1;
  92.          return 1;
  93.  
  94.      } else if ((Fumbling || Glib) && !rn2(5)) {
  95.          pline_The("bullwhip slips out of your %s.", body_part(HAND));
  96.          dropx(obj);
  97.  
  98.      } else if (u.utrap && u.utraptype == TT_PIT) {
  99.          /*
  100.           * Assumptions:
  101.           *
  102.           * if you're in a pit
  103.           *    - you are attempting to get out of the pit
  104.           * or, if you are applying it towards a small monster
  105.           *    - then it is assumed that you are trying to hit it
  106.           * else if the monster is wielding a weapon
  107.           *    - you are attempting to disarm a monster
  108.           * else
  109.           *    - you are attempting to hit the monster.
  110.           *
  111.           * if you're confused (and thus off the mark)
  112.           *    - you only end up hitting.
  113.           *
  114.           */
  115.          const char *wrapped_what = (char *) 0;
  116.  
  117.          if (mtmp) {
  118.              if (bigmonst(mtmp->data)) {
  119.                  wrapped_what = strcpy(buf, mon_nam(mtmp));
  120.              } else if (proficient) {
  121.                  if (attack(mtmp))
  122.                      return 1;
  123.                  else
  124.                      pline1(msg_snap);
  125.              }
  126.          }
  127.          if (!wrapped_what) {
  128.              if (IS_FURNITURE(levl[rx][ry].typ))
  129.                  wrapped_what = something;
  130.              else if (sobj_at(BOULDER, rx, ry))
  131.                  wrapped_what = "a boulder";
  132.          }
  133.          if (wrapped_what) {
  134.              coord cc;
  135.  
  136.              cc.x = rx;
  137.              cc.y = ry;
  138.              You("wrap your bullwhip around %s.", wrapped_what);
  139.              if (proficient && rn2(proficient + 2)) {
  140.                  if (!mtmp || enexto(&cc, rx, ry, youmonst.data)) {
  141.                      You("yank yourself out of the pit!");
  142.                      teleds(cc.x, cc.y, TRUE);
  143.                      u.utrap = 0;
  144.                      vision_full_recalc = 1;
  145.                  }
  146.              } else {
  147.                  pline1(msg_slipsfree);
  148.              }
  149.              if (mtmp)
  150.                  wakeup(mtmp);
  151.          } else
  152.              pline1(msg_snap);
  153.  
  154.      } else if (mtmp) {
  155.          if (!canspotmon(mtmp) && !glyph_is_invisible(levl[rx][ry].glyph)) {
  156.              pline("A monster is there that you couldn't see.");
  157.              map_invisible(rx, ry);
  158.          }
  159.          otmp = MON_WEP(mtmp); /* can be null */
  160.          if (otmp) {
  161.              char onambuf[BUFSZ];
  162.              const char *mon_hand;
  163.              boolean gotit = proficient && (!Fumbling || !rn2(10));
  164.  
  165.              Strcpy(onambuf, cxname(otmp));
  166.              if (gotit) {
  167.                  mon_hand = mbodypart(mtmp, HAND);
  168.                  if (bimanual(otmp))
  169.                      mon_hand = makeplural(mon_hand);
  170.              } else
  171.                  mon_hand = 0; /* lint suppression */
  172.  
  173.              You("wrap your bullwhip around %s.", yname(otmp));
  174.              if (gotit && mwelded(otmp)) {
  175.                  pline("%s welded to %s %s%c",
  176.                        (otmp->quan == 1L) ? "It is" : "They are", mhis(mtmp),
  177.                        mon_hand, !otmp->bknown ? '!' : '.');
  178.                  otmp->bknown = 1;
  179.                  gotit = FALSE; /* can't pull it free */
  180.              }
  181.              if (gotit) {
  182.                  obj_extract_self(otmp);
  183.                  possibly_unwield(mtmp, FALSE);
  184.                  setmnotwielded(mtmp, otmp);
  185.  
  186.                  switch (rn2(proficient + 1)) {
  187.                  case 2:
  188.                      /* to floor near you */
  189.                      You("yank %s to the %s!", yname(otmp),
  190.                          surface(u.ux, u.uy));
  191.                      place_object(otmp, u.ux, u.uy);
  192.                      stackobj(otmp);
  193.                      break;
  194.                  case 3:
  195.  #if 0
  196.                      /* right to you */
  197.                      if (!rn2(25)) {
  198.                          /* proficient with whip, but maybe not
  199.                             so proficient at catching weapons */
  200.                          int hitu, hitvalu;
  201.  
  202.                          hitvalu = 8 + otmp->spe;
  203.                          hitu = thitu(hitvalu,
  204.                                       dmgval(otmp, &youmonst),
  205.                                       otmp, (char *)0);
  206.                          if (hitu) {
  207.                              pline_The("%s hits you as you try to snatch it!",
  208.                                        the(onambuf));
  209.                          }
  210.                          place_object(otmp, u.ux, u.uy);
  211.                          stackobj(otmp);
  212.                          break;
  213.                      }
  214.  #endif /* 0 */
  215.                      /* right into your inventory */
  216.                      You("snatch %s!", yname(otmp));
  217.                      if (otmp->otyp == CORPSE
  218.                          && touch_petrifies(&mons[otmp->corpsenm]) && !uarmg
  219.                          && !Stone_resistance
  220.                          && !(poly_when_stoned(youmonst.data)
  221.                               && polymon(PM_STONE_GOLEM))) {
  222.                          char kbuf[BUFSZ];
  223.  
  224.                          Sprintf(kbuf, "%s corpse",
  225.                                  an(mons[otmp->corpsenm].mname));
  226.                          pline("Snatching %s is a fatal mistake.", kbuf);
  227.                          instapetrify(kbuf);
  228.                      }
  229.                      otmp = hold_another_object(
  230.                          otmp, "You drop %s!", doname(otmp), (const char *) 0);
  231.                      break;
  232.                  default:
  233.                      /* to floor beneath mon */
  234.                      You("yank %s from %s %s!", the(onambuf),
  235.                          s_suffix(mon_nam(mtmp)), mon_hand);
  236.                      obj_no_longer_held(otmp);
  237.                      place_object(otmp, mtmp->mx, mtmp->my);
  238.                      stackobj(otmp);
  239.                      break;
  240.                  }
  241.              } else {
  242.                  pline1(msg_slipsfree);
  243.              }
  244.              wakeup(mtmp);
  245.          } else {
  246.              if (mtmp->m_ap_type && !Protection_from_shape_changers
  247.                  && !sensemon(mtmp))
  248.                  stumble_onto_mimic(mtmp);
  249.              else
  250.                  You("flick your bullwhip towards %s.", mon_nam(mtmp));
  251.              if (proficient) {
  252.                  if (attack(mtmp))
  253.                      return 1;
  254.                  else
  255.                      pline1(msg_snap);
  256.              }
  257.          }
  258.  
  259.      } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
  260.          /* it must be air -- water checked above */
  261.          You("snap your whip through thin air.");
  262.  
  263.      } else {
  264.          pline1(msg_snap);
  265.      }
  266.      return 1;
  267.  }
  268.  

find_poleable_mon

  1.  static const char
  2.      not_enough_room[] = "There's not enough room here to use that.",
  3.      where_to_hit[] = "Where do you want to hit?",
  4.      cant_see_spot[] = "won't hit anything if you can't see that spot.",
  5.      cant_reach[] = "can't reach that spot from here.";
  6.  
  7.  /* find pos of monster in range, if only one monster */
  8.  boolean
  9.  find_poleable_mon(pos, min_range, max_range)
  10.  coord *pos;
  11.  int min_range, max_range;
  12.  {
  13.      struct monst *mtmp;
  14.      struct monst *selmon = (struct monst *) 0;
  15.  
  16.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  17.          if (mtmp && !DEADMONSTER(mtmp) && !mtmp->mtame
  18.              && cansee(mtmp->mx, mtmp->my)
  19.              && distu(mtmp->mx, mtmp->my) <= max_range
  20.              && distu(mtmp->mx, mtmp->my) >= min_range) {
  21.              if (selmon)
  22.                  return FALSE;
  23.              selmon = mtmp;
  24.          }
  25.      if (!selmon)
  26.          return FALSE;
  27.      pos->x = selmon->mx;
  28.      pos->y = selmon->my;
  29.      return TRUE;
  30.  }
  31.  

display_polearm_positions

  1.  static int polearm_range_min = -1;
  2.  static int polearm_range_max = -1;
  3.  
  4.  void
  5.  display_polearm_positions(state)
  6.  int state;
  7.  {
  8.      if (state == 0) {
  9.          tmp_at(DISP_BEAM, cmap_to_glyph(S_goodpos));
  10.      } else if (state == 1) {
  11.          int x, y, dx, dy;
  12.  
  13.          for (dx = -4; dx <= 4; dx++)
  14.              for (dy = -4; dy <= 4; dy++) {
  15.                  x = dx + (int) u.ux;
  16.                  y = dy + (int) u.uy;
  17.                  if (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
  18.                      && distu(x, y) >= polearm_range_min
  19.                      && distu(x, y) <= polearm_range_max) {
  20.                      tmp_at(x, y);
  21.                  }
  22.              }
  23.      } else {
  24.          tmp_at(DISP_END, 0);
  25.      }
  26.  }
  27.  

use_pole

  1.  /* Distance attacks by pole-weapons */
  2.  STATIC_OVL int
  3.  use_pole(obj)
  4.  struct obj *obj;
  5.  {
  6.      int res = 0, typ, max_range, min_range, glyph;
  7.      coord cc;
  8.      struct monst *mtmp;
  9.      struct monst *hitm = context.polearm.hitmon;
  10.  
  11.      /* Are you allowed to use the pole? */
  12.      if (u.uswallow) {
  13.          pline(not_enough_room);
  14.          return 0;
  15.      }
  16.      if (obj != uwep) {
  17.          if (!wield_tool(obj, "swing"))
  18.              return 0;
  19.          else
  20.              res = 1;
  21.      }
  22.      /* assert(obj == uwep); */
  23.  
  24.      /*
  25.       * Calculate allowable range (pole's reach is always 2 steps):
  26.       *  unskilled and basic: orthogonal direction, 4..4;
  27.       *  skilled: as basic, plus knight's jump position, 4..5;
  28.       *  expert: as skilled, plus diagonal, 4..8.
  29.       *      ...9...
  30.       *      .85458.
  31.       *      .52125.
  32.       *      9410149
  33.       *      .52125.
  34.       *      .85458.
  35.       *      ...9...
  36.       *  (Note: no roles in nethack can become expert or better
  37.       *  for polearm skill; Yeoman in slash'em can become expert.)
  38.       */
  39.      min_range = 4;
  40.      typ = uwep_skill_type();
  41.      if (typ == P_NONE || P_SKILL(typ) <= P_BASIC)
  42.          max_range = 4;
  43.      else if (P_SKILL(typ) == P_SKILLED)
  44.          max_range = 5;
  45.      else
  46.          max_range = 8; /* (P_SKILL(typ) >= P_EXPERT) */
  47.  
  48.      polearm_range_min = min_range;
  49.      polearm_range_max = max_range;
  50.  
  51.      /* Prompt for a location */
  52.      pline(where_to_hit);
  53.      cc.x = u.ux;
  54.      cc.y = u.uy;
  55.      if (!find_poleable_mon(&cc, min_range, max_range) && hitm
  56.          && !DEADMONSTER(hitm) && cansee(hitm->mx, hitm->my)
  57.          && distu(hitm->mx, hitm->my) <= max_range
  58.          && distu(hitm->mx, hitm->my) >= min_range) {
  59.          cc.x = hitm->mx;
  60.          cc.y = hitm->my;
  61.      }
  62.      getpos_sethilite(display_polearm_positions);
  63.      if (getpos(&cc, TRUE, "the spot to hit") < 0)
  64.          return res; /* ESC; uses turn iff polearm became wielded */
  65.  
  66.      glyph = glyph_at(cc.x, cc.y);
  67.      if (distu(cc.x, cc.y) > max_range) {
  68.          pline("Too far!");
  69.          return res;
  70.      } else if (distu(cc.x, cc.y) < min_range) {
  71.          pline("Too close!");
  72.          return res;
  73.      } else if (!cansee(cc.x, cc.y) && !glyph_is_monster(glyph)
  74.                 && !glyph_is_invisible(glyph) && !glyph_is_statue(glyph)) {
  75.          You(cant_see_spot);
  76.          return res;
  77.      } else if (!couldsee(cc.x, cc.y)) { /* Eyes of the Overworld */
  78.          You(cant_reach);
  79.          return res;
  80.      }
  81.  
  82.      context.polearm.hitmon = NULL;
  83.      /* Attack the monster there */
  84.      bhitpos = cc;
  85.      if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != (struct monst *) 0) {
  86.          if (attack_checks(mtmp, uwep))
  87.              return res;
  88.          if (overexertion())
  89.              return 1; /* burn nutrition; maybe pass out */
  90.          context.polearm.hitmon = mtmp;
  91.          check_caitiff(mtmp);
  92.          notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
  93.          (void) thitmonst(mtmp, uwep);
  94.      } else if (glyph_is_statue(glyph) /* might be hallucinatory */
  95.                 && sobj_at(STATUE, bhitpos.x, bhitpos.y)) {
  96.          struct trap *t = t_at(bhitpos.x, bhitpos.y);
  97.  
  98.          if (t && t->ttyp == STATUE_TRAP
  99.              && activate_statue_trap(t, t->tx, t->ty, FALSE)) {
  100.              ; /* feedback has been give by animate_statue() */
  101.          } else {
  102.              /* Since statues look like monsters now, we say something
  103.                 different from "you miss" or "there's nobody there".
  104.                 Note:  we only do this when a statue is displayed here,
  105.                 because the player is probably attempting to attack it;
  106.                 other statues obscured by anything are just ignored. */
  107.              pline("Thump!  Your blow bounces harmlessly off the statue.");
  108.              wake_nearto(bhitpos.x, bhitpos.y, 25);
  109.          }
  110.      } else {
  111.          /* no monster here and no statue seen or remembered here */
  112.          if (glyph_is_invisible(glyph)) {
  113.              /* now you know that nothing is there... */
  114.              unmap_object(bhitpos.x, bhitpos.y);
  115.              newsym(bhitpos.x, bhitpos.y);
  116.          }
  117.          You("miss; there is no one there to hit.");
  118.      }
  119.      u_wipe_engr(2); /* same as for melee or throwing */
  120.      return 1;
  121.  }
  122.  

use_cream_pie

  1.  STATIC_OVL int
  2.  use_cream_pie(obj)
  3.  struct obj *obj;
  4.  {
  5.      boolean wasblind = Blind;
  6.      boolean wascreamed = u.ucreamed;
  7.      boolean several = FALSE;
  8.  
  9.      if (obj->quan > 1L) {
  10.          several = TRUE;
  11.          obj = splitobj(obj, 1L);
  12.      }
  13.      if (Hallucination)
  14.          You("give yourself a facial.");
  15.      else
  16.          pline("You immerse your %s in %s%s.", body_part(FACE),
  17.                several ? "one of " : "",
  18.                several ? makeplural(the(xname(obj))) : the(xname(obj)));
  19.      if (can_blnd((struct monst *) 0, &youmonst, AT_WEAP, obj)) {
  20.          int blindinc = rnd(25);
  21.          u.ucreamed += blindinc;
  22.          make_blinded(Blinded + (long) blindinc, FALSE);
  23.          if (!Blind || (Blind && wasblind))
  24.              pline("There's %ssticky goop all over your %s.",
  25.                    wascreamed ? "more " : "", body_part(FACE));
  26.          else /* Blind  && !wasblind */
  27.              You_cant("see through all the sticky goop on your %s.",
  28.                       body_part(FACE));
  29.      }
  30.  
  31.      setnotworn(obj);
  32.      /* useup() is appropriate, but we want costly_alteration()'s message */
  33.      costly_alteration(obj, COST_SPLAT);
  34.      obj_extract_self(obj);
  35.      delobj(obj);
  36.      return 0;
  37.  }
  38.  

use_grapple

  1.  STATIC_OVL int
  2.  use_grapple(obj)
  3.  struct obj *obj;
  4.  {
  5.      int res = 0, typ, max_range = 4, tohit;
  6.      boolean save_confirm;
  7.      coord cc;
  8.      struct monst *mtmp;
  9.      struct obj *otmp;
  10.  
  11.      /* Are you allowed to use the hook? */
  12.      if (u.uswallow) {
  13.          pline(not_enough_room);
  14.          return 0;
  15.      }
  16.      if (obj != uwep) {
  17.          if (!wield_tool(obj, "cast"))
  18.              return 0;
  19.          else
  20.              res = 1;
  21.      }
  22.      /* assert(obj == uwep); */
  23.  
  24.      /* Prompt for a location */
  25.      pline(where_to_hit);
  26.      cc.x = u.ux;
  27.      cc.y = u.uy;
  28.      if (getpos(&cc, TRUE, "the spot to hit") < 0)
  29.          return res; /* ESC; uses turn iff grapnel became wielded */
  30.  
  31.      /* Calculate range; unlike use_pole(), there's no minimum for range */
  32.      typ = uwep_skill_type();
  33.      if (typ == P_NONE || P_SKILL(typ) <= P_BASIC)
  34.          max_range = 4;
  35.      else if (P_SKILL(typ) == P_SKILLED)
  36.          max_range = 5;
  37.      else
  38.          max_range = 8;
  39.      if (distu(cc.x, cc.y) > max_range) {
  40.          pline("Too far!");
  41.          return res;
  42.      } else if (!cansee(cc.x, cc.y)) {
  43.          You(cant_see_spot);
  44.          return res;
  45.      } else if (!couldsee(cc.x, cc.y)) { /* Eyes of the Overworld */
  46.          You(cant_reach);
  47.          return res;
  48.      }
  49.  
  50.      /* What do you want to hit? */
  51.      tohit = rn2(5);
  52.      if (typ != P_NONE && P_SKILL(typ) >= P_SKILLED) {
  53.          winid tmpwin = create_nhwindow(NHW_MENU);
  54.          anything any;
  55.          char buf[BUFSZ];
  56.          menu_item *selected;
  57.  
  58.          any = zeroany; /* set all bits to zero */
  59.          any.a_int = 1; /* use index+1 (cant use 0) as identifier */
  60.          start_menu(tmpwin);
  61.          any.a_int++;
  62.          Sprintf(buf, "an object on the %s", surface(cc.x, cc.y));
  63.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
  64.                   MENU_UNSELECTED);
  65.          any.a_int++;
  66.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "a monster",
  67.                   MENU_UNSELECTED);
  68.          any.a_int++;
  69.          Sprintf(buf, "the %s", surface(cc.x, cc.y));
  70.          add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
  71.                   MENU_UNSELECTED);
  72.          end_menu(tmpwin, "Aim for what?");
  73.          tohit = rn2(4);
  74.          if (select_menu(tmpwin, PICK_ONE, &selected) > 0
  75.              && rn2(P_SKILL(typ) > P_SKILLED ? 20 : 2))
  76.              tohit = selected[0].item.a_int - 1;
  77.          free((genericptr_t) selected);
  78.          destroy_nhwindow(tmpwin);
  79.      }
  80.  
  81.      /* possibly scuff engraving at your feet;
  82.         any engraving at the target location is unaffected */
  83.      if (tohit == 2 || !rn2(2))
  84.          u_wipe_engr(rnd(2));
  85.  
  86.      /* What did you hit? */
  87.      switch (tohit) {
  88.      case 0: /* Trap */
  89.          /* FIXME -- untrap needs to deal with non-adjacent traps */
  90.          break;
  91.      case 1: /* Object */
  92.          if ((otmp = level.objects[cc.x][cc.y]) != 0) {
  93.              You("snag an object from the %s!", surface(cc.x, cc.y));
  94.              (void) pickup_object(otmp, 1L, FALSE);
  95.              /* If pickup fails, leave it alone */
  96.              newsym(cc.x, cc.y);
  97.              return 1;
  98.          }
  99.          break;
  100.      case 2: /* Monster */
  101.          bhitpos = cc;
  102.          if ((mtmp = m_at(cc.x, cc.y)) == (struct monst *) 0)
  103.              break;
  104.          notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
  105.          save_confirm = flags.confirm;
  106.          if (verysmall(mtmp->data) && !rn2(4)
  107.              && enexto(&cc, u.ux, u.uy, (struct permonst *) 0)) {
  108.              flags.confirm = FALSE;
  109.              (void) attack_checks(mtmp, uwep);
  110.              flags.confirm = save_confirm;
  111.              check_caitiff(mtmp); /* despite fact there's no damage */
  112.              You("pull in %s!", mon_nam(mtmp));
  113.              mtmp->mundetected = 0;
  114.              rloc_to(mtmp, cc.x, cc.y);
  115.              return 1;
  116.          } else if ((!bigmonst(mtmp->data) && !strongmonst(mtmp->data))
  117.                     || rn2(4)) {
  118.              flags.confirm = FALSE;
  119.              (void) attack_checks(mtmp, uwep);
  120.              flags.confirm = save_confirm;
  121.              check_caitiff(mtmp);
  122.              (void) thitmonst(mtmp, uwep);
  123.              return 1;
  124.          }
  125.      /* FALL THROUGH */
  126.      case 3: /* Surface */
  127.          if (IS_AIR(levl[cc.x][cc.y].typ) || is_pool(cc.x, cc.y))
  128.              pline_The("hook slices through the %s.", surface(cc.x, cc.y));
  129.          else {
  130.              You("are yanked toward the %s!", surface(cc.x, cc.y));
  131.              hurtle(sgn(cc.x - u.ux), sgn(cc.y - u.uy), 1, FALSE);
  132.              spoteffects(TRUE);
  133.          }
  134.          return 1;
  135.      default: /* Yourself (oops!) */
  136.          if (P_SKILL(typ) <= P_BASIC) {
  137.              You("hook yourself!");
  138.              losehp(Maybe_Half_Phys(rn1(10, 10)), "a grappling hook",
  139.                     KILLED_BY);
  140.              return 1;
  141.          }
  142.          break;
  143.      }
  144.      pline1(nothing_happens);
  145.      return 1;
  146.  }
  147.  

do_break_wand

  1.  #define BY_OBJECT ((struct monst *) 0)
  2.  
  3.  /* return 1 if the wand is broken, hence some time elapsed */
  4.  STATIC_OVL int
  5.  do_break_wand(obj)
  6.  struct obj *obj;
  7.  {
  8.      static const char nothing_else_happens[] = "But nothing else happens...";
  9.      register int i, x, y;
  10.      register struct monst *mon;
  11.      int dmg, damage;
  12.      boolean affects_objects;
  13.      boolean shop_damage = FALSE;
  14.      boolean fillmsg = FALSE;
  15.      int expltype = EXPL_MAGICAL;
  16.      char confirm[QBUFSZ], buf[BUFSZ];
  17.      boolean is_fragile = (!strcmp(OBJ_DESCR(objects[obj->otyp]), "balsa"));
  18.  
  19.      if (!paranoid_query(ParanoidBreakwand,
  20.                         safe_qbuf(confirm,
  21.                                   "Are you really sure you want to break ",
  22.                                   "?", obj, yname, ysimple_name, "the wand")))
  23.          return 0;
  24.  
  25.      if (nohands(youmonst.data)) {
  26.          You_cant("break %s without hands!", yname(obj));
  27.          return 0;
  28.      } else if (ACURR(A_STR) < (is_fragile ? 5 : 10)) {
  29.          You("don't have the strength to break %s!", yname(obj));
  30.          return 0;
  31.      }
  32.      pline("Raising %s high above your %s, you break it in two!", yname(obj),
  33.            body_part(HEAD));
  34.  
  35.      /* [ALI] Do this first so that wand is removed from bill. Otherwise,
  36.       * the freeinv() below also hides it from setpaid() which causes problems.
  37.       */
  38.      if (obj->unpaid) {
  39.          check_unpaid(obj); /* Extra charge for use */
  40.          costly_alteration(obj, COST_DSTROY);
  41.      }
  42.  
  43.      current_wand = obj; /* destroy_item might reset this */
  44.      freeinv(obj);       /* hide it from destroy_item instead... */
  45.      setnotworn(obj);    /* so we need to do this ourselves */
  46.  
  47.      if (!zappable(obj)) {
  48.          pline(nothing_else_happens);
  49.          goto discard_broken_wand;
  50.      }
  51.      /* successful call to zappable() consumes a charge; put it back */
  52.      obj->spe++;
  53.      /* might have "wrested" a final charge, taking it from 0 to -1;
  54.         if so, we just brought it back up to 0, which wouldn't do much
  55.         below so give it 1..3 charges now, usually making it stronger
  56.         than an ordinary last charge (the wand is already gone from
  57.         inventory, so perm_invent can't accidentally reveal this) */
  58.      if (!obj->spe)
  59.          obj->spe = rnd(3);
  60.  
  61.      obj->ox = u.ux;
  62.      obj->oy = u.uy;
  63.      dmg = obj->spe * 4;
  64.      affects_objects = FALSE;
  65.  
  66.      switch (obj->otyp) {
  67.      case WAN_WISHING:
  68.      case WAN_NOTHING:
  69.      case WAN_LOCKING:
  70.      case WAN_PROBING:
  71.      case WAN_ENLIGHTENMENT:
  72.      case WAN_OPENING:
  73.      case WAN_SECRET_DOOR_DETECTION:
  74.          pline(nothing_else_happens);
  75.          goto discard_broken_wand;
  76.      case WAN_DEATH:
  77.      case WAN_LIGHTNING:
  78.          dmg *= 4;
  79.          goto wanexpl;
  80.      case WAN_FIRE:
  81.          expltype = EXPL_FIERY;
  82.      case WAN_COLD:
  83.          if (expltype == EXPL_MAGICAL)
  84.              expltype = EXPL_FROSTY;
  85.          dmg *= 2;
  86.      case WAN_MAGIC_MISSILE:
  87.      wanexpl:
  88.          explode(u.ux, u.uy, -(obj->otyp), dmg, WAND_CLASS, expltype);
  89.          makeknown(obj->otyp); /* explode describes the effect */
  90.          goto discard_broken_wand;
  91.      case WAN_STRIKING:
  92.          /* we want this before the explosion instead of at the very end */
  93.          pline("A wall of force smashes down around you!");
  94.          dmg = d(1 + obj->spe, 6); /* normally 2d12 */
  95.          /*FALLTHRU*/
  96.      case WAN_CANCELLATION:
  97.      case WAN_POLYMORPH:
  98.      case WAN_TELEPORTATION:
  99.      case WAN_UNDEAD_TURNING:
  100.          affects_objects = TRUE;
  101.          break;
  102.      default:
  103.          break;
  104.      }
  105.  
  106.      /* magical explosion and its visual effect occur before specific effects
  107.       */
  108.      /* [TODO?  This really ought to prevent the explosion from being
  109.         fatal so that we never leave a bones file where none of the
  110.         surrounding targets (or underlying objects) got affected yet.] */
  111.      explode(obj->ox, obj->oy, -(obj->otyp), rnd(dmg), WAND_CLASS,
  112.              EXPL_MAGICAL);
  113.  
  114.      /* prepare for potential feedback from polymorph... */
  115.      zapsetup();
  116.  
  117.      /* this makes it hit us last, so that we can see the action first */
  118.      for (i = 0; i <= 8; i++) {
  119.          bhitpos.x = x = obj->ox + xdir[i];
  120.          bhitpos.y = y = obj->oy + ydir[i];
  121.          if (!isok(x, y))
  122.              continue;
  123.  
  124.          if (obj->otyp == WAN_DIGGING) {
  125.              schar typ;
  126.  
  127.              if (dig_check(BY_OBJECT, FALSE, x, y)) {
  128.                  if (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)) {
  129.                      /* normally, pits and holes don't anger guards, but they
  130.                       * do if it's a wall or door that's being dug */
  131.                      watch_dig((struct monst *) 0, x, y, TRUE);
  132.                      if (*in_rooms(x, y, SHOPBASE))
  133.                          shop_damage = TRUE;
  134.                  }
  135.                  /*
  136.                   * Let liquid flow into the newly created pits.
  137.                   * Adjust corresponding code in music.c for
  138.                   * drum of earthquake if you alter this sequence.
  139.                   */
  140.                  typ = fillholetyp(x, y, FALSE);
  141.                  if (typ != ROOM) {
  142.                      levl[x][y].typ = typ;
  143.                      liquid_flow(x, y, typ, t_at(x, y),
  144.                                  fillmsg
  145.                                    ? (char *) 0
  146.                                    : "Some holes are quickly filled with %s!");
  147.                      fillmsg = TRUE;
  148.                  } else
  149.                      digactualhole(x, y, BY_OBJECT, (rn2(obj->spe) < 3
  150.                                                      || (!Can_dig_down(&u.uz)
  151.                                                          && !levl[x][y].candig))
  152.                                                        ? PIT
  153.                                                        : HOLE);
  154.              }
  155.              continue;
  156.          } else if (obj->otyp == WAN_CREATE_MONSTER) {
  157.              /* u.ux,u.uy creates it near you--x,y might create it in rock */
  158.              (void) makemon((struct permonst *) 0, u.ux, u.uy, NO_MM_FLAGS);
  159.              continue;
  160.          } else if (x != u.ux || y != u.uy) {
  161.              /*
  162.               * Wand breakage is targetting a square adjacent to the hero,
  163.               * which might contain a monster or a pile of objects or both.
  164.               * Handle objects last; avoids having undead turning raise an
  165.               * undead's corpse and then attack resulting undead monster.
  166.               * obj->bypass in bhitm() prevents the polymorphing of items
  167.               * dropped due to monster's polymorph and prevents undead
  168.               * turning that kills an undead from raising resulting corpse.
  169.               */
  170.              if ((mon = m_at(x, y)) != 0) {
  171.                  (void) bhitm(mon, obj);
  172.                  /* if (context.botl) bot(); */
  173.              }
  174.              if (affects_objects && level.objects[x][y]) {
  175.                  (void) bhitpile(obj, bhito, x, y, 0);
  176.                  if (context.botl)
  177.                      bot(); /* potion effects */
  178.              }
  179.          } else {
  180.              /*
  181.               * Wand breakage is targetting the hero.  Using xdir[]+ydir[]
  182.               * deltas for location selection causes this case to happen
  183.               * after all the surrounding squares have been handled.
  184.               * Process objects first, in case damage is fatal and leaves
  185.               * bones, or teleportation sends one or more of the objects to
  186.               * same destination as hero (lookhere/autopickup); also avoids
  187.               * the polymorphing of gear dropped due to hero's transformation.
  188.               * (Unlike with monsters being hit by zaps, we can't rely on use
  189.               * of obj->bypass in the zap code to accomplish that last case
  190.               * since it's also used by retouch_equipment() for polyself.)
  191.               */
  192.              if (affects_objects && level.objects[x][y]) {
  193.                  (void) bhitpile(obj, bhito, x, y, 0);
  194.                  if (context.botl)
  195.                      bot(); /* potion effects */
  196.              }
  197.              damage = zapyourself(obj, FALSE);
  198.              if (damage) {
  199.                  Sprintf(buf, "killed %sself by breaking a wand", uhim());
  200.                  losehp(Maybe_Half_Phys(damage), buf, NO_KILLER_PREFIX);
  201.              }
  202.              if (context.botl)
  203.                  bot(); /* blindness */
  204.          }
  205.      }
  206.  
  207.      /* potentially give post zap/break feedback */
  208.      zapwrapup();
  209.  
  210.      /* Note: if player fell thru, this call is a no-op.
  211.         Damage is handled in digactualhole in that case */
  212.      if (shop_damage)
  213.          pay_for_damage("dig into", FALSE);
  214.  
  215.      if (obj->otyp == WAN_LIGHT)
  216.          litroom(TRUE, obj); /* only needs to be done once */
  217.  
  218.  discard_broken_wand:
  219.      obj = current_wand; /* [see dozap() and destroy_item()] */
  220.      current_wand = 0;
  221.      if (obj)
  222.          delobj(obj);
  223.      nomul(0);
  224.      return 1;
  225.  }
  226.  

add_class

  1.  STATIC_OVL void
  2.  add_class(cl, class)
  3.  char *cl;
  4.  char class;
  5.  {
  6.      char tmp[2];
  7.  
  8.      tmp[0] = class;
  9.      tmp[1] = '\0';
  10.      Strcat(cl, tmp);
  11.  }
  12.  

setapplyclasses

  1.  static const char tools[] = { TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 0 };
  2.  
  3.  /* augment tools[] if various items are carried */
  4.  STATIC_OVL void
  5.  setapplyclasses(class_list)
  6.  char class_list[];
  7.  {
  8.      register struct obj *otmp;
  9.      int otyp;
  10.      boolean knowoil, knowtouchstone, addpotions, addstones, addfood;
  11.  
  12.      knowoil = objects[POT_OIL].oc_name_known;
  13.      knowtouchstone = objects[TOUCHSTONE].oc_name_known;
  14.      addpotions = addstones = addfood = FALSE;
  15.      for (otmp = invent; otmp; otmp = otmp->nobj) {
  16.          otyp = otmp->otyp;
  17.          if (otyp == POT_OIL
  18.              || (otmp->oclass == POTION_CLASS
  19.                  && (!otmp->dknown
  20.                      || (!knowoil && !objects[otyp].oc_name_known))))
  21.              addpotions = TRUE;
  22.          if (otyp == TOUCHSTONE
  23.              || (is_graystone(otmp)
  24.                  && (!otmp->dknown
  25.                      || (!knowtouchstone && !objects[otyp].oc_name_known))))
  26.              addstones = TRUE;
  27.          if (otyp == CREAM_PIE || otyp == EUCALYPTUS_LEAF)
  28.              addfood = TRUE;
  29.      }
  30.  
  31.      class_list[0] = '\0';
  32.      if (addpotions || addstones)
  33.          add_class(class_list, ALL_CLASSES);
  34.      Strcat(class_list, tools);
  35.      if (addpotions)
  36.          add_class(class_list, POTION_CLASS);
  37.      if (addstones)
  38.          add_class(class_list, GEM_CLASS);
  39.      if (addfood)
  40.          add_class(class_list, FOOD_CLASS);
  41.  }
  42.  

doapply

  1.  /* the 'a' command */
  2.  int
  3.  doapply()
  4.  {
  5.      struct obj *obj;
  6.      register int res = 1;
  7.      char class_list[MAXOCLASSES + 2];
  8.  
  9.      if (check_capacity((char *) 0))
  10.          return 0;
  11.  
  12.      setapplyclasses(class_list); /* tools[] */
  13.      obj = getobj(class_list, "use or apply");
  14.      if (!obj)
  15.          return 0;
  16.  
  17.      if (!retouch_object(&obj, FALSE))
  18.          return 1; /* evading your grasp costs a turn; just be
  19.                       grateful that you don't drop it as well */
  20.  
  21.      if (obj->oclass == WAND_CLASS)
  22.          return do_break_wand(obj);
  23.  
  24.      switch (obj->otyp) {
  25.      case BLINDFOLD:
  26.      case LENSES:
  27.          if (obj == ublindf) {
  28.              if (!cursed(obj))
  29.                  Blindf_off(obj);
  30.          } else if (!ublindf) {
  31.              Blindf_on(obj);
  32.          } else {
  33.              You("are already %s.", ublindf->otyp == TOWEL
  34.                                         ? "covered by a towel"
  35.                                         : ublindf->otyp == BLINDFOLD
  36.                                               ? "wearing a blindfold"
  37.                                               : "wearing lenses");
  38.          }
  39.          break;
  40.      case CREAM_PIE:
  41.          res = use_cream_pie(obj);
  42.          break;
  43.      case BULLWHIP:
  44.          res = use_whip(obj);
  45.          break;
  46.      case GRAPPLING_HOOK:
  47.          res = use_grapple(obj);
  48.          break;
  49.      case LARGE_BOX:
  50.      case CHEST:
  51.      case ICE_BOX:
  52.      case SACK:
  53.      case BAG_OF_HOLDING:
  54.      case OILSKIN_SACK:
  55.          res = use_container(&obj, 1);
  56.          break;
  57.      case BAG_OF_TRICKS:
  58.          (void) bagotricks(obj, FALSE, (int *) 0);
  59.          break;
  60.      case CAN_OF_GREASE:
  61.          use_grease(obj);
  62.          break;
  63.      case LOCK_PICK:
  64.      case CREDIT_CARD:
  65.      case SKELETON_KEY:
  66.          res = (pick_lock(obj) != 0);
  67.          break;
  68.      case PICK_AXE:
  69.      case DWARVISH_MATTOCK:
  70.          res = use_pick_axe(obj);
  71.          break;
  72.      case TINNING_KIT:
  73.          use_tinning_kit(obj);
  74.          break;
  75.      case LEASH:
  76.          use_leash(obj);
  77.          break;
  78.      case SADDLE:
  79.          res = use_saddle(obj);
  80.          break;
  81.      case MAGIC_WHISTLE:
  82.          use_magic_whistle(obj);
  83.          break;
  84.      case TIN_WHISTLE:
  85.          use_whistle(obj);
  86.          break;
  87.      case EUCALYPTUS_LEAF:
  88.          /* MRKR: Every Australian knows that a gum leaf makes an excellent
  89.           * whistle, especially if your pet is a tame kangaroo named Skippy.
  90.           */
  91.          if (obj->blessed) {
  92.              use_magic_whistle(obj);
  93.              /* sometimes the blessing will be worn off */
  94.              if (!rn2(49)) {
  95.                  if (!Blind) {
  96.                      pline("%s %s.", Yobjnam2(obj, "glow"), hcolor("brown"));
  97.                      obj->bknown = 1;
  98.                  }
  99.                  unbless(obj);
  100.              }
  101.          } else {
  102.              use_whistle(obj);
  103.          }
  104.          break;
  105.      case STETHOSCOPE:
  106.          res = use_stethoscope(obj);
  107.          break;
  108.      case MIRROR:
  109.          res = use_mirror(obj);
  110.          break;
  111.      case BELL:
  112.      case BELL_OF_OPENING:
  113.          use_bell(&obj);
  114.          break;
  115.      case CANDELABRUM_OF_INVOCATION:
  116.          use_candelabrum(obj);
  117.          break;
  118.      case WAX_CANDLE:
  119.      case TALLOW_CANDLE:
  120.          use_candle(&obj);
  121.          break;
  122.      case OIL_LAMP:
  123.      case MAGIC_LAMP:
  124.      case BRASS_LANTERN:
  125.          use_lamp(obj);
  126.          break;
  127.      case POT_OIL:
  128.          light_cocktail(obj);
  129.          break;
  130.      case EXPENSIVE_CAMERA:
  131.          res = use_camera(obj);
  132.          break;
  133.      case TOWEL:
  134.          res = use_towel(obj);
  135.          break;
  136.      case CRYSTAL_BALL:
  137.          use_crystal_ball(&obj);
  138.          break;
  139.      case MAGIC_MARKER:
  140.          res = dowrite(obj);
  141.          break;
  142.      case TIN_OPENER:
  143.          if (!carrying(TIN)) {
  144.              You("have no tin to open.");
  145.              goto xit;
  146.          }
  147.          You("cannot open a tin without eating or discarding its contents.");
  148.          if (flags.verbose)
  149.              pline("In order to eat, use the 'e' command.");
  150.          if (obj != uwep)
  151.              pline(
  152.            "Opening the tin will be much easier if you wield the tin opener.");
  153.          goto xit;
  154.  
  155.      case FIGURINE:
  156.          use_figurine(&obj);
  157.          break;
  158.      case UNICORN_HORN:
  159.          use_unicorn_horn(obj);
  160.          break;
  161.      case WOODEN_FLUTE:
  162.      case MAGIC_FLUTE:
  163.      case TOOLED_HORN:
  164.      case FROST_HORN:
  165.      case FIRE_HORN:
  166.      case WOODEN_HARP:
  167.      case MAGIC_HARP:
  168.      case BUGLE:
  169.      case LEATHER_DRUM:
  170.      case DRUM_OF_EARTHQUAKE:
  171.          res = do_play_instrument(obj);
  172.          break;
  173.      case HORN_OF_PLENTY: /* not a musical instrument */
  174.          (void) hornoplenty(obj, FALSE);
  175.          break;
  176.      case LAND_MINE:
  177.      case BEARTRAP:
  178.          use_trap(obj);
  179.          break;
  180.      case FLINT:
  181.      case LUCKSTONE:
  182.      case LOADSTONE:
  183.      case TOUCHSTONE:
  184.          use_stone(obj);
  185.          break;
  186.      default:
  187.          /* Pole-weapons can strike at a distance */
  188.          if (is_pole(obj)) {
  189.              res = use_pole(obj);
  190.              break;
  191.          } else if (is_pick(obj) || is_axe(obj)) {
  192.              res = use_pick_axe(obj);
  193.              break;
  194.          }
  195.          pline("Sorry, I don't know how to use that.");
  196.      xit:
  197.          nomul(0);
  198.          return 0;
  199.      }
  200.      if (res && obj && obj->oartifact)
  201.          arti_speak(obj);
  202.      nomul(0);
  203.      return res;
  204.  }
  205.  

unfixable_trouble_count

  1.  /* Keep track of unfixable troubles for purposes of messages saying you feel
  2.   * great.
  3.   */
  4.  int
  5.  unfixable_trouble_count(is_horn)
  6.  boolean is_horn;
  7.  {
  8.      int unfixable_trbl = 0;
  9.  
  10.      if (Stoned)
  11.          unfixable_trbl++;
  12.      if (Strangled)
  13.          unfixable_trbl++;
  14.      if (Wounded_legs && !u.usteed)
  15.          unfixable_trbl++;
  16.      if (Slimed)
  17.          unfixable_trbl++;
  18.      /* lycanthropy is undesirable, but it doesn't actually make you feel bad */
  19.  
  20.      if (!is_horn || (Confusion & ~TIMEOUT))
  21.          unfixable_trbl++;
  22.      if (!is_horn || (Sick & ~TIMEOUT))
  23.          unfixable_trbl++;
  24.      if (!is_horn || (HHallucination & ~TIMEOUT))
  25.          unfixable_trbl++;
  26.      if (!is_horn || (Vomiting & ~TIMEOUT))
  27.          unfixable_trbl++;
  28.      if (!is_horn || (HStun & ~TIMEOUT))
  29.          unfixable_trbl++;
  30.      if (!is_horn || (HDeaf & ~TIMEOUT))
  31.          unfixable_trbl++;
  32.  
  33.      return unfixable_trbl;
  34.  }
  35.  
  36.  /*apply.c*/