Source:NetHack 3.6.0/src/attrib.c

From NetHackWiki
Jump to: navigation, search

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

Top of file

  1.  /* NetHack 3.6	attrib.c	$NHDT-Date: 1449269911 2015/12/04 22:58:31 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
  2.  /*      Copyright 1988, 1989, 1990, 1992, M. Stephenson           */
  3.  /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5.  /*  attribute modification routines. */
  6.  
  7.  #include "hack.h"
  8.  #include <ctype.h>
  9.  
  10.  /* part of the output on gain or loss of attribute */
  11.  static const char
  12.      *const plusattr[] = { "strong", "smart", "wise",
  13.                            "agile",  "tough", "charismatic" },
  14.      *const minusattr[] = { "weak",    "stupid",
  15.                             "foolish", "clumsy",
  16.                             "fragile", "repulsive" };
  17.  
  18.  static const struct innate {
  19.      schar ulevel;
  20.      long *ability;
  21.      const char *gainstr, *losestr;
  22.  } arc_abil[] = { { 1, &(HStealth), "", "" },
  23.                   { 1, &(HFast), "", "" },
  24.                   { 10, &(HSearching), "perceptive", "" },
  25.                   { 0, 0, 0, 0 } },
  26.  
  27.    bar_abil[] = { { 1, &(HPoison_resistance), "", "" },
  28.                   { 7, &(HFast), "quick", "slow" },
  29.                   { 15, &(HStealth), "stealthy", "" },
  30.                   { 0, 0, 0, 0 } },
  31.  
  32.    cav_abil[] = { { 7, &(HFast), "quick", "slow" },
  33.                   { 15, &(HWarning), "sensitive", "" },
  34.                   { 0, 0, 0, 0 } },
  35.  
  36.    hea_abil[] = { { 1, &(HPoison_resistance), "", "" },
  37.                   { 15, &(HWarning), "sensitive", "" },
  38.                   { 0, 0, 0, 0 } },
  39.  
  40.    kni_abil[] = { { 7, &(HFast), "quick", "slow" }, { 0, 0, 0, 0 } },
  41.  
  42.    mon_abil[] = { { 1, &(HFast), "", "" },
  43.                   { 1, &(HSleep_resistance), "", "" },
  44.                   { 1, &(HSee_invisible), "", "" },
  45.                   { 3, &(HPoison_resistance), "healthy", "" },
  46.                   { 5, &(HStealth), "stealthy", "" },
  47.                   { 7, &(HWarning), "sensitive", "" },
  48.                   { 9, &(HSearching), "perceptive", "unaware" },
  49.                   { 11, &(HFire_resistance), "cool", "warmer" },
  50.                   { 13, &(HCold_resistance), "warm", "cooler" },
  51.                   { 15, &(HShock_resistance), "insulated", "conductive" },
  52.                   { 17, &(HTeleport_control), "controlled", "uncontrolled" },
  53.                   { 0, 0, 0, 0 } },
  54.  
  55.    pri_abil[] = { { 15, &(HWarning), "sensitive", "" },
  56.                   { 20, &(HFire_resistance), "cool", "warmer" },
  57.                   { 0, 0, 0, 0 } },
  58.  
  59.    ran_abil[] = { { 1, &(HSearching), "", "" },
  60.                   { 7, &(HStealth), "stealthy", "" },
  61.                   { 15, &(HSee_invisible), "", "" },
  62.                   { 0, 0, 0, 0 } },
  63.  
  64.    rog_abil[] = { { 1, &(HStealth), "", "" },
  65.                   { 10, &(HSearching), "perceptive", "" },
  66.                   { 0, 0, 0, 0 } },
  67.  
  68.    sam_abil[] = { { 1, &(HFast), "", "" },
  69.                   { 15, &(HStealth), "stealthy", "" },
  70.                   { 0, 0, 0, 0 } },
  71.  
  72.    tou_abil[] = { { 10, &(HSearching), "perceptive", "" },
  73.                   { 20, &(HPoison_resistance), "hardy", "" },
  74.                   { 0, 0, 0, 0 } },
  75.  
  76.    val_abil[] = { { 1, &(HCold_resistance), "", "" },
  77.                   { 1, &(HStealth), "", "" },
  78.                   { 7, &(HFast), "quick", "slow" },
  79.                   { 0, 0, 0, 0 } },
  80.  
  81.    wiz_abil[] = { { 15, &(HWarning), "sensitive", "" },
  82.                   { 17, &(HTeleport_control), "controlled", "uncontrolled" },
  83.                   { 0, 0, 0, 0 } },
  84.  
  85.    /* Intrinsics conferred by race */
  86.      elf_abil[] = { { 4, &(HSleep_resistance), "awake", "tired" },
  87.                     { 0, 0, 0, 0 } },
  88.  
  89.    orc_abil[] = { { 1, &(HPoison_resistance), "", "" }, { 0, 0, 0, 0 } };
  90.  
  91.  STATIC_DCL void NDECL(exerper);
  92.  STATIC_DCL void FDECL(postadjabil, (long *));
  93.  STATIC_DCL const struct innate *FDECL(check_innate_abil, (long *, long));
  94.  STATIC_DCL int FDECL(innately, (long *));
  95.  

