Source:NetHack 3.6.1/src/wizard.c

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

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

Top of file

  1.  /* NetHack 3.6	wizard.c	$NHDT-Date: 1456618999 2016/02/28 00:23:19 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
  2.  /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  /*-Copyright (c) Robert Patrick Rankin, 2016. */
  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.  /* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
  3.  /*             - heavily modified to give the wiz balls.  (genat!mike)   */
  4.  /*             - dewimped and given some maledictions. -3. */
  5.  /*             - generalized for 3.1 (mike@bullns.on01.bull.ca) */
  6.  
  7.  #include "hack.h"
  8.  #include "qtext.h"
  9.  
  10.  extern const int monstr[];
  11.  
  12.  STATIC_DCL short FDECL(which_arti, (int));
  13.  STATIC_DCL boolean FDECL(mon_has_arti, (struct monst *, SHORT_P));
  14.  STATIC_DCL struct monst *FDECL(other_mon_has_arti, (struct monst *, SHORT_P));
  15.  STATIC_DCL struct obj *FDECL(on_ground, (SHORT_P));
  16.  STATIC_DCL boolean FDECL(you_have, (int));
  17.  STATIC_DCL unsigned long FDECL(target_on, (int, struct monst *));
  18.  STATIC_DCL unsigned long FDECL(strategy, (struct monst *));
  19.  
  20.  /* adding more neutral creatures will tend to reduce the number of monsters
  21.     summoned by nasty(); adding more lawful creatures will reduce the number
  22.     of monsters summoned by lawfuls; adding more chaotic creatures will reduce
  23.     the number of monsters summoned by chaotics; prior to 3.6.1, there were
  24.     only four lawful candidates, so lawful summoners tended to summon more
  25.     (trying to get lawful or neutral but obtaining chaotic instead) than
  26.     their chaotic counterparts */
  27.  static NEARDATA const int nasties[] = {
  28.      /* neutral */
  29.      PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR,
  30.      PM_OWLBEAR, PM_PURPLE_WORM, PM_XAN, PM_UMBER_HULK,
  31.      PM_XORN, PM_ZRUTY, PM_LEOCROTTA, PM_BALUCHITHERIUM,
  32.      PM_CARNIVOROUS_APE, PM_FIRE_ELEMENTAL, PM_JABBERWOCK,
  33.      PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME,
  34.      /* chaotic */
  35.      PM_BLACK_DRAGON, PM_RED_DRAGON, PM_ARCH_LICH, PM_VAMPIRE_LORD,
  36.      PM_MASTER_MIND_FLAYER, PM_DISENCHANTER, PM_WINGED_GARGOYLE,
  37.      PM_STORM_GIANT, PM_OLOG_HAI, PM_ELF_LORD, PM_ELVENKING,
  38.      PM_OGRE_KING, PM_CAPTAIN, PM_GREMLIN,
  39.      /* lawful */
  40.      PM_SILVER_DRAGON, PM_ORANGE_DRAGON, PM_GREEN_DRAGON,
  41.      PM_YELLOW_DRAGON, PM_GUARDIAN_NAGA, PM_FIRE_GIANT,
  42.      PM_ALEAX, PM_COUATL, PM_HORNED_DEVIL, PM_BARBED_DEVIL,
  43.      /* (titans, ki-rin, and golden nagas are suitably nasty, but
  44.         they're summoners so would aggravate excessive summoning) */
  45.  };
  46.  
  47.  static NEARDATA const unsigned wizapp[] = {
  48.      PM_HUMAN,      PM_WATER_DEMON,  PM_VAMPIRE,       PM_RED_DRAGON,
  49.      PM_TROLL,      PM_UMBER_HULK,   PM_XORN,          PM_XAN,
  50.      PM_COCKATRICE, PM_FLOATING_EYE, PM_GUARDIAN_NAGA, PM_TRAPPER,
  51.  };
  52.  

amulet

  1.  /* If you've found the Amulet, make the Wizard appear after some time */
  2.  /* Also, give hints about portal locations, if amulet is worn/wielded -dlc */
  3.  void
  4.  amulet()
  5.  {
  6.      struct monst *mtmp;
  7.      struct trap *ttmp;
  8.      struct obj *amu;
  9.  
  10.  #if 0 /* caller takes care of this check */
  11.      if (!u.uhave.amulet)
  12.          return;
  13.  #endif
  14.      if ((((amu = uamul) != 0 && amu->otyp == AMULET_OF_YENDOR)
  15.           || ((amu = uwep) != 0 && amu->otyp == AMULET_OF_YENDOR))
  16.          && !rn2(15)) {
  17.          for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
  18.              if (ttmp->ttyp == MAGIC_PORTAL) {
  19.                  int du = distu(ttmp->tx, ttmp->ty);
  20.                  if (du <= 9)
  21.                      pline("%s hot!", Tobjnam(amu, "feel"));
  22.                  else if (du <= 64)
  23.                      pline("%s very warm.", Tobjnam(amu, "feel"));
  24.                  else if (du <= 144)
  25.                      pline("%s warm.", Tobjnam(amu, "feel"));
  26.                  /* else, the amulet feels normal */
  27.                  break;
  28.              }
  29.          }
  30.      }
  31.  
  32.      if (!context.no_of_wizards)
  33.          return;
  34.      /* find Wizard, and wake him if necessary */
  35.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  36.          if (DEADMONSTER(mtmp))
  37.              continue;
  38.          if (mtmp->iswiz && mtmp->msleeping && !rn2(40)) {
  39.              mtmp->msleeping = 0;
  40.              if (distu(mtmp->mx, mtmp->my) > 2)
  41.                  You(
  42.        "get the creepy feeling that somebody noticed your taking the Amulet.");
  43.              return;
  44.          }
  45.      }
  46.  }
  47.  

mon_has_amulet

  1.  int
  2.  mon_has_amulet(mtmp)
  3.  register struct monst *mtmp;
  4.  {
  5.      register struct obj *otmp;
  6.  
  7.      for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  8.          if (otmp->otyp == AMULET_OF_YENDOR)
  9.              return 1;
  10.      return 0;
  11.  }
  12.  

mon_has_special

  1.  int
  2.  mon_has_special(mtmp)
  3.  register struct monst *mtmp;
  4.  {
  5.      register struct obj *otmp;
  6.  
  7.      for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  8.          if (otmp->otyp == AMULET_OF_YENDOR
  9.              || any_quest_artifact(otmp)
  10.              || otmp->otyp == BELL_OF_OPENING
  11.              || otmp->otyp == CANDELABRUM_OF_INVOCATION
  12.              || otmp->otyp == SPE_BOOK_OF_THE_DEAD)
  13.              return 1;
  14.      return 0;
  15.  }
  16.  
  17.  /*
  18.   *      New for 3.1  Strategy / Tactics for the wiz, as well as other
  19.   *      monsters that are "after" something (defined via mflag3).
  20.   *
  21.   *      The strategy section decides *what* the monster is going
  22.   *      to attempt, the tactics section implements the decision.
  23.   */
  24.  #define STRAT(w, x, y, typ)                            \
  25.      ((unsigned long) (w) | ((unsigned long) (x) << 16) \
  26.       | ((unsigned long) (y) << 8) | (unsigned long) (typ))
  27.  
  28.  #define M_Wants(mask) (mtmp->data->mflags3 & (mask))
  29.  

which_arti

  1.  STATIC_OVL short
  2.  which_arti(mask)
  3.  register int mask;
  4.  {
  5.      switch (mask) {
  6.      case M3_WANTSAMUL:
  7.          return AMULET_OF_YENDOR;
  8.      case M3_WANTSBELL:
  9.          return BELL_OF_OPENING;
  10.      case M3_WANTSCAND:
  11.          return CANDELABRUM_OF_INVOCATION;
  12.      case M3_WANTSBOOK:
  13.          return SPE_BOOK_OF_THE_DEAD;
  14.      default:
  15.          break; /* 0 signifies quest artifact */
  16.      }
  17.      return 0;
  18.  }
  19.  

mon_has_arti

  1.  /*
  2.   *      If "otyp" is zero, it triggers a check for the quest_artifact,
  3.   *      since bell, book, candle, and amulet are all objects, not really
  4.   *      artifacts right now.  [MRS]
  5.   */
  6.  STATIC_OVL boolean
  7.  mon_has_arti(mtmp, otyp)
  8.  register struct monst *mtmp;
  9.  register short otyp;
  10.  {
  11.      register struct obj *otmp;
  12.  
  13.      for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
  14.          if (otyp) {
  15.              if (otmp->otyp == otyp)
  16.                  return 1;
  17.          } else if (any_quest_artifact(otmp))
  18.              return 1;
  19.      }
  20.      return 0;
  21.  }
  22.  

other_mon_has_arti

  1.  STATIC_OVL struct monst *
  2.  other_mon_has_arti(mtmp, otyp)
  3.  register struct monst *mtmp;
  4.  register short otyp;
  5.  {
  6.      register struct monst *mtmp2;
  7.  
  8.      for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon)
  9.          /* no need for !DEADMONSTER check here since they have no inventory */
  10.          if (mtmp2 != mtmp)
  11.              if (mon_has_arti(mtmp2, otyp))
  12.                  return mtmp2;
  13.  
  14.      return (struct monst *) 0;
  15.  }
  16.  

on_ground

  1.  STATIC_OVL struct obj *
  2.  on_ground(otyp)
  3.  register short otyp;
  4.  {
  5.      register struct obj *otmp;
  6.  
  7.      for (otmp = fobj; otmp; otmp = otmp->nobj)
  8.          if (otyp) {
  9.              if (otmp->otyp == otyp)
  10.                  return otmp;
  11.          } else if (any_quest_artifact(otmp))
  12.              return otmp;
  13.      return (struct obj *) 0;
  14.  }
  15.  

you_have

  1.  STATIC_OVL boolean
  2.  you_have(mask)
  3.  register int mask;
  4.  {
  5.      switch (mask) {
  6.      case M3_WANTSAMUL:
  7.          return (boolean) u.uhave.amulet;
  8.      case M3_WANTSBELL:
  9.          return (boolean) u.uhave.bell;
  10.      case M3_WANTSCAND:
  11.          return (boolean) u.uhave.menorah;
  12.      case M3_WANTSBOOK:
  13.          return (boolean) u.uhave.book;
  14.      case M3_WANTSARTI:
  15.          return (boolean) u.uhave.questart;
  16.      default:
  17.          break;
  18.      }
  19.      return 0;
  20.  }
  21.  

target_on

  1.  STATIC_OVL unsigned long
  2.  target_on(mask, mtmp)
  3.  register int mask;
  4.  register struct monst *mtmp;
  5.  {
  6.      register short otyp;
  7.      register struct obj *otmp;
  8.      register struct monst *mtmp2;
  9.  
  10.      if (!M_Wants(mask))
  11.          return (unsigned long) STRAT_NONE;
  12.  
  13.      otyp = which_arti(mask);
  14.      if (!mon_has_arti(mtmp, otyp)) {
  15.          if (you_have(mask))
  16.              return STRAT(STRAT_PLAYER, u.ux, u.uy, mask);
  17.          else if ((otmp = on_ground(otyp)))
  18.              return STRAT(STRAT_GROUND, otmp->ox, otmp->oy, mask);
  19.          else if ((mtmp2 = other_mon_has_arti(mtmp, otyp)) != 0
  20.                   /* when seeking the Amulet, avoid targetting the Wizard
  21.                      or temple priests (to protect Moloch's high priest) */
  22.                   && (otyp != AMULET_OF_YENDOR
  23.                       || (!mtmp2->iswiz && !inhistemple(mtmp2))))
  24.              return STRAT(STRAT_MONSTR, mtmp2->mx, mtmp2->my, mask);
  25.      }
  26.      return (unsigned long) STRAT_NONE;
  27.  }
  28.  

strategy

  1.  STATIC_OVL unsigned long
  2.  strategy(mtmp)
  3.  register struct monst *mtmp;
  4.  {
  5.      unsigned long strat, dstrat;
  6.  
  7.      if (!is_covetous(mtmp->data)
  8.          /* perhaps a shopkeeper has been polymorphed into a master
  9.             lich; we don't want it teleporting to the stairs to heal
  10.             because that will leave its shop untended */
  11.          || (mtmp->isshk && inhishop(mtmp))
  12.          /* likewise for temple priests */
  13.          || (mtmp->ispriest && inhistemple(mtmp)))
  14.          return (unsigned long) STRAT_NONE;
  15.  
  16.      switch ((mtmp->mhp * 3) / mtmp->mhpmax) { /* 0-3 */
  17.  
  18.      default:
  19.      case 0: /* panic time - mtmp is almost snuffed */
  20.          return (unsigned long) STRAT_HEAL;
  21.  
  22.      case 1: /* the wiz is less cautious */
  23.          if (mtmp->data != &mons[PM_WIZARD_OF_YENDOR])
  24.              return (unsigned long) STRAT_HEAL;
  25.      /* else fall through */
  26.  
  27.      case 2:
  28.          dstrat = STRAT_HEAL;
  29.          break;
  30.  
  31.      case 3:
  32.          dstrat = STRAT_NONE;
  33.          break;
  34.      }
  35.  
  36.      if (context.made_amulet)
  37.          if ((strat = target_on(M3_WANTSAMUL, mtmp)) != STRAT_NONE)
  38.              return strat;
  39.  
  40.      if (u.uevent.invoked) { /* priorities change once gate opened */
  41.          if ((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE)
  42.              return strat;
  43.          if ((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE)
  44.              return strat;
  45.          if ((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE)
  46.              return strat;
  47.          if ((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE)
  48.              return strat;
  49.      } else {
  50.          if ((strat = target_on(M3_WANTSBOOK, mtmp)) != STRAT_NONE)
  51.              return strat;
  52.          if ((strat = target_on(M3_WANTSBELL, mtmp)) != STRAT_NONE)
  53.              return strat;
  54.          if ((strat = target_on(M3_WANTSCAND, mtmp)) != STRAT_NONE)
  55.              return strat;
  56.          if ((strat = target_on(M3_WANTSARTI, mtmp)) != STRAT_NONE)
  57.              return strat;
  58.      }
  59.      return dstrat;
  60.  }
  61.  

choose_stairs

  1.  void
  2.  choose_stairs(sx, sy)
  3.  xchar *sx;
  4.  xchar *sy;
  5.  {
  6.      xchar x = 0, y = 0;
  7.  
  8.      if (builds_up(&u.uz)) {
  9.          if (xdnstair) {
  10.              x = xdnstair;
  11.              y = ydnstair;
  12.          } else if (xdnladder) {
  13.              x = xdnladder;
  14.              y = ydnladder;
  15.          }
  16.      } else {
  17.          if (xupstair) {
  18.              x = xupstair;
  19.              y = yupstair;
  20.          } else if (xupladder) {
  21.              x = xupladder;
  22.              y = yupladder;
  23.          }
  24.      }
  25.  
  26.      if (!x && sstairs.sx) {
  27.          x = sstairs.sx;
  28.          y = sstairs.sy;
  29.      }
  30.  
  31.      if (x && y) {
  32.          *sx = x;
  33.          *sy = y;
  34.      }
  35.  
  36.  }
  37.  

tactics

  1.  int
  2.  tactics(mtmp)
  3.  register struct monst *mtmp;
  4.  {
  5.      unsigned long strat = strategy(mtmp);
  6.      xchar sx = 0, sy = 0;
  7.  
  8.      mtmp->mstrategy =
  9.          (mtmp->mstrategy & (STRAT_WAITMASK | STRAT_APPEARMSG)) | strat;
  10.  
  11.      switch (strat) {
  12.      case STRAT_HEAL: /* hide and recover */
  13.          /* if wounded, hole up on or near the stairs (to block them) */
  14.          choose_stairs(&sx, &sy);
  15.          mtmp->mavenge = 1; /* covetous monsters attack while fleeing */
  16.          if (In_W_tower(mtmp->mx, mtmp->my, &u.uz)
  17.              || (mtmp->iswiz && !sx && !mon_has_amulet(mtmp))) {
  18.              if (!rn2(3 + mtmp->mhp / 10))
  19.                  (void) rloc(mtmp, TRUE);
  20.          } else if (sx && (mtmp->mx != sx || mtmp->my != sy)) {
  21.              if (!mnearto(mtmp, sx, sy, TRUE)) {
  22.                  m_into_limbo(mtmp);
  23.                  return 0;
  24.              }
  25.          }
  26.          /* if you're not around, cast healing spells */
  27.          if (distu(mtmp->mx, mtmp->my) > (BOLT_LIM * BOLT_LIM))
  28.              if (mtmp->mhp <= mtmp->mhpmax - 8) {
  29.                  mtmp->mhp += rnd(8);
  30.                  return 1;
  31.              }
  32.          /*FALLTHRU*/
  33.  
  34.      case STRAT_NONE: /* harass */
  35.          if (!rn2(!mtmp->mflee ? 5 : 33))
  36.              mnexto(mtmp);
  37.          return 0;
  38.  
  39.      default: /* kill, maim, pillage! */
  40.      {
  41.          long where = (strat & STRAT_STRATMASK);
  42.          xchar tx = STRAT_GOALX(strat), ty = STRAT_GOALY(strat);
  43.          int targ = (int) (strat & STRAT_GOAL);
  44.          struct obj *otmp;
  45.  
  46.          if (!targ) { /* simply wants you to close */
  47.              return 0;
  48.          }
  49.          if ((u.ux == tx && u.uy == ty) || where == STRAT_PLAYER) {
  50.              /* player is standing on it (or has it) */
  51.              mnexto(mtmp);
  52.              return 0;
  53.          }
  54.          if (where == STRAT_GROUND) {
  55.              if (!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) {
  56.                  /* teleport to it and pick it up */
  57.                  rloc_to(mtmp, tx, ty); /* clean old pos */
  58.  
  59.                  if ((otmp = on_ground(which_arti(targ))) != 0) {
  60.                      if (cansee(mtmp->mx, mtmp->my))
  61.                          pline("%s picks up %s.", Monnam(mtmp),
  62.                                (distu(mtmp->mx, mtmp->my) <= 5)
  63.                                    ? doname(otmp)
  64.                                    : distant_name(otmp, doname));
  65.                      obj_extract_self(otmp);
  66.                      (void) mpickobj(mtmp, otmp);
  67.                      return 1;
  68.                  } else
  69.                      return 0;
  70.              } else {
  71.                  /* a monster is standing on it - cause some trouble */
  72.                  if (!rn2(5))
  73.                      mnexto(mtmp);
  74.                  return 0;
  75.              }
  76.          } else { /* a monster has it - 'port beside it. */
  77.              if (!mnearto(mtmp, tx, ty, FALSE))
  78.                  m_into_limbo(mtmp);
  79.              return 0;
  80.          }
  81.      }
  82.      }
  83.      /*NOTREACHED*/
  84.      return 0;
  85.  }
  86.  

has_aggravatables

  1.  /* are there any monsters mon could aggravate? */
  2.  boolean
  3.  has_aggravatables(mon)
  4.  struct monst *mon;
  5.  {
  6.      struct monst *mtmp;
  7.      boolean in_w_tower = In_W_tower(mon->mx, mon->my, &u.uz);
  8.  
  9.      if (in_w_tower != In_W_tower(u.ux, u.uy, &u.uz))
  10.          return FALSE;
  11.  
  12.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  13.          if (DEADMONSTER(mtmp))
  14.              continue;
  15.          if (in_w_tower != In_W_tower(mtmp->mx, mtmp->my, &u.uz))
  16.              continue;
  17.          if ((mtmp->mstrategy & STRAT_WAITFORU) != 0
  18.              || mtmp->msleeping || !mtmp->mcanmove)
  19.              return TRUE;
  20.      }
  21.      return FALSE;
  22.  }
  23.  

aggravate

  1.  void
  2.  aggravate()
  3.  {
  4.      register struct monst *mtmp;
  5.      boolean in_w_tower = In_W_tower(u.ux, u.uy, &u.uz);
  6.  
  7.      for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  8.          if (DEADMONSTER(mtmp))
  9.              continue;
  10.          if (in_w_tower != In_W_tower(mtmp->mx, mtmp->my, &u.uz))
  11.              continue;
  12.          mtmp->mstrategy &= ~(STRAT_WAITFORU | STRAT_APPEARMSG);
  13.          mtmp->msleeping = 0;
  14.          if (!mtmp->mcanmove && !rn2(5)) {
  15.              mtmp->mfrozen = 0;
  16.              mtmp->mcanmove = 1;
  17.          }
  18.      }
  19.  }
  20.  

clonewiz

  1.  void
  2.  clonewiz()
  3.  {
  4.      register struct monst *mtmp2;
  5.  
  6.      if ((mtmp2 = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy, NO_MM_FLAGS))
  7.          != 0) {
  8.          mtmp2->msleeping = mtmp2->mtame = mtmp2->mpeaceful = 0;
  9.          if (!u.uhave.amulet && rn2(2)) { /* give clone a fake */
  10.              (void) add_to_minv(mtmp2,
  11.                                 mksobj(FAKE_AMULET_OF_YENDOR, TRUE, FALSE));
  12.          }
  13.          mtmp2->m_ap_type = M_AP_MONSTER;
  14.          mtmp2->mappearance = wizapp[rn2(SIZE(wizapp))];
  15.          newsym(mtmp2->mx, mtmp2->my);
  16.      }
  17.  }
  18.  

pick_nasty

  1.  /* also used by newcham() */
  2.  int
  3.  pick_nasty()
  4.  {
  5.      int res = nasties[rn2(SIZE(nasties))];
  6.  
  7.      /* To do?  Possibly should filter for appropriate forms when
  8.       * in the elemental planes or surrounded by water or lava.
  9.       *
  10.       * We want monsters represented by uppercase on rogue level,
  11.       * but we don't try very hard.
  12.       */
  13.      if (Is_rogue_level(&u.uz)
  14.          && !('A' <= mons[res].mlet && mons[res].mlet <= 'Z'))
  15.          res = nasties[rn2(SIZE(nasties))];
  16.  
  17.      return res;
  18.  }
  19.  

nasty

  1.  /* create some nasty monsters, aligned with the caster or neutral; chaotic
  2.     and unaligned are treated as equivalent; if summoner is Null, this is
  3.     for late-game harassment (after the Wizard has been killed at least once
  4.     or the invocation ritual has been performed), in which case we treat
  5.     'summoner' as neutral, since that will produce the greatest number of
  6.     creatures on average (in 3.6.0 and earlier, Null was treated as chaotic);
  7.     returns the number of monsters created */
  8.  int
  9.  nasty(summoner)
  10.  struct monst *summoner;
  11.  {
  12.      register struct monst *mtmp;
  13.      register int i, j;
  14.      int castalign = (summoner ? sgn(summoner->data->maligntyp) : 0);
  15.      coord bypos;
  16.      int count, census, tmp, makeindex, s_cls, m_cls;
  17.  
  18.  #define MAXNASTIES 10 /* more than this can be created */
  19.  
  20.      /* some candidates may be created in groups, so simple count
  21.         of non-null makemon() return is inadequate */
  22.      census = monster_census(FALSE);
  23.  
  24.      if (!rn2(10) && Inhell) {
  25.          /* this might summon a demon prince or lord */
  26.          count = msummon((struct monst *) 0); /* summons like WoY */
  27.      } else {
  28.          count = 0;
  29.          s_cls = summoner ? summoner->data->mlet : 0;
  30.          tmp = (u.ulevel > 3) ? u.ulevel / 3 : 1;
  31.          /* if we don't have a casting monster, nasties appear around hero,
  32.             otherwise they'll appear around spot summoner thinks she's at */
  33.          bypos.x = u.ux;
  34.          bypos.y = u.uy;
  35.          for (i = rnd(tmp); i > 0 && count < MAXNASTIES; --i)
  36.              /* Of the 42 nasties[], 10 are lawful, 14 are chaotic,
  37.               * and 18 are neutral.
  38.               *
  39.               * Neutral caster, used for late-game harrassment,
  40.               * has 18/42 chance to stop the inner loop on each
  41.               * critter, 24/42 chance for another iteration.
  42.               * Lawful caster has 28/42 chance to stop unless the
  43.               * summoner is an angel or demon, in which case the
  44.               * chance is 26/42.
  45.               * Chaotic or unaligned caster has 32/42 chance to
  46.               * stop, so will summon fewer creatures on average.
  47.               *
  48.               * The outer loop potentially gives chaotic/unaligned
  49.               * a chance to even things up since others will hit
  50.               * MAXNASTIES sooner, but its number of iterations is
  51.               * randomized so it won't always do so.
  52.               */
  53.              for (j = 0; j < 20; j++) {
  54.                  /* Don't create more spellcasters of the monsters' level or
  55.                   * higher--avoids chain summoners filling up the level.
  56.                   */
  57.                  do {
  58.                      makeindex = pick_nasty();
  59.                      m_cls = mons[makeindex].mlet;
  60.                  } while (summoner
  61.                           && ((attacktype(&mons[makeindex], AT_MAGC)
  62.                                && monstr[makeindex] >= monstr[summoner->mnum])
  63.                               || (s_cls == S_DEMON && m_cls == S_ANGEL)
  64.                               || (s_cls == S_ANGEL && m_cls == S_DEMON)));
  65.                  /* do this after picking the monster to place */
  66.                  if (summoner && !enexto(&bypos, summoner->mux, summoner->muy,
  67.                                          &mons[makeindex]))
  68.                      continue;
  69.                  /* this honors genocide but overrides extinction; it ignores
  70.                     inside-hell-only (G_HELL) & outside-hell-only (G_NOHELL) */
  71.                  if ((mtmp = makemon(&mons[makeindex], bypos.x, bypos.y,
  72.                                      NO_MM_FLAGS)) != 0) {
  73.                      mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
  74.                      set_malign(mtmp);
  75.                  } else /* random monster to substitute for geno'd selection */
  76.                      mtmp = makemon((struct permonst *) 0, bypos.x, bypos.y,
  77.                                     NO_MM_FLAGS);
  78.                  if (mtmp) {
  79.                      /* delay first use of spell or breath attack */
  80.                      mtmp->mspec_used = rnd(4);
  81.                      if (++count >= MAXNASTIES
  82.                          || mtmp->data->maligntyp == 0
  83.                          || sgn(mtmp->data->maligntyp) == castalign)
  84.                          break;
  85.                  }
  86.              }
  87.      }
  88.  
  89.      if (count)
  90.          count = monster_census(FALSE) - census;
  91.      return count;
  92.  }
  93.  

resurrect

  1.  /* Let's resurrect the wizard, for some unexpected fun. */
  2.  void
  3.  resurrect()
  4.  {
  5.      struct monst *mtmp, **mmtmp;
  6.      long elapsed;
  7.      const char *verb;
  8.  
  9.      if (!context.no_of_wizards) {
  10.          /* make a new Wizard */
  11.          verb = "kill";
  12.          mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy, MM_NOWAIT);
  13.          /* affects experience; he's not coming back from a corpse
  14.             but is subject to repeated killing like a revived corpse */
  15.          if (mtmp) mtmp->mrevived = 1;
  16.      } else {
  17.          /* look for a migrating Wizard */
  18.          verb = "elude";
  19.          mmtmp = &migrating_mons;
  20.          while ((mtmp = *mmtmp) != 0) {
  21.              if (mtmp->iswiz
  22.                  /* if he has the Amulet, he won't bring it to you */
  23.                  && !mon_has_amulet(mtmp)
  24.                  && (elapsed = monstermoves - mtmp->mlstmv) > 0L) {
  25.                  mon_catchup_elapsed_time(mtmp, elapsed);
  26.                  if (elapsed >= LARGEST_INT)
  27.                      elapsed = LARGEST_INT - 1;
  28.                  elapsed /= 50L;
  29.                  if (mtmp->msleeping && rn2((int) elapsed + 1))
  30.                      mtmp->msleeping = 0;
  31.                  if (mtmp->mfrozen == 1) /* would unfreeze on next move */
  32.                      mtmp->mfrozen = 0, mtmp->mcanmove = 1;
  33.                  if (mtmp->mcanmove && !mtmp->msleeping) {
  34.                      *mmtmp = mtmp->nmon;
  35.                      mon_arrive(mtmp, TRUE);
  36.                      /* note: there might be a second Wizard; if so,
  37.                         he'll have to wait til the next resurrection */
  38.                      break;
  39.                  }
  40.              }
  41.              mmtmp = &mtmp->nmon;
  42.          }
  43.      }
  44.  
  45.      if (mtmp) {
  46.          mtmp->mtame = mtmp->mpeaceful = 0; /* paranoia */
  47.          set_malign(mtmp);
  48.          if (!Deaf) {
  49.              pline("A voice booms out...");
  50.              verbalize("So thou thought thou couldst %s me, fool.", verb);
  51.          }
  52.      }
  53.  }
  54.  

intervene

  1.  /* Here, we make trouble for the poor shmuck who actually
  2.     managed to do in the Wizard. */
  3.  void
  4.  intervene()
  5.  {
  6.      int which = Is_astralevel(&u.uz) ? rnd(4) : rn2(6);
  7.      /* cases 0 and 5 don't apply on the Astral level */
  8.      switch (which) {
  9.      case 0:
  10.      case 1:
  11.          You_feel("vaguely nervous.");
  12.          break;
  13.      case 2:
  14.          if (!Blind)
  15.              You("notice a %s glow surrounding you.", hcolor(NH_BLACK));
  16.          rndcurse();
  17.          break;
  18.      case 3:
  19.          aggravate();
  20.          break;
  21.      case 4:
  22.          (void) nasty((struct monst *) 0);
  23.          break;
  24.      case 5:
  25.          resurrect();
  26.          break;
  27.      }
  28.  }
  29.  

wizdead

  1.  void
  2.  wizdead()
  3.  {
  4.      context.no_of_wizards--;
  5.      if (!u.uevent.udemigod) {
  6.          u.uevent.udemigod = TRUE;
  7.          u.udg_cnt = rn1(250, 50);
  8.      }
  9.  }
  10.  
  11.  const char *const random_insult[] = {
  12.      "antic",      "blackguard",   "caitiff",    "chucklehead",
  13.      "coistrel",   "craven",       "cretin",     "cur",
  14.      "dastard",    "demon fodder", "dimwit",     "dolt",
  15.      "fool",       "footpad",      "imbecile",   "knave",
  16.      "maledict",   "miscreant",    "niddering",  "poltroon",
  17.      "rattlepate", "reprobate",    "scapegrace", "varlet",
  18.      "villein", /* (sic.) */
  19.      "wittol",     "worm",         "wretch",
  20.  };
  21.  
  22.  const char *const random_malediction[] = {
  23.      "Hell shall soon claim thy remains,", "I chortle at thee, thou pathetic",
  24.      "Prepare to die, thou", "Resistance is useless,",
  25.      "Surrender or die, thou", "There shall be no mercy, thou",
  26.      "Thou shalt repent of thy cunning,", "Thou art as a flea to me,",
  27.      "Thou art doomed,", "Thy fate is sealed,",
  28.      "Verily, thou shalt be one dead"
  29.  };
  30.  

cuss

  1.  /* Insult or intimidate the player */
  2.  void
  3.  cuss(mtmp)
  4.  register struct monst *mtmp;
  5.  {
  6.      if (Deaf)
  7.          return;
  8.      if (mtmp->iswiz) {
  9.          if (!rn2(5)) /* typical bad guy action */
  10.              pline("%s laughs fiendishly.", Monnam(mtmp));
  11.          else if (u.uhave.amulet && !rn2(SIZE(random_insult)))
  12.              verbalize("Relinquish the amulet, %s!",
  13.                        random_insult[rn2(SIZE(random_insult))]);
  14.          else if (u.uhp < 5 && !rn2(2)) /* Panic */
  15.              verbalize(rn2(2) ? "Even now thy life force ebbs, %s!"
  16.                               : "Savor thy breath, %s, it be thy last!",
  17.                        random_insult[rn2(SIZE(random_insult))]);
  18.          else if (mtmp->mhp < 5 && !rn2(2)) /* Parthian shot */
  19.              verbalize(rn2(2) ? "I shall return." : "I'll be back.");
  20.          else
  21.              verbalize("%s %s!",
  22.                        random_malediction[rn2(SIZE(random_malediction))],
  23.                        random_insult[rn2(SIZE(random_insult))]);
  24.      } else if (is_lminion(mtmp)
  25.                 && !(mtmp->isminion && EMIN(mtmp)->renegade)) {
  26.          com_pager(rn2(QTN_ANGELIC - 1 + (Hallucination ? 1 : 0))
  27.                    + QT_ANGELIC);
  28.      } else {
  29.          if (!rn2(is_minion(mtmp->data) ? 100 : 5))
  30.              pline("%s casts aspersions on your ancestry.", Monnam(mtmp));
  31.          else
  32.              com_pager(rn2(QTN_DEMONIC) + QT_DEMONIC);
  33.      }
  34.  }
  35.  
  36.  /*wizard.c*/