text: /* NetHack 3.7	pray.c	$NHDT-Date: 1621208529 2021/05/16 23:42:09 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.147 $ */
  /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */
  /* NetHack may be freely redistributed.  See license for details. */
  
  #include "hack.h"
  
  static int prayer_done(void);
  static struct obj *worst_cursed_item(void);
  static int in_trouble(void);
  static void fix_worst_trouble(int);
  static void angrygods(aligntyp);
  static void at_your_feet(const char *);
  static void gcrownu(void);
  static void pleased(aligntyp);
  static void godvoice(aligntyp, const char *);
  static void god_zaps_you(aligntyp);
  static void fry_by_god(aligntyp, boolean);
  static void gods_angry(aligntyp);
  static void gods_upset(aligntyp);
  static void consume_offering(struct obj *);
  static boolean water_prayer(boolean);
  static boolean blocked_boulder(int, int);
  
  /* simplify a few tests */
  #define Cursed_obj(obj, typ) ((obj) && (obj)->otyp == (typ) && (obj)->cursed)
  
  /*
   * Logic behind deities and altars and such:
   * + prayers are made to your god if not on an altar, and to the altar's god
   *   if you are on an altar
   * + If possible, your god answers all prayers, which is why bad things happen
   *   if you try to pray on another god's altar
   * + sacrifices work basically the same way, but the other god may decide to
   *   accept your allegiance, after which they are your god.  If rejected,
   *   your god takes over with your punishment.
   * + if you're in Gehennom, all messages come from Moloch
   */
  
  /*
   *      Moloch, who dwells in Gehennom, is the "renegade" cruel god
   *      responsible for the theft of the Amulet from Marduk, the Creator.
   *      Moloch is unaligned.
   */
  static const char *const Moloch = "Moloch";
  
  static const char *const godvoices[] = {
      "booms out", "thunders", "rings out", "booms",
  };
  
  #define PIOUS 20
  #define DEVOUT 14
  #define FERVENT 9
  #define STRIDENT 4
  
  /*
   * The actual trouble priority is determined by the order of the
   * checks performed in in_trouble() rather than by these numeric
   * values, so keep that code and these values synchronized in
   * order to have the values be meaningful.
   */
  
  #define TROUBLE_STONED 14
  #define TROUBLE_SLIMED 13
  #define TROUBLE_STRANGLED 12
  #define TROUBLE_LAVA 11
  #define TROUBLE_SICK 10
  #define TROUBLE_STARVING 9
  #define TROUBLE_REGION 8 /* stinking cloud */
  #define TROUBLE_HIT 7
  #define TROUBLE_LYCANTHROPE 6
  #define TROUBLE_COLLAPSING 5
  #define TROUBLE_STUCK_IN_WALL 4
  #define TROUBLE_CURSED_LEVITATION 3
  #define TROUBLE_UNUSEABLE_HANDS 2
  #define TROUBLE_CURSED_BLINDFOLD 1
  
  #define TROUBLE_PUNISHED (-1)
  #define TROUBLE_FUMBLING (-2)
  #define TROUBLE_CURSED_ITEMS (-3)
  #define TROUBLE_SADDLE (-4)
  #define TROUBLE_BLIND (-5)
  #define TROUBLE_POISONED (-6)
  #define TROUBLE_WOUNDED_LEGS (-7)
  #define TROUBLE_HUNGRY (-8)
  #define TROUBLE_STUNNED (-9)
  #define TROUBLE_CONFUSED (-10)
  #define TROUBLE_HALLUCINATION (-11)
  
  
  #define ugod_is_angry() (u.ualign.record < 0)
  #define on_altar() IS_ALTAR(levl[u.ux][u.uy].typ)
  #define on_shrine() ((levl[u.ux][u.uy].altarmask & AM_SHRINE) != 0)
  #define a_align(x, y) ((aligntyp) Amask2align(levl[x][y].altarmask & AM_MASK))
  
  /* critically low hit points if hp <= 5 or hp <= maxhp/N for some N */
  boolean
  critically_low_hp(boolean only_if_injured) /* determines whether maxhp <= 5
                                                matters */
  {
      int divisor, hplim, curhp = Upolyd ? u.mh : u.uhp,
                          maxhp = Upolyd ? u.mhmax : u.uhpmax;
  
      if (only_if_injured && !(curhp < maxhp))
          return FALSE;
      /* if maxhp is extremely high, use lower threshold for the division test
         (golden glow cuts off at 11+5*lvl, nurse interaction at 25*lvl; this
         ought to use monster hit dice--and a smaller multiplier--rather than
         ulevel when polymorphed, but polyself doesn't maintain that) */
      hplim = 15 * u.ulevel;
      if (maxhp > hplim)
          maxhp = hplim;
      /* 7 used to be the unconditional divisor */
      switch (xlev_to_rank(u.ulevel)) { /* maps 1..30 into 0..8 */
      case 0:
      case 1:
          divisor = 5;
          break; /* explvl 1 to 5 */
      case 2:
      case 3:
          divisor = 6;
          break; /* explvl 6 to 13 */
      case 4:
      case 5:
          divisor = 7;
          break; /* explvl 14 to 21 */
      case 6:
      case 7:
          divisor = 8;
          break; /* explvl 22 to 29 */
      default:
          divisor = 9;
          break; /* explvl 30+ */
      }
      /* 5 is a magic number in TROUBLE_HIT handling below */
      return (boolean) (curhp <= 5 || curhp * divisor <= maxhp);
  }
  
  /* return True if surrounded by impassible rock, regardless of the state
     of your own location (for example, inside a doorless closet) */
  boolean
  stuck_in_wall(void)
  {
      int i, j, x, y, count = 0;
  
      if (Passes_walls)
          return FALSE;
      for (i = -1; i <= 1; i++) {
          x = u.ux + i;
          for (j = -1; j <= 1; j++) {
              if (!i && !j)
                  continue;
              y = u.uy + j;
              if (!isok(x, y)
                  || (IS_ROCK(levl[x][y].typ)
                      && (levl[x][y].typ != SDOOR && levl[x][y].typ != SCORR))
                  || (blocked_boulder(i, j) && !throws_rocks(g.youmonst.data)))
                  ++count;
          }
      }
      return (count == 8) ? TRUE : FALSE;
  }
  
  /*
   * Return 0 if nothing particular seems wrong, positive numbers for
   * serious trouble, and negative numbers for comparative annoyances.
   * This returns the worst problem. There may be others, and the gods
   * may fix more than one.
   *
   * This could get as bizarre as noting surrounding opponents, (or
   * hostile dogs), but that's really hard.
   *
   * We could force rehumanize of polyselfed people, but we can't tell
   * unintentional shape changes from the other kind. Oh well.
   * 3.4.2: make an exception if polymorphed into a form which lacks
   * hands; that's a case where the ramifications override this doubt.
   */
  static int
  in_trouble(void)
  {
      struct obj *otmp;
      int i;
  
      /*
       * major troubles
       */
      if (Stoned)
          return TROUBLE_STONED;
      if (Slimed)
          return TROUBLE_SLIMED;
      if (Strangled)
          return TROUBLE_STRANGLED;
      if (u.utrap && u.utraptype == TT_LAVA)
          return TROUBLE_LAVA;
      if (Sick)
          return TROUBLE_SICK;
      if (u.uhs >= WEAK)
          return TROUBLE_STARVING;
      if (region_danger())
          return TROUBLE_REGION;
      if (critically_low_hp(FALSE))
          return TROUBLE_HIT;
      if (u.ulycn >= LOW_PM)
          return TROUBLE_LYCANTHROPE;
      if (near_capacity() >= EXT_ENCUMBER && AMAX(A_STR) - ABASE(A_STR) > 3)
          return TROUBLE_COLLAPSING;
      if (stuck_in_wall())
          return TROUBLE_STUCK_IN_WALL;
      if (Cursed_obj(uarmf, LEVITATION_BOOTS)
          || stuck_ring(uleft, RIN_LEVITATION)
          || stuck_ring(uright, RIN_LEVITATION))
          return TROUBLE_CURSED_LEVITATION;
      if (nohands(g.youmonst.data) || !freehand()) {
          /* for bag/box access [cf use_container()]...
             make sure it's a case that we know how to handle;
             otherwise "fix all troubles" would get stuck in a loop */
          if (welded(uwep))
              return TROUBLE_UNUSEABLE_HANDS;
          if (Upolyd && nohands(g.youmonst.data)
              && (!Unchanging || ((otmp = unchanger()) != 0 && otmp->cursed)))
              return TROUBLE_UNUSEABLE_HANDS;
      }
      if (Blindfolded && ublindf->cursed)
          return TROUBLE_CURSED_BLINDFOLD;
  
      /*
       * minor troubles
       */
      if (Punished || (u.utrap && u.utraptype == TT_BURIEDBALL))
          return TROUBLE_PUNISHED;
      if (Cursed_obj(uarmg, GAUNTLETS_OF_FUMBLING)
          || Cursed_obj(uarmf, FUMBLE_BOOTS))
          return TROUBLE_FUMBLING;
      if (worst_cursed_item())
          return TROUBLE_CURSED_ITEMS;
      if (u.usteed) { /* can't voluntarily dismount from a cursed saddle */
          otmp = which_armor(u.usteed, W_SADDLE);
          if (Cursed_obj(otmp, SADDLE))
              return TROUBLE_SADDLE;
      }
  
      if (Blinded > 1 && haseyes(g.youmonst.data)
          && (!u.uswallow
              || !attacktype_fordmg(u.ustuck->data, AT_ENGL, AD_BLND)))
          return TROUBLE_BLIND;
      /* deafness isn't it's own trouble; healing magic cures deafness
         when it cures blindness, so do the same with trouble repair */
      if ((HDeaf & TIMEOUT) > 1L)
          return TROUBLE_BLIND;
  
      for (i = 0; i < A_MAX; i++)
          if (ABASE(i) < AMAX(i))
              return TROUBLE_POISONED;
      if (Wounded_legs && !u.usteed)
          return TROUBLE_WOUNDED_LEGS;
      if (u.uhs >= HUNGRY)
          return TROUBLE_HUNGRY;
      if (HStun & TIMEOUT)
          return TROUBLE_STUNNED;
      if (HConfusion & TIMEOUT)
          return TROUBLE_CONFUSED;
      if (HHallucination & TIMEOUT)
          return TROUBLE_HALLUCINATION;
      return 0;
  }
  
  /* select an item for TROUBLE_CURSED_ITEMS */
  static struct obj *
  worst_cursed_item(void)
  {
      register struct obj *otmp;
  
      /* if strained or worse, check for loadstone first */
      if (near_capacity() >= HVY_ENCUMBER) {
          for (otmp = g.invent; otmp; otmp = otmp->nobj)
              if (Cursed_obj(otmp, LOADSTONE))
                  return otmp;
      }
      /* weapon takes precedence if it is interfering
         with taking off a ring or putting on a shield */
      if (welded(uwep) && (uright || bimanual(uwep))) { /* weapon */
          otmp = uwep;
      /* gloves come next, due to rings */
      } else if (uarmg && uarmg->cursed) { /* gloves */
          otmp = uarmg;
      /* then shield due to two handed weapons and spells */
      } else if (uarms && uarms->cursed) { /* shield */
          otmp = uarms;
      /* then cloak due to body armor */
      } else if (uarmc && uarmc->cursed) { /* cloak */
          otmp = uarmc;
      } else if (uarm && uarm->cursed) { /* suit */
          otmp = uarm;
      /* if worn helmet of opposite alignment is making you an adherent
         of the current god, he/she/it won't uncurse that for you */
      } else if (uarmh && uarmh->cursed /* helmet */
                 && uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT) {
          otmp = uarmh;
      } else if (uarmf && uarmf->cursed) { /* boots */
          otmp = uarmf;
      } else if (uarmu && uarmu->cursed) { /* shirt */
          otmp = uarmu;
      } else if (uamul && uamul->cursed) { /* amulet */
          otmp = uamul;
      } else if (uleft && uleft->cursed) { /* left ring */
          otmp = uleft;
      } else if (uright && uright->cursed) { /* right ring */
          otmp = uright;
      } else if (ublindf && ublindf->cursed) { /* eyewear */
          otmp = ublindf; /* must be non-blinding lenses */
      /* if weapon wasn't handled above, do it now */
      } else if (welded(uwep)) { /* weapon */
          otmp = uwep;
      /* active secondary weapon even though it isn't welded */
      } else if (uswapwep && uswapwep->cursed && u.twoweap) {
          otmp = uswapwep;
      /* all worn items ought to be handled by now */
      } else {
          for (otmp = g.invent; otmp; otmp = otmp->nobj) {
              if (!otmp->cursed)
                  continue;
              if (otmp->otyp == LOADSTONE || confers_luck(otmp))
                  break;
          }
      }
      return otmp;
  }
  
  static void
  fix_worst_trouble(int trouble)
  {
      int i;
      struct obj *otmp = 0;
      const char *what = (const char *) 0;
      static NEARDATA const char leftglow[] = "Your left ring softly glows",
                                 rightglow[] = "Your right ring softly glows";
  
      switch (trouble) {
      case TROUBLE_STONED:
          make_stoned(0L, "You feel more limber.", 0, (char *) 0);
          break;
      case TROUBLE_SLIMED:
          make_slimed(0L, "The slime disappears.");
          break;
      case TROUBLE_STRANGLED:
          if (uamul && uamul->otyp == AMULET_OF_STRANGULATION) {
              Your("amulet vanishes!");
              useup(uamul);
          }
          You("can breathe again.");
          Strangled = 0;
          g.context.botl = 1;
          break;
      case TROUBLE_LAVA:
          You("are back on solid ground.");
          /* teleport should always succeed, but if not, just untrap them */
          if (!safe_teleds(FALSE))
              reset_utrap(TRUE);
          break;
      case TROUBLE_STARVING:
          /* temporarily lost strength recovery now handled by init_uhunger() */
          /*FALLTHRU*/
      case TROUBLE_HUNGRY:
          Your("%s feels content.", body_part(STOMACH));
          init_uhunger();
          g.context.botl = 1;
          break;
      case TROUBLE_SICK:
          You_feel("better.");
          make_sick(0L, (char *) 0, FALSE, SICK_ALL);
          break;
      case TROUBLE_REGION:
          /* stinking cloud, with hero vulnerable to HP loss */
          region_safety();
          break;
      case TROUBLE_HIT:
          /* "fix all troubles" will keep trying if hero has
             5 or less hit points, so make sure they're always
             boosted to be more than that */
          You_feel("much better.");
          if (Upolyd) {
              u.mhmax += rnd(5);
              if (u.mhmax <= 5)
                  u.mhmax = 5 + 1;
              u.mh = u.mhmax;
          }
          if (u.uhpmax < u.ulevel * 5 + 11)
              u.uhpmax += rnd(5);
          if (u.uhpmax <= 5)
              u.uhpmax = 5 + 1;
          if (u.uhpmax > u.uhppeak)
              u.uhppeak = u.uhpmax;
          u.uhp = u.uhpmax;
          g.context.botl = 1;
          break;
      case TROUBLE_COLLAPSING:
          /* override Fixed_abil; uncurse that if feasible */
          You_feel("%sstronger.",
                   (AMAX(A_STR) - ABASE(A_STR) > 6) ? "much " : "");
          ABASE(A_STR) = AMAX(A_STR);
          g.context.botl = 1;
          if (Fixed_abil) {
              if ((otmp = stuck_ring(uleft, RIN_SUSTAIN_ABILITY)) != 0) {
                  if (otmp == uleft)
                      what = leftglow;
              } else if ((otmp = stuck_ring(uright, RIN_SUSTAIN_ABILITY)) != 0) {
                  if (otmp == uright)
                      what = rightglow;
              }
              if (otmp)
                  goto decurse;
          }
          break;
      case TROUBLE_STUCK_IN_WALL:
          /* no control, but works on no-teleport levels */
          if (safe_teleds(FALSE)) {
              Your("surroundings change.");
          } else {
              /* safe_teleds() couldn't find a safe place; perhaps the
                 level is completely full.  As a last resort, confer
                 intrinsic wall/rock-phazing.  Hero might get stuck
                 again fairly soon....
                 Without something like this, fix_all_troubles can get
                 stuck in an infinite loop trying to fix STUCK_IN_WALL
                 and repeatedly failing. */
              set_itimeout(&HPasses_walls, (long) (d(4, 4) + 4)); /* 8..20 */
              /* how else could you move between packed rocks or among
                 lattice forming "solid" rock? */
              You_feel("much slimmer.");
          }
          break;
      case TROUBLE_CURSED_LEVITATION:
          if (Cursed_obj(uarmf, LEVITATION_BOOTS)) {
              otmp = uarmf;
          } else if ((otmp = stuck_ring(uleft, RIN_LEVITATION)) != 0) {
              if (otmp == uleft)
                  what = leftglow;
          } else if ((otmp = stuck_ring(uright, RIN_LEVITATION)) != 0) {
              if (otmp == uright)
                  what = rightglow;
          }
          goto decurse;
      case TROUBLE_UNUSEABLE_HANDS:
          if (welded(uwep)) {
              otmp = uwep;
              goto decurse;
          }
          if (Upolyd && nohands(g.youmonst.data)) {
              if (!Unchanging) {
                  Your("shape becomes uncertain.");
                  rehumanize(); /* "You return to {normal} form." */
              } else if ((otmp = unchanger()) != 0 && otmp->cursed) {
                  /* otmp is an amulet of unchanging */
                  goto decurse;
              }
          }
          if (nohands(g.youmonst.data) || !freehand())
              impossible("fix_worst_trouble: couldn't cure hands.");
          break;
      case TROUBLE_CURSED_BLINDFOLD:
          otmp = ublindf;
          goto decurse;
      case TROUBLE_LYCANTHROPE:
          you_unwere(TRUE);
          break;
      /*
       */
      case TROUBLE_PUNISHED:
          Your("chain disappears.");
          if (u.utrap && u.utraptype == TT_BURIEDBALL)
              buried_ball_to_freedom();
          else
              unpunish();
          break;
      case TROUBLE_FUMBLING:
          if (Cursed_obj(uarmg, GAUNTLETS_OF_FUMBLING))
              otmp = uarmg;
          else if (Cursed_obj(uarmf, FUMBLE_BOOTS))
              otmp = uarmf;
          goto decurse;
          /*NOTREACHED*/
          break;
      case TROUBLE_CURSED_ITEMS:
          otmp = worst_cursed_item();
          if (otmp == uright)
              what = rightglow;
          else if (otmp == uleft)
              what = leftglow;
   decurse:
          if (!otmp) {
              impossible("fix_worst_trouble: nothing to uncurse.");
              return;
          }
          if (otmp == uarmg && Glib) {
              make_glib(0);
              Your("%s are no longer slippery.", gloves_simple_name(uarmg));
              if (!otmp->cursed)
                  break;
          }
          if (!Blind || (otmp == ublindf && Blindfolded_only)) {
              pline("%s %s.",
                    what ? what : (const char *) Yobjnam2(otmp, "softly glow"),
                    hcolor(NH_AMBER));
              iflags.last_msg = PLNMSG_OBJ_GLOWS;
              otmp->bknown = !Hallucination; /* ok to skip set_bknown() */
          }
          uncurse(otmp);
          update_inventory();
          break;
      case TROUBLE_POISONED:
          /* override Fixed_abil; ignore items which confer that */
          if (Hallucination)
              pline("There's a tiger in your tank.");
          else
              You_feel("in good health again.");
          for (i = 0; i < A_MAX; i++) {
              if (ABASE(i) < AMAX(i)) {
                  ABASE(i) = AMAX(i);
                  g.context.botl = 1;
              }
          }
          (void) encumber_msg();
          break;
      case TROUBLE_BLIND: { /* handles deafness as well as blindness */
          char msgbuf[BUFSZ];
          const char *eyes = body_part(EYE);
          boolean cure_deaf = (HDeaf & TIMEOUT) ? TRUE : FALSE;
  
          msgbuf[0] = '\0';
          if (Blinded) {
              if (eyecount(g.youmonst.data) != 1)
                  eyes = makeplural(eyes);
              Sprintf(msgbuf, "Your %s %s better", eyes, vtense(eyes, "feel"));
              u.ucreamed = 0;
              make_blinded(0L, FALSE);
          }
          if (cure_deaf) {
              make_deaf(0L, FALSE);
              if (!Deaf)
                  Sprintf(eos(msgbuf), "%s can hear again",
                          !*msgbuf ? "You" : " and you");
          }
          if (*msgbuf)
              pline("%s.", msgbuf);
          break;
      }
      case TROUBLE_WOUNDED_LEGS:
          heal_legs(0);
          break;
      case TROUBLE_STUNNED:
          make_stunned(0L, TRUE);
          break;
      case TROUBLE_CONFUSED:
          make_confused(0L, TRUE);
          break;
      case TROUBLE_HALLUCINATION:
          pline("Looks like you are back in Kansas.");
          (void) make_hallucinated(0L, FALSE, 0L);
          break;
      case TROUBLE_SADDLE:
          otmp = which_armor(u.usteed, W_SADDLE);
          if (!Blind) {
              pline("%s %s.", Yobjnam2(otmp, "softly glow"), hcolor(NH_AMBER));
              set_bknown(otmp, 1);
          }
          uncurse(otmp);
          break;
      }
  }
  
  /* "I am sometimes shocked by... the nuns who never take a bath without
   * wearing a bathrobe all the time.  When asked why, since no man can see them,
   * they reply 'Oh, but you forget the good God'.  Apparently they conceive of
   * the Deity as a Peeping Tom, whose omnipotence enables Him to see through
   * bathroom walls, but who is foiled by bathrobes." --Bertrand Russell, 1943
   * Divine wrath, dungeon walls, and armor follow the same principle.
   */
  static void
  god_zaps_you(aligntyp resp_god)
  {
      if (u.uswallow) {
          pline(
            "Suddenly a bolt of lightning comes down at you from the heavens!");
          pline("It strikes %s!", mon_nam(u.ustuck));
          if (!resists_elec(u.ustuck)) {
              pline("%s fries to a crisp!", Monnam(u.ustuck));
              /* Yup, you get experience.  It takes guts to successfully
               * pull off this trick on your god, anyway.
               * Other credit/blame applies (luck or alignment adjustments),
               * but not direct kill count (pacifist conduct).
               */
              xkilled(u.ustuck, XKILL_NOMSG | XKILL_NOCONDUCT);
          } else
              pline("%s seems unaffected.", Monnam(u.ustuck));
      } else {
          pline("Suddenly, a bolt of lightning strikes you!");
          if (Reflecting) {
              shieldeff(u.ux, u.uy);
              if (Blind)
                  pline("For some reason you're unaffected.");
              else
                  (void) ureflects("%s reflects from your %s.", "It");
              monstseesu(M_SEEN_REFL);
          } else if (Shock_resistance) {
              shieldeff(u.ux, u.uy);
              pline("It seems not to affect you.");
              monstseesu(M_SEEN_ELEC);
          } else
              fry_by_god(resp_god, FALSE);
      }
  
      pline("%s is not deterred...", align_gname(resp_god));
      if (u.uswallow) {
          pline("A wide-angle disintegration beam aimed at you hits %s!",
                mon_nam(u.ustuck));
          if (!resists_disint(u.ustuck)) {
              pline("%s disintegrates into a pile of dust!", Monnam(u.ustuck));
              xkilled(u.ustuck, XKILL_NOMSG | XKILL_NOCORPSE | XKILL_NOCONDUCT);
          } else
              pline("%s seems unaffected.", Monnam(u.ustuck));
      } else {
          pline("A wide-angle disintegration beam hits you!");
  
          /* disintegrate shield and body armor before disintegrating
           * the impudent mortal, like black dragon breath -3.
           */
          if (uarms && !(EReflecting & W_ARMS)
              && !(EDisint_resistance & W_ARMS))
              (void) destroy_arm(uarms);
          if (uarmc && !(EReflecting & W_ARMC)
              && !(EDisint_resistance & W_ARMC))
              (void) destroy_arm(uarmc);
          if (uarm && !(EReflecting & W_ARM) && !(EDisint_resistance & W_ARM)
              && !uarmc)
              (void) destroy_arm(uarm);
          if (uarmu && !uarm && !uarmc)
              (void) destroy_arm(uarmu);
          if (!Disint_resistance) {
              fry_by_god(resp_god, TRUE);
          } else {
              You("bask in its %s glow for a minute...", NH_BLACK);
              godvoice(resp_god, "I believe it not!");
              monstseesu(M_SEEN_DISINT);
          }
          if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)) {
              /* one more try for high altars */
              verbalize("Thou cannot escape my wrath, mortal!");
              summon_minion(resp_god, FALSE);
              summon_minion(resp_god, FALSE);
              summon_minion(resp_god, FALSE);
              verbalize("Destroy %s, my servants!", uhim());
          }
      }
  }
  
  static void
  fry_by_god(aligntyp resp_god, boolean via_disintegration)
  {
      You("%s!", !via_disintegration ? "fry to a crisp"
                                     : "disintegrate into a pile of dust");
      g.killer.format = KILLED_BY;
      Sprintf(g.killer.name, "the wrath of %s", align_gname(resp_god));
      done(DIED);
  }
  
  static void
  angrygods(aligntyp resp_god)
  {
      int maxanger;
  
      if (Inhell)
          resp_god = A_NONE;
      u.ublessed = 0;
  
      /* changed from tmp = u.ugangr + abs (u.uluck) -- rph */
      /* added test for alignment diff -dlc */
      if (resp_god != u.ualign.type)
          maxanger = u.ualign.record / 2 + (Luck > 0 ? -Luck / 3 : -Luck);
      else
          maxanger = 3 * u.ugangr + ((Luck > 0 || u.ualign.record >= STRIDENT)
                                     ? -Luck / 3
                                     : -Luck);
      if (maxanger < 1)
          maxanger = 1; /* possible if bad align & good luck */
      else if (maxanger > 15)
          maxanger = 15; /* be reasonable */
  
      switch (rn2(maxanger)) {
      case 0:
      case 1:
          You_feel("that %s is %s.", align_gname(resp_god),
                   Hallucination ? "bummed" : "displeased");
          break;
      case 2:
      case 3:
          godvoice(resp_god, (char *) 0);
          pline("\"Thou %s, %s.\"",
                (ugod_is_angry() && resp_god == u.ualign.type)
                    ? "hast strayed from the path"
                    : "art arrogant",
                g.youmonst.data->mlet == S_HUMAN ? "mortal" : "creature");
          verbalize("Thou must relearn thy lessons!");
          (void) adjattrib(A_WIS, -1, FALSE);
          losexp((char *) 0);
          break;
      case 6:
          if (!Punished) {
              gods_angry(resp_god);
              punish((struct obj *) 0);
              break;
          } /* else fall thru */
      case 4:
      case 5:
          gods_angry(resp_god);
          if (!Blind && !Antimagic)
              pline("%s glow surrounds you.", An(hcolor(NH_BLACK)));
          rndcurse();
          break;
      case 7:
      case 8:
          godvoice(resp_god, (char *) 0);
          verbalize("Thou durst %s me?",
                    (on_altar() && (a_align(u.ux, u.uy) != resp_god))
                        ? "scorn"
                        : "call upon");
          /* [why isn't this using verbalize()?] */
          pline("\"Then die, %s!\"",
                (g.youmonst.data->mlet == S_HUMAN) ? "mortal" : "creature");
          summon_minion(resp_god, FALSE);
          break;
  
      default:
          gods_angry(resp_god);
          god_zaps_you(resp_god);
          break;
      }
      u.ublesscnt = rnz(300);
      return;
  }
  
  /* helper to print "str appears at your feet", or appropriate */
  static void
  at_your_feet(const char *str)
  {
      if (Blind)
          str = Something;
      if (u.uswallow) {
          /* barrier between you and the floor */
          pline("%s %s into %s %s.", str, vtense(str, "drop"),
                s_suffix(mon_nam(u.ustuck)), mbodypart(u.ustuck, STOMACH));
      } else {
          pline("%s %s %s your %s!", str,
                Blind ? "lands" : vtense(str, "appear"),
                Levitation ? "beneath" : "at", makeplural(body_part(FOOT)));
      }
  }
  
  static void
  gcrownu(void)
  {
      struct obj *obj;
      boolean already_exists, in_hand;
      short class_gift;
  #define ok_wep(o) ((o) && ((o)->oclass == WEAPON_CLASS || is_weptool(o)))
  
      HSee_invisible |= FROMOUTSIDE;
      HFire_resistance |= FROMOUTSIDE;
      HCold_resistance |= FROMOUTSIDE;
      HShock_resistance |= FROMOUTSIDE;
      HSleep_resistance |= FROMOUTSIDE;
      HPoison_resistance |= FROMOUTSIDE;
      godvoice(u.ualign.type, (char *) 0);
  
      class_gift = STRANGE_OBJECT;
      /* 3.3.[01] had this in the A_NEUTRAL case,
         preventing chaotic wizards from receiving a spellbook */
      if (Role_if(PM_WIZARD)
          && (!uwep || (uwep->oartifact != ART_VORPAL_BLADE
                        && uwep->oartifact != ART_STORMBRINGER))
          && !carrying(SPE_FINGER_OF_DEATH)) {
          class_gift = SPE_FINGER_OF_DEATH;
      } else if (Role_if(PM_MONK) && (!uwep || !uwep->oartifact)
                 && !carrying(SPE_RESTORE_ABILITY)) {
          /* monks rarely wield a weapon */
          class_gift = SPE_RESTORE_ABILITY;
      }
  
      obj = ok_wep(uwep) ? uwep : 0;
      already_exists = in_hand = FALSE; /* lint suppression */
      switch (u.ualign.type) {
      case A_LAWFUL:
          u.uevent.uhand_of_elbereth = 1;
          verbalize("I crown thee...  The Hand of Elbereth!");
          livelog_printf(LL_DIVINEGIFT,
                         "was crowned \"The Hand of Elbereth\" by %s", u_gname());
          break;
      case A_NEUTRAL:
          u.uevent.uhand_of_elbereth = 2;
          in_hand = (uwep && uwep->oartifact == ART_VORPAL_BLADE);
          already_exists =
              exist_artifact(LONG_SWORD, artiname(ART_VORPAL_BLADE));
          verbalize("Thou shalt be my Envoy of Balance!");
          livelog_printf(LL_DIVINEGIFT, "became %s Envoy of Balance",
                         s_suffix(u_gname()));
          break;
      case A_CHAOTIC:
          u.uevent.uhand_of_elbereth = 3;
          in_hand = (uwep && uwep->oartifact == ART_STORMBRINGER);
          already_exists =
              exist_artifact(RUNESWORD, artiname(ART_STORMBRINGER));
          verbalize("Thou art chosen to %s for My Glory!",
                    ((already_exists && !in_hand)
                     || class_gift != STRANGE_OBJECT) ? "take lives"
                    : "steal souls");
          livelog_printf(LL_DIVINEGIFT, "was chosen to %s for the Glory of %s",
                         ((already_exists && !in_hand)
                          || class_gift != STRANGE_OBJECT) ? "take lives"
                         : "steal souls",
                         u_gname());
          break;
      }
  
      if (objects[class_gift].oc_class == SPBOOK_CLASS) {
          obj = mksobj(class_gift, TRUE, FALSE);
          bless(obj);
          obj->bknown = 1; /* ok to skip set_bknown() */
          at_your_feet("A spellbook");
          dropy(obj);
          u.ugifts++;
          /* when getting a new book for known spell, enhance
             currently wielded weapon rather than the book */
          if (known_spell(class_gift) && ok_wep(uwep))
              obj = uwep; /* to be blessed,&c */
      }
  
      switch (u.ualign.type) {
      case A_LAWFUL:
          if (class_gift != STRANGE_OBJECT) {
              ; /* already got bonus above */
          } else if (obj && obj->otyp == LONG_SWORD && !obj->oartifact) {
              if (!Blind)
                  Your("sword shines brightly for a moment.");
              obj = oname(obj, artiname(ART_EXCALIBUR));
              if (obj && obj->oartifact == ART_EXCALIBUR)
                  u.ugifts++;
          }
          /* acquire Excalibur's skill regardless of weapon or gift */
          unrestrict_weapon_skill(P_LONG_SWORD);
          if (obj && obj->oartifact == ART_EXCALIBUR)
              discover_artifact(ART_EXCALIBUR);
          break;
      case A_NEUTRAL:
          if (class_gift != STRANGE_OBJECT) {
              ; /* already got bonus above */
          } else if (obj && in_hand) {
              Your("%s goes snicker-snack!", xname(obj));
              obj->dknown = TRUE;
          } else if (!already_exists) {
              obj = mksobj(LONG_SWORD, FALSE, FALSE);
              obj = oname(obj, artiname(ART_VORPAL_BLADE));
              obj->spe = 1;
              at_your_feet("A sword");
              dropy(obj);
              u.ugifts++;
          }
          /* acquire Vorpal Blade's skill regardless of weapon or gift */
          unrestrict_weapon_skill(P_LONG_SWORD);
          if (obj && obj->oartifact == ART_VORPAL_BLADE)
              discover_artifact(ART_VORPAL_BLADE);
          break;
      case A_CHAOTIC: {
          char swordbuf[BUFSZ];
  
          Sprintf(swordbuf, "%s sword", hcolor(NH_BLACK));
          if (class_gift != STRANGE_OBJECT) {
              ; /* already got bonus above */
          } else if (obj && in_hand) {
              Your("%s hums ominously!", swordbuf);
              obj->dknown = TRUE;
          } else if (!already_exists) {
              obj = mksobj(RUNESWORD, FALSE, FALSE);
              obj = oname(obj, artiname(ART_STORMBRINGER));
              obj->spe = 1;
              at_your_feet(An(swordbuf));
              dropy(obj);
              u.ugifts++;
          }
          /* acquire Stormbringer's skill regardless of weapon or gift */
          unrestrict_weapon_skill(P_BROAD_SWORD);
          if (obj && obj->oartifact == ART_STORMBRINGER)
              discover_artifact(ART_STORMBRINGER);
          break;
      }
      default:
          obj = 0; /* lint */
          break;
      }
  
      /* enhance weapon regardless of alignment or artifact status */
      if (ok_wep(obj)) {
          bless(obj);
          obj->oeroded = obj->oeroded2 = 0;
          obj->oerodeproof = TRUE;
          obj->bknown = obj->rknown = 1; /* ok to skip set_bknown() */
          if (obj->spe < 1)
              obj->spe = 1;
          /* acquire skill in this weapon */
          unrestrict_weapon_skill(weapon_type(obj));
      } else if (class_gift == STRANGE_OBJECT) {
          /* opportunity knocked, but there was nobody home... */
          You_feel("unworthy.");
      }
      update_inventory();
  
      /* lastly, confer an extra skill slot/credit beyond the
         up-to-29 you can get from gaining experience levels */
      add_weapon_skill(1);
      return;
  }
  
  static void
  pleased(aligntyp g_align)
  {
      /* don't use p_trouble, worst trouble may get fixed while praying */
      int trouble = in_trouble(); /* what's your worst difficulty? */
      int pat_on_head = 0, kick_on_butt;
  
      You_feel("that %s is %s.", align_gname(g_align),
               (u.ualign.record >= DEVOUT)
                   ? Hallucination ? "pleased as punch" : "well-pleased"
                   : (u.ualign.record >= STRIDENT)
                         ? Hallucination ? "ticklish" : "pleased"
                         : Hallucination ? "full" : "satisfied");
  
      /* not your deity */
      if (on_altar() && g.p_aligntyp != u.ualign.type) {
          adjalign(-1);
          return;
      } else if (u.ualign.record < 2 && trouble <= 0)
          adjalign(1);
  
      /*
       * Depending on your luck & align level, the god you prayed to will:
       *  - fix your worst problem if it's major;
       *  - fix all your major problems;
       *  - fix your worst problem if it's minor;
       *  - fix all of your problems;
       *  - do you a gratuitous favor.
       *
       * If you make it to the last category, you roll randomly again
       * to see what they do for you.
       *
       * If your luck is at least 0, then you are guaranteed rescued from
       * your worst major problem.
       */
      if (!trouble && u.ualign.record >= DEVOUT) {
          /* if hero was in trouble, but got better, no special favor */
          if (g.p_trouble == 0)
              pat_on_head = 1;
      } else {
          int action, prayer_luck;
          int tryct = 0;
  
          /* Negative luck is normally impossible here (can_pray() forces
             prayer failure in that situation), but it's possible for
             Luck to drop during the period of prayer occupation and
             become negative by the time we get here.  [Reported case
             was lawful character whose stinking cloud caused a delayed
             killing of a peaceful human, triggering the "murderer"
             penalty while successful prayer was in progress.  It could
             also happen due to inconvenient timing on Friday 13th, but
             the magnitude there (-1) isn't big enough to cause trouble.]
             We don't bother remembering start-of-prayer luck, just make
             sure it's at least -1 so that Luck+2 is big enough to avoid
             a divide by zero crash when generating a random number.  */
          prayer_luck = max(Luck, -1); /* => (prayer_luck + 2 > 0) */
          action = rn1(prayer_luck + (on_altar() ? 3 + on_shrine() : 2), 1);
          if (!on_altar())
              action = min(action, 3);
          if (u.ualign.record < STRIDENT)
              action = (u.ualign.record > 0 || !rnl(2)) ? 1 : 0;
  
          switch (min(action, 5)) {
          case 5:
              pat_on_head = 1;
              /*FALLTHRU*/
          case 4:
              do
                  fix_worst_trouble(trouble);
              while ((trouble = in_trouble()) != 0);
              break;
  
          case 3:
              fix_worst_trouble(trouble);
          case 2:
              /* arbitrary number of tries */
              while ((trouble = in_trouble()) > 0 && (++tryct < 10))
                  fix_worst_trouble(trouble);
              break;
  
          case 1:
              if (trouble > 0)
                  fix_worst_trouble(trouble);
          case 0:
              break; /* your god blows you off, too bad */
          }
      }
  
      /* note: can't get pat_on_head unless all troubles have just been
         fixed or there were no troubles to begin with; hallucination
         won't be in effect so special handling for it is superfluous */
      if (pat_on_head)
          switch (rn2((Luck + 6) >> 1)) {
          case 0:
              break;
          case 1:
              if (uwep && (welded(uwep) || uwep->oclass == WEAPON_CLASS
                           || is_weptool(uwep))) {
                  char repair_buf[BUFSZ];
  
                  *repair_buf = '\0';
                  if (uwep->oeroded || uwep->oeroded2)
                      Sprintf(repair_buf, " and %s now as good as new",
                              otense(uwep, "are"));
  
                  if (uwep->cursed) {
                      if (!Blind) {
                          pline("%s %s%s.", Yobjnam2(uwep, "softly glow"),
                                hcolor(NH_AMBER), repair_buf);
                          iflags.last_msg = PLNMSG_OBJ_GLOWS;
                      } else
                          You_feel("the power of %s over %s.", u_gname(),
                                   yname(uwep));
                      uncurse(uwep);
                      uwep->bknown = 1; /* ok to bypass set_bknown() */
                      *repair_buf = '\0';
                  } else if (!uwep->blessed) {
                      if (!Blind) {
                          pline("%s with %s aura%s.",
                                Yobjnam2(uwep, "softly glow"),
                                an(hcolor(NH_LIGHT_BLUE)), repair_buf);
                          iflags.last_msg = PLNMSG_OBJ_GLOWS;
                      } else
                          You_feel("the blessing of %s over %s.", u_gname(),
                                   yname(uwep));
                      bless(uwep);
                      uwep->bknown = 1; /* ok to bypass set_bknown() */
                      *repair_buf = '\0';
                  }
  
                  /* fix any rust/burn/rot damage, but don't protect
                     against future damage */
                  if (uwep->oeroded || uwep->oeroded2) {
                      uwep->oeroded = uwep->oeroded2 = 0;
                      /* only give this message if we didn't just bless
                         or uncurse (which has already given a message) */
                      if (*repair_buf)
                          pline("%s as good as new!",
                                Yobjnam2(uwep, Blind ? "feel" : "look"));
                  }
                  update_inventory();
              }
              break;
          case 3:
              /* takes 2 hints to get the music to enter the stronghold;
                 skip if you've solved it via mastermind or destroyed the
                 drawbridge (both set uopened_dbridge) or if you've already
                 travelled past the Valley of the Dead (gehennom_entered) */
              if (!u.uevent.uopened_dbridge && !u.uevent.gehennom_entered) {
                  if (u.uevent.uheard_tune < 1) {
                      godvoice(g_align, (char *) 0);
                      verbalize("Hark, %s!", (g.youmonst.data->mlet == S_HUMAN)
                                                 ? "mortal"
                                                 : "creature");
                      verbalize(
                         "To enter the castle, thou must play the right tune!");
                      u.uevent.uheard_tune++;
                      break;
                  } else if (u.uevent.uheard_tune < 2) {
                      You_hear("a divine music...");
                      pline("It sounds like:  \"%s\".", g.tune);
                      u.uevent.uheard_tune++;
                      record_achievement(ACH_TUNE);
                      break;
                  }
              }
              /*FALLTHRU*/
          case 2:
              if (!Blind)
                  You("are surrounded by %s glow.", an(hcolor(NH_GOLDEN)));
              /* if any levels have been lost (and not yet regained),
                 treat this effect like blessed full healing */
              if (u.ulevel < u.ulevelmax) {
                  u.ulevelmax -= 1; /* see potion.c */
                  pluslvl(FALSE);
              } else {
                  u.uhpmax += 5;
                  if (u.uhpmax > u.uhppeak)
                      u.uhppeak = u.uhpmax;
                  if (Upolyd)
                      u.mhmax += 5;
              }
              u.uhp = u.uhpmax;
              if (Upolyd)
                  u.mh = u.mhmax;
              if (ABASE(A_STR) < AMAX(A_STR)) {
                  ABASE(A_STR) = AMAX(A_STR);
                  g.context.botl = 1; /* before potential message */
                  (void) encumber_msg();
              }
              if (u.uhunger < 900)
                  init_uhunger();
              /* luck couldn't have been negative at start of prayer because
                 the prayer would have failed, but might have been decremented
                 due to a timed event (delayed death of peaceful monster hit
                 by hero-created stinking cloud) during the praying interval */
              if (u.uluck < 0)
                  u.uluck = 0;
              /* superfluous; if hero was blinded we'd be handling trouble
                 rather than issuing a pat-on-head */
              u.ucreamed = 0;
              make_blinded(0L, TRUE);
              g.context.botl = 1;
              break;
          case 4: {
              register struct obj *otmp;
              int any = 0;
  
              if (Blind)
                  You_feel("the power of %s.", u_gname());
              else
                  You("are surrounded by %s aura.", an(hcolor(NH_LIGHT_BLUE)));
              for (otmp = g.invent; otmp; otmp = otmp->nobj) {
                  if (otmp->cursed
                      && (otmp != uarmh /* [see worst_cursed_item()] */
                          || uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT)) {
                      if (!Blind) {
                          pline("%s %s.", Yobjnam2(otmp, "softly glow"),
                                hcolor(NH_AMBER));
                          iflags.last_msg = PLNMSG_OBJ_GLOWS;
                          otmp->bknown = 1; /* ok to bypass set_bknown() */
                          ++any;
                      }
                      uncurse(otmp);
                  }
              }
              if (any)
                  update_inventory();
              break;
          }
          case 5: {
              static NEARDATA const char msg[] =
                  "\"and thus I grant thee the gift of %s!\"";
  
              godvoice(u.ualign.type,
                       "Thou hast pleased me with thy progress,");
              if (!(HTelepat & INTRINSIC)) {
                  HTelepat |= FROMOUTSIDE;
                  pline(msg, "Telepathy");
                  if (Blind)
                      see_monsters();
              } else if (!(HFast & INTRINSIC)) {
                  HFast |= FROMOUTSIDE;
                  pline(msg, "Speed");
              } else if (!(HStealth & INTRINSIC)) {
                  HStealth |= FROMOUTSIDE;
                  pline(msg, "Stealth");
              } else {
                  if (!(HProtection & INTRINSIC)) {
                      HProtection |= FROMOUTSIDE;
                      if (!u.ublessed)
                          u.ublessed = rn1(3, 2);
                  } else
                      u.ublessed++;
                  pline(msg, "my protection");
              }
              verbalize("Use it wisely in my name!");
              break;
          }
          case 7:
          case 8:
              if (u.ualign.record >= PIOUS && !u.uevent.uhand_of_elbereth) {
                  gcrownu();
                  break;
              }
              /*FALLTHRU*/
          case 6: {
              struct obj *otmp;
              int trycnt = u.ulevel + 1;
  
              /* not yet known spells given preference over already known ones;
                 also, try to grant a spell for which there is a skill slot */
              otmp = mkobj(SPBOOK_no_NOVEL, TRUE);
              while (--trycnt > 0) {
                  if (otmp->otyp != SPE_BLANK_PAPER) {
                      if (!known_spell(otmp->otyp)
                          && !P_RESTRICTED(spell_skilltype(otmp->otyp)))
                          break; /* usable, but not yet known */
                  } else {
                      if (!objects[SPE_BLANK_PAPER].oc_name_known
                          || carrying(MAGIC_MARKER))
                          break;
                  }
                  otmp->otyp = rnd_class(g.bases[SPBOOK_CLASS], SPE_BLANK_PAPER);
              }
              if (!u.uconduct.literate && !known_spell(otmp->otyp)) {
                  if (force_learn_spell(otmp->otyp))
                      pline("Divine knowledge of %s fills your mind!",
                            OBJ_NAME(objects[otmp->otyp]));
                  obfree(otmp, (struct obj *) 0);
              } else {
                  bless(otmp);
                  at_your_feet("A spellbook");
                  place_object(otmp, u.ux, u.uy);
                  newsym(u.ux, u.uy);
              }
              break;
          }
          default:
              impossible("Confused deity!");
              break;
          }
  
      u.ublesscnt = rnz(350);
      kick_on_butt = u.uevent.udemigod ? 1 : 0;
      if (u.uevent.uhand_of_elbereth)
          kick_on_butt++;
      if (kick_on_butt)
          u.ublesscnt += kick_on_butt * rnz(1000);
  
      /* Avoid games that go into infinite loops of copy-pasted commands
         with no human interaction; this is a DoS vector against the
         computer running NetHack.  Once the turn counter is over 100000,
         every additional 100 turns increases the prayer timeout by 1,
         thus eventually hunger prayers will fail and some other source
         of nutrition will be required.  The increase gets throttled if
         it ever reaches 32K so that configurations using 16-bit ints are
         still viable. */
      if (g.moves > 100000L) {
          long incr = (g.moves - 100000L) / 100L,
               largest_ublesscnt_incr = (long) (LARGEST_INT - u.ublesscnt);
  
          if (incr > largest_ublesscnt_incr)
              incr = largest_ublesscnt_incr;
          u.ublesscnt += (int) incr;
      }
  
      return;
  }
  
  /* either blesses or curses water on the altar,
   * returns true if it found any water here.
   */
  static boolean
  water_prayer(boolean bless_water)
  {
      register struct obj *otmp;
      register long changed = 0;
      boolean other = FALSE, bc_known = !(Blind || Hallucination);
  
      for (otmp = g.level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) {
          /* turn water into (un)holy water */
          if (otmp->otyp == POT_WATER
              && (bless_water ? !otmp->blessed : !otmp->cursed)) {
              otmp->blessed = bless_water;
              otmp->cursed = !bless_water;
              otmp->bknown = bc_known; /* ok to bypass set_bknown() */
              changed += otmp->quan;
          } else if (otmp->oclass == POTION_CLASS)
              other = TRUE;
      }
      if (!Blind && changed) {
          pline("%s potion%s on the altar glow%s %s for a moment.",
                ((other && changed > 1L) ? "Some of the"
                                         : (other ? "One of the" : "The")),
                ((other || changed > 1L) ? "s" : ""), (changed > 1L ? "" : "s"),
                (bless_water ? hcolor(NH_LIGHT_BLUE) : hcolor(NH_BLACK)));
      }
      return (boolean) (changed > 0L);
  }
  
  static void
  godvoice(aligntyp g_align, const char *words)
  {
      const char *quot = "";
  
      if (words)
          quot = "\"";
      else
          words = "";
  
      pline_The("voice of %s %s: %s%s%s", align_gname(g_align),
                godvoices[rn2(SIZE(godvoices))], quot, words, quot);
  }
  
  static void
  gods_angry(aligntyp g_align)
  {
      godvoice(g_align, "Thou hast angered me.");
  }
  
  /* The g_align god is upset with you. */
  static void
  gods_upset(aligntyp g_align)
  {
      if (g_align == u.ualign.type)
          u.ugangr++;
      else if (u.ugangr)
          u.ugangr--;
      angrygods(g_align);
  }
  
  static void
  consume_offering(struct obj *otmp)
  {
      if (Hallucination)
          switch (rn2(3)) {
          case 0:
              Your("sacrifice sprouts wings and a propeller and roars away!");
              break;
          case 1:
              Your("sacrifice puffs up, swelling bigger and bigger, and pops!");
              break;
          case 2:
              Your(
       "sacrifice collapses into a cloud of dancing particles and fades away!");
              break;
          }
      else if (Blind && u.ualign.type == A_LAWFUL)
          Your("sacrifice disappears!");
      else
          Your("sacrifice is consumed in a %s!",
               u.ualign.type == A_LAWFUL
                  ? "flash of light"
                  : u.ualign.type == A_NEUTRAL
                      ? "cloud of smoke"
                      : "burst of flame");
      if (carried(otmp))
          useup(otmp);
      else
          useupf(otmp, 1L);
      exercise(A_WIS, TRUE);
  }
  
  /* the #offer command - sacrifice something to the gods */
  int
  dosacrifice(void)
  {
      static NEARDATA const char
          cloud_of_smoke[] = "A cloud of %s smoke surrounds you...";
      register struct obj *otmp;
      int value = 0, pm;
      boolean highaltar;
      aligntyp altaralign = a_align(u.ux, u.uy);
  
      if (!on_altar() || u.uswallow) {
          You("are not standing on an altar.");
          return ECMD_OK;
      }
      highaltar = ((Is_astralevel(&u.uz) || Is_sanctum(&u.uz))
                   && (levl[u.ux][u.uy].altarmask & AM_SHRINE));
  
      otmp = floorfood("sacrifice", 1);
      if (!otmp)
          return ECMD_OK;
      /*
       * Was based on nutritional value and aging behavior (< 50 moves).
       * Sacrificing a food ration got you max luck instantly, making the
       * gods as easy to please as an angry dog!
       *
       * Now only accepts corpses, based on the game's evaluation of their
       * toughness.  Human and pet sacrifice, as well as sacrificing unicorns
       * of your alignment, is strongly discouraged.
       */
  #define MAXVALUE 24 /* Highest corpse value (besides Wiz) */
  
      if (otmp->otyp == CORPSE) {
          register struct permonst *ptr = &mons[otmp->corpsenm];
          struct monst *mtmp;
  
          /* KMH, conduct */
          if (!u.uconduct.gnostic++)
              livelog_printf(LL_CONDUCT,
                             "rejected atheism by offering %s on an altar of %s",
                             corpse_xname(otmp, (const char *) 0, CXN_ARTICLE),
                             a_gname());
  
          /* you're handling this corpse, even if it was killed upon the altar
           */
          feel_cockatrice(otmp, TRUE);
          if (rider_corpse_revival(otmp, FALSE))
              return ECMD_TIME;
  
          if (otmp->corpsenm == PM_ACID_BLOB
              || (g.moves <= peek_at_iced_corpse_age(otmp) + 50)) {
              value = mons[otmp->corpsenm].difficulty + 1;
              if (otmp->oeaten)
                  value = eaten_stat(value, otmp);
          }
  
          /* same race or former pet results apply even if the corpse is
             too old (value==0) */
          if (your_race(ptr)) {
              if (is_demon(g.youmonst.data)) {
                  You("find the idea very satisfying.");
                  exercise(A_WIS, TRUE);
              } else if (u.ualign.type != A_CHAOTIC) {
                  pline("You'll regret this infamous offense!");
                  exercise(A_WIS, FALSE);
              }
  
              if (highaltar
                  && (altaralign != A_CHAOTIC || u.ualign.type != A_CHAOTIC)) {
                  goto desecrate_high_altar;
              } else if (altaralign != A_CHAOTIC && altaralign != A_NONE) {
                  /* curse the lawful/neutral altar */
                  pline_The("altar is stained with %s blood.", g.urace.adj);
                  levl[u.ux][u.uy].altarmask = AM_CHAOTIC;
                  newsym(u.ux, u.uy); /* in case Invisible to self */
                  angry_priest();
              } else {
                  struct monst *dmon;
                  const char *demonless_msg;
  
                  /* Human sacrifice on a chaotic or unaligned altar */
                  /* is equivalent to demon summoning */
                  if (altaralign == A_CHAOTIC && u.ualign.type != A_CHAOTIC) {
                      pline(
                      "The blood floods the altar, which vanishes in %s cloud!",
                            an(hcolor(NH_BLACK)));
                      levl[u.ux][u.uy].typ = ROOM;
                      levl[u.ux][u.uy].altarmask = 0;
                      newsym(u.ux, u.uy);
                      angry_priest();
                      demonless_msg = "cloud dissipates";
                  } else {
                      /* either you're chaotic or altar is Moloch's or both */
                      pline_The("blood covers the altar!");
                      change_luck(altaralign == A_NONE ? -2 : 2);
                      demonless_msg = "blood coagulates";
                  }
                  if ((pm = dlord(altaralign)) != NON_PM
                      && (dmon = makemon(&mons[pm], u.ux, u.uy, MM_NOMSG))
                             != 0) {
                      char dbuf[BUFSZ];
  
                      Strcpy(dbuf, a_monnam(dmon));
                      if (!strcmpi(dbuf, "it"))
                          Strcpy(dbuf, "something dreadful");
                      else
                          dmon->mstrategy &= ~STRAT_APPEARMSG;
                      You("have summoned %s!", dbuf);
                      if (sgn(u.ualign.type) == sgn(dmon->data->maligntyp))
                          dmon->mpeaceful = TRUE;
                      You("are terrified, and unable to move.");
                      nomul(-3);
                      g.multi_reason = "being terrified of a demon";
                      g.nomovemsg = 0;
                  } else
                      pline_The("%s.", demonless_msg);
              }
  
              if (u.ualign.type != A_CHAOTIC) {
                  adjalign(-5);
                  u.ugangr += 3;
                  (void) adjattrib(A_WIS, -1, TRUE);
                  if (!Inhell)
                      angrygods(u.ualign.type);
                  change_luck(-5);
              } else
                  adjalign(5);
              if (carried(otmp))
                  useup(otmp);
              else
                  useupf(otmp, 1L);
              return ECMD_TIME;
          } else if (has_omonst(otmp)
                     && (mtmp = get_mtraits(otmp, FALSE)) != 0
                     && mtmp->mtame) {
                  /* mtmp is a temporary pointer to a tame monster's attributes,
                   * not a real monster */
              pline("So this is how you repay loyalty?");
              adjalign(-3);
              value = -1;
              HAggravate_monster |= FROMOUTSIDE;
          } else if (!value) {
              ; /* too old; don't give undead or unicorn bonus or penalty */
          } else if (is_undead(ptr)) { /* Not demons--no demon corpses */
              /* most undead that leave a corpse yield 'human' (or other race)
                 corpse so won't get here; the exception is wraith; give the
                 bonus for wraith to chaotics too because they are sacrificing
                 something valuable (unless hero refuses to eat such things) */
              if (u.ualign.type != A_CHAOTIC
                  /* reaching this side of the 'or' means hero is chaotic */
                  || (ptr == &mons[PM_WRAITH] && u.uconduct.unvegetarian))
                  value += 1;
          } else if (is_unicorn(ptr)) {
              int unicalign = sgn(ptr->maligntyp);
  
              if (unicalign == altaralign) {
                  /* When same as altar, always a very bad action.
                   */
                  pline("Such an action is an insult to %s!",
                        (unicalign == A_CHAOTIC) ? "chaos"
                           : unicalign ? "law" : "balance");
                  (void) adjattrib(A_WIS, -1, TRUE);
                  value = -5;
              } else if (u.ualign.type == altaralign) {
                  /* When different from altar, and altar is same as yours,
                   * it's a very good action.
                   */
                  if (u.ualign.record < ALIGNLIM)
                      You_feel("appropriately %s.", align_str(u.ualign.type));
                  else
                      You_feel("you are thoroughly on the right path.");
                  adjalign(5);
                  value += 3;
              } else if (unicalign == u.ualign.type) {
                  /* When sacrificing unicorn of your alignment to altar not of
                   * your alignment, your god gets angry and it's a conversion.
                   */
                  u.ualign.record = -1;
                  value = 1;
              } else {
                  /* Otherwise, unicorn's alignment is different from yours
                   * and different from the altar's.  It's an ordinary (well,
                   * with a bonus) sacrifice on a cross-aligned altar.
                   */
                  value += 3;
              }
          }
      } /* corpse */
  
      if (otmp->otyp == AMULET_OF_YENDOR) {
          if (!highaltar) {
   too_soon:
              if (altaralign == A_NONE && Inhell)
                  /* hero has left Moloch's Sanctum so is in the process
                     of getting away with the Amulet (outside of Gehennom,
                     fall through to the "ashamed" feedback) */
                  gods_upset(A_NONE);
              else
                  You_feel("%s.",
                           Hallucination
                              ? "homesick"
                              /* if on track, give a big hint */
                              : (altaralign == u.ualign.type)
                                 ? "an urge to return to the surface"
                                 /* else headed towards celestial disgrace */
                                 : "ashamed");
              return ECMD_TIME;
          } else {
              /* The final Test.  Did you win? */
              if (uamul == otmp)
                  Amulet_off();
              if (carried(otmp))
                  useup(otmp); /* well, it's gone now */
              else
                  useupf(otmp, 1L);
              You("offer the Amulet of Yendor to %s...", a_gname());
              if (altaralign == A_NONE) {
                  /* Moloch's high altar */
                  if (u.ualign.record > -99)
                      u.ualign.record = -99;
                  pline(
                "An invisible choir chants, and you are bathed in darkness...");
                  /*[apparently shrug/snarl can be sensed without being seen]*/
                  pline("%s shrugs and retains dominion over %s,", Moloch,
                        u_gname());
                  pline("then mercilessly snuffs out your life.");
                  Sprintf(g.killer.name, "%s indifference", s_suffix(Moloch));
                  g.killer.format = KILLED_BY;
                  done(DIED);
                  /* life-saved (or declined to die in wizard/explore mode) */
                  pline("%s snarls and tries again...", Moloch);
                  fry_by_god(A_NONE, TRUE); /* wrath of Moloch */
                  /* declined to die in wizard or explore mode */
                  pline(cloud_of_smoke, hcolor(NH_BLACK));
                  done(ESCAPED);
              } else if (u.ualign.type != altaralign) {
                  /* And the opposing team picks you up and
                     carries you off on their shoulders */
                  adjalign(-99);
                  pline("%s accepts your gift, and gains dominion over %s...",
                        a_gname(), u_gname());
                  pline("%s is enraged...", u_gname());
                  pline("Fortunately, %s permits you to live...", a_gname());
                  pline(cloud_of_smoke, hcolor(NH_ORANGE));
                  done(ESCAPED);
              } else { /* super big win */
                  u.uevent.ascended = 1;
                  adjalign(10);
                  pline(
                 "An invisible choir sings, and you are bathed in radiance...");
                  godvoice(altaralign, "Mortal, thou hast done well!");
                  display_nhwindow(WIN_MESSAGE, FALSE);
                  verbalize(
            "In return for thy service, I grant thee the gift of Immortality!");
                  You("ascend to the status of Demigod%s...",
                      flags.female ? "dess" : "");
                  done(ASCENDED);
              }
              /*NOTREACHED*/
          }
      } /* real Amulet */
  
      if (otmp->otyp == FAKE_AMULET_OF_YENDOR) {
          if (!highaltar && !otmp->known)
              goto too_soon;
          You_hear("a nearby thunderclap.");
          if (!otmp->known) {
              You("realize you have made a %s.",
                  Hallucination ? "boo-boo" : "mistake");
              otmp->known = TRUE;
              change_luck(-1);
              return ECMD_TIME;
          } else {
              /* don't you dare try to fool the gods */
              if (Deaf)
                  pline("Oh, no."); /* didn't hear thunderclap */
              change_luck(-3);
              adjalign(-1);
              u.ugangr += 3;
              value = -3;
          }
      } /* fake Amulet */
  
      if (value == 0) {
          pline1(nothing_happens);
          return ECMD_TIME;
      }
  
      if (altaralign != u.ualign.type && highaltar) {
   desecrate_high_altar:
          /*
           * REAL BAD NEWS!!! High altars cannot be converted.  Even an attempt
           * gets the god who owns it truly pissed off.
           */
          You_feel("the air around you grow charged...");
          pline("Suddenly, you realize that %s has noticed you...", a_gname());
          godvoice(altaralign,
                   "So, mortal!  You dare desecrate my High Temple!");
          /* Throw everything we have at the player */
          god_zaps_you(altaralign);
      } else if (value < 0) { /* don't think the gods are gonna like this... */
          gods_upset(altaralign);
      } else {
          int saved_anger = u.ugangr;
          int saved_cnt = u.ublesscnt;
          int saved_luck = u.uluck;
  
          /* Sacrificing at an altar of a different alignment */
          if (u.ualign.type != altaralign) {
              /* Is this a conversion ? */
              /* An unaligned altar in Gehennom will always elicit rejection. */
              if (ugod_is_angry() || (altaralign == A_NONE && Inhell)) {
                  if (u.ualignbase[A_CURRENT] == u.ualignbase[A_ORIGINAL]
                      && altaralign != A_NONE) {
                      You("have a strong feeling that %s is angry...",
                          u_gname());
                      consume_offering(otmp);
                      pline("%s accepts your allegiance.", a_gname());
  
                      uchangealign(altaralign, 0);
                      /* Beware, Conversion is costly */
                      change_luck(-3);
                      u.ublesscnt += 300;
                  } else {
                      u.ugangr += 3;
                      adjalign(-5);
                      pline("%s rejects your sacrifice!", a_gname());
                      godvoice(altaralign, "Suffer, infidel!");
                      change_luck(-5);
                      (void) adjattrib(A_WIS, -2, TRUE);
                      if (!Inhell)
                          angrygods(u.ualign.type);
                  }
                  return ECMD_TIME;
              } else {
                  consume_offering(otmp);
                  You("sense a conflict between %s and %s.", u_gname(),
                      a_gname());
                  if (rn2(8 + u.ulevel) > 5) {
                      struct monst *pri;
                      boolean shrine;
  
                      You_feel("the power of %s increase.", u_gname());
                      exercise(A_WIS, TRUE);
                      change_luck(1);
                      shrine = on_shrine();
                      levl[u.ux][u.uy].altarmask = Align2amask(u.ualign.type);
                      if (shrine)
                          levl[u.ux][u.uy].altarmask |= AM_SHRINE;
                      newsym(u.ux, u.uy); /* in case Invisible to self */
                      if (!Blind)
                          pline_The("altar glows %s.",
                                    hcolor((u.ualign.type == A_LAWFUL)
                                              ? NH_WHITE
                                              : u.ualign.type
                                                 ? NH_BLACK
                                                 : (const char *) "gray"));
  
                      if (rnl(u.ulevel) > 6 && u.ualign.record > 0
                          && rnd(u.ualign.record) > (3 * ALIGNLIM) / 4)
                          summon_minion(altaralign, TRUE);
                      /* anger priest; test handles bones files */
                      if ((pri = findpriest(temple_occupied(u.urooms)))
                          && !p_coaligned(pri))
                          angry_priest();
                  } else {
                      pline("Unluckily, you feel the power of %s decrease.",
                            u_gname());
                      change_luck(-1);
                      exercise(A_WIS, FALSE);
                      if (rnl(u.ulevel) > 6 && u.ualign.record > 0
                          && rnd(u.ualign.record) > (7 * ALIGNLIM) / 8)
                          summon_minion(altaralign, TRUE);
                  }
                  return ECMD_TIME;
              }
          }
  
          consume_offering(otmp);
          /* OK, you get brownie points. */
          if (u.ugangr) {
              u.ugangr -= ((value * (u.ualign.type == A_CHAOTIC ? 2 : 3))
                           / MAXVALUE);
              if (u.ugangr < 0)
                  u.ugangr = 0;
              if (u.ugangr != saved_anger) {
                  if (u.ugangr) {
                      pline("%s seems %s.", u_gname(),
                            Hallucination ? "groovy" : "slightly mollified");
  
                      if ((int) u.uluck < 0)
                          change_luck(1);
                  } else {
                      pline("%s seems %s.", u_gname(),
                            Hallucination ? "cosmic (not a new fact)"
                                          : "mollified");
  
                      if ((int) u.uluck < 0)
                          u.uluck = 0;
                  }
              } else { /* not satisfied yet */
                  if (Hallucination)
                      pline_The("gods seem tall.");
                  else
                      You("have a feeling of inadequacy.");
              }
          } else if (ugod_is_angry()) {
              if (value > MAXVALUE)
                  value = MAXVALUE;
              if (value > -u.ualign.record)
                  value = -u.ualign.record;
              adjalign(value);
              You_feel("partially absolved.");
          } else if (u.ublesscnt > 0) {
              u.ublesscnt -= ((value * (u.ualign.type == A_CHAOTIC ? 500 : 300))
                              / MAXVALUE);
              if (u.ublesscnt < 0)
                  u.ublesscnt = 0;
              if (u.ublesscnt != saved_cnt) {
                  if (u.ublesscnt) {
                      if (Hallucination)
                          You("realize that the gods are not like you and I.");
                      else
                          You("have a hopeful feeling.");
                      if ((int) u.uluck < 0)
                          change_luck(1);
                  } else {
                      if (Hallucination)
                          pline("Overall, there is a smell of fried onions.");
                      else
                          You("have a feeling of reconciliation.");
                      if ((int) u.uluck < 0)
                          u.uluck = 0;
                  }
              }
          } else {
              int nartifacts = nartifact_exist();
  
              /* you were already in pretty good standing */
              /* The player can gain an artifact */
              /* The chance goes down as the number of artifacts goes up */
              if (u.ulevel > 2 && u.uluck >= 0
                  && !rn2(10 + (2 * u.ugifts * nartifacts))) {
                  otmp = mk_artifact((struct obj *) 0, a_align(u.ux, u.uy));
                  if (otmp) {
                      if (otmp->spe < 0)
                          otmp->spe = 0;
                      if (otmp->cursed)
                          uncurse(otmp);
                      otmp->oerodeproof = TRUE;
                      at_your_feet("An object");
                      dropy(otmp);
                      godvoice(u.ualign.type, "Use my gift wisely!");
                      u.ugifts++;
                      u.ublesscnt = rnz(300 + (50 * nartifacts));
                      exercise(A_WIS, TRUE);
                      livelog_printf (LL_DIVINEGIFT|LL_ARTIFACT,
                                      "had %s bestowed upon %s by %s",
                                      artiname(otmp->oartifact),
                                      uhim(), align_gname(u.ualign.type));
                      /* make sure we can use this weapon */
                      unrestrict_weapon_skill(weapon_type(otmp));
                      if (!Hallucination && !Blind) {
                          otmp->dknown = 1;
                          makeknown(otmp->otyp);
                          discover_artifact(otmp->oartifact);
                      }
                      return ECMD_TIME;
                  }
              }
              change_luck((value * LUCKMAX) / (MAXVALUE * 2));
              if ((int) u.uluck < 0)
                  u.uluck = 0;
              if (u.uluck != saved_luck) {
                  if (Blind)
                      You("think %s brushed your %s.", something,
                          body_part(FOOT));
                  else
                      You(Hallucination
                      ? "see crabgrass at your %s.  A funny thing in a dungeon."
                              : "glimpse a four-leaf clover at your %s.",
                          makeplural(body_part(FOOT)));
              }
          }
      }
      return ECMD_TIME;
  }
  
  /* determine prayer results in advance; also used for enlightenment */
  boolean
  can_pray(boolean praying) /* false means no messages should be given */
  {
      int alignment;
  
      g.p_aligntyp = on_altar() ? a_align(u.ux, u.uy) : u.ualign.type;
      g.p_trouble = in_trouble();
  
      if (is_demon(g.youmonst.data) /* ok if chaotic or none (Moloch) */
          && (g.p_aligntyp == A_LAWFUL || g.p_aligntyp != A_NEUTRAL)) {
          if (praying)
              pline_The("very idea of praying to a %s god is repugnant to you.",
                        g.p_aligntyp ? "lawful" : "neutral");
          return FALSE;
      }
  
      if (praying)
          You("begin praying to %s.", align_gname(g.p_aligntyp));
  
      if (u.ualign.type && u.ualign.type == -g.p_aligntyp)
          alignment = -u.ualign.record; /* Opposite alignment altar */
      else if (u.ualign.type != g.p_aligntyp)
          alignment = u.ualign.record / 2; /* Different alignment altar */
      else
          alignment = u.ualign.record;
  
      if (g.p_aligntyp == A_NONE) /* praying to Moloch */
          g.p_type = -2;
      else if ((g.p_trouble > 0) ? (u.ublesscnt > 200) /* big trouble */
               : (g.p_trouble < 0) ? (u.ublesscnt > 100) /* minor difficulties */
                 : (u.ublesscnt > 0))                  /* not in trouble */
          g.p_type = 0;                     /* too soon... */
      else if ((int) Luck < 0 || u.ugangr || alignment < 0)
          g.p_type = 1; /* too naughty... */
      else /* alignment >= 0 */ {
          if (on_altar() && u.ualign.type != g.p_aligntyp)
              g.p_type = 2;
          else
              g.p_type = 3;
      }
  
      if (is_undead(g.youmonst.data) && !Inhell
          && (g.p_aligntyp == A_LAWFUL
              || (g.p_aligntyp == A_NEUTRAL && !rn2(10))))
          g.p_type = -1;
      /* Note:  when !praying, the random factor for neutrals makes the
         return value a non-deterministic approximation for enlightenment.
         This case should be uncommon enough to live with... */
  
      return !praying ? (boolean) (g.p_type == 3 && !Inhell) : TRUE;
  }
  
  /* #pray commmand */
  int
  dopray(void)
  {
      /* Confirm accidental slips of Alt-P */
      if (ParanoidPray && yn("Are you sure you want to pray?") != 'y')
          return ECMD_OK;
  
      if (!u.uconduct.gnostic++)
          /* breaking conduct should probably occur in can_pray() at
           * "You begin praying to %s", as demons who find praying repugnant
           * should not break conduct.  Also we can add more detail to the
           * livelog message as p_aligntyp will be known.
           */
          livelog_printf(LL_CONDUCT, "rejected atheism with a prayer");
  
      /* set up p_type and p_alignment */
      if (!can_pray(TRUE))
          return ECMD_OK;
  
      if (wizard && g.p_type >= 0) {
          if (yn("Force the gods to be pleased?") == 'y') {
              u.ublesscnt = 0;
              if (u.uluck < 0)
                  u.uluck = 0;
              if (u.ualign.record <= 0)
                  u.ualign.record = 1;
              u.ugangr = 0;
              if (g.p_type < 2)
                  g.p_type = 3;
          }
      }
      nomul(-3);
      g.multi_reason = "praying";
      g.nomovemsg = "You finish your prayer.";
      g.afternmv = prayer_done;
  
      if (g.p_type == 3 && !Inhell) {
          /* if you've been true to your god you can't die while you pray */
          if (!Blind)
              You("are surrounded by a shimmering light.");
          u.uinvulnerable = TRUE;
      }
  
      return ECMD_TIME;
  }
  
  static int
  prayer_done(void) /* M. Stephenson (1.0.3b) */
  {
      aligntyp alignment = g.p_aligntyp;
  
      u.uinvulnerable = FALSE;
      if (g.p_type == -2) {
          /* praying at an unaligned altar, not necessarily in Gehennom */
          You("%s diabolical laughter all around you...",
              !Deaf ? "hear" : "intuit");
          wake_nearby();
          adjalign(-2);
          exercise(A_WIS, FALSE);
          if (!Inhell) {
              /* hero's god[dess] seems to be keeping his/her head down */
              pline("Nothing else happens."); /* not actually true... */
              return 1;
          } /* else use regular Inhell result below */
      } else if (g.p_type == -1) {
          /* praying while poly'd into an undead creature while non-chaotic */
          godvoice(alignment,
                   (alignment == A_LAWFUL)
                      ? "Vile creature, thou durst call upon me?"
                      : "Walk no more, perversion of nature!");
          You_feel("like you are falling apart.");
          /* KMH -- Gods have mastery over unchanging */
          rehumanize();
          /* no Half_physical_damage adjustment here */
          losehp(rnd(20), "residual undead turning effect", KILLED_BY_AN);
          exercise(A_CON, FALSE);
          return 1;
      }
      if (Inhell) {
          pline("Since you are in Gehennom, %s can't help you.",
                align_gname(alignment));
          /* haltingly aligned is least likely to anger */
          if (u.ualign.record <= 0 || rnl(u.ualign.record))
              angrygods(u.ualign.type);
          return 0;
      }
  
      if (g.p_type == 0) {
          if (on_altar() && u.ualign.type != alignment)
              (void) water_prayer(FALSE);
          u.ublesscnt += rnz(250);
          change_luck(-3);
          gods_upset(u.ualign.type);
      } else if (g.p_type == 1) {
          if (on_altar() && u.ualign.type != alignment)
              (void) water_prayer(FALSE);
          angrygods(u.ualign.type); /* naughty */
      } else if (g.p_type == 2) {
          if (water_prayer(FALSE)) {
              /* attempted water prayer on a non-coaligned altar */
              u.ublesscnt += rnz(250);
              change_luck(-3);
              gods_upset(u.ualign.type);
          } else
              pleased(alignment);
      } else {
          /* coaligned */
          if (on_altar())
              (void) water_prayer(TRUE);
          pleased(alignment); /* nice */
      }
      return 1;
  }
  
  /* #turn command */
  int
  doturn(void)
  {
      /* Knights & Priest(esse)s only please */
      struct monst *mtmp, *mtmp2;
      const char *Gname;
      int once, range, xlev;
  
      if (!Role_if(PM_CLERIC) && !Role_if(PM_KNIGHT)) {
          /* Try to use the "turn undead" spell. */
          if (known_spell(SPE_TURN_UNDEAD))
              return spelleffects(SPE_TURN_UNDEAD, FALSE);
          You("don't know how to turn undead!");
          return ECMD_OK;
      }
      if (!u.uconduct.gnostic++)
          livelog_printf(LL_CONDUCT, "rejected atheism by turning undead");
  
      Gname = halu_gname(u.ualign.type);
  
      /* [What about needing free hands (does #turn involve any gesturing)?] */
      if (!can_chant(&g.youmonst)) {
          /* "evilness": "demons and undead" is too verbose and too precise */
          You("are %s upon %s to turn aside evilness.",
              Strangled ? "not able to call" : "incapable of calling", Gname);
          /* violates agnosticism due to intent; conduct tracking is not
             supposed to affect play but we make an exception here:  use a
             move if this is the first time agnostic conduct has been broken */
          return (u.uconduct.gnostic == 1) ? ECMD_TIME : ECMD_OK;
      }
      if ((u.ualign.type != A_CHAOTIC
           && (is_demon(g.youmonst.data)
               || is_undead(g.youmonst.data) || is_vampshifter(&g.youmonst)))
          || u.ugangr > 6) { /* "Die, mortal!" */
          pline("For some reason, %s seems to ignore you.", Gname);
          aggravate();
          exercise(A_WIS, FALSE);
          return ECMD_TIME;
      }
      if (Inhell) {
          pline("Since you are in Gehennom, %s %s help you.",
                /* not actually calling upon Moloch but use alternate
                   phrasing anyway if hallucinatory feedback says it's him */
                Gname, !strcmp(Gname, Moloch) ? "won't" : "can't");
          aggravate();
          return ECMD_TIME;
      }
      pline("Calling upon %s, you chant an arcane formula.", Gname);
      exercise(A_WIS, TRUE);
  
      /* note: does not perform unturn_dead() on victims' inventories */
      range = BOLT_LIM + (u.ulevel / 5); /* 8 to 14 */
      range *= range;
      once = 0;
      for (mtmp = fmon; mtmp; mtmp = mtmp2) {
          mtmp2 = mtmp->nmon;
          if (DEADMONSTER(mtmp))
              continue;
          /* 3.6.3: used to use cansee() here but the purpose is to prevent
             #turn operating through walls, not to require that the hero be
             able to see the target location */
          if (!couldsee(mtmp->mx, mtmp->my)
              || distu(mtmp->mx, mtmp->my) > range)
              continue;
  
          if (!mtmp->mpeaceful
              && (is_undead(mtmp->data) || is_vampshifter(mtmp)
                  || (is_demon(mtmp->data) && (u.ulevel > (MAXULEV / 2))))) {
              mtmp->msleeping = 0;
              if (Confusion) {
                  if (!once++)
                      pline("Unfortunately, your voice falters.");
                  mtmp->mflee = 0;
                  mtmp->mfrozen = 0;
                  mtmp->mcanmove = 1;
              } else if (!resist(mtmp, '\0', 0, TELL)) {
                  xlev = 6;
                  switch (mtmp->data->mlet) {
                  /* this is intentional, lichs are tougher
                     than zombies. */
                  case S_LICH:
                      xlev += 2;
                      /*FALLTHRU*/
                  case S_GHOST:
                      xlev += 2;
                      /*FALLTHRU*/
                  case S_VAMPIRE:
                      xlev += 2;
                      /*FALLTHRU*/
                  case S_WRAITH:
                      xlev += 2;
                      /*FALLTHRU*/
                  case S_MUMMY:
                      xlev += 2;
                      /*FALLTHRU*/
                  case S_ZOMBIE:
                      if (u.ulevel >= xlev && !resist(mtmp, '\0', 0, NOTELL)) {
                          if (u.ualign.type == A_CHAOTIC) {
                              mtmp->mpeaceful = 1;
                              set_malign(mtmp);
                          } else { /* damn them */
                              killed(mtmp);
                          }
                          break;
                      } /* else flee */
                  /*FALLTHRU*/
                  default:
                      monflee(mtmp, 0, FALSE, TRUE);
                      break;
                  }
              }
          }
      }
  
      /*
       *  There is no detrimental effect on self for successful #turn
       *  while in demon or undead form.  That can only be done while
       *  chaotic oneself (see "For some reason" above) and chaotic
       *  turning only makes targets peaceful.
       *
       *  Paralysis duration probably ought to be based on the strengh
       *  of turned creatures rather than on turner's level.
       *  Why doesn't this honor Free_action?  [Because being able to
       *  repeat #turn every turn would be too powerful.  Maybe instead
       *  of nomul(-N) we should add the equivalent of mon->mspec_used
       *  for the hero and refuse to #turn when it's non-zero?  Or have
       *  both and u.uspec_used only matters when Free_action prevents
       *  the brief paralysis?]
       */
      nomul(-(5 - ((u.ulevel - 1) / 6))); /* -5 .. -1 */
      g.multi_reason = "trying to turn the monsters";
      g.nomovemsg = You_can_move_again;
      return ECMD_TIME;
  }
  
  int
  altarmask_at(int x, int y)
  {
      int res = 0;
  
      if (isok(x, y)) {
          struct monst *mon = m_at(x, y);
  
          if (mon && M_AP_TYPE(mon) == M_AP_FURNITURE
              && mon->mappearance == S_altar)
              res = has_mcorpsenm(mon) ? MCORPSENM(mon) : 0;
          else if (IS_ALTAR(levl[x][y].typ))
              res = levl[x][y].altarmask;
      }
      return res;
  }
  
  const char *
  a_gname(void)
  {
      return a_gname_at(u.ux, u.uy);
  }
  
  /* returns the name of an altar's deity */
  const char *
  a_gname_at(xchar x, xchar y)
  {
      if (!IS_ALTAR(levl[x][y].typ))
          return (char *) 0;
  
      return align_gname(a_align(x, y));
  }
  
  /* returns the name of the hero's deity */
  const char *
  u_gname(void)
  {
      return align_gname(u.ualign.type);
  }
  
  const char *
  align_gname(aligntyp alignment)
  {
      const char *gnam;
  
      switch (alignment) {
      case A_NONE:
          gnam = Moloch;
          break;
      case A_LAWFUL:
          gnam = g.urole.lgod;
          break;
      case A_NEUTRAL:
          gnam = g.urole.ngod;
          break;
      case A_CHAOTIC:
          gnam = g.urole.cgod;
          break;
      default:
          impossible("unknown alignment.");
          gnam = "someone";
          break;
      }
      if (*gnam == '_')
          ++gnam;
      return gnam;
  }
  
  static const char *const hallu_gods[] = {
      "the Flying Spaghetti Monster", /* Church of the FSM */
      "Eris",                         /* Discordianism */
      "the Martians",                 /* every science fiction ever */
      "Xom",                          /* Crawl */
      "AnDoR dRaKoN",                 /* ADOM */
      "the Central Bank of Yendor",   /* economics */
      "Tooth Fairy",                  /* real world(?) */
      "Om",                           /* Discworld */
      "Yawgmoth",                     /* Magic: the Gathering */
      "Morgoth",                      /* LoTR */
      "Cthulhu",                      /* Lovecraft */
      "the Ori",                      /* Stargate */
      "destiny",                      /* why not? */
      "your Friend the Computer",     /* Paranoia */
  };
  
  /* hallucination handling for priest/minion names: select a random god
     iff character is hallucinating */
  const char *
  halu_gname(aligntyp alignment)
  {
      const char *gnam = NULL;
      int which;
  
      if (!Hallucination)
          return align_gname(alignment);
  
      /* Some roles (Priest) don't have a pantheon unless we're playing as
         that role, so keep trying until we get a role which does have one.
         [If playing a Priest, the current pantheon will be twice as likely
         to get picked as any of the others.  That's not significant enough
         to bother dealing with.] */
      do
          which = randrole(TRUE);
      while (!roles[which].lgod);
  
      switch (rn2_on_display_rng(9)) {
      case 0:
      case 1:
          gnam = roles[which].lgod;
          break;
      case 2:
      case 3:
          gnam = roles[which].ngod;
          break;
      case 4:
      case 5:
          gnam = roles[which].cgod;
          break;
      case 6:
      case 7:
          gnam = hallu_gods[rn2_on_display_rng(SIZE(hallu_gods))];
          break;
      case 8:
          gnam = Moloch;
          break;
      default:
          impossible("rn2 broken in halu_gname?!?");
      }
      if (!gnam) {
          impossible("No random god name?");
          gnam = "your Friend the Computer"; /* Paranoia */
      }
      if (*gnam == '_')
          ++gnam;
      return gnam;
  }
  
  /* deity's title */
  const char *
  align_gtitle(aligntyp alignment)
  {
      const char *gnam, *result = "god";
  
      switch (alignment) {
      case A_LAWFUL:
          gnam = g.urole.lgod;
          break;
      case A_NEUTRAL:
          gnam = g.urole.ngod;
          break;
      case A_CHAOTIC:
          gnam = g.urole.cgod;
          break;
      default:
          gnam = 0;
          break;
      }
      if (gnam && *gnam == '_')
          result = "goddess";
      return result;
  }
  
  void
  altar_wrath(int x, int y)
  {
      aligntyp altaralign = a_align(x, y);
  
      if (u.ualign.type == altaralign && u.ualign.record > -rn2(4)) {
          godvoice(altaralign, "How darest thou desecrate my altar!");
          (void) adjattrib(A_WIS, -1, FALSE);
          u.ualign.record--;
      } else {
          pline("%s %s%s:",
                !Deaf ? "A voice (could it be"
                      : "Despite your deafness, you seem to hear",
                align_gname(altaralign),
                !Deaf ? "?) whispers" : " say");
          verbalize("Thou shalt pay, infidel!");
          /* higher luck is more likely to be reduced; as it approaches -5
             the chance to lose another point drops down, eventually to 0 */
          if (Luck > -5 && rn2(Luck + 6))
              change_luck(rn2(20) ? -1 : -2);
      }
  }
  
  /* assumes isok() at one space away, but not necessarily at two */
  static boolean
  blocked_boulder(int dx, int dy)
  {
      register struct obj *otmp;
      int nx, ny;
      long count = 0L;
  
      for (otmp = g.level.objects[u.ux + dx][u.uy + dy]; otmp;
           otmp = otmp->nexthere) {
          if (otmp->otyp == BOULDER)
              count += otmp->quan;
      }
  
      nx = u.ux + 2 * dx, ny = u.uy + 2 * dy; /* next spot beyond boulder(s) */
      switch (count) {
      case 0:
          /* no boulders--not blocked */
          return FALSE;
      case 1:
          /* possibly blocked depending on if it's pushable */
          break;
      case 2:
          /* this is only approximate since multiple boulders might sink */
          if (is_pool_or_lava(nx, ny)) /* does its own isok() check */
              break; /* still need Sokoban check below */
          /*FALLTHRU*/
      default:
          /* more than one boulder--blocked after they push the top one;
             don't force them to push it first to find out */
          return TRUE;
      }
  
      if (dx && dy && Sokoban) /* can't push boulder diagonally in Sokoban */
          return TRUE;
      if (!isok(nx, ny))
          return TRUE;
      if (IS_ROCK(levl[nx][ny].typ))
          return TRUE;
      if (sobj_at(BOULDER, nx, ny))
          return TRUE;
  
      return FALSE;
  }
  
  /*pray.c*/
  