adjattrib

  1.  /* adjust an attribute; return TRUE if change is made, FALSE otherwise */
  2.  boolean
  3.  adjattrib(ndx, incr, msgflg)
  4.  int ndx, incr;
  5.  int msgflg; /* positive => no message, zero => message, and */
  6.  {           /* negative => conditional (msg if change made) */
  7.      int old_acurr;
  8.      boolean abonflg;
  9.      const char *attrstr;
  10.  
  11.      if (Fixed_abil || !incr)
  12.          return FALSE;
  13.  
  14.      if ((ndx == A_INT || ndx == A_WIS) && uarmh && uarmh->otyp == DUNCE_CAP) {
  15.          if (msgflg == 0)
  16.              Your("cap constricts briefly, then relaxes again.");
  17.          return FALSE;
  18.      }
  19.  
  20.      old_acurr = ACURR(ndx);
  21.      if (incr > 0) {
  22.          ABASE(ndx) += incr;
  23.          if (ABASE(ndx) > AMAX(ndx)) {
  24.              incr = ABASE(ndx) - AMAX(ndx);
  25.              AMAX(ndx) += incr;
  26.              if (AMAX(ndx) > ATTRMAX(ndx))
  27.                  AMAX(ndx) = ATTRMAX(ndx);
  28.              ABASE(ndx) = AMAX(ndx);
  29.          }
  30.          attrstr = plusattr[ndx];
  31.          abonflg = (ABON(ndx) < 0);
  32.      } else {
  33.          ABASE(ndx) += incr;
  34.          if (ABASE(ndx) < ATTRMIN(ndx)) {
  35.              incr = ABASE(ndx) - ATTRMIN(ndx);
  36.              ABASE(ndx) = ATTRMIN(ndx);
  37.              AMAX(ndx) += incr;
  38.              if (AMAX(ndx) < ATTRMIN(ndx))
  39.                  AMAX(ndx) = ATTRMIN(ndx);
  40.          }
  41.          attrstr = minusattr[ndx];
  42.          abonflg = (ABON(ndx) > 0);
  43.      }
  44.      if (ACURR(ndx) == old_acurr) {
  45.          if (msgflg == 0 && flags.verbose)
  46.              pline("You're %s as %s as you can get.",
  47.                    abonflg ? "currently" : "already", attrstr);
  48.          return FALSE;
  49.      }
  50.  
  51.      if (msgflg <= 0)
  52.          You_feel("%s%s!", (incr > 1 || incr < -1) ? "very " : "", attrstr);
  53.      context.botl = 1;
  54.      if (moves > 1 && (ndx == A_STR || ndx == A_CON))
  55.          (void) encumber_msg();
  56.      return TRUE;
  57.  }
  58.  

gainstr

  1.  void
  2.  gainstr(otmp, incr, givemsg)
  3.  struct obj *otmp;
  4.  int incr;
  5.  boolean givemsg;
  6.  {
  7.      int num = incr;
  8.  
  9.      if (!num) {
  10.          if (ABASE(A_STR) < 18)
  11.              num = (rn2(4) ? 1 : rnd(6));
  12.          else if (ABASE(A_STR) < STR18(85))
  13.              num = rnd(10);
  14.          else
  15.              num = 1;
  16.      }
  17.      (void) adjattrib(A_STR, (otmp && otmp->cursed) ? -num : num,
  18.                       givemsg ? -1 : 1);
  19.  }
  20.  

losestr

  1.  /* may kill you; cause may be poison or monster like 'a' */
  2.  void
  3.  losestr(num)
  4.  register int num;
  5.  {
  6.      int ustr = ABASE(A_STR) - num;
  7.  
  8.      while (ustr < 3) {
  9.          ++ustr;
  10.          --num;
  11.          if (Upolyd) {
  12.              u.mh -= 6;
  13.              u.mhmax -= 6;
  14.          } else {
  15.              u.uhp -= 6;
  16.              u.uhpmax -= 6;
  17.          }
  18.      }
  19.      (void) adjattrib(A_STR, -num, 1);
  20.  }
  21.  

poisontell

  1.  static const struct poison_effect_message {
  2.      void VDECL((*delivery_func), (const char *, ...));
  3.      const char *effect_msg;
  4.  } poiseff[] = {
  5.      { You_feel, "weaker" },             /* A_STR */
  6.      { Your, "brain is on fire" },       /* A_INT */
  7.      { Your, "judgement is impaired" },  /* A_WIS */
  8.      { Your, "muscles won't obey you" }, /* A_DEX */
  9.      { You_feel, "very sick" },          /* A_CON */
  10.      { You, "break out in hives" }       /* A_CHA */
  11.  };
  12.  
  13.  /* feedback for attribute loss due to poisoning */
  14.  void
  15.  poisontell(typ, exclaim)
  16.  int typ;         /* which attribute */
  17.  boolean exclaim; /* emphasis */
  18.  {
  19.      void VDECL((*func), (const char *, ...)) = poiseff[typ].delivery_func;
  20.  
  21.      (*func)("%s%c", poiseff[typ].effect_msg, exclaim ? '!' : '.');
  22.  }
  23.  

poisoned

  1.  /* called when an attack or trap has poisoned the hero (used to be in mon.c)
  2.   */
  3.  void
  4.  poisoned(reason, typ, pkiller, fatal, thrown_weapon)
  5.  const char *reason,    /* controls what messages we display */
  6.      *pkiller;          /* for score+log file if fatal */
  7.  int typ, fatal;        /* if fatal is 0, limit damage to adjattrib */
  8.  boolean thrown_weapon; /* thrown weapons are less deadly */
  9.  {
  10.      int i, loss, kprefix = KILLED_BY_AN;
  11.  
  12.      /* inform player about being poisoned unless that's already been done;
  13.         "blast" has given a "blast of poison gas" message; "poison arrow",
  14.         "poison dart", etc have implicitly given poison messages too... */
  15.      if (strcmp(reason, "blast") && !strstri(reason, "poison")) {
  16.          boolean plural = (reason[strlen(reason) - 1] == 's') ? 1 : 0;
  17.  
  18.          /* avoid "The" Orcus's sting was poisoned... */
  19.          pline("%s%s %s poisoned!", isupper(*reason) ? "" : "The ", reason,
  20.                plural ? "were" : "was");
  21.      }
  22.      if (Poison_resistance) {
  23.          if (!strcmp(reason, "blast"))
  24.              shieldeff(u.ux, u.uy);
  25.          pline_The("poison doesn't seem to affect you.");
  26.          return;
  27.      }
  28.  
  29.      /* suppress killer prefix if it already has one */
  30.      i = name_to_mon(pkiller);
  31.      if (i >= LOW_PM && (mons[i].geno & G_UNIQ)) {
  32.          kprefix = KILLED_BY;
  33.          if (!type_is_pname(&mons[i]))
  34.              pkiller = the(pkiller);
  35.      } else if (!strncmpi(pkiller, "the ", 4) || !strncmpi(pkiller, "an ", 3)
  36.                 || !strncmpi(pkiller, "a ", 2)) {
  37.          /*[ does this need a plural check too? ]*/
  38.          kprefix = KILLED_BY;
  39.      }
  40.  
  41.      i = !fatal ? 1 : rn2(fatal + (thrown_weapon ? 20 : 0));
  42.      if (i == 0 && typ != A_CHA) {
  43.          /* instant kill */
  44.          u.uhp = -1;
  45.          pline_The("poison was deadly...");
  46.      } else if (i > 5) {
  47.          /* HP damage; more likely--but less severe--with missiles */
  48.          loss = thrown_weapon ? rnd(6) : rn1(10, 6);
  49.          losehp(loss, pkiller, kprefix); /* poison damage */
  50.      } else {
  51.          /* attribute loss; if typ is A_STR, reduction in current and
  52.             maximum HP will occur once strength has dropped down to 3 */
  53.          loss = (thrown_weapon || !fatal) ? 1 : d(2, 2); /* was rn1(3,3) */
  54.          /* check that a stat change was made */
  55.          if (adjattrib(typ, -loss, 1))
  56.              poisontell(typ, TRUE);
  57.      }
  58.  
  59.      if (u.uhp < 1) {
  60.          killer.format = kprefix;
  61.          Strcpy(killer.name, pkiller);
  62.          /* "Poisoned by a poisoned ___" is redundant */
  63.          done(strstri(pkiller, "poison") ? DIED : POISONING);
  64.      }
  65.      (void) encumber_msg();
  66.  }
  67.  

change_luck

  1.  void
  2.  change_luck(n)
  3.  register schar n;
  4.  {
  5.      u.uluck += n;
  6.      if (u.uluck < 0 && u.uluck < LUCKMIN)
  7.          u.uluck = LUCKMIN;
  8.      if (u.uluck > 0 && u.uluck > LUCKMAX)
  9.          u.uluck = LUCKMAX;
  10.  }
  11.  

stone_luck

  1.  int
  2.  stone_luck(parameter)
  3.  boolean parameter; /* So I can't think up of a good name.  So sue me. --KAA */
  4.  {
  5.      register struct obj *otmp;
  6.      register long bonchance = 0;
  7.  
  8.      for (otmp = invent; otmp; otmp = otmp->nobj)
  9.          if (confers_luck(otmp)) {
  10.              if (otmp->cursed)
  11.                  bonchance -= otmp->quan;
  12.              else if (otmp->blessed)
  13.                  bonchance += otmp->quan;
  14.              else if (parameter)
  15.                  bonchance += otmp->quan;
  16.          }
  17.  
  18.      return sgn((int) bonchance);
  19.  }
  20.  

set_moreluck

  1.  /* there has just been an inventory change affecting a luck-granting item */
  2.  void
  3.  set_moreluck()
  4.  {
  5.      int luckbon = stone_luck(TRUE);
  6.  
  7.      if (!luckbon && !carrying(LUCKSTONE))
  8.          u.moreluck = 0;
  9.      else if (luckbon >= 0)
  10.          u.moreluck = LUCKADD;
  11.      else
  12.          u.moreluck = -LUCKADD;
  13.  }
  14.  

restore_attrib

  1.  void
  2.  restore_attrib()
  3.  {
  4.      int i;
  5.  
  6.      for (i = 0; i < A_MAX; i++) { /* all temporary losses/gains */
  7.  
  8.          if (ATEMP(i) && ATIME(i)) {
  9.              if (!(--(ATIME(i)))) { /* countdown for change */
  10.                  ATEMP(i) += ATEMP(i) > 0 ? -1 : 1;
  11.  
  12.                  if (ATEMP(i)) /* reset timer */
  13.                      ATIME(i) = 100 / ACURR(A_CON);
  14.              }
  15.          }
  16.      }
  17.      (void) encumber_msg();
  18.  }
  19.  

exercise

  1.  #define AVAL 50 /* tune value for exercise gains */
  2.  
  3.  void
  4.  exercise(i, inc_or_dec)
  5.  int i;
  6.  boolean inc_or_dec;
  7.  {
  8.      debugpline0("Exercise:");
  9.      if (i == A_INT || i == A_CHA)
  10.          return; /* can't exercise these */
  11.  
  12.      /* no physical exercise while polymorphed; the body's temporary */
  13.      if (Upolyd && i != A_WIS)
  14.          return;
  15.  
  16.      if (abs(AEXE(i)) < AVAL) {
  17.          /*
  18.           *      Law of diminishing returns (Part I):
  19.           *
  20.           *      Gain is harder at higher attribute values.
  21.           *      79% at "3" --> 0% at "18"
  22.           *      Loss is even at all levels (50%).
  23.           *
  24.           *      Note: *YES* ACURR is the right one to use.
  25.           */
  26.          AEXE(i) += (inc_or_dec) ? (rn2(19) > ACURR(i)) : -rn2(2);
  27.          debugpline3("%s, %s AEXE = %d",
  28.                      (i == A_STR) ? "Str" : (i == A_WIS) ? "Wis" : (i == A_DEX)
  29.                                                                        ? "Dex"
  30.                                                                        : "Con",
  31.                      (inc_or_dec) ? "inc" : "dec", AEXE(i));
  32.      }
  33.      if (moves > 0 && (i == A_STR || i == A_CON))
  34.          (void) encumber_msg();
  35.  }
  36.  

exerper

  1.  STATIC_OVL void
  2.  exerper()
  3.  {
  4.      if (!(moves % 10)) {
  5.          /* Hunger Checks */
  6.  
  7.          int hs = (u.uhunger > 1000) ? SATIATED : (u.uhunger > 150)
  8.                                                       ? NOT_HUNGRY
  9.                                                       : (u.uhunger > 50)
  10.                                                             ? HUNGRY
  11.                                                             : (u.uhunger > 0)
  12.                                                                   ? WEAK
  13.                                                                   : FAINTING;
  14.  
  15.          debugpline0("exerper: Hunger checks");
  16.          switch (hs) {
  17.          case SATIATED:
  18.              exercise(A_DEX, FALSE);
  19.              if (Role_if(PM_MONK))
  20.                  exercise(A_WIS, FALSE);
  21.              break;
  22.          case NOT_HUNGRY:
  23.              exercise(A_CON, TRUE);
  24.              break;
  25.          case WEAK:
  26.              exercise(A_STR, FALSE);
  27.              if (Role_if(PM_MONK)) /* fasting */
  28.                  exercise(A_WIS, TRUE);
  29.              break;
  30.          case FAINTING:
  31.          case FAINTED:
  32.              exercise(A_CON, FALSE);
  33.              break;
  34.          }
  35.  
  36.          /* Encumbrance Checks */
  37.          debugpline0("exerper: Encumber checks");
  38.          switch (near_capacity()) {
  39.          case MOD_ENCUMBER:
  40.              exercise(A_STR, TRUE);
  41.              break;
  42.          case HVY_ENCUMBER:
  43.              exercise(A_STR, TRUE);
  44.              exercise(A_DEX, FALSE);
  45.              break;
  46.          case EXT_ENCUMBER:
  47.              exercise(A_DEX, FALSE);
  48.              exercise(A_CON, FALSE);
  49.              break;
  50.          }
  51.      }
  52.  
  53.      /* status checks */
  54.      if (!(moves % 5)) {
  55.          debugpline0("exerper: Status checks");
  56.          if ((HClairvoyant & (INTRINSIC | TIMEOUT)) && !BClairvoyant)
  57.              exercise(A_WIS, TRUE);
  58.          if (HRegeneration)
  59.              exercise(A_STR, TRUE);
  60.  
  61.          if (Sick || Vomiting)
  62.              exercise(A_CON, FALSE);
  63.          if (Confusion || Hallucination)
  64.              exercise(A_WIS, FALSE);
  65.          if ((Wounded_legs && !u.usteed) || Fumbling || HStun)
  66.              exercise(A_DEX, FALSE);
  67.      }
  68.  }
  69.  

exerchk

  1.  /* exercise/abuse text (must be in attribute order, not botl order);
  2.     phrased as "You must have been [][0]." or "You haven't been [][1]." */
  3.  static NEARDATA const char *const exertext[A_MAX][2] = {
  4.      { "exercising diligently", "exercising properly" },           /* Str */
  5.      { 0, 0 },                                                     /* Int */
  6.      { "very observant", "paying attention" },                     /* Wis */
  7.      { "working on your reflexes", "working on reflexes lately" }, /* Dex */
  8.      { "leading a healthy life-style", "watching your health" },   /* Con */
  9.      { 0, 0 },                                                     /* Cha */
  10.  };
  11.  
  12.  void
  13.  exerchk()
  14.  {
  15.      int i, ax, mod_val, lolim, hilim;
  16.  
  17.      /*  Check out the periodic accumulations */
  18.      exerper();
  19.  
  20.      if (moves >= context.next_attrib_check) {
  21.          debugpline1("exerchk: ready to test. multi = %d.", multi);
  22.      }
  23.      /*  Are we ready for a test? */
  24.      if (moves >= context.next_attrib_check && !multi) {
  25.          debugpline0("exerchk: testing.");
  26.          /*
  27.           *      Law of diminishing returns (Part II):
  28.           *
  29.           *      The effects of "exercise" and "abuse" wear
  30.           *      off over time.  Even if you *don't* get an
  31.           *      increase/decrease, you lose some of the
  32.           *      accumulated effects.
  33.           */
  34.          for (i = 0; i < A_MAX; ++i) {
  35.              ax = AEXE(i);
  36.              /* nothing to do here if no exercise or abuse has occurred
  37.                 (Int and Cha always fall into this category) */
  38.              if (!ax)
  39.                  continue; /* ok to skip nextattrib */
  40.  
  41.              mod_val = sgn(ax); /* +1 or -1; used below */
  42.              /* no further effect for exercise if at max or abuse if at min;
  43.                 can't exceed 18 via exercise even if actual max is higher */
  44.              lolim = ATTRMIN(i); /* usually 3; might be higher */
  45.              hilim = ATTRMAX(i); /* usually 18; maybe lower or higher */
  46.              if (hilim > 18)
  47.                  hilim = 18;
  48.              if ((ax < 0) ? (ABASE(i) <= lolim) : (ABASE(i) >= hilim))
  49.                  goto nextattrib;
  50.              /* can't exercise non-Wisdom while polymorphed; previous
  51.                 exercise/abuse gradually wears off without impact then */
  52.              if (Upolyd && i != A_WIS)
  53.                  goto nextattrib;
  54.  
  55.              debugpline2("exerchk: testing %s (%d).",
  56.                          (i == A_STR)
  57.                              ? "Str"
  58.                              : (i == A_INT)
  59.                                    ? "Int?"
  60.                                    : (i == A_WIS)
  61.                                          ? "Wis"
  62.                                          : (i == A_DEX)
  63.                                                ? "Dex"
  64.                                                : (i == A_CON)
  65.                                                      ? "Con"
  66.                                                      : (i == A_CHA)
  67.                                                            ? "Cha?"
  68.                                                            : "???",
  69.                          ax);
  70.              /*
  71.               *  Law of diminishing returns (Part III):
  72.               *
  73.               *  You don't *always* gain by exercising.
  74.               *  [MRS 92/10/28 - Treat Wisdom specially for balance.]
  75.               */
  76.              if (rn2(AVAL) > ((i != A_WIS) ? (abs(ax) * 2 / 3) : abs(ax)))
  77.                  goto nextattrib;
  78.  
  79.              debugpline1("exerchk: changing %d.", i);
  80.              if (adjattrib(i, mod_val, -1)) {
  81.                  debugpline1("exerchk: changed %d.", i);
  82.                  /* if you actually changed an attrib - zero accumulation */
  83.                  AEXE(i) = ax = 0;
  84.                  /* then print an explanation */
  85.                  You("%s %s.",
  86.                      (mod_val > 0) ? "must have been" : "haven't been",
  87.                      exertext[i][(mod_val > 0) ? 0 : 1]);
  88.              }
  89.          nextattrib:
  90.              /* this used to be ``AEXE(i) /= 2'' but that would produce
  91.                 platform-dependent rounding/truncation for negative vals */
  92.              AEXE(i) = (abs(ax) / 2) * mod_val;
  93.          }
  94.          context.next_attrib_check += rn1(200, 800);
  95.          debugpline1("exerchk: next check at %ld.", context.next_attrib_check);
  96.      }
  97.  }
  98.  

init_attr

  1.  void
  2.  init_attr(np)
  3.  register int np;
  4.  {
  5.      register int i, x, tryct;
  6.  
  7.      for (i = 0; i < A_MAX; i++) {
  8.          ABASE(i) = AMAX(i) = urole.attrbase[i];
  9.          ATEMP(i) = ATIME(i) = 0;
  10.          np -= urole.attrbase[i];
  11.      }
  12.  
  13.      tryct = 0;
  14.      while (np > 0 && tryct < 100) {
  15.          x = rn2(100);
  16.          for (i = 0; (i < A_MAX) && ((x -= urole.attrdist[i]) > 0); i++)
  17.              ;
  18.          if (i >= A_MAX)
  19.              continue; /* impossible */
  20.  
  21.          if (ABASE(i) >= ATTRMAX(i)) {
  22.              tryct++;
  23.              continue;
  24.          }
  25.          tryct = 0;
  26.          ABASE(i)++;
  27.          AMAX(i)++;
  28.          np--;
  29.      }
  30.  
  31.      tryct = 0;
  32.      while (np < 0 && tryct < 100) { /* for redistribution */
  33.  
  34.          x = rn2(100);
  35.          for (i = 0; (i < A_MAX) && ((x -= urole.attrdist[i]) > 0); i++)
  36.              ;
  37.          if (i >= A_MAX)
  38.              continue; /* impossible */
  39.  
  40.          if (ABASE(i) <= ATTRMIN(i)) {
  41.              tryct++;
  42.              continue;
  43.          }
  44.          tryct = 0;
  45.          ABASE(i)--;
  46.          AMAX(i)--;
  47.          np++;
  48.      }
  49.  }
  50.  

redist_attr

  1.  void
  2.  redist_attr()
  3.  {
  4.      register int i, tmp;
  5.  
  6.      for (i = 0; i < A_MAX; i++) {
  7.          if (i == A_INT || i == A_WIS)
  8.              continue;
  9.          /* Polymorphing doesn't change your mind */
  10.          tmp = AMAX(i);
  11.          AMAX(i) += (rn2(5) - 2);
  12.          if (AMAX(i) > ATTRMAX(i))
  13.              AMAX(i) = ATTRMAX(i);
  14.          if (AMAX(i) < ATTRMIN(i))
  15.              AMAX(i) = ATTRMIN(i);
  16.          ABASE(i) = ABASE(i) * AMAX(i) / tmp;
  17.          /* ABASE(i) > ATTRMAX(i) is impossible */
  18.          if (ABASE(i) < ATTRMIN(i))
  19.              ABASE(i) = ATTRMIN(i);
  20.      }
  21.      (void) encumber_msg();
  22.  }
  23.  

postadjabil

  1.  STATIC_OVL
  2.  void
  3.  postadjabil(ability)
  4.  long *ability;
  5.  {
  6.      if (!ability)
  7.          return;
  8.      if (ability == &(HWarning) || ability == &(HSee_invisible))
  9.          see_monsters();
  10.  }
  11.  

check_innate_abil

  1.  STATIC_OVL const struct innate *
  2.  check_innate_abil(ability, frommask)
  3.  long *ability;
  4.  long frommask;
  5.  {
  6.      const struct innate *abil = 0;
  7.  
  8.      if (frommask == FROMEXPER)
  9.          switch (Role_switch) {
  10.          case PM_ARCHEOLOGIST:
  11.              abil = arc_abil;
  12.              break;
  13.          case PM_BARBARIAN:
  14.              abil = bar_abil;
  15.              break;
  16.          case PM_CAVEMAN:
  17.              abil = cav_abil;
  18.              break;
  19.          case PM_HEALER:
  20.              abil = hea_abil;
  21.              break;
  22.          case PM_KNIGHT:
  23.              abil = kni_abil;
  24.              break;
  25.          case PM_MONK:
  26.              abil = mon_abil;
  27.              break;
  28.          case PM_PRIEST:
  29.              abil = pri_abil;
  30.              break;
  31.          case PM_RANGER:
  32.              abil = ran_abil;
  33.              break;
  34.          case PM_ROGUE:
  35.              abil = rog_abil;
  36.              break;
  37.          case PM_SAMURAI:
  38.              abil = sam_abil;
  39.              break;
  40.          case PM_TOURIST:
  41.              abil = tou_abil;
  42.              break;
  43.          case PM_VALKYRIE:
  44.              abil = val_abil;
  45.              break;
  46.          case PM_WIZARD:
  47.              abil = wiz_abil;
  48.              break;
  49.          default:
  50.              break;
  51.          }
  52.      else if (frommask == FROMRACE)
  53.          switch (Race_switch) {
  54.          case PM_ELF:
  55.              abil = elf_abil;
  56.              break;
  57.          case PM_ORC:
  58.              abil = orc_abil;
  59.              break;
  60.          case PM_HUMAN:
  61.          case PM_DWARF:
  62.          case PM_GNOME:
  63.          default:
  64.              break;
  65.          }
  66.  
  67.      while (abil && abil->ability) {
  68.          if ((abil->ability == ability) && (u.ulevel >= abil->ulevel))
  69.              return abil;
  70.          abil++;
  71.      }
  72.      return (struct innate *) 0;
  73.  }
  74.  

innately

  1.  /*
  2.   * returns 1 if FROMRACE or FROMEXPER and exper level == 1
  3.   * returns 2 if FROMEXPER and exper level > 1
  4.   * otherwise returns 0
  5.   */
  6.  STATIC_OVL int
  7.  innately(ability)
  8.  long *ability;
  9.  {
  10.      const struct innate *iptr;
  11.  
  12.      if ((iptr = check_innate_abil(ability, FROMRACE)) != 0)
  13.          return 1;
  14.      else if ((iptr = check_innate_abil(ability, FROMEXPER)) != 0)
  15.          return (iptr->ulevel == 1) ? 1 : 2;
  16.      return 0;
  17.  }
  18.  

is_innate

  1.  int
  2.  is_innate(propidx)
  3.  int propidx;
  4.  {
  5.      if (propidx == BLINDED && !haseyes(youmonst.data))
  6.          return 1;
  7.      return innately(&u.uprops[propidx].intrinsic);
  8.  }
  9.  

from_what

  1.  char *
  2.  from_what(propidx)
  3.  int propidx; /* special cases can have negative values */
  4.  {
  5.      static char buf[BUFSZ];
  6.  
  7.      buf[0] = '\0';
  8.      /*
  9.       * Restrict the source of the attributes just to debug mode for now
  10.       */
  11.      if (wizard) {
  12.          static NEARDATA const char because_of[] = " because of %s";
  13.  
  14.          if (propidx >= 0) {
  15.              char *p;
  16.              struct obj *obj = (struct obj *) 0;
  17.              int innate = is_innate(propidx);
  18.  
  19.              if (innate == 2)
  20.                  Strcpy(buf, " because of your experience");
  21.              else if (innate == 1)
  22.                  Strcpy(buf, " innately");
  23.              else if (wizard
  24.                       && (obj = what_gives(&u.uprops[propidx].extrinsic)))
  25.                  Sprintf(buf, because_of, obj->oartifact
  26.                                               ? bare_artifactname(obj)
  27.                                               : ysimple_name(obj));
  28.              else if (propidx == BLINDED && u.uroleplay.blind)
  29.                  Sprintf(buf, " from birth");
  30.              else if (propidx == BLINDED && Blindfolded_only)
  31.                  Sprintf(buf, because_of, ysimple_name(ublindf));
  32.  
  33.              /* remove some verbosity and/or redundancy */
  34.              if ((p = strstri(buf, " pair of ")) != 0)
  35.                  copynchars(p + 1, p + 9, BUFSZ); /* overlapping buffers ok */
  36.              else if (propidx == STRANGLED
  37.                       && (p = strstri(buf, " of strangulation")) != 0)
  38.                  *p = '\0';
  39.  
  40.          } else { /* negative property index */
  41.              /* if more blocking capabilities get implemented we'll need to
  42.                 replace this with what_blocks() comparable to what_gives() */
  43.              switch (-propidx) {
  44.              case BLINDED:
  45.                  if (ublindf
  46.                      && ublindf->oartifact == ART_EYES_OF_THE_OVERWORLD)
  47.                      Sprintf(buf, because_of, bare_artifactname(ublindf));
  48.                  break;
  49.              case INVIS:
  50.                  if (u.uprops[INVIS].blocked & W_ARMC)
  51.                      Sprintf(buf, because_of,
  52.                              ysimple_name(uarmc)); /* mummy wrapping */
  53.                  break;
  54.              case CLAIRVOYANT:
  55.                  if (wizard && (u.uprops[CLAIRVOYANT].blocked & W_ARMH))
  56.                      Sprintf(buf, because_of,
  57.                              ysimple_name(uarmh)); /* cornuthaum */
  58.                  break;
  59.              }
  60.          }
  61.  
  62.      } /*wizard*/
  63.      return buf;
  64.  }
  65.  

adjabil

  1.  void
  2.  adjabil(oldlevel, newlevel)
  3.  int oldlevel, newlevel;
  4.  {
  5.      register const struct innate *abil, *rabil;
  6.      long prevabil, mask = FROMEXPER;
  7.  
  8.      switch (Role_switch) {
  9.      case PM_ARCHEOLOGIST:
  10.          abil = arc_abil;
  11.          break;
  12.      case PM_BARBARIAN:
  13.          abil = bar_abil;
  14.          break;
  15.      case PM_CAVEMAN:
  16.          abil = cav_abil;
  17.          break;
  18.      case PM_HEALER:
  19.          abil = hea_abil;
  20.          break;
  21.      case PM_KNIGHT:
  22.          abil = kni_abil;
  23.          break;
  24.      case PM_MONK:
  25.          abil = mon_abil;
  26.          break;
  27.      case PM_PRIEST:
  28.          abil = pri_abil;
  29.          break;
  30.      case PM_RANGER:
  31.          abil = ran_abil;
  32.          break;
  33.      case PM_ROGUE:
  34.          abil = rog_abil;
  35.          break;
  36.      case PM_SAMURAI:
  37.          abil = sam_abil;
  38.          break;
  39.      case PM_TOURIST:
  40.          abil = tou_abil;
  41.          break;
  42.      case PM_VALKYRIE:
  43.          abil = val_abil;
  44.          break;
  45.      case PM_WIZARD:
  46.          abil = wiz_abil;
  47.          break;
  48.      default:
  49.          abil = 0;
  50.          break;
  51.      }
  52.  
  53.      switch (Race_switch) {
  54.      case PM_ELF:
  55.          rabil = elf_abil;
  56.          break;
  57.      case PM_ORC:
  58.          rabil = orc_abil;
  59.          break;
  60.      case PM_HUMAN:
  61.      case PM_DWARF:
  62.      case PM_GNOME:
  63.      default:
  64.          rabil = 0;
  65.          break;
  66.      }
  67.  
  68.      while (abil || rabil) {
  69.          /* Have we finished with the intrinsics list? */
  70.          if (!abil || !abil->ability) {
  71.              /* Try the race intrinsics */
  72.              if (!rabil || !rabil->ability)
  73.                  break;
  74.              abil = rabil;
  75.              rabil = 0;
  76.              mask = FROMRACE;
  77.          }
  78.          prevabil = *(abil->ability);
  79.          if (oldlevel < abil->ulevel && newlevel >= abil->ulevel) {
  80.              /* Abilities gained at level 1 can never be lost
  81.               * via level loss, only via means that remove _any_
  82.               * sort of ability.  A "gain" of such an ability from
  83.               * an outside source is devoid of meaning, so we set
  84.               * FROMOUTSIDE to avoid such gains.
  85.               */
  86.              if (abil->ulevel == 1)
  87.                  *(abil->ability) |= (mask | FROMOUTSIDE);
  88.              else
  89.                  *(abil->ability) |= mask;
  90.              if (!(*(abil->ability) & INTRINSIC & ~mask)) {
  91.                  if (*(abil->gainstr))
  92.                      You_feel("%s!", abil->gainstr);
  93.              }
  94.          } else if (oldlevel >= abil->ulevel && newlevel < abil->ulevel) {
  95.              *(abil->ability) &= ~mask;
  96.              if (!(*(abil->ability) & INTRINSIC)) {
  97.                  if (*(abil->losestr))
  98.                      You_feel("%s!", abil->losestr);
  99.                  else if (*(abil->gainstr))
  100.                      You_feel("less %s!", abil->gainstr);
  101.              }
  102.          }
  103.          if (prevabil != *(abil->ability)) /* it changed */
  104.              postadjabil(abil->ability);
  105.          abil++;
  106.      }
  107.  
  108.      if (oldlevel > 0) {
  109.          if (newlevel > oldlevel)
  110.              add_weapon_skill(newlevel - oldlevel);
  111.          else
  112.              lose_weapon_skill(oldlevel - newlevel);
  113.      }
  114.  }
  115.  

newhp

  1.  int
  2.  newhp()
  3.  {
  4.      int hp, conplus;
  5.  
  6.      if (u.ulevel == 0) {
  7.          /* Initialize hit points */
  8.          hp = urole.hpadv.infix + urace.hpadv.infix;
  9.          if (urole.hpadv.inrnd > 0)
  10.              hp += rnd(urole.hpadv.inrnd);
  11.          if (urace.hpadv.inrnd > 0)
  12.              hp += rnd(urace.hpadv.inrnd);
  13.          if (moves <= 1L) { /* initial hero; skip for polyself to new man */
  14.              /* Initialize alignment stuff */
  15.              u.ualign.type = aligns[flags.initalign].value;
  16.              u.ualign.record = urole.initrecord;
  17.          }
  18.          /* no Con adjustment for initial hit points */
  19.      } else {
  20.          if (u.ulevel < urole.xlev) {
  21.              hp = urole.hpadv.lofix + urace.hpadv.lofix;
  22.              if (urole.hpadv.lornd > 0)
  23.                  hp += rnd(urole.hpadv.lornd);
  24.              if (urace.hpadv.lornd > 0)
  25.                  hp += rnd(urace.hpadv.lornd);
  26.          } else {
  27.              hp = urole.hpadv.hifix + urace.hpadv.hifix;
  28.              if (urole.hpadv.hirnd > 0)
  29.                  hp += rnd(urole.hpadv.hirnd);
  30.              if (urace.hpadv.hirnd > 0)
  31.                  hp += rnd(urace.hpadv.hirnd);
  32.          }
  33.          if (ACURR(A_CON) <= 3)
  34.              conplus = -2;
  35.          else if (ACURR(A_CON) <= 6)
  36.              conplus = -1;
  37.          else if (ACURR(A_CON) <= 14)
  38.              conplus = 0;
  39.          else if (ACURR(A_CON) <= 16)
  40.              conplus = 1;
  41.          else if (ACURR(A_CON) == 17)
  42.              conplus = 2;
  43.          else if (ACURR(A_CON) == 18)
  44.              conplus = 3;
  45.          else
  46.              conplus = 4;
  47.          hp += conplus;
  48.      }
  49.      if (hp <= 0)
  50.          hp = 1;
  51.      if (u.ulevel < MAXULEV)
  52.          u.uhpinc[u.ulevel] = (xchar) hp;
  53.      return hp;
  54.  }
  55.  

acurr

  1.  schar
  2.  acurr(x)
  3.  int x;
  4.  {
  5.      register int tmp = (u.abon.a[x] + u.atemp.a[x] + u.acurr.a[x]);
  6.  
  7.      if (x == A_STR) {
  8.          if (tmp >= 125 || (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER))
  9.              return (schar) 125;
  10.          else
  11.  #ifdef WIN32_BUG
  12.              return (x = ((tmp <= 3) ? 3 : tmp));
  13.  #else
  14.          return (schar) ((tmp <= 3) ? 3 : tmp);
  15.  #endif
  16.      } else if (x == A_CHA) {
  17.          if (tmp < 18
  18.              && (youmonst.data->mlet == S_NYMPH || u.umonnum == PM_SUCCUBUS
  19.                  || u.umonnum == PM_INCUBUS))
  20.              return (schar) 18;
  21.      } else if (x == A_INT || x == A_WIS) {
  22.          /* yes, this may raise int/wis if player is sufficiently
  23.           * stupid.  there are lower levels of cognition than "dunce".
  24.           */
  25.          if (uarmh && uarmh->otyp == DUNCE_CAP)
  26.              return (schar) 6;
  27.      }
  28. #ifdef WIN32_BUG
  29.      return (x = ((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp));
  30.  #else
  31.      return (schar) ((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp);
  32.  #endif
  33.  }
  34.  

acurrstr

  1.  /* condense clumsy ACURR(A_STR) value into value that fits into game formulas
  2.   */
  3.  schar
  4.  acurrstr()
  5.  {
  6.      register int str = ACURR(A_STR);
  7.  
  8.      if (str <= 18)
  9.          return (schar) str;
  10.      if (str <= 121)
  11.          return (schar) (19 + str / 50); /* map to 19..21 */
  12.      else
  13.          return (schar) (min(str, 125) - 100); /* 22..25 */
  14.  }
  15.  

extremeattr

  1.  /* when wearing (or taking off) an unID'd item, this routine is used
  2.     to distinguish between observable +0 result and no-visible-effect
  3.     due to an attribute not being able to exceed maximum or minimum */
  4.  boolean
  5.  extremeattr(attrindx) /* does attrindx's value match its max or min? */
  6.  int attrindx;
  7.  {
  8.      /* Fixed_abil and racial MINATTR/MAXATTR aren't relevant here */
  9.      int lolimit = 3, hilimit = 25, curval = ACURR(attrindx);
  10.  
  11.      /* upper limit for Str is 25 but its value is encoded differently */
  12.      if (attrindx == A_STR) {
  13.          hilimit = STR19(25); /* 125 */
  14.          /* lower limit for Str can also be 25 */
  15.          if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER)
  16.              lolimit = hilimit;
  17.      }
  18.      /* this exception is hypothetical; the only other worn item affecting
  19.         Int or Wis is another helmet so can't be in use at the same time */
  20.      if (attrindx == A_INT || attrindx == A_WIS) {
  21.          if (uarmh && uarmh->otyp == DUNCE_CAP)
  22.              hilimit = lolimit = 6;
  23.      }
  24.  
  25.      /* are we currently at either limit? */
  26.      return (curval == lolimit || curval == hilimit) ? TRUE : FALSE;
  27.  }
  28.  

adjalign

  1.  /* avoid possible problems with alignment overflow, and provide a centralized
  2.     location for any future alignment limits */
  3.  void
  4.  adjalign(n)
  5.  int n;
  6.  {
  7.      int newalign = u.ualign.record + n;
  8.  
  9.      if (n < 0) {
  10.          if (newalign < u.ualign.record)
  11.              u.ualign.record = newalign;
  12.      } else if (newalign > u.ualign.record) {
  13.          u.ualign.record = newalign;
  14.          if (u.ualign.record > ALIGNLIM)
  15.              u.ualign.record = ALIGNLIM;
  16.      }
  17.  }
  18.  

uchangealign

  1.  /* change hero's alignment type, possibly losing use of artifacts */
  2.  void
  3.  uchangealign(newalign, reason)
  4.  int newalign;
  5.  int reason; /* 0==conversion, 1==helm-of-OA on, 2==helm-of-OA off */
  6.  {
  7.      aligntyp oldalign = u.ualign.type;
  8.  
  9.      u.ublessed = 0;   /* lose divine protection */
  10.      context.botl = 1; /* status line needs updating */
  11.      if (reason == 0) {
  12.          /* conversion via altar */
  13.          u.ualignbase[A_CURRENT] = (aligntyp) newalign;
  14.          /* worn helm of opposite alignment might block change */
  15.          if (!uarmh || uarmh->otyp != HELM_OF_OPPOSITE_ALIGNMENT)
  16.              u.ualign.type = u.ualignbase[A_CURRENT];
  17.          You("have a %ssense of a new direction.",
  18.              (u.ualign.type != oldalign) ? "sudden " : "");
  19.      } else {
  20.          /* putting on or taking off a helm of opposite alignment */
  21.          u.ualign.type = (aligntyp) newalign;
  22.          if (reason == 1)
  23.              Your("mind oscillates %s.", Hallucination ? "wildly" : "briefly");
  24.          else if (reason == 2)
  25.              Your("mind is %s.", Hallucination
  26.                                      ? "much of a muchness"
  27.                                      : "back in sync with your body");
  28.      }
  29.  
  30.      if (u.ualign.type != oldalign) {
  31.          u.ualign.record = 0; /* slate is wiped clean */
  32.          retouch_equipment(0);
  33.      }
  34.  }
  35.  
  36.  /*attrib.c*/