Source:NetHack 3.6.1/src/potion.c

From NetHackWiki
(Redirected from Source:Ref/make confused)
Jump to: navigation, search

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

Top of file

  1.  /* NetHack 3.6	potion.c	$NHDT-Date: 1520797133 2018/03/11 19:38:53 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.144 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /*-Copyright (c) Robert Patrick Rankin, 2013. */
  4.  /* NetHack may be freely redistributed.  See license for details. */

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.

  1.  
  2.  #include "hack.h"
  3.  
  4.  boolean notonhead = FALSE;
  5.  
  6.  static NEARDATA int nothing, unkn;
  7.  static NEARDATA const char beverages[] = { POTION_CLASS, 0 };
  8.  
  9.  STATIC_DCL long FDECL(itimeout, (long));
  10.  STATIC_DCL long FDECL(itimeout_incr, (long, int));
  11.  STATIC_DCL void NDECL(ghost_from_bottle);
  12.  STATIC_DCL boolean
  13.  FDECL(H2Opotion_dip, (struct obj *, struct obj *, BOOLEAN_P, const char *));
  14.  STATIC_DCL short FDECL(mixtype, (struct obj *, struct obj *));
  15.  

itimeout

  1.  /* force `val' to be within valid range for intrinsic timeout value */
  2.  STATIC_OVL long
  3.  itimeout(val)
  4.  long val;
  5.  {
  6.      if (val >= TIMEOUT)
  7.          val = TIMEOUT;
  8.      else if (val < 1)
  9.          val = 0;
  10.  
  11.      return val;
  12.  }
  13.  

itimeout_incr

  1.  /* increment `old' by `incr' and force result to be valid intrinsic timeout */
  2.  STATIC_OVL long
  3.  itimeout_incr(old, incr)
  4.  long old;
  5.  int incr;
  6.  {
  7.      return itimeout((old & TIMEOUT) + (long) incr);
  8.  }
  9.  

set_itimeout

  1.  /* set the timeout field of intrinsic `which' */
  2.  void
  3.  set_itimeout(which, val)
  4.  long *which, val;
  5.  {
  6.      *which &= ~TIMEOUT;
  7.      *which |= itimeout(val);
  8.  }
  9.  

incr_itimeout

  1.  /* increment the timeout field of intrinsic `which' */
  2.  void
  3.  incr_itimeout(which, incr)
  4.  long *which;
  5.  int incr;
  6.  {
  7.      set_itimeout(which, itimeout_incr(*which, incr));
  8.  }
  9.  

make_confused

  1.  void
  2.  make_confused(xtime, talk)
  3.  long xtime;
  4.  boolean talk;
  5.  {
  6.      long old = HConfusion;
  7.  
  8.      if (Unaware)
  9.          talk = FALSE;
  10.  
  11.      if (!xtime && old) {
  12.          if (talk)
  13.              You_feel("less %s now.", Hallucination ? "trippy" : "confused");
  14.      }
  15.      if ((xtime && !old) || (!xtime && old))
  16.          context.botl = TRUE;
  17.  
  18.      set_itimeout(&HConfusion, xtime);
  19.  }
  20.  

make_stunned

  1.  void
  2.  make_stunned(xtime, talk)
  3.  long xtime;
  4.  boolean talk;
  5.  {
  6.      long old = HStun;
  7.  
  8.      if (Unaware)
  9.          talk = FALSE;
  10.  
  11.      if (!xtime && old) {
  12.          if (talk)
  13.              You_feel("%s now.",
  14.                       Hallucination ? "less wobbly" : "a bit steadier");
  15.      }
  16.      if (xtime && !old) {
  17.          if (talk) {
  18.              if (u.usteed)
  19.                  You("wobble in the saddle.");
  20.              else
  21.                  You("%s...", stagger(youmonst.data, "stagger"));
  22.          }
  23.      }
  24.      if ((!xtime && old) || (xtime && !old))
  25.          context.botl = TRUE;
  26.  
  27.      set_itimeout(&HStun, xtime);
  28.  }
  29.  

make_sick

  1.  void
  2.  make_sick(xtime, cause, talk, type)
  3.  long xtime;
  4.  const char *cause; /* sickness cause */
  5.  boolean talk;
  6.  int type;
  7.  {
  8.      long old = Sick;
  9.  
  10.  #if 0
  11.      if (Unaware)
  12.          talk = FALSE;
  13.  #endif
  14.      if (xtime > 0L) {
  15.          if (Sick_resistance)
  16.              return;
  17.          if (!old) {
  18.              /* newly sick */
  19.              You_feel("deathly sick.");
  20.          } else {
  21.              /* already sick */
  22.              if (talk)
  23.                  You_feel("%s worse.", xtime <= Sick / 2L ? "much" : "even");
  24.          }
  25.          set_itimeout(&Sick, xtime);
  26.          u.usick_type |= type;
  27.          context.botl = TRUE;
  28.      } else if (old && (type & u.usick_type)) {
  29.          /* was sick, now not */
  30.          u.usick_type &= ~type;
  31.          if (u.usick_type) { /* only partly cured */
  32.              if (talk)
  33.                  You_feel("somewhat better.");
  34.              set_itimeout(&Sick, Sick * 2); /* approximation */
  35.          } else {
  36.              if (talk)
  37.                  You_feel("cured.  What a relief!");
  38.              Sick = 0L; /* set_itimeout(&Sick, 0L) */
  39.          }
  40.          context.botl = TRUE;
  41.      }
  42.  
  43.      if (Sick) {
  44.          exercise(A_CON, FALSE);
  45.          delayed_killer(SICK, KILLED_BY_AN, cause);
  46.      } else
  47.          dealloc_killer(find_delayed_killer(SICK));
  48.  }
  49.  

make_slimed

  1.  void
  2.  make_slimed(xtime, msg)
  3.  long xtime;
  4.  const char *msg;
  5.  {
  6.      long old = Slimed;
  7.  
  8.  #if 0
  9.      if (Unaware)
  10.          msg = 0;
  11.  #endif
  12.      set_itimeout(&Slimed, xtime);
  13.      if ((xtime != 0L) ^ (old != 0L)) {
  14.          context.botl = TRUE;
  15.          if (msg)
  16.              pline1(msg);
  17.      }
  18.      if (!Slimed)
  19.          dealloc_killer(find_delayed_killer(SLIMED));
  20.  }
  21.  

make_stoned

  1.  /* start or stop petrification */
  2.  void
  3.  make_stoned(xtime, msg, killedby, killername)
  4.  long xtime;
  5.  const char *msg;
  6.  int killedby;
  7.  const char *killername;
  8.  {
  9.      long old = Stoned;
  10.  
  11.  #if 0
  12.      if (Unaware)
  13.          msg = 0;
  14.  #endif
  15.      set_itimeout(&Stoned, xtime);
  16.      if ((xtime != 0L) ^ (old != 0L)) {
  17.          context.botl = TRUE;
  18.          if (msg)
  19.              pline1(msg);
  20.      }
  21.      if (!Stoned)
  22.          dealloc_killer(find_delayed_killer(STONED));
  23.      else if (!old)
  24.          delayed_killer(STONED, killedby, killername);
  25.  }
  26.  

make_vomiting

  1.  void
  2.  make_vomiting(xtime, talk)
  3.  long xtime;
  4.  boolean talk;
  5.  {
  6.      long old = Vomiting;
  7.  
  8.      if (Unaware)
  9.          talk = FALSE;
  10.  
  11.      set_itimeout(&Vomiting, xtime);
  12.      context.botl = TRUE;
  13.      if (!xtime && old)
  14.          if (talk)
  15.              You_feel("much less nauseated now.");
  16.  }
  17.  
  18.  static const char vismsg[] = "vision seems to %s for a moment but is %s now.";
  19.  static const char eyemsg[] = "%s momentarily %s.";
  20.  

make_blinded

  1.  void
  2.  make_blinded(xtime, talk)
  3.  long xtime;
  4.  boolean talk;
  5.  {
  6.      long old = Blinded;
  7.      boolean u_could_see, can_see_now;
  8.      const char *eyes;
  9.  
  10.      /* we need to probe ahead in case the Eyes of the Overworld
  11.         are or will be overriding blindness */
  12.      u_could_see = !Blind;
  13.      Blinded = xtime ? 1L : 0L;
  14.      can_see_now = !Blind;
  15.      Blinded = old; /* restore */
  16.  
  17.      if (Unaware)
  18.          talk = FALSE;
  19.  
  20.      if (can_see_now && !u_could_see) { /* regaining sight */
  21.          if (talk) {
  22.              if (Hallucination)
  23.                  pline("Far out!  Everything is all cosmic again!");
  24.              else
  25.                  You("can see again.");
  26.          }
  27.      } else if (old && !xtime) {
  28.          /* clearing temporary blindness without toggling blindness */
  29.          if (talk) {
  30.              if (!haseyes(youmonst.data)) {
  31.                  strange_feeling((struct obj *) 0, (char *) 0);
  32.              } else if (Blindfolded) {
  33.                  eyes = body_part(EYE);
  34.                  if (eyecount(youmonst.data) != 1)
  35.                      eyes = makeplural(eyes);
  36.                  Your(eyemsg, eyes, vtense(eyes, "itch"));
  37.              } else { /* Eyes of the Overworld */
  38.                  Your(vismsg, "brighten", Hallucination ? "sadder" : "normal");
  39.              }
  40.          }
  41.      }
  42.  
  43.      if (u_could_see && !can_see_now) { /* losing sight */
  44.          if (talk) {
  45.              if (Hallucination)
  46.                  pline("Oh, bummer!  Everything is dark!  Help!");
  47.              else
  48.                  pline("A cloud of darkness falls upon you.");
  49.          }
  50.          /* Before the hero goes blind, set the ball&chain variables. */
  51.          if (Punished)
  52.              set_bc(0);
  53.      } else if (!old && xtime) {
  54.          /* setting temporary blindness without toggling blindness */
  55.          if (talk) {
  56.              if (!haseyes(youmonst.data)) {
  57.                  strange_feeling((struct obj *) 0, (char *) 0);
  58.              } else if (Blindfolded) {
  59.                  eyes = body_part(EYE);
  60.                  if (eyecount(youmonst.data) != 1)
  61.                      eyes = makeplural(eyes);
  62.                  Your(eyemsg, eyes, vtense(eyes, "twitch"));
  63.              } else { /* Eyes of the Overworld */
  64.                  Your(vismsg, "dim", Hallucination ? "happier" : "normal");
  65.              }
  66.          }
  67.      }
  68.  
  69.      set_itimeout(&Blinded, xtime);
  70.  
  71.      if (u_could_see ^ can_see_now) { /* one or the other but not both */
  72.          context.botl = TRUE;
  73.          vision_full_recalc = 1; /* blindness just got toggled */
  74.          /* this vision recalculation used to be deferred until
  75.             moveloop(), but that made it possible for vision
  76.             irregularities to occur (cited case was force bolt
  77.             hitting adjacent potion of blindness and then a
  78.             secret door; hero was blinded by vapors but then
  79.             got the message "a door appears in the wall") */
  80.          vision_recalc(0);
  81.          if (Blind_telepat || Infravision)
  82.              see_monsters();
  83.  
  84.          /* avoid either of the sequences
  85.             "Sting starts glowing", [become blind], "Sting stops quivering" or
  86.             "Sting starts quivering", [regain sight], "Sting stops glowing"
  87.             by giving "Sting is quivering" when becoming blind or
  88.             "Sting is glowing" when regaining sight so that the eventual
  89.             "stops" message matches */
  90.          if (warn_obj_cnt && uwep && (EWarn_of_mon & W_WEP) != 0L)
  91.              Sting_effects(-1);
  92.          /* update dknown flag for inventory picked up while blind */
  93.          if (can_see_now)
  94.              learn_unseen_invent();
  95.      }
  96.  }
  97.  

make_hallucinated

  1.  boolean
  2.  make_hallucinated(xtime, talk, mask)
  3.  long xtime; /* nonzero if this is an attempt to turn on hallucination */
  4.  boolean talk;
  5.  long mask; /* nonzero if resistance status should change by mask */
  6.  {
  7.      long old = HHallucination;
  8.      boolean changed = 0;
  9.      const char *message, *verb;
  10.  
  11.      if (Unaware)
  12.          talk = FALSE;
  13.  
  14.      message = (!xtime) ? "Everything %s SO boring now."
  15.                         : "Oh wow!  Everything %s so cosmic!";
  16.      verb = (!Blind) ? "looks" : "feels";
  17.  
  18.      if (mask) {
  19.          if (HHallucination)
  20.              changed = TRUE;
  21.  
  22.          if (!xtime)
  23.              EHalluc_resistance |= mask;
  24.          else
  25.              EHalluc_resistance &= ~mask;
  26.      } else {
  27.          if (!EHalluc_resistance && (!!HHallucination != !!xtime))
  28.              changed = TRUE;
  29.          set_itimeout(&HHallucination, xtime);
  30.  
  31.          /* clearing temporary hallucination without toggling vision */
  32.          if (!changed && !HHallucination && old && talk) {
  33.              if (!haseyes(youmonst.data)) {
  34.                  strange_feeling((struct obj *) 0, (char *) 0);
  35.              } else if (Blind) {
  36.                  const char *eyes = body_part(EYE);
  37.  
  38.                  if (eyecount(youmonst.data) != 1)
  39.                      eyes = makeplural(eyes);
  40.                  Your(eyemsg, eyes, vtense(eyes, "itch"));
  41.              } else { /* Grayswandir */
  42.                  Your(vismsg, "flatten", "normal");
  43.              }
  44.          }
  45.      }
  46.  
  47.      if (changed) {
  48.          /* in case we're mimicking an orange (hallucinatory form
  49.             of mimicking gold) update the mimicking's-over message */
  50.          if (!Hallucination)
  51.              eatmupdate();
  52.  
  53.          if (u.uswallow) {
  54.              swallowed(0); /* redraw swallow display */
  55.          } else {
  56.              /* The see_* routines should be called *before* the pline. */
  57.              see_monsters();
  58.              see_objects();
  59.              see_traps();
  60.          }
  61.  
  62.          /* for perm_inv and anything similar
  63.          (eg. Qt windowport's equipped items display) */
  64.          update_inventory();
  65.  
  66.          context.botl = TRUE;
  67.          if (talk)
  68.              pline(message, verb);
  69.      }
  70.      return changed;
  71.  }
  72.  

make_deaf

  1.  void
  2.  make_deaf(xtime, talk)
  3.  long xtime;
  4.  boolean talk;
  5.  {
  6.      long old = HDeaf;
  7.  
  8.      if (Unaware)
  9.          talk = FALSE;
  10.  
  11.      set_itimeout(&HDeaf, xtime);
  12.      if ((xtime != 0L) ^ (old != 0L)) {
  13.          context.botl = TRUE;
  14.          if (talk)
  15.              You(old ? "can hear again." : "are unable to hear anything.");
  16.      }
  17.  }
  18.  

self_invis_message

  1.  void
  2.  self_invis_message()
  3.  {
  4.      pline("%s %s.",
  5.            Hallucination ? "Far out, man!  You"
  6.                          : "Gee!  All of a sudden, you",
  7.            See_invisible ? "can see right through yourself"
  8.                          : "can't see yourself");
  9.  }
  10.  

ghost_from_bottle

  1.  STATIC_OVL void
  2.  ghost_from_bottle()
  3.  {
  4.      struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS);
  5.  
  6.      if (!mtmp) {
  7.          pline("This bottle turns out to be empty.");
  8.          return;
  9.      }
  10.      if (Blind) {
  11.          pline("As you open the bottle, %s emerges.", something);
  12.          return;
  13.      }
  14.      pline("As you open the bottle, an enormous %s emerges!",
  15.            Hallucination ? rndmonnam(NULL) : (const char *) "ghost");
  16.      if (flags.verbose)
  17.          You("are frightened to death, and unable to move.");
  18.      nomul(-3);
  19.      multi_reason = "being frightened to death";
  20.      nomovemsg = "You regain your composure.";
  21.  }
  22.  

dodrink

  1.  /* "Quaffing is like drinking, except you spill more." - Terry Pratchett */
  2.  int
  3.  dodrink()
  4.  {
  5.      register struct obj *otmp;
  6.      const char *potion_descr;
  7.  
  8.      if (Strangled) {
  9.          pline("If you can't breathe air, how can you drink liquid?");
  10.          return 0;
  11.      }
  12.      /* Is there a fountain to drink from here? */
  13.      if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)
  14.          /* not as low as floor level but similar restrictions apply */
  15.          && can_reach_floor(FALSE)) {
  16.          if (yn("Drink from the fountain?") == 'y') {
  17.              drinkfountain();
  18.              return 1;
  19.          }
  20.      }
  21.      /* Or a kitchen sink? */
  22.      if (IS_SINK(levl[u.ux][u.uy].typ)
  23.          /* not as low as floor level but similar restrictions apply */
  24.          && can_reach_floor(FALSE)) {
  25.          if (yn("Drink from the sink?") == 'y') {
  26.              drinksink();
  27.              return 1;
  28.          }
  29.      }
  30.      /* Or are you surrounded by water? */
  31.      if (Underwater && !u.uswallow) {
  32.          if (yn("Drink the water around you?") == 'y') {
  33.              pline("Do you know what lives in this water?");
  34.              return 1;
  35.          }
  36.      }
  37.  
  38.      otmp = getobj(beverages, "drink");
  39.      if (!otmp)
  40.          return 0;
  41.  
  42.      /* quan > 1 used to be left to useup(), but we need to force
  43.         the current potion to be unworn, and don't want to do
  44.         that for the entire stack when starting with more than 1.
  45.         [Drinking a wielded potion of polymorph can trigger a shape
  46.         change which causes hero's weapon to be dropped.  In 3.4.x,
  47.         that led to an "object lost" panic since subsequent useup()
  48.         was no longer dealing with an inventory item.  Unwearing
  49.         the current potion is intended to keep it in inventory.] */
  50.      if (otmp->quan > 1L) {
  51.          otmp = splitobj(otmp, 1L);
  52.          otmp->owornmask = 0L; /* rest of original stuck unaffected */
  53.      } else if (otmp->owornmask) {
  54.          remove_worn_item(otmp, FALSE);
  55.      }
  56.      otmp->in_use = TRUE; /* you've opened the stopper */
  57.  
  58.      potion_descr = OBJ_DESCR(objects[otmp->otyp]);
  59.      if (potion_descr) {
  60.          if (!strcmp(potion_descr, "milky")
  61.              && !(mvitals[PM_GHOST].mvflags & G_GONE)
  62.              && !rn2(POTION_OCCUPANT_CHANCE(mvitals[PM_GHOST].born))) {
  63.              ghost_from_bottle();
  64.              useup(otmp);
  65.              return 1;
  66.          } else if (!strcmp(potion_descr, "smoky")
  67.                     && !(mvitals[PM_DJINNI].mvflags & G_GONE)
  68.                     && !rn2(POTION_OCCUPANT_CHANCE(mvitals[PM_DJINNI].born))) {
  69.              djinni_from_bottle(otmp);
  70.              useup(otmp);
  71.              return 1;
  72.          }
  73.      }
  74.      return dopotion(otmp);
  75.  }
  76.  

dopotion

  1.  int
  2.  dopotion(otmp)
  3.  register struct obj *otmp;
  4.  {
  5.      int retval;
  6.  
  7.      otmp->in_use = TRUE;
  8.      nothing = unkn = 0;
  9.      if ((retval = peffects(otmp)) >= 0)
  10.          return retval;
  11.  
  12.      if (nothing) {
  13.          unkn++;
  14.          You("have a %s feeling for a moment, then it passes.",
  15.              Hallucination ? "normal" : "peculiar");
  16.      }
  17.      if (otmp->dknown && !objects[otmp->otyp].oc_name_known) {
  18.          if (!unkn) {
  19.              makeknown(otmp->otyp);
  20.              more_experienced(0, 10);
  21.          } else if (!objects[otmp->otyp].oc_uname)
  22.              docall(otmp);
  23.      }
  24.      useup(otmp);
  25.      return 1;
  26.  }
  27.  

peffects

  1.  int
  2.  peffects(otmp)
  3.  register struct obj *otmp;
  4.  {
  5.      register int i, ii, lim;
  6.  
  7.      switch (otmp->otyp) {
  8.      case POT_RESTORE_ABILITY:
  9.      case SPE_RESTORE_ABILITY:
  10.          unkn++;
  11.          if (otmp->cursed) {
  12.              pline("Ulch!  This makes you feel mediocre!");
  13.              break;
  14.          } else {
  15.              /* unlike unicorn horn, overrides Fixed_abil */
  16.              pline("Wow!  This makes you feel %s!",
  17.                    (otmp->blessed)
  18.                        ? (unfixable_trouble_count(FALSE) ? "better" : "great")
  19.                        : "good");
  20.              i = rn2(A_MAX); /* start at a random point */
  21.              for (ii = 0; ii < A_MAX; ii++) {
  22.                  lim = AMAX(i);
  23.                  /* this used to adjust 'lim' for A_STR when u.uhs was
  24.                     WEAK or worse, but that's handled via ATEMP(A_STR) now */
  25.                  if (ABASE(i) < lim) {
  26.                      ABASE(i) = lim;
  27.                      context.botl = 1;
  28.                      /* only first found if not blessed */
  29.                      if (!otmp->blessed)
  30.                          break;
  31.                  }
  32.                  if (++i >= A_MAX)
  33.                      i = 0;
  34.              }
  35.  
  36.              /* when using the potion (not the spell) also restore lost levels,
  37.                 to make the potion more worth keeping around for players with
  38.                 the spell or with a unihorn; this is better than full healing
  39.                 in that it can restore all of them, not just half, and a
  40.                 blessed potion restores them all at once */
  41.              if (otmp->otyp == POT_RESTORE_ABILITY &&
  42.                  u.ulevel < u.ulevelmax) {
  43.                  do {
  44.                      pluslvl(FALSE);
  45.                  } while (u.ulevel < u.ulevelmax && otmp->blessed);
  46.              }
  47.          }
  48.          break;
  49.      case POT_HALLUCINATION:
  50.          if (Hallucination || Halluc_resistance)
  51.              nothing++;
  52.          (void) make_hallucinated(
  53.              itimeout_incr(HHallucination, rn1(200, 600 - 300 * bcsign(otmp))),
  54.              TRUE, 0L);
  55.          break;
  56.      case POT_WATER:
  57.          if (!otmp->blessed && !otmp->cursed) {
  58.              pline("This tastes like %s.", hliquid("water"));
  59.              u.uhunger += rnd(10);
  60.              newuhs(FALSE);
  61.              break;
  62.          }
  63.          unkn++;
  64.          if (is_undead(youmonst.data) || is_demon(youmonst.data)
  65.              || u.ualign.type == A_CHAOTIC) {
  66.              if (otmp->blessed) {
  67.                  pline("This burns like %s!", hliquid("acid"));
  68.                  exercise(A_CON, FALSE);
  69.                  if (u.ulycn >= LOW_PM) {
  70.                      Your("affinity to %s disappears!",
  71.                           makeplural(mons[u.ulycn].mname));
  72.                      if (youmonst.data == &mons[u.ulycn])
  73.                          you_unwere(FALSE);
  74.                      set_ulycn(NON_PM); /* cure lycanthropy */
  75.                  }
  76.                  losehp(Maybe_Half_Phys(d(2, 6)), "potion of holy water",
  77.                         KILLED_BY_AN);
  78.              } else if (otmp->cursed) {
  79.                  You_feel("quite proud of yourself.");
  80.                  healup(d(2, 6), 0, 0, 0);
  81.                  if (u.ulycn >= LOW_PM && !Upolyd)
  82.                      you_were();
  83.                  exercise(A_CON, TRUE);
  84.              }
  85.          } else {
  86.              if (otmp->blessed) {
  87.                  You_feel("full of awe.");
  88.                  make_sick(0L, (char *) 0, TRUE, SICK_ALL);
  89.                  exercise(A_WIS, TRUE);
  90.                  exercise(A_CON, TRUE);
  91.                  if (u.ulycn >= LOW_PM)
  92.                      you_unwere(TRUE); /* "Purified" */
  93.                  /* make_confused(0L, TRUE); */
  94.              } else {
  95.                  if (u.ualign.type == A_LAWFUL) {
  96.                      pline("This burns like %s!", hliquid("acid"));
  97.                      losehp(Maybe_Half_Phys(d(2, 6)), "potion of unholy water",
  98.                             KILLED_BY_AN);
  99.                  } else
  100.                      You_feel("full of dread.");
  101.                  if (u.ulycn >= LOW_PM && !Upolyd)
  102.                      you_were();
  103.                  exercise(A_CON, FALSE);
  104.              }
  105.          }
  106.          break;
  107.      case POT_BOOZE:
  108.          unkn++;
  109.          pline("Ooph!  This tastes like %s%s!",
  110.                otmp->odiluted ? "watered down " : "",
  111.                Hallucination ? "dandelion wine" : "liquid fire");
  112.          if (!otmp->blessed)
  113.              make_confused(itimeout_incr(HConfusion, d(3, 8)), FALSE);
  114.          /* the whiskey makes us feel better */
  115.          if (!otmp->odiluted)
  116.              healup(1, 0, FALSE, FALSE);
  117.          u.uhunger += 10 * (2 + bcsign(otmp));
  118.          newuhs(FALSE);
  119.          exercise(A_WIS, FALSE);
  120.          if (otmp->cursed) {
  121.              You("pass out.");
  122.              multi = -rnd(15);
  123.              nomovemsg = "You awake with a headache.";
  124.          }
  125.          break;
  126.      case POT_ENLIGHTENMENT:
  127.          if (otmp->cursed) {
  128.              unkn++;
  129.              You("have an uneasy feeling...");
  130.              exercise(A_WIS, FALSE);
  131.          } else {
  132.              if (otmp->blessed) {
  133.                  (void) adjattrib(A_INT, 1, FALSE);
  134.                  (void) adjattrib(A_WIS, 1, FALSE);
  135.              }
  136.              You_feel("self-knowledgeable...");
  137.              display_nhwindow(WIN_MESSAGE, FALSE);
  138.              enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
  139.              pline_The("feeling subsides.");
  140.              exercise(A_WIS, TRUE);
  141.          }
  142.          break;
  143.      case SPE_INVISIBILITY:
  144.          /* spell cannot penetrate mummy wrapping */
  145.          if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
  146.              You_feel("rather itchy under %s.", yname(uarmc));
  147.              break;
  148.          }
  149.          /* FALLTHRU */
  150.      case POT_INVISIBILITY:
  151.          if (Invis || Blind || BInvis) {
  152.              nothing++;
  153.          } else {
  154.              self_invis_message();
  155.          }
  156.          if (otmp->blessed)
  157.              HInvis |= FROMOUTSIDE;
  158.          else
  159.              incr_itimeout(&HInvis, rn1(15, 31));
  160.          newsym(u.ux, u.uy); /* update position */
  161.          if (otmp->cursed) {
  162.              pline("For some reason, you feel your presence is known.");
  163.              aggravate();
  164.          }
  165.          break;
  166.      case POT_SEE_INVISIBLE: /* tastes like fruit juice in Rogue */
  167.      case POT_FRUIT_JUICE: {
  168.          int msg = Invisible && !Blind;
  169.  
  170.          unkn++;
  171.          if (otmp->cursed)
  172.              pline("Yecch!  This tastes %s.",
  173.                    Hallucination ? "overripe" : "rotten");
  174.          else
  175.              pline(
  176.                  Hallucination
  177.                      ? "This tastes like 10%% real %s%s all-natural beverage."
  178.                      : "This tastes like %s%s.",
  179.                  otmp->odiluted ? "reconstituted " : "", fruitname(TRUE));
  180.          if (otmp->otyp == POT_FRUIT_JUICE) {
  181.              u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp));
  182.              newuhs(FALSE);
  183.              break;
  184.          }
  185.          if (!otmp->cursed) {
  186.              /* Tell them they can see again immediately, which
  187.               * will help them identify the potion...
  188.               */
  189.              make_blinded(0L, TRUE);
  190.          }
  191.          if (otmp->blessed)
  192.              HSee_invisible |= FROMOUTSIDE;
  193.          else
  194.              incr_itimeout(&HSee_invisible, rn1(100, 750));
  195.          set_mimic_blocking(); /* do special mimic handling */
  196.          see_monsters();       /* see invisible monsters */
  197.          newsym(u.ux, u.uy);   /* see yourself! */
  198.          if (msg && !Blind) {  /* Blind possible if polymorphed */
  199.              You("can see through yourself, but you are visible!");
  200.              unkn--;
  201.          }
  202.          break;
  203.      }
  204.      case POT_PARALYSIS:
  205.          if (Free_action) {
  206.              You("stiffen momentarily.");
  207.          } else {
  208.              if (Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
  209.                  You("are motionlessly suspended.");
  210.              else if (u.usteed)
  211.                  You("are frozen in place!");
  212.              else
  213.                  Your("%s are frozen to the %s!", makeplural(body_part(FOOT)),
  214.                       surface(u.ux, u.uy));
  215.              nomul(-(rn1(10, 25 - 12 * bcsign(otmp))));
  216.              multi_reason = "frozen by a potion";
  217.              nomovemsg = You_can_move_again;
  218.              exercise(A_DEX, FALSE);
  219.          }
  220.          break;
  221.      case POT_SLEEPING:
  222.          if (Sleep_resistance || Free_action) {
  223.              You("yawn.");
  224.          } else {
  225.              You("suddenly fall asleep!");
  226.              fall_asleep(-rn1(10, 25 - 12 * bcsign(otmp)), TRUE);
  227.          }
  228.          break;
  229.      case POT_MONSTER_DETECTION:
  230.      case SPE_DETECT_MONSTERS:
  231.          if (otmp->blessed) {
  232.              int x, y;
  233.  
  234.              if (Detect_monsters)
  235.                  nothing++;
  236.              unkn++;
  237.              /* after a while, repeated uses become less effective */
  238.              if ((HDetect_monsters & TIMEOUT) >= 300L)
  239.                  i = 1;
  240.              else
  241.                  i = rn1(40, 21);
  242.              incr_itimeout(&HDetect_monsters, i);
  243.              for (x = 1; x < COLNO; x++) {
  244.                  for (y = 0; y < ROWNO; y++) {
  245.                      if (levl[x][y].glyph == GLYPH_INVISIBLE) {
  246.                          unmap_object(x, y);
  247.                          newsym(x, y);
  248.                      }
  249.                      if (MON_AT(x, y))
  250.                          unkn = 0;
  251.                  }
  252.              }
  253.              see_monsters();
  254.              if (unkn)
  255.                  You_feel("lonely.");
  256.              break;
  257.          }
  258.          if (monster_detect(otmp, 0))
  259.              return 1; /* nothing detected */
  260.          exercise(A_WIS, TRUE);
  261.          break;
  262.      case POT_OBJECT_DETECTION:
  263.      case SPE_DETECT_TREASURE:
  264.          if (object_detect(otmp, 0))
  265.              return 1; /* nothing detected */
  266.          exercise(A_WIS, TRUE);
  267.          break;
  268.      case POT_SICKNESS:
  269.          pline("Yecch!  This stuff tastes like poison.");
  270.          if (otmp->blessed) {
  271.              pline("(But in fact it was mildly stale %s.)", fruitname(TRUE));
  272.              if (!Role_if(PM_HEALER)) {
  273.                  /* NB: blessed otmp->fromsink is not possible */
  274.                  losehp(1, "mildly contaminated potion", KILLED_BY_AN);
  275.              }
  276.          } else {
  277.              if (Poison_resistance)
  278.                  pline("(But in fact it was biologically contaminated %s.)",
  279.                        fruitname(TRUE));
  280.              if (Role_if(PM_HEALER)) {
  281.                  pline("Fortunately, you have been immunized.");
  282.              } else {
  283.                  char contaminant[BUFSZ];
  284.                  int typ = rn2(A_MAX);
  285.  
  286.                  Sprintf(contaminant, "%s%s",
  287.                          (Poison_resistance) ? "mildly " : "",
  288.                          (otmp->fromsink) ? "contaminated tap water"
  289.                                           : "contaminated potion");
  290.                  if (!Fixed_abil) {
  291.                      poisontell(typ, FALSE);
  292.                      (void) adjattrib(typ, Poison_resistance ? -1 : -rn1(4, 3),
  293.                                       1);
  294.                  }
  295.                  if (!Poison_resistance) {
  296.                      if (otmp->fromsink)
  297.                          losehp(rnd(10) + 5 * !!(otmp->cursed), contaminant,
  298.                                 KILLED_BY);
  299.                      else
  300.                          losehp(rnd(10) + 5 * !!(otmp->cursed), contaminant,
  301.                                 KILLED_BY_AN);
  302.                  } else {
  303.                      /* rnd loss is so that unblessed poorer than blessed */
  304.                      losehp(1 + rn2(2), contaminant,
  305.                             (otmp->fromsink) ? KILLED_BY : KILLED_BY_AN);
  306.                  }
  307.                  exercise(A_CON, FALSE);
  308.              }
  309.          }
  310.          if (Hallucination) {
  311.              You("are shocked back to your senses!");
  312.              (void) make_hallucinated(0L, FALSE, 0L);
  313.          }
  314.          break;
  315.      case POT_CONFUSION:
  316.          if (!Confusion) {
  317.              if (Hallucination) {
  318.                  pline("What a trippy feeling!");
  319.                  unkn++;
  320.              } else
  321.                  pline("Huh, What?  Where am I?");
  322.          } else
  323.              nothing++;
  324.          make_confused(itimeout_incr(HConfusion,
  325.                                      rn1(7, 16 - 8 * bcsign(otmp))),
  326.                        FALSE);
  327.          break;
  328.      case POT_GAIN_ABILITY:
  329.          if (otmp->cursed) {
  330.              pline("Ulch!  That potion tasted foul!");
  331.              unkn++;
  332.          } else if (Fixed_abil) {
  333.              nothing++;
  334.          } else {      /* If blessed, increase all; if not, try up to */
  335.              int itmp; /* 6 times to find one which can be increased. */
  336.  
  337.              i = -1;   /* increment to 0 */
  338.              for (ii = A_MAX; ii > 0; ii--) {
  339.                  i = (otmp->blessed ? i + 1 : rn2(A_MAX));
  340.                  /* only give "your X is already as high as it can get"
  341.                     message on last attempt (except blessed potions) */
  342.                  itmp = (otmp->blessed || ii == 1) ? 0 : -1;
  343.                  if (adjattrib(i, 1, itmp) && !otmp->blessed)
  344.                      break;
  345.              }
  346.          }
  347.          break;
  348.      case POT_SPEED:
  349.          if (Wounded_legs && !otmp->cursed && !u.usteed) {
  350.              /* heal_legs() would heal steeds legs */
  351.              heal_legs();
  352.              unkn++;
  353.              break;
  354.          }
  355.          /* FALLTHRU */
  356.      case SPE_HASTE_SELF:
  357.          if (!Very_fast) { /* wwf@doe.carleton.ca */
  358.              You("are suddenly moving %sfaster.", Fast ? "" : "much ");
  359.          } else {
  360.              Your("%s get new energy.", makeplural(body_part(LEG)));
  361.              unkn++;
  362.          }
  363.          exercise(A_DEX, TRUE);
  364.          incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp)));
  365.          break;
  366.      case POT_BLINDNESS:
  367.          if (Blind)
  368.              nothing++;
  369.          make_blinded(itimeout_incr(Blinded,
  370.                                     rn1(200, 250 - 125 * bcsign(otmp))),
  371.                       (boolean) !Blind);
  372.          break;
  373.      case POT_GAIN_LEVEL:
  374.          if (otmp->cursed) {
  375.              unkn++;
  376.              /* they went up a level */
  377.              if ((ledger_no(&u.uz) == 1 && u.uhave.amulet)
  378.                  || Can_rise_up(u.ux, u.uy, &u.uz)) {
  379.                  const char *riseup = "rise up, through the %s!";
  380.  
  381.                  if (ledger_no(&u.uz) == 1) {
  382.                      You(riseup, ceiling(u.ux, u.uy));
  383.                      goto_level(&earth_level, FALSE, FALSE, FALSE);
  384.                  } else {
  385.                      register int newlev = depth(&u.uz) - 1;
  386.                      d_level newlevel;
  387.  
  388.                      get_level(&newlevel, newlev);
  389.                      if (on_level(&newlevel, &u.uz)) {
  390.                          pline("It tasted bad.");
  391.                          break;
  392.                      } else
  393.                          You(riseup, ceiling(u.ux, u.uy));
  394.                      goto_level(&newlevel, FALSE, FALSE, FALSE);
  395.                  }
  396.              } else
  397.                  You("have an uneasy feeling.");
  398.              break;
  399.          }
  400.          pluslvl(FALSE);
  401.          /* blessed potions place you at a random spot in the
  402.             middle of the new level instead of the low point */
  403.          if (otmp->blessed)
  404.              u.uexp = rndexp(TRUE);
  405.          break;
  406.      case POT_HEALING:
  407.          You_feel("better.");
  408.          healup(d(6 + 2 * bcsign(otmp), 4), !otmp->cursed ? 1 : 0,
  409.                 !!otmp->blessed, !otmp->cursed);
  410.          exercise(A_CON, TRUE);
  411.          break;
  412.      case POT_EXTRA_HEALING:
  413.          You_feel("much better.");
  414.          healup(d(6 + 2 * bcsign(otmp), 8),
  415.                 otmp->blessed ? 5 : !otmp->cursed ? 2 : 0, !otmp->cursed,
  416.                 TRUE);
  417.          (void) make_hallucinated(0L, TRUE, 0L);
  418.          exercise(A_CON, TRUE);
  419.          exercise(A_STR, TRUE);
  420.          break;
  421.      case POT_FULL_HEALING:
  422.          You_feel("completely healed.");
  423.          healup(400, 4 + 4 * bcsign(otmp), !otmp->cursed, TRUE);
  424.          /* Restore one lost level if blessed */
  425.          if (otmp->blessed && u.ulevel < u.ulevelmax) {
  426.              /* when multiple levels have been lost, drinking
  427.                 multiple potions will only get half of them back */
  428.              u.ulevelmax -= 1;
  429.              pluslvl(FALSE);
  430.          }
  431.          (void) make_hallucinated(0L, TRUE, 0L);
  432.          exercise(A_STR, TRUE);
  433.          exercise(A_CON, TRUE);
  434.          break;
  435.      case POT_LEVITATION:
  436.      case SPE_LEVITATION:
  437.          /*
  438.           * BLevitation will be set if levitation is blocked due to being
  439.           * inside rock (currently or formerly in phazing xorn form, perhaps)
  440.           * but it doesn't prevent setting or incrementing Levitation timeout
  441.           * (which will take effect after escaping from the rock if it hasn't
  442.           * expired by then).
  443.           */
  444.          if (!Levitation && !BLevitation) {
  445.              /* kludge to ensure proper operation of float_up() */
  446.              set_itimeout(&HLevitation, 1L);
  447.              float_up();
  448.              /* This used to set timeout back to 0, then increment it below
  449.                 for blessed and uncursed effects.  But now we leave it so
  450.                 that cursed effect yields "you float down" on next turn.
  451.                 Blessed and uncursed get one extra turn duration. */
  452.          } else /* already levitating, or can't levitate */
  453.              nothing++;
  454.  
  455.          if (otmp->cursed) {
  456.              /* 'already levitating' used to block the cursed effect(s)
  457.                 aside from ~I_SPECIAL; it was not clear whether that was
  458.                 intentional; either way, it no longer does (as of 3.6.1) */
  459.              HLevitation &= ~I_SPECIAL; /* can't descend upon demand */
  460.              if (BLevitation) {
  461.                  ; /* rising via levitation is blocked */
  462.              } else if ((u.ux == xupstair && u.uy == yupstair)
  463.                      || (sstairs.up && u.ux == sstairs.sx && u.uy == sstairs.sy)
  464.                      || (xupladder && u.ux == xupladder && u.uy == yupladder)) {
  465.                  (void) doup();
  466.                  /* in case we're already Levitating, which would have
  467.                     resulted in incrementing 'nothing' */
  468.                  nothing = 0; /* not nothing after all */
  469.              } else if (has_ceiling(&u.uz)) {
  470.                  int dmg = rnd(!uarmh ? 10 : !is_metallic(uarmh) ? 6 : 3);
  471.  
  472.                  You("hit your %s on the %s.", body_part(HEAD),
  473.                      ceiling(u.ux, u.uy));
  474.                  losehp(Maybe_Half_Phys(dmg), "colliding with the ceiling",
  475.                         KILLED_BY);
  476.                  nothing = 0; /* not nothing after all */
  477.              }
  478.          } else if (otmp->blessed) {
  479.              /* at this point, timeout is already at least 1 */
  480.              incr_itimeout(&HLevitation, rn1(50, 250));
  481.              /* can descend at will (stop levitating via '>') provided timeout
  482.                 is the only factor (ie, not also wearing Lev ring or boots) */
  483.              HLevitation |= I_SPECIAL;
  484.          } else /* timeout is already at least 1 */
  485.              incr_itimeout(&HLevitation, rn1(140, 10));
  486.  
  487.          if (Levitation && IS_SINK(levl[u.ux][u.uy].typ))
  488.              spoteffects(FALSE);
  489.          /* levitating blocks flying */
  490.          float_vs_flight();
  491.          break;
  492.      case POT_GAIN_ENERGY: { /* M. Stephenson */
  493.          int num;
  494.  
  495.          if (otmp->cursed)
  496.              You_feel("lackluster.");
  497.          else
  498.              pline("Magical energies course through your body.");
  499.  
  500.          /* old: num = rnd(5) + 5 * otmp->blessed + 1;
  501.           *      blessed:  +7..11 max & current (+9 avg)
  502.           *      uncursed: +2.. 6 max & current (+4 avg)
  503.           *      cursed:   -2.. 6 max & current (-4 avg)
  504.           * new: (3.6.0)
  505.           *      blessed:  +3..18 max (+10.5 avg), +9..54 current (+31.5 avg)
  506.           *      uncursed: +2..12 max (+ 7   avg), +6..36 current (+21   avg)
  507.           *      cursed:   -1.. 6 max (- 3.5 avg), -3..18 current (-10.5 avg)
  508.           */
  509.          num = d(otmp->blessed ? 3 : !otmp->cursed ? 2 : 1, 6);
  510.          if (otmp->cursed)
  511.              num = -num; /* subtract instead of add when cursed */
  512.          u.uenmax += num;
  513.          if (u.uenmax <= 0)
  514.              u.uenmax = 0;
  515.          u.uen += 3 * num;
  516.          if (u.uen > u.uenmax)
  517.              u.uen = u.uenmax;
  518.          else if (u.uen <= 0)
  519.              u.uen = 0;
  520.          context.botl = 1;
  521.          exercise(A_WIS, TRUE);
  522.          break;
  523.      }
  524.      case POT_OIL: { /* P. Winner */
  525.          boolean good_for_you = FALSE;
  526.  
  527.          if (otmp->lamplit) {
  528.              if (likes_fire(youmonst.data)) {
  529.                  pline("Ahh, a refreshing drink.");
  530.                  good_for_you = TRUE;
  531.              } else {
  532.                  You("burn your %s.", body_part(FACE));
  533.                  /* fire damage */
  534.                  losehp(d(Fire_resistance ? 1 : 3, 4), "burning potion of oil",
  535.                         KILLED_BY_AN);
  536.              }
  537.          } else if (otmp->cursed)
  538.              pline("This tastes like castor oil.");
  539.          else
  540.              pline("That was smooth!");
  541.          exercise(A_WIS, good_for_you);
  542.          break;
  543.      }
  544.      case POT_ACID:
  545.          if (Acid_resistance) {
  546.              /* Not necessarily a creature who _likes_ acid */
  547.              pline("This tastes %s.", Hallucination ? "tangy" : "sour");
  548.          } else {
  549.              int dmg;
  550.  
  551.              pline("This burns%s!",
  552.                    otmp->blessed ? " a little" : otmp->cursed ? " a lot"
  553.                                                               : " like acid");
  554.              dmg = d(otmp->cursed ? 2 : 1, otmp->blessed ? 4 : 8);
  555.              losehp(Maybe_Half_Phys(dmg), "potion of acid", KILLED_BY_AN);
  556.              exercise(A_CON, FALSE);
  557.          }
  558.          if (Stoned)
  559.              fix_petrification();
  560.          unkn++; /* holy/unholy water can burn like acid too */
  561.          break;
  562.      case POT_POLYMORPH:
  563.          You_feel("a little %s.", Hallucination ? "normal" : "strange");
  564.          if (!Unchanging)
  565.              polyself(0);
  566.          break;
  567.      default:
  568.          impossible("What a funny potion! (%u)", otmp->otyp);
  569.          return 0;
  570.      }
  571.      return -1;
  572.  }
  573.  

healup

  1.  void
  2.  healup(nhp, nxtra, curesick, cureblind)
  3.  int nhp, nxtra;
  4.  register boolean curesick, cureblind;
  5.  {
  6.      if (nhp) {
  7.          if (Upolyd) {
  8.              u.mh += nhp;
  9.              if (u.mh > u.mhmax)
  10.                  u.mh = (u.mhmax += nxtra);
  11.          } else {
  12.              u.uhp += nhp;
  13.              if (u.uhp > u.uhpmax)
  14.                  u.uhp = (u.uhpmax += nxtra);
  15.          }
  16.      }
  17.      if (cureblind) {
  18.          /* 3.6.1: it's debatible whether healing magic should clean off
  19.             mundane 'dirt', but if it doesn't, blindness isn't cured */
  20.          u.ucreamed = 0;
  21.          make_blinded(0L, TRUE);
  22.      }
  23.      if (curesick) {
  24.          make_vomiting(0L, TRUE);
  25.          make_sick(0L, (char *) 0, TRUE, SICK_ALL);
  26.      }
  27.      context.botl = 1;
  28.      return;
  29.  }
  30.  

strange_feeling

  1.  void
  2.  strange_feeling(obj, txt)
  3.  struct obj *obj;
  4.  const char *txt;
  5.  {
  6.      if (flags.beginner || !txt)
  7.          You("have a %s feeling for a moment, then it passes.",
  8.              Hallucination ? "normal" : "strange");
  9.      else
  10.          pline1(txt);
  11.  
  12.      if (!obj) /* e.g., crystal ball finds no traps */
  13.          return;
  14.  
  15.      if (obj->dknown && !objects[obj->otyp].oc_name_known
  16.          && !objects[obj->otyp].oc_uname)
  17.          docall(obj);
  18.  
  19.      useup(obj);
  20.  }
  21.  
  22.  const char *bottlenames[] = { "bottle", "phial", "flagon", "carafe",
  23.                                "flask",  "jar",   "vial" };
  24.  

bottlename

  1.  const char *
  2.  bottlename()
  3.  {
  4.      return bottlenames[rn2(SIZE(bottlenames))];
  5.  }
  6.  

H2Opotion_dip

  1.  /* handle item dipped into water potion or steed saddle splashed by same */
  2.  STATIC_OVL boolean
  3.  H2Opotion_dip(potion, targobj, useeit, objphrase)
  4.  struct obj *potion, *targobj;
  5.  boolean useeit;
  6.  const char *objphrase; /* "Your widget glows" or "Steed's saddle glows" */
  7.  {
  8.      void FDECL((*func), (OBJ_P)) = 0;
  9.      const char *glowcolor = 0;
  10.  #define COST_alter (-2)
  11.  #define COST_none (-1)
  12.      int costchange = COST_none;
  13.      boolean altfmt = FALSE, res = FALSE;
  14.  
  15.      if (!potion || potion->otyp != POT_WATER)
  16.          return FALSE;
  17.  
  18.      if (potion->blessed) {
  19.          if (targobj->cursed) {
  20.              func = uncurse;
  21.              glowcolor = NH_AMBER;
  22.              costchange = COST_UNCURS;
  23.          } else if (!targobj->blessed) {
  24.              func = bless;
  25.              glowcolor = NH_LIGHT_BLUE;
  26.              costchange = COST_alter;
  27.              altfmt = TRUE; /* "with a <color> aura" */
  28.          }
  29.      } else if (potion->cursed) {
  30.          if (targobj->blessed) {
  31.              func = unbless;
  32.              glowcolor = "brown";
  33.              costchange = COST_UNBLSS;
  34.          } else if (!targobj->cursed) {
  35.              func = curse;
  36.              glowcolor = NH_BLACK;
  37.              costchange = COST_alter;
  38.              altfmt = TRUE;
  39.          }
  40.      } else {
  41.          /* dipping into uncursed water; carried() check skips steed saddle */
  42.          if (carried(targobj)) {
  43.              if (water_damage(targobj, 0, TRUE) != ER_NOTHING)
  44.                  res = TRUE;
  45.          }
  46.      }
  47.      if (func) {
  48.          /* give feedback before altering the target object;
  49.             this used to set obj->bknown even when not seeing
  50.             the effect; now hero has to see the glow, and bknown
  51.             is cleared instead of set if perception is distorted */
  52.          if (useeit) {
  53.              glowcolor = hcolor(glowcolor);
  54.              if (altfmt)
  55.                  pline("%s with %s aura.", objphrase, an(glowcolor));
  56.              else
  57.                  pline("%s %s.", objphrase, glowcolor);
  58.              iflags.last_msg = PLNMSG_OBJ_GLOWS;
  59.              targobj->bknown = !Hallucination;
  60.          }
  61.          /* potions of water are the only shop goods whose price depends
  62.             on their curse/bless state */
  63.          if (targobj->unpaid && targobj->otyp == POT_WATER) {
  64.              if (costchange == COST_alter)
  65.                  /* added blessing or cursing; update shop
  66.                     bill to reflect item's new higher price */
  67.                  alter_cost(targobj, 0L);
  68.              else if (costchange != COST_none)
  69.                  /* removed blessing or cursing; you
  70.                     degraded it, now you'll have to buy it... */
  71.                  costly_alteration(targobj, costchange);
  72.          }
  73.          /* finally, change curse/bless state */
  74.          (*func)(targobj);
  75.          res = TRUE;
  76.      }
  77.      return res;
  78.  }
  79.  

potionhit

  1.  /* potion obj hits monster mon, which might be youmonst; obj always used up */
  2.  void
  3.  potionhit(mon, obj, how)
  4.  struct monst *mon;
  5.  struct obj *obj;
  6.  int how;
  7.  {
  8.      const char *botlnam = bottlename();
  9.      boolean isyou = (mon == &youmonst);
  10.      int distance, tx, ty;
  11.      struct obj *saddle = (struct obj *) 0;
  12.      boolean hit_saddle = FALSE, your_fault = (how <= POTHIT_HERO_THROW);
  13.  
  14.      if (isyou) {
  15.          tx = u.ux, ty = u.uy;
  16.          distance = 0;
  17.          pline_The("%s crashes on your %s and breaks into shards.", botlnam,
  18.                    body_part(HEAD));
  19.          losehp(Maybe_Half_Phys(rnd(2)),
  20.                 (how == POTHIT_OTHER_THROW) ? "propelled potion" /* scatter */
  21.                                             : "thrown potion",
  22.                 KILLED_BY_AN);
  23.      } else {
  24.          tx = mon->mx, ty = mon->my;
  25.          /* sometimes it hits the saddle */
  26.          if (((mon->misc_worn_check & W_SADDLE)
  27.               && (saddle = which_armor(mon, W_SADDLE)))
  28.              && (!rn2(10)
  29.                  || (obj->otyp == POT_WATER
  30.                      && ((rnl(10) > 7 && obj->cursed)
  31.                          || (rnl(10) < 4 && obj->blessed) || !rn2(3)))))
  32.              hit_saddle = TRUE;
  33.          distance = distu(tx, ty);
  34.          if (!cansee(tx, ty)) {
  35.              pline("Crash!");
  36.          } else {
  37.              char *mnam = mon_nam(mon);
  38.              char buf[BUFSZ];
  39.  
  40.              if (hit_saddle && saddle) {
  41.                  Sprintf(buf, "%s saddle",
  42.                          s_suffix(x_monnam(mon, ARTICLE_THE, (char *) 0,
  43.                                            (SUPPRESS_IT | SUPPRESS_SADDLE),
  44.                                            FALSE)));
  45.              } else if (has_head(mon->data)) {
  46.                  Sprintf(buf, "%s %s", s_suffix(mnam),
  47.                          (notonhead ? "body" : "head"));
  48.              } else {
  49.                  Strcpy(buf, mnam);
  50.              }
  51.              pline_The("%s crashes on %s and breaks into shards.", botlnam,
  52.                        buf);
  53.          }
  54.          if (rn2(5) && mon->mhp > 1 && !hit_saddle)
  55.              mon->mhp--;
  56.      }
  57.  
  58.      /* oil doesn't instantly evaporate; Neither does a saddle hit */
  59.      if (obj->otyp != POT_OIL && !hit_saddle && cansee(tx, ty))
  60.          pline("%s.", Tobjnam(obj, "evaporate"));
  61.  
  62.      if (isyou) {
  63.          switch (obj->otyp) {
  64.          case POT_OIL:
  65.              if (obj->lamplit)
  66.                  explode_oil(obj, u.ux, u.uy);
  67.              break;
  68.          case POT_POLYMORPH:
  69.              You_feel("a little %s.", Hallucination ? "normal" : "strange");
  70.              if (!Unchanging && !Antimagic)
  71.                  polyself(0);
  72.              break;
  73.          case POT_ACID:
  74.              if (!Acid_resistance) {
  75.                  int dmg;
  76.  
  77.                  pline("This burns%s!",
  78.                        obj->blessed ? " a little"
  79.                                     : obj->cursed ? " a lot" : "");
  80.                  dmg = d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
  81.                  losehp(Maybe_Half_Phys(dmg), "potion of acid", KILLED_BY_AN);
  82.              }
  83.              break;
  84.          }
  85.      } else if (hit_saddle && saddle) {
  86.          char *mnam, buf[BUFSZ], saddle_glows[BUFSZ];
  87.          boolean affected = FALSE;
  88.          boolean useeit = !Blind && canseemon(mon) && cansee(tx, ty);
  89.  
  90.          mnam = x_monnam(mon, ARTICLE_THE, (char *) 0,
  91.                          (SUPPRESS_IT | SUPPRESS_SADDLE), FALSE);
  92.          Sprintf(buf, "%s", upstart(s_suffix(mnam)));
  93.  
  94.          switch (obj->otyp) {
  95.          case POT_WATER:
  96.              Sprintf(saddle_glows, "%s %s", buf, aobjnam(saddle, "glow"));
  97.              affected = H2Opotion_dip(obj, saddle, useeit, saddle_glows);
  98.              break;
  99.          case POT_POLYMORPH:
  100.              /* Do we allow the saddle to polymorph? */
  101.              break;
  102.          }
  103.          if (useeit && !affected)
  104.              pline("%s %s wet.", buf, aobjnam(saddle, "get"));
  105.      } else {
  106.          boolean angermon = your_fault, cureblind = FALSE;
  107.  
  108.          switch (obj->otyp) {
  109.          case POT_FULL_HEALING:
  110.              cureblind = TRUE;
  111.              /*FALLTHRU*/
  112.          case POT_EXTRA_HEALING:
  113.              if (!obj->cursed)
  114.                  cureblind = TRUE;
  115.              /*FALLTHRU*/
  116.          case POT_HEALING:
  117.              if (obj->blessed)
  118.                  cureblind = TRUE;
  119.              if (mon->data == &mons[PM_PESTILENCE])
  120.                  goto do_illness;
  121.              /*FALLTHRU*/
  122.          case POT_RESTORE_ABILITY:
  123.          case POT_GAIN_ABILITY:
  124.          do_healing:
  125.              angermon = FALSE;
  126.              if (mon->mhp < mon->mhpmax) {
  127.                  mon->mhp = mon->mhpmax;
  128.                  if (canseemon(mon))
  129.                      pline("%s looks sound and hale again.", Monnam(mon));
  130.              }
  131.              if (cureblind)
  132.                  mcureblindness(mon, canseemon(mon));
  133.              break;
  134.          case POT_SICKNESS:
  135.              if (mon->data == &mons[PM_PESTILENCE])
  136.                  goto do_healing;
  137.              if (dmgtype(mon->data, AD_DISE)
  138.                  /* won't happen, see prior goto */
  139.                  || dmgtype(mon->data, AD_PEST)
  140.                  /* most common case */
  141.                  || resists_poison(mon)) {
  142.                  if (canseemon(mon))
  143.                      pline("%s looks unharmed.", Monnam(mon));
  144.                  break;
  145.              }
  146.          do_illness:
  147.              if ((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
  148.                  mon->mhpmax /= 2;
  149.              if ((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
  150.                  mon->mhp /= 2;
  151.              if (mon->mhp > mon->mhpmax)
  152.                  mon->mhp = mon->mhpmax;
  153.              if (canseemon(mon))
  154.                  pline("%s looks rather ill.", Monnam(mon));
  155.              break;
  156.          case POT_CONFUSION:
  157.          case POT_BOOZE:
  158.              if (!resist(mon, POTION_CLASS, 0, NOTELL))
  159.                  mon->mconf = TRUE;
  160.              break;
  161.          case POT_INVISIBILITY: {
  162.              boolean sawit = canspotmon(mon);
  163.  
  164.              angermon = FALSE;
  165.              mon_set_minvis(mon);
  166.              if (sawit && !canspotmon(mon) && cansee(mon->mx, mon->my))
  167.                  map_invisible(mon->mx, mon->my);
  168.              break;
  169.          }
  170.          case POT_SLEEPING:
  171.              /* wakeup() doesn't rouse victims of temporary sleep */
  172.              if (sleep_monst(mon, rnd(12), POTION_CLASS)) {
  173.                  pline("%s falls asleep.", Monnam(mon));
  174.                  slept_monst(mon);
  175.              }
  176.              break;
  177.          case POT_PARALYSIS:
  178.              if (mon->mcanmove) {
  179.                  /* really should be rnd(5) for consistency with players
  180.                   * breathing potions, but...
  181.                   */
  182.                  paralyze_monst(mon, rnd(25));
  183.              }
  184.              break;
  185.          case POT_SPEED:
  186.              angermon = FALSE;
  187.              mon_adjust_speed(mon, 1, obj);
  188.              break;
  189.          case POT_BLINDNESS:
  190.              if (haseyes(mon->data)) {
  191.                  int btmp = 64 + rn2(32)
  192.                              + rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
  193.  
  194.                  btmp += mon->mblinded;
  195.                  mon->mblinded = min(btmp, 127);
  196.                  mon->mcansee = 0;
  197.              }
  198.              break;
  199.          case POT_WATER:
  200.              if (is_undead(mon->data) || is_demon(mon->data)
  201.                  || is_were(mon->data) || is_vampshifter(mon)) {
  202.                  if (obj->blessed) {
  203.                      pline("%s %s in pain!", Monnam(mon),
  204.                            is_silent(mon->data) ? "writhes" : "shrieks");
  205.                      if (!is_silent(mon->data))
  206.                          wake_nearto(tx, ty, mon->data->mlevel * 10);
  207.                      mon->mhp -= d(2, 6);
  208.                      /* should only be by you */
  209.                      if (mon->mhp < 1)
  210.                          killed(mon);
  211.                      else if (is_were(mon->data) && !is_human(mon->data))
  212.                          new_were(mon); /* revert to human */
  213.                  } else if (obj->cursed) {
  214.                      angermon = FALSE;
  215.                      if (canseemon(mon))
  216.                          pline("%s looks healthier.", Monnam(mon));
  217.                      mon->mhp += d(2, 6);
  218.                      if (mon->mhp > mon->mhpmax)
  219.                          mon->mhp = mon->mhpmax;
  220.                      if (is_were(mon->data) && is_human(mon->data)
  221.                          && !Protection_from_shape_changers)
  222.                          new_were(mon); /* transform into beast */
  223.                  }
  224.              } else if (mon->data == &mons[PM_GREMLIN]) {
  225.                  angermon = FALSE;
  226.                  (void) split_mon(mon, (struct monst *) 0);
  227.              } else if (mon->data == &mons[PM_IRON_GOLEM]) {
  228.                  if (canseemon(mon))
  229.                      pline("%s rusts.", Monnam(mon));
  230.                  mon->mhp -= d(1, 6);
  231.                  /* should only be by you */
  232.                  if (mon->mhp < 1)
  233.                      killed(mon);
  234.              }
  235.              break;
  236.          case POT_OIL:
  237.              if (obj->lamplit)
  238.                  explode_oil(obj, tx, ty);
  239.              break;
  240.          case POT_ACID:
  241.              if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) {
  242.                  pline("%s %s in pain!", Monnam(mon),
  243.                        is_silent(mon->data) ? "writhes" : "shrieks");
  244.                  if (!is_silent(mon->data))
  245.                      wake_nearto(tx, ty, mon->data->mlevel * 10);
  246.                  mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
  247.                  if (mon->mhp < 1) {
  248.                      if (your_fault)
  249.                          killed(mon);
  250.                      else
  251.                          monkilled(mon, "", AD_ACID);
  252.                  }
  253.              }
  254.              break;
  255.          case POT_POLYMORPH:
  256.              (void) bhitm(mon, obj);
  257.              break;
  258.          /*
  259.          case POT_GAIN_LEVEL:
  260.          case POT_LEVITATION:
  261.          case POT_FRUIT_JUICE:
  262.          case POT_MONSTER_DETECTION:
  263.          case POT_OBJECT_DETECTION:
  264.              break;
  265.          */
  266.          }
  267.          /* target might have been killed */
  268.          if (mon->mhp > 0) {
  269.              if (angermon)
  270.                  wakeup(mon, TRUE);
  271.              else
  272.                  mon->msleeping = 0;
  273.          }
  274.      }
  275.  
  276.      /* Note: potionbreathe() does its own docall() */
  277.      if ((distance == 0 || (distance < 3 && rn2(5)))
  278.          && (!breathless(youmonst.data) || haseyes(youmonst.data)))
  279.          potionbreathe(obj);
  280.      else if (obj->dknown && !objects[obj->otyp].oc_name_known
  281.               && !objects[obj->otyp].oc_uname && cansee(tx, ty))
  282.          docall(obj);
  283.  
  284.      if (*u.ushops && obj->unpaid) {
  285.          struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
  286.  
  287.          /* neither of the first two cases should be able to happen;
  288.             only the hero should ever have an unpaid item, and only
  289.             when inside a tended shop */
  290.          if (!shkp) /* if shkp was killed, unpaid ought to cleared already */
  291.              obj->unpaid = 0;
  292.          else if (context.mon_moving) /* obj thrown by monster */
  293.              subfrombill(obj, shkp);
  294.          else /* obj thrown by hero */
  295.              (void) stolen_value(obj, u.ux, u.uy, (boolean) shkp->mpeaceful,
  296.                                  FALSE);
  297.      }
  298.      obfree(obj, (struct obj *) 0);
  299.  }
  300.  

potionbreathe

  1.  /* vapors are inhaled or get in your eyes */
  2.  void
  3.  potionbreathe(obj)
  4.  register struct obj *obj;
  5.  {
  6.      int i, ii, isdone, kn = 0;
  7.      boolean cureblind = FALSE;
  8.  
  9.      /* potion of unholy water might be wielded; prevent
  10.         you_were() -> drop_weapon() from dropping it so that it
  11.         remains in inventory where our caller expects it to be */
  12.      obj->in_use = 1;
  13.  
  14.      switch (obj->otyp) {
  15.      case POT_RESTORE_ABILITY:
  16.      case POT_GAIN_ABILITY:
  17.          if (obj->cursed) {
  18.              if (!breathless(youmonst.data))
  19.                  pline("Ulch!  That potion smells terrible!");
  20.              else if (haseyes(youmonst.data)) {
  21.                  const char *eyes = body_part(EYE);
  22.  
  23.                  if (eyecount(youmonst.data) != 1)
  24.                      eyes = makeplural(eyes);
  25.                  Your("%s %s!", eyes, vtense(eyes, "sting"));
  26.              }
  27.              break;
  28.          } else {
  29.              i = rn2(A_MAX); /* start at a random point */
  30.              for (isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
  31.                  if (ABASE(i) < AMAX(i)) {
  32.                      ABASE(i)++;
  33.                      /* only first found if not blessed */
  34.                      isdone = !(obj->blessed);
  35.                      context.botl = 1;
  36.                  }
  37.                  if (++i >= A_MAX)
  38.                      i = 0;
  39.              }
  40.          }
  41.          break;
  42.      case POT_FULL_HEALING:
  43.          if (Upolyd && u.mh < u.mhmax)
  44.              u.mh++, context.botl = 1;
  45.          if (u.uhp < u.uhpmax)
  46.              u.uhp++, context.botl = 1;
  47.          cureblind = TRUE;
  48.          /*FALLTHRU*/
  49.      case POT_EXTRA_HEALING:
  50.          if (Upolyd && u.mh < u.mhmax)
  51.              u.mh++, context.botl = 1;
  52.          if (u.uhp < u.uhpmax)
  53.              u.uhp++, context.botl = 1;
  54.          if (!obj->cursed)
  55.              cureblind = TRUE;
  56.          /*FALLTHRU*/
  57.      case POT_HEALING:
  58.          if (Upolyd && u.mh < u.mhmax)
  59.              u.mh++, context.botl = 1;
  60.          if (u.uhp < u.uhpmax)
  61.              u.uhp++, context.botl = 1;
  62.          if (obj->blessed)
  63.              cureblind = TRUE;
  64.          if (cureblind)
  65.              make_blinded(0L, !u.ucreamed);
  66.          exercise(A_CON, TRUE);
  67.          break;
  68.      case POT_SICKNESS:
  69.          if (!Role_if(PM_HEALER)) {
  70.              if (Upolyd) {
  71.                  if (u.mh <= 5)
  72.                      u.mh = 1;
  73.                  else
  74.                      u.mh -= 5;
  75.              } else {
  76.                  if (u.uhp <= 5)
  77.                      u.uhp = 1;
  78.                  else
  79.                      u.uhp -= 5;
  80.              }
  81.              context.botl = 1;
  82.              exercise(A_CON, FALSE);
  83.          }
  84.          break;
  85.      case POT_HALLUCINATION:
  86.          You("have a momentary vision.");
  87.          break;
  88.      case POT_CONFUSION:
  89.      case POT_BOOZE:
  90.          if (!Confusion)
  91.              You_feel("somewhat dizzy.");
  92.          make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE);
  93.          break;
  94.      case POT_INVISIBILITY:
  95.          if (!Blind && !Invis) {
  96.              kn++;
  97.              pline("For an instant you %s!",
  98.                    See_invisible ? "could see right through yourself"
  99.                                  : "couldn't see yourself");
  100.          }
  101.          break;
  102.      case POT_PARALYSIS:
  103.          kn++;
  104.          if (!Free_action) {
  105.              pline("%s seems to be holding you.", Something);
  106.              nomul(-rnd(5));
  107.              multi_reason = "frozen by a potion";
  108.              nomovemsg = You_can_move_again;
  109.              exercise(A_DEX, FALSE);
  110.          } else
  111.              You("stiffen momentarily.");
  112.          break;
  113.      case POT_SLEEPING:
  114.          kn++;
  115.          if (!Free_action && !Sleep_resistance) {
  116.              You_feel("rather tired.");
  117.              nomul(-rnd(5));
  118.              multi_reason = "sleeping off a magical draught";
  119.              nomovemsg = You_can_move_again;
  120.              exercise(A_DEX, FALSE);
  121.          } else
  122.              You("yawn.");
  123.          break;
  124.      case POT_SPEED:
  125.          if (!Fast)
  126.              Your("knees seem more flexible now.");
  127.          incr_itimeout(&HFast, rnd(5));
  128.          exercise(A_DEX, TRUE);
  129.          break;
  130.      case POT_BLINDNESS:
  131.          if (!Blind && !Unaware) {
  132.              kn++;
  133.              pline("It suddenly gets dark.");
  134.          }
  135.          make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE);
  136.          if (!Blind && !Unaware)
  137.              Your1(vision_clears);
  138.          break;
  139.      case POT_WATER:
  140.          if (u.umonnum == PM_GREMLIN) {
  141.              (void) split_mon(&youmonst, (struct monst *) 0);
  142.          } else if (u.ulycn >= LOW_PM) {
  143.              /* vapor from [un]holy water will trigger
  144.                 transformation but won't cure lycanthropy */
  145.              if (obj->blessed && youmonst.data == &mons[u.ulycn])
  146.                  you_unwere(FALSE);
  147.              else if (obj->cursed && !Upolyd)
  148.                  you_were();
  149.          }
  150.          break;
  151.      case POT_ACID:
  152.      case POT_POLYMORPH:
  153.          exercise(A_CON, FALSE);
  154.          break;
  155.      /*
  156.      case POT_GAIN_LEVEL:
  157.      case POT_LEVITATION:
  158.      case POT_FRUIT_JUICE:
  159.      case POT_MONSTER_DETECTION:
  160.      case POT_OBJECT_DETECTION:
  161.      case POT_OIL:
  162.          break;
  163.       */
  164.      }
  165.      /* note: no obfree() -- that's our caller's responsibility */
  166.      if (obj->dknown) {
  167.          if (kn)
  168.              makeknown(obj->otyp);
  169.          else if (!objects[obj->otyp].oc_name_known
  170.                   && !objects[obj->otyp].oc_uname)
  171.              docall(obj);
  172.      }
  173.  }
  174.  

mixtype

  1.  /* returns the potion type when o1 is dipped in o2 */
  2.  STATIC_OVL short
  3.  mixtype(o1, o2)
  4.  register struct obj *o1, *o2;
  5.  {
  6.      /* cut down on the number of cases below */
  7.      if (o1->oclass == POTION_CLASS
  8.          && (o2->otyp == POT_GAIN_LEVEL || o2->otyp == POT_GAIN_ENERGY
  9.              || o2->otyp == POT_HEALING || o2->otyp == POT_EXTRA_HEALING
  10.              || o2->otyp == POT_FULL_HEALING || o2->otyp == POT_ENLIGHTENMENT
  11.              || o2->otyp == POT_FRUIT_JUICE)) {
  12.          struct obj *swp;
  13.  
  14.          swp = o1;
  15.          o1 = o2;
  16.          o2 = swp;
  17.      }
  18.  
  19.      switch (o1->otyp) {
  20.      case POT_HEALING:
  21.          switch (o2->otyp) {
  22.          case POT_SPEED:
  23.          case POT_GAIN_LEVEL:
  24.          case POT_GAIN_ENERGY:
  25.              return POT_EXTRA_HEALING;
  26.          }
  27.      case POT_EXTRA_HEALING:
  28.          switch (o2->otyp) {
  29.          case POT_GAIN_LEVEL:
  30.          case POT_GAIN_ENERGY:
  31.              return POT_FULL_HEALING;
  32.          }
  33.      case POT_FULL_HEALING:
  34.          switch (o2->otyp) {
  35.          case POT_GAIN_LEVEL:
  36.          case POT_GAIN_ENERGY:
  37.              return POT_GAIN_ABILITY;
  38.          }
  39.      case UNICORN_HORN:
  40.          switch (o2->otyp) {
  41.          case POT_SICKNESS:
  42.              return POT_FRUIT_JUICE;
  43.          case POT_HALLUCINATION:
  44.          case POT_BLINDNESS:
  45.          case POT_CONFUSION:
  46.              return POT_WATER;
  47.          }
  48.          break;
  49.      case AMETHYST: /* "a-methyst" == "not intoxicated" */
  50.          if (o2->otyp == POT_BOOZE)
  51.              return POT_FRUIT_JUICE;
  52.          break;
  53.      case POT_GAIN_LEVEL:
  54.      case POT_GAIN_ENERGY:
  55.          switch (o2->otyp) {
  56.          case POT_CONFUSION:
  57.              return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT);
  58.          case POT_HEALING:
  59.              return POT_EXTRA_HEALING;
  60.          case POT_EXTRA_HEALING:
  61.              return POT_FULL_HEALING;
  62.          case POT_FULL_HEALING:
  63.              return POT_GAIN_ABILITY;
  64.          case POT_FRUIT_JUICE:
  65.              return POT_SEE_INVISIBLE;
  66.          case POT_BOOZE:
  67.              return POT_HALLUCINATION;
  68.          }
  69.          break;
  70.      case POT_FRUIT_JUICE:
  71.          switch (o2->otyp) {
  72.          case POT_SICKNESS:
  73.              return POT_SICKNESS;
  74.          case POT_ENLIGHTENMENT:
  75.          case POT_SPEED:
  76.              return POT_BOOZE;
  77.          case POT_GAIN_LEVEL:
  78.          case POT_GAIN_ENERGY:
  79.              return POT_SEE_INVISIBLE;
  80.          }
  81.          break;
  82.      case POT_ENLIGHTENMENT:
  83.          switch (o2->otyp) {
  84.          case POT_LEVITATION:
  85.              if (rn2(3))
  86.                  return POT_GAIN_LEVEL;
  87.              break;
  88.          case POT_FRUIT_JUICE:
  89.              return POT_BOOZE;
  90.          case POT_BOOZE:
  91.              return POT_CONFUSION;
  92.          }
  93.          break;
  94.      }
  95.  
  96.      return STRANGE_OBJECT;
  97.  }
  98.  

dodip

  1.  /* #dip command */
  2.  int
  3.  dodip()
  4.  {
  5.      static const char Dip_[] = "Dip ";
  6.      register struct obj *potion, *obj;
  7.      struct obj *singlepotion;
  8.      uchar here;
  9.      char allowall[2];
  10.      short mixture;
  11.      char qbuf[QBUFSZ], obuf[QBUFSZ];
  12.      const char *shortestname; /* last resort obj name for prompt */
  13.  
  14.      allowall[0] = ALL_CLASSES;
  15.      allowall[1] = '\0';
  16.      if (!(obj = getobj(allowall, "dip")))
  17.          return 0;
  18.      if (inaccessible_equipment(obj, "dip", FALSE))
  19.          return 0;
  20.  
  21.      shortestname = (is_plural(obj) || pair_of(obj)) ? "them" : "it";
  22.      /*
  23.       * Bypass safe_qbuf() since it doesn't handle varying suffix without
  24.       * an awful lot of support work.  Format the object once, even though
  25.       * the fountain and pool prompts offer a lot more room for it.
  26.       * 3.6.0 used thesimpleoname() unconditionally, which posed no risk
  27.       * of buffer overflow but drew bug reports because it omits user-
  28.       * supplied type name.
  29.       * getobj: "What do you want to dip <the object> into? [xyz or ?*] "
  30.       */
  31.      Strcpy(obuf, short_oname(obj, doname, thesimpleoname,
  32.                               /* 128 - (24 + 54 + 1) leaves 49 for <object> */
  33.                               QBUFSZ - sizeof "What do you want to dip \
  34.   into? [abdeghjkmnpqstvwyzBCEFHIKLNOQRTUWXZ#-# or ?*] "));
  35.  
  36.      here = levl[u.ux][u.uy].typ;
  37.      /* Is there a fountain to dip into here? */
  38.      if (IS_FOUNTAIN(here)) {
  39.          Sprintf(qbuf, "%s%s into the fountain?", Dip_,
  40.                  flags.verbose ? obuf : shortestname);
  41.          /* "Dip <the object> into the fountain?" */
  42.          if (yn(qbuf) == 'y') {
  43.              dipfountain(obj);
  44.              return 1;
  45.          }
  46.      } else if (is_pool(u.ux, u.uy)) {
  47.          const char *pooltype = waterbody_name(u.ux, u.uy);
  48.  
  49.          Sprintf(qbuf, "%s%s into the %s?", Dip_,
  50.                  flags.verbose ? obuf : shortestname, pooltype);
  51.          /* "Dip <the object> into the {pool, moat, &c}?" */
  52.          if (yn(qbuf) == 'y') {
  53.              if (Levitation) {
  54.                  floating_above(pooltype);
  55.              } else if (u.usteed && !is_swimmer(u.usteed->data)
  56.                         && P_SKILL(P_RIDING) < P_BASIC) {
  57.                  rider_cant_reach(); /* not skilled enough to reach */
  58.              } else {
  59.                  if (obj->otyp == POT_ACID)
  60.                      obj->in_use = 1;
  61.                  if (water_damage(obj, 0, TRUE) != ER_DESTROYED && obj->in_use)
  62.                      useup(obj);
  63.              }
  64.              return 1;
  65.          }
  66.      }
  67.  
  68.      /* "What do you want to dip <the object> into? [xyz or ?*] " */
  69.      Sprintf(qbuf, "dip %s into", flags.verbose ? obuf : shortestname);
  70.      potion = getobj(beverages, qbuf);
  71.      if (!potion)
  72.          return 0;
  73.      if (potion == obj && potion->quan == 1L) {
  74.          pline("That is a potion bottle, not a Klein bottle!");
  75.          return 0;
  76.      }
  77.      potion->in_use = TRUE; /* assume it will be used up */
  78.      if (potion->otyp == POT_WATER) {
  79.          boolean useeit = !Blind || (obj == ublindf && Blindfolded_only);
  80.          const char *obj_glows = Yobjnam2(obj, "glow");
  81.  
  82.          if (H2Opotion_dip(potion, obj, useeit, obj_glows))
  83.              goto poof;
  84.      } else if (obj->otyp == POT_POLYMORPH || potion->otyp == POT_POLYMORPH) {
  85.          /* some objects can't be polymorphed */
  86.          if (obj->otyp == potion->otyp /* both POT_POLY */
  87.              || obj->otyp == WAN_POLYMORPH || obj->otyp == SPE_POLYMORPH
  88.              || obj == uball || obj == uskin
  89.              || obj_resists(obj->otyp == POT_POLYMORPH ? potion : obj,
  90.                             5, 95)) {
  91.              pline1(nothing_happens);
  92.          } else {
  93.              boolean was_wep, was_swapwep, was_quiver;
  94.              short save_otyp = obj->otyp;
  95.  
  96.              /* KMH, conduct */
  97.              u.uconduct.polypiles++;
  98.  
  99.              was_wep = (obj == uwep);
  100.              was_swapwep = (obj == uswapwep);
  101.              was_quiver = (obj == uquiver);
  102.  
  103.              obj = poly_obj(obj, STRANGE_OBJECT);
  104.  
  105.              if (was_wep)
  106.                  setuwep(obj);
  107.              else if (was_swapwep)
  108.                  setuswapwep(obj);
  109.              else if (was_quiver)
  110.                  setuqwep(obj);
  111.  
  112.              if (obj->otyp != save_otyp) {
  113.                  makeknown(POT_POLYMORPH);
  114.                  useup(potion);
  115.                  prinv((char *) 0, obj, 0L);
  116.                  return 1;
  117.              } else {
  118.                  pline("Nothing seems to happen.");
  119.                  goto poof;
  120.              }
  121.          }
  122.          potion->in_use = FALSE; /* didn't go poof */
  123.          return 1;
  124.      } else if (obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
  125.          int amt = (int) obj->quan;
  126.          boolean magic;
  127.  
  128.          mixture = mixtype(obj, potion);
  129.  
  130.          magic = (mixture != STRANGE_OBJECT) ? objects[mixture].oc_magic
  131.              : (objects[obj->otyp].oc_magic || objects[potion->otyp].oc_magic);
  132.          Strcpy(qbuf, "The"); /* assume full stack */
  133.          if (amt > (magic ? 3 : 7)) {
  134.              /* trying to dip multiple potions will usually affect only a
  135.                 subset; pick an amount between 3 and 8, inclusive, for magic
  136.                 potion result, between 7 and N for non-magic */
  137.              if (magic)
  138.                  amt = rnd(min(amt, 8) - (3 - 1)) + (3 - 1); /* 1..6 + 2 */
  139.              else
  140.                  amt = rnd(amt - (7 - 1)) + (7 - 1); /* 1..(N-6) + 6 */
  141.  
  142.              if ((long) amt < obj->quan) {
  143.                  obj = splitobj(obj, (long) amt);
  144.                  Sprintf(qbuf, "%ld of the", obj->quan);
  145.              }
  146.          }
  147.          /* [N of] the {obj(s)} mix(es) with [one of] {the potion}... */
  148.          pline("%s %s %s with %s%s...", qbuf, simpleonames(obj),
  149.                otense(obj, "mix"), (potion->quan > 1L) ? "one of " : "",
  150.                thesimpleoname(potion));
  151.          /* Mixing potions is dangerous...
  152.             KMH, balance patch -- acid is particularly unstable */
  153.          if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
  154.              /* it would be better to use up the whole stack in advance
  155.                 of the message, but we can't because we need to keep it
  156.                 around for potionbreathe() [and we can't set obj->in_use
  157.                 to 'amt' because that's not implemented] */
  158.              obj->in_use = 1;
  159.              pline("BOOM!  They explode!");
  160.              wake_nearto(u.ux, u.uy, (BOLT_LIM + 1) * (BOLT_LIM + 1));
  161.              exercise(A_STR, FALSE);
  162.              if (!breathless(youmonst.data) || haseyes(youmonst.data))
  163.                  potionbreathe(obj);
  164.              useupall(obj);
  165.              useup(potion);
  166.              losehp(amt + rnd(9), /* not physical damage */
  167.                     "alchemic blast", KILLED_BY_AN);
  168.              return 1;
  169.          }
  170.  
  171.          obj->blessed = obj->cursed = obj->bknown = 0;
  172.          if (Blind || Hallucination)
  173.              obj->dknown = 0;
  174.  
  175.          if (mixture != STRANGE_OBJECT) {
  176.              obj->otyp = mixture;
  177.          } else {
  178.              switch (obj->odiluted ? 1 : rnd(8)) {
  179.              case 1:
  180.                  obj->otyp = POT_WATER;
  181.                  break;
  182.              case 2:
  183.              case 3:
  184.                  obj->otyp = POT_SICKNESS;
  185.                  break;
  186.              case 4: {
  187.                  struct obj *otmp = mkobj(POTION_CLASS, FALSE);
  188.  
  189.                  obj->otyp = otmp->otyp;
  190.                  obfree(otmp, (struct obj *) 0);
  191.                  break;
  192.              }
  193.              default:
  194.                  useupall(obj);
  195.                  useup(potion);
  196.                  if (!Blind)
  197.                      pline_The("mixture glows brightly and evaporates.");
  198.                  return 1;
  199.              }
  200.          }
  201.          obj->odiluted = (obj->otyp != POT_WATER);
  202.  
  203.          if (obj->otyp == POT_WATER && !Hallucination) {
  204.              pline_The("mixture bubbles%s.", Blind ? "" : ", then clears");
  205.          } else if (!Blind) {
  206.              pline_The("mixture looks %s.",
  207.                        hcolor(OBJ_DESCR(objects[obj->otyp])));
  208.          }
  209.  
  210.          useup(potion);
  211.          /* this is required when 'obj' was split off from a bigger stack,
  212.             so that 'obj' will now be assigned its own inventory slot;
  213.             it has a side-effect of merging 'obj' into another compatible
  214.             stack if there is one, so we do it even when no split has
  215.             been made in order to get the merge result for both cases;
  216.             as a consequence, mixing while Fumbling drops the mixture */
  217.          freeinv(obj);
  218.          (void) hold_another_object(obj, "You drop %s!", doname(obj),
  219.                                     (const char *) 0);
  220.          return 1;
  221.      }
  222.  
  223.      if (potion->otyp == POT_ACID && obj->otyp == CORPSE
  224.          && obj->corpsenm == PM_LICHEN && !Blind) {
  225.          pline("%s %s %s around the edges.", The(cxname(obj)),
  226.                otense(obj, "turn"),
  227.                potion->odiluted ? hcolor(NH_ORANGE) : hcolor(NH_RED));
  228.          potion->in_use = FALSE; /* didn't go poof */
  229.          return 1;
  230.      }
  231.  
  232.      if (potion->otyp == POT_WATER && obj->otyp == TOWEL) {
  233.          pline_The("towel soaks it up!");
  234.          /* wetting towel already done via water_damage() in H2Opotion_dip */
  235.          goto poof;
  236.      }
  237.  
  238.      if (is_poisonable(obj)) {
  239.          if (potion->otyp == POT_SICKNESS && !obj->opoisoned) {
  240.              char buf[BUFSZ];
  241.  
  242.              if (potion->quan > 1L)
  243.                  Sprintf(buf, "One of %s", the(xname(potion)));
  244.              else
  245.                  Strcpy(buf, The(xname(potion)));
  246.              pline("%s forms a coating on %s.", buf, the(xname(obj)));
  247.              obj->opoisoned = TRUE;
  248.              goto poof;
  249.          } else if (obj->opoisoned && (potion->otyp == POT_HEALING
  250.                                        || potion->otyp == POT_EXTRA_HEALING
  251.                                        || potion->otyp == POT_FULL_HEALING)) {
  252.              pline("A coating wears off %s.", the(xname(obj)));
  253.              obj->opoisoned = 0;
  254.              goto poof;
  255.          }
  256.      }
  257.  
  258.      if (potion->otyp == POT_ACID) {
  259.          if (erode_obj(obj, 0, ERODE_CORRODE, EF_GREASE) != ER_NOTHING)
  260.              goto poof;
  261.      }
  262.  
  263.      if (potion->otyp == POT_OIL) {
  264.          boolean wisx = FALSE;
  265.  
  266.          if (potion->lamplit) { /* burning */
  267.              fire_damage(obj, TRUE, u.ux, u.uy);
  268.          } else if (potion->cursed) {
  269.              pline_The("potion spills and covers your %s with oil.",
  270.                        makeplural(body_part(FINGER)));
  271.              incr_itimeout(&Glib, d(2, 10));
  272.          } else if (obj->oclass != WEAPON_CLASS && !is_weptool(obj)) {
  273.              /* the following cases apply only to weapons */
  274.              goto more_dips;
  275.              /* Oil removes rust and corrosion, but doesn't unburn.
  276.               * Arrows, etc are classed as metallic due to arrowhead
  277.               * material, but dipping in oil shouldn't repair them.
  278.               */
  279.          } else if ((!is_rustprone(obj) && !is_corrodeable(obj))
  280.                     || is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) {
  281.              /* uses up potion, doesn't set obj->greased */
  282.              pline("%s %s with an oily sheen.", Yname2(obj),
  283.                    otense(obj, "gleam"));
  284.          } else {
  285.              pline("%s %s less %s.", Yname2(obj), otense(obj, "are"),
  286.                    (obj->oeroded && obj->oeroded2)
  287.                        ? "corroded and rusty"
  288.                        : obj->oeroded ? "rusty" : "corroded");
  289.              if (obj->oeroded > 0)
  290.                  obj->oeroded--;
  291.              if (obj->oeroded2 > 0)
  292.                  obj->oeroded2--;
  293.              wisx = TRUE;
  294.          }
  295.          exercise(A_WIS, wisx);
  296.          makeknown(potion->otyp);
  297.          useup(potion);
  298.          return 1;
  299.      }
  300.  more_dips:
  301.  
  302.      /* Allow filling of MAGIC_LAMPs to prevent identification by player */
  303.      if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP)
  304.          && (potion->otyp == POT_OIL)) {
  305.          /* Turn off engine before fueling, turn off fuel too :-)  */
  306.          if (obj->lamplit || potion->lamplit) {
  307.              useup(potion);
  308.              explode(u.ux, u.uy, 11, d(6, 6), 0, EXPL_FIERY);
  309.              exercise(A_WIS, FALSE);
  310.              return 1;
  311.          }
  312.          /* Adding oil to an empty magic lamp renders it into an oil lamp */
  313.          if ((obj->otyp == MAGIC_LAMP) && obj->spe == 0) {
  314.              obj->otyp = OIL_LAMP;
  315.              obj->age = 0;
  316.          }
  317.          if (obj->age > 1000L) {
  318.              pline("%s %s full.", Yname2(obj), otense(obj, "are"));
  319.              potion->in_use = FALSE; /* didn't go poof */
  320.          } else {
  321.              You("fill %s with oil.", yname(obj));
  322.              check_unpaid(potion);        /* Yendorian Fuel Tax */
  323.              obj->age += 2 * potion->age; /* burns more efficiently */
  324.              if (obj->age > 1500L)
  325.                  obj->age = 1500L;
  326.              useup(potion);
  327.              exercise(A_WIS, TRUE);
  328.          }
  329.          makeknown(POT_OIL);
  330.          obj->spe = 1;
  331.          update_inventory();
  332.          return 1;
  333.      }
  334.  
  335.      potion->in_use = FALSE; /* didn't go poof */
  336.      if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST)
  337.          && (mixture = mixtype(obj, potion)) != STRANGE_OBJECT) {
  338.          char oldbuf[BUFSZ], newbuf[BUFSZ];
  339.          short old_otyp = potion->otyp;
  340.          boolean old_dknown = FALSE;
  341.          boolean more_than_one = potion->quan > 1L;
  342.  
  343.          oldbuf[0] = '\0';
  344.          if (potion->dknown) {
  345.              old_dknown = TRUE;
  346.              Sprintf(oldbuf, "%s ", hcolor(OBJ_DESCR(objects[potion->otyp])));
  347.          }
  348.          /* with multiple merged potions, split off one and
  349.             just clear it */
  350.          if (potion->quan > 1L) {
  351.              singlepotion = splitobj(potion, 1L);
  352.          } else
  353.              singlepotion = potion;
  354.  
  355.          costly_alteration(singlepotion, COST_NUTRLZ);
  356.          singlepotion->otyp = mixture;
  357.          singlepotion->blessed = 0;
  358.          if (mixture == POT_WATER)
  359.              singlepotion->cursed = singlepotion->odiluted = 0;
  360.          else
  361.              singlepotion->cursed = obj->cursed; /* odiluted left as-is */
  362.          singlepotion->bknown = FALSE;
  363.          if (Blind) {
  364.              singlepotion->dknown = FALSE;
  365.          } else {
  366.              singlepotion->dknown = !Hallucination;
  367.              if (mixture == POT_WATER && singlepotion->dknown)
  368.                  Sprintf(newbuf, "clears");
  369.              else
  370.                  Sprintf(newbuf, "turns %s",
  371.                          hcolor(OBJ_DESCR(objects[mixture])));
  372.              pline_The("%spotion%s %s.", oldbuf,
  373.                        more_than_one ? " that you dipped into" : "", newbuf);
  374.              if (!objects[old_otyp].oc_uname
  375.                  && !objects[old_otyp].oc_name_known && old_dknown) {
  376.                  struct obj fakeobj;
  377.                  fakeobj = zeroobj;
  378.                  fakeobj.dknown = 1;
  379.                  fakeobj.otyp = old_otyp;
  380.                  fakeobj.oclass = POTION_CLASS;
  381.                  docall(&fakeobj);
  382.              }
  383.          }
  384.          obj_extract_self(singlepotion);
  385.          singlepotion =
  386.              hold_another_object(singlepotion, "You juggle and drop %s!",
  387.                                  doname(singlepotion), (const char *) 0);
  388.          update_inventory();
  389.          return 1;
  390.      }
  391.  
  392.      pline("Interesting...");
  393.      return 1;
  394.  
  395.  poof:
  396.      if (!objects[potion->otyp].oc_name_known
  397.          && !objects[potion->otyp].oc_uname)
  398.          docall(potion);
  399.      useup(potion);
  400.      return 1;
  401.  }
  402.  

mongrantswish

  1.  /* *monp grants a wish and then leaves the game */
  2.  void
  3.  mongrantswish(monp)
  4.  struct monst **monp;
  5.  {
  6.      struct monst *mon = *monp;
  7.      int mx = mon->mx, my = mon->my, glyph = glyph_at(mx, my);
  8.  
  9.      /* remove the monster first in case wish proves to be fatal
  10.         (blasted by artifact), to keep it out of resulting bones file */
  11.      mongone(mon);
  12.      *monp = 0; /* inform caller that monster is gone */
  13.      /* hide that removal from player--map is visible during wish prompt */
  14.      tmp_at(DISP_ALWAYS, glyph);
  15.      tmp_at(mx, my);
  16.      /* grant the wish */
  17.      makewish();
  18.      /* clean up */
  19.      tmp_at(DISP_END, 0);
  20.  }
  21.  

djinni_from_bottle

  1.  void
  2.  djinni_from_bottle(obj)
  3.  struct obj *obj;
  4.  {
  5.      struct monst *mtmp;
  6.      int chance;
  7.  
  8.      if (!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy, NO_MM_FLAGS))) {
  9.          pline("It turns out to be empty.");
  10.          return;
  11.      }
  12.  
  13.      if (!Blind) {
  14.          pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
  15.          pline("%s speaks.", Monnam(mtmp));
  16.      } else {
  17.          You("smell acrid fumes.");
  18.          pline("%s speaks.", Something);
  19.      }
  20.  
  21.      chance = rn2(5);
  22.      if (obj->blessed)
  23.          chance = (chance == 4) ? rnd(4) : 0;
  24.      else if (obj->cursed)
  25.          chance = (chance == 0) ? rn2(4) : 4;
  26.      /* 0,1,2,3,4:  b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */
  27.  
  28.      switch (chance) {
  29.      case 0:
  30.          verbalize("I am in your debt.  I will grant one wish!");
  31.          /* give a wish and discard the monster (mtmp set to null) */
  32.          mongrantswish(&mtmp);
  33.          break;
  34.      case 1:
  35.          verbalize("Thank you for freeing me!");
  36.          (void) tamedog(mtmp, (struct obj *) 0);
  37.          break;
  38.      case 2:
  39.          verbalize("You freed me!");
  40.          mtmp->mpeaceful = TRUE;
  41.          set_malign(mtmp);
  42.          break;
  43.      case 3:
  44.          verbalize("It is about time!");
  45.          if (canspotmon(mtmp))
  46.              pline("%s vanishes.", Monnam(mtmp));
  47.          mongone(mtmp);
  48.          break;
  49.      default:
  50.          verbalize("You disturbed me, fool!");
  51.          mtmp->mpeaceful = FALSE;
  52.          set_malign(mtmp);
  53.          break;
  54.      }
  55.  }
  56.  

split_mon

  1.  /* clone a gremlin or mold (2nd arg non-null implies heat as the trigger);
  2.     hit points are cut in half (odd HP stays with original) */
  3.  struct monst *
  4.  split_mon(mon, mtmp)
  5.  struct monst *mon,  /* monster being split */
  6.               *mtmp; /* optional attacker whose heat triggered it */
  7.  {
  8.      struct monst *mtmp2;
  9.      char reason[BUFSZ];
  10.  
  11.      reason[0] = '\0';
  12.      if (mtmp)
  13.          Sprintf(reason, " from %s heat",
  14.                  (mtmp == &youmonst) ? the_your[1]
  15.                                      : (const char *) s_suffix(mon_nam(mtmp)));
  16.  
  17.      if (mon == &youmonst) {
  18.          mtmp2 = cloneu();
  19.          if (mtmp2) {
  20.              mtmp2->mhpmax = u.mhmax / 2;
  21.              u.mhmax -= mtmp2->mhpmax;
  22.              context.botl = 1;
  23.              You("multiply%s!", reason);
  24.          }
  25.      } else {
  26.          mtmp2 = clone_mon(mon, 0, 0);
  27.          if (mtmp2) {
  28.              mtmp2->mhpmax = mon->mhpmax / 2;
  29.              mon->mhpmax -= mtmp2->mhpmax;
  30.              if (canspotmon(mon))
  31.                  pline("%s multiplies%s!", Monnam(mon), reason);
  32.          }
  33.      }
  34.      return mtmp2;
  35.  }
  36.  
  37.  /*potion.c*/