-/* NetHack 3.6 attrib.c $NHDT-Date: 1449269911 2015/12/04 22:58:31 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
+/* NetHack 3.6 attrib.c $NHDT-Date: 1494034337 2017/05/06 01:32:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.62 $ */
/* Copyright 1988, 1989, 1990, 1992, M. Stephenson */
/* NetHack may be freely redistributed. See license for details. */
"\8aÔ\94²\82¯\82¾", "\95s\8aí\97p\82¾",
"\82Ð\8eã\82¾","\8fX\82¢" };
#endif
+/* also used by enlightenment for non-abbreviated status info */
+const char
+#if 0 /*JP*/
+ *const attrname[] = { "strength", "intelligence", "wisdom",
+ "dexterity", "constitution", "charisma" };
+#else
+ *const attrname[] = { "\8b\82³", "\92m\97Í", "\8c«\82³",
+ "\91f\91\81\82³", "\91Ï\8bv\97Í", "\96£\97Í" };
+#endif
static const struct innate {
schar ulevel;
{ 0, 0, 0, 0 } },
/* Intrinsics conferred by race */
+ dwa_abil[] = { { 1, &HInfravision, "", "" },
+ { 0, 0, 0, 0 } },
+
+ elf_abil[] = { { 1, &HInfravision, "", "" },
/*JP
- elf_abil[] = { { 4, &(HSleep_resistance), "awake", "tired" },
+ { 4, &HSleep_resistance, "awake", "tired" },
*/
- elf_abil[] = { { 4, &(HSleep_resistance), "\96Ú\82ª\8ao\82ß\82½", "\96°\82\82È\82Á\82½" },
- { 0, 0, 0, 0 } },
+ { 4, &(HSleep_resistance), "\96Ú\82ª\8ao\82ß\82½", "\96°\82\82È\82Á\82½" },
+ { 0, 0, 0, 0 } },
- orc_abil[] = { { 1, &(HPoison_resistance), "", "" }, { 0, 0, 0, 0 } };
+ gno_abil[] = { { 1, &HInfravision, "", "" },
+ { 0, 0, 0, 0 } },
+
+ orc_abil[] = { { 1, &HInfravision, "", "" },
+ { 1, &HPoison_resistance, "", "" },
+ { 0, 0, 0, 0 } },
+
+ hum_abil[] = { { 0, 0, 0, 0 } };
STATIC_DCL void NDECL(exerper);
STATIC_DCL void FDECL(postadjabil, (long *));
+STATIC_DCL const struct innate *FDECL(role_abil, (int));
STATIC_DCL const struct innate *FDECL(check_innate_abil, (long *, long));
STATIC_DCL int FDECL(innately, (long *));
int ndx, incr;
int msgflg; /* positive => no message, zero => message, and */
{ /* negative => conditional (msg if change made) */
- int old_acurr;
+ int old_acurr, old_abase;
boolean abonflg;
const char *attrstr;
}
old_acurr = ACURR(ndx);
+ old_abase = ABASE(ndx);
if (incr > 0) {
ABASE(ndx) += incr;
if (ABASE(ndx) > AMAX(ndx)) {
abonflg = (ABON(ndx) > 0);
}
if (ACURR(ndx) == old_acurr) {
- if (msgflg == 0 && flags.verbose)
+ if (msgflg == 0 && flags.verbose) {
+ if (ABASE(ndx) == old_abase)
#if 0 /*JP*/
- pline("You're %s as %s as you can get.",
- abonflg ? "currently" : "already", attrstr);
+ pline("You're %s as %s as you can get.",
+ abonflg ? "currently" : "already", attrstr);
#else
- You("%s\8f\\95ª\82É%s\81D",
- abonflg ? "\8d¡\82Ì\82Æ\82±\82ë" : "\8aù\82É", attrstr);
+ You("%s\8f\\95ª\82É%s\81D",
+ abonflg ? "\8d¡\82Ì\82Æ\82±\82ë" : "\8aù\82É", attrstr);
#endif
+ else /* current stayed the same but base value changed */
+ Your("innate %s has %s.", attrname[ndx],
+ (incr > 0) ? "improved" : "declined");
+ }
return FALSE;
}
boolean exclaim; /* emphasis */
{
void VDECL((*func), (const char *, ...)) = poiseff[typ].delivery_func;
+ const char *msg_txt = poiseff[typ].effect_msg;
+
+ /*
+ * "You feel weaker" or "you feel very sick" aren't appropriate when
+ * wearing or wielding something (gauntlets of power, Ogresmasher)
+ * which forces the attribute to maintain its maximum value.
+ * Phrasing for other attributes which might have fixed values
+ * (dunce cap) is such that we don't need message fixups for them.
+ */
+ if (typ == A_STR && ACURR(A_STR) == STR19(25))
+ msg_txt = "innately weaker";
+ else if (typ == A_CON && ACURR(A_CON) == 25)
+ msg_txt = "sick inside";
/*JP
- (*func)("%s%c", poiseff[typ].effect_msg, exclaim ? '!' : '.');
+ (*func)("%s%c", msg_txt, exclaim ? '!' : '.');
*/
- (*func)("%s%s", poiseff[typ].effect_msg, exclaim ? "\81I" : "\81D");
+ (*func)("%s%s", msg_txt, exclaim ? "\81I" : "\81D");
}
-/* called when an attack or trap has poisoned the hero (used to be in mon.c)
- */
+/* called when an attack or trap has poisoned hero (used to be in mon.c) */
void
poisoned(reason, typ, pkiller, fatal, thrown_weapon)
const char *reason, /* controls what messages we display */
- *pkiller; /* for score+log file if fatal */
+ *pkiller; /* for score+log file if fatal */
int typ, fatal; /* if fatal is 0, limit damage to adjattrib */
boolean thrown_weapon; /* thrown weapons are less deadly */
{
/* avoid "The" Orcus's sting was poisoned... */
#if 0 /*JP*/
- pline("%s%s %s poisoned!", isupper(*reason) ? "" : "The ", reason,
+ pline("%s%s %s poisoned!",
+ isupper((uchar) *reason) ? "" : "The ", reason,
plural ? "were" : "was");
#else
pline("%s\82Í\93Å\82É\82¨\82©\82³\82ê\82Ä\82¢\82é\81I", reason);
if (i == 0 && typ != A_CHA) {
/* instant kill */
u.uhp = -1;
+ context.botl = TRUE;
/*JP
pline_The("poison was deadly...");
*/
void
restore_attrib()
{
- int i;
+ int i, equilibrium;;
- for (i = 0; i < A_MAX; i++) { /* all temporary losses/gains */
+ /*
+ * Note: this gets called on every turn but ATIME() is never set
+ * to non-zero anywhere, and ATEMP() is only used for strength loss
+ * from hunger, so it doesn't actually do anything.
+ */
- if (ATEMP(i) && ATIME(i)) {
+ for (i = 0; i < A_MAX; i++) { /* all temporary losses/gains */
+ equilibrium = (i == A_STR && u.uhs >= WEAK) ? -1 : 0;
+ if (ATEMP(i) != equilibrium && ATIME(i) != 0) {
if (!(--(ATIME(i)))) { /* countdown for change */
- ATEMP(i) += ATEMP(i) > 0 ? -1 : 1;
-
+ ATEMP(i) += (ATEMP(i) > 0) ? -1 : 1;
+ context.botl = 1;
if (ATEMP(i)) /* reset timer */
ATIME(i) = 100 / ACURR(A_CON);
}
}
}
- (void) encumber_msg();
+ if (context.botl)
+ (void) encumber_msg();
}
#define AVAL 50 /* tune value for exercise gains */
}
STATIC_OVL const struct innate *
+role_abil(r)
+int r;
+{
+ const struct {
+ short role;
+ const struct innate *abil;
+ } roleabils[] = {
+ { PM_ARCHEOLOGIST, arc_abil },
+ { PM_BARBARIAN, bar_abil },
+ { PM_CAVEMAN, cav_abil },
+ { PM_HEALER, hea_abil },
+ { PM_KNIGHT, kni_abil },
+ { PM_MONK, mon_abil },
+ { PM_PRIEST, pri_abil },
+ { PM_RANGER, ran_abil },
+ { PM_ROGUE, rog_abil },
+ { PM_SAMURAI, sam_abil },
+ { PM_TOURIST, tou_abil },
+ { PM_VALKYRIE, val_abil },
+ { PM_WIZARD, wiz_abil },
+ { 0, 0 }
+ };
+ int i;
+
+ for (i = 0; roleabils[i].abil && roleabils[i].role != r; i++)
+ continue;
+ return roleabils[i].abil;
+}
+
+STATIC_OVL const struct innate *
check_innate_abil(ability, frommask)
long *ability;
long frommask;
const struct innate *abil = 0;
if (frommask == FROMEXPER)
- switch (Role_switch) {
- case PM_ARCHEOLOGIST:
- abil = arc_abil;
- break;
- case PM_BARBARIAN:
- abil = bar_abil;
- break;
- case PM_CAVEMAN:
- abil = cav_abil;
- break;
- case PM_HEALER:
- abil = hea_abil;
- break;
- case PM_KNIGHT:
- abil = kni_abil;
- break;
- case PM_MONK:
- abil = mon_abil;
- break;
- case PM_PRIEST:
- abil = pri_abil;
- break;
- case PM_RANGER:
- abil = ran_abil;
- break;
- case PM_ROGUE:
- abil = rog_abil;
- break;
- case PM_SAMURAI:
- abil = sam_abil;
- break;
- case PM_TOURIST:
- abil = tou_abil;
- break;
- case PM_VALKYRIE:
- abil = val_abil;
- break;
- case PM_WIZARD:
- abil = wiz_abil;
- break;
- default:
- break;
- }
+ abil = role_abil(Role_switch);
else if (frommask == FROMRACE)
switch (Race_switch) {
+ case PM_DWARF:
+ abil = dwa_abil;
+ break;
case PM_ELF:
abil = elf_abil;
break;
+ case PM_GNOME:
+ abil = gno_abil;
+ break;
case PM_ORC:
abil = orc_abil;
break;
case PM_HUMAN:
- case PM_DWARF:
- case PM_GNOME:
+ abil = hum_abil;
+ break;
default:
break;
}
return (struct innate *) 0;
}
-/*
- * returns 1 if FROMRACE or FROMEXPER and exper level == 1
- * returns 2 if FROMEXPER and exper level > 1
- * otherwise returns 0
- */
+/* reasons for innate ability */
+#define FROM_NONE 0
+#define FROM_ROLE 1 /* from experience at level 1 */
+#define FROM_RACE 2
+#define FROM_INTR 3 /* intrinsically (eating some corpse or prayer reward) */
+#define FROM_EXP 4 /* from experience for some level > 1 */
+#define FROM_FORM 5
+#define FROM_LYCN 6
+
+/* check whether particular ability has been obtained via innate attribute */
STATIC_OVL int
innately(ability)
long *ability;
{
const struct innate *iptr;
+ if ((iptr = check_innate_abil(ability, FROMEXPER)) != 0)
+ return (iptr->ulevel == 1) ? FROM_ROLE : FROM_EXP;
if ((iptr = check_innate_abil(ability, FROMRACE)) != 0)
- return 1;
- else if ((iptr = check_innate_abil(ability, FROMEXPER)) != 0)
- return (iptr->ulevel == 1) ? 1 : 2;
- return 0;
+ return FROM_RACE;
+ if ((*ability & FROMOUTSIDE) != 0L)
+ return FROM_INTR;
+ if ((*ability & FROMFORM) != 0L)
+ return FROM_FORM;
+ return FROM_NONE;
}
int
is_innate(propidx)
int propidx;
{
+ int innateness;
+
+ /* innately() would report FROM_FORM for this; caller wants specificity */
+ if (propidx == DRAIN_RES && u.ulycn >= LOW_PM)
+ return FROM_LYCN;
+ if (propidx == FAST && Very_fast)
+ return FROM_NONE; /* can't become very fast innately */
+ if ((innateness = innately(&u.uprops[propidx].intrinsic)) != FROM_NONE)
+ return innateness;
+ if (propidx == JUMPING && Role_if(PM_KNIGHT)
+ /* knight has intrinsic jumping, but extrinsic is more versatile so
+ ignore innateness if equipment is going to claim responsibility */
+ && !u.uprops[propidx].extrinsic)
+ return FROM_ROLE;
if (propidx == BLINDED && !haseyes(youmonst.data))
- return 1;
- return innately(&u.uprops[propidx].intrinsic);
+ return FROM_FORM;
+ return FROM_NONE;
}
char *
char *p;
#endif
struct obj *obj = (struct obj *) 0;
- int innate = is_innate(propidx);
+ int innateness = is_innate(propidx);
- if (innate == 2)
+ /*
+ * Properties can be obtained from multiple sources and we
+ * try to pick the most significant one. Classification
+ * priority is not set in stone; current precedence is:
+ * "from the start" (from role or race at level 1),
+ * "from outside" (eating corpse, divine reward, blessed potion),
+ * "from experience" (from role or race at level 2+),
+ * "from current form" (while polymorphed),
+ * "from timed effect" (potion or spell),
+ * "from worn/wielded equipment" (Firebrand, elven boots, &c),
+ * "from carried equipment" (mainly quest artifacts).
+ * There are exceptions. Versatile jumping from spell or boots
+ * takes priority over knight's innate but limited jumping.
+ */
+ if (propidx == BLINDED && u.uroleplay.blind)
/*JP
- Strcpy(buf, " because of your experience");
+ Sprintf(buf, " from birth");
*/
- Strcpy(buf, "\8co\8c±\82É\82æ\82Á\82Ä");
- else if (innate == 1)
+ Sprintf(buf, "\90¶\82Ü\82ê\82Ä\82©\82ç\82¸\82Á\82Æ");
+ else if (innateness == FROM_ROLE || innateness == FROM_RACE)
/*JP
Strcpy(buf, " innately");
*/
Strcpy(buf, "\90¶\82Ü\82ê\82È\82ª\82ç\82É");
+ else if (innateness == FROM_INTR) /* [].intrinsic & FROMOUTSIDE */
+ Strcpy(buf, " intrinsically");
+ else if (innateness == FROM_EXP)
+/*JP
+ Strcpy(buf, " because of your experience");
+*/
+ Strcpy(buf, "\8co\8c±\82É\82æ\82Á\82Ä");
+ else if (innateness == FROM_LYCN)
+ Strcpy(buf, " due to your lycanthropy");
+ else if (innateness == FROM_FORM)
+ Strcpy(buf, " from current creature form");
+ else if (propidx == FAST && Very_fast)
+ Sprintf(buf, because_of,
+ ((HFast & TIMEOUT) != 0L) ? "a potion or spell"
+ : ((EFast & W_ARMF) != 0L && uarmf->dknown
+ && objects[uarmf->otyp].oc_name_known)
+ ? ysimple_name(uarmf) /* speed boots */
+ : EFast ? "worn equipment"
+ : something);
else if (wizard
- && (obj = what_gives(&u.uprops[propidx].extrinsic)))
+ && (obj = what_gives(&u.uprops[propidx].extrinsic)) != 0)
Sprintf(buf, because_of, obj->oartifact
? bare_artifactname(obj)
/*JP
: ysimple_name(obj));
*/
: simpleonames(obj));
- else if (propidx == BLINDED && u.uroleplay.blind)
-/*JP
- Sprintf(buf, " from birth");
-*/
- Sprintf(buf, "\90¶\82Ü\82ê\82Ä\82©\82ç\82¸\82Á\82Æ");
else if (propidx == BLINDED && Blindfolded_only)
/*JP
Sprintf(buf, because_of, ysimple_name(ublindf));
register const struct innate *abil, *rabil;
long prevabil, mask = FROMEXPER;
- switch (Role_switch) {
- case PM_ARCHEOLOGIST:
- abil = arc_abil;
- break;
- case PM_BARBARIAN:
- abil = bar_abil;
- break;
- case PM_CAVEMAN:
- abil = cav_abil;
- break;
- case PM_HEALER:
- abil = hea_abil;
- break;
- case PM_KNIGHT:
- abil = kni_abil;
- break;
- case PM_MONK:
- abil = mon_abil;
- break;
- case PM_PRIEST:
- abil = pri_abil;
- break;
- case PM_RANGER:
- abil = ran_abil;
- break;
- case PM_ROGUE:
- abil = rog_abil;
- break;
- case PM_SAMURAI:
- abil = sam_abil;
- break;
- case PM_TOURIST:
- abil = tou_abil;
- break;
- case PM_VALKYRIE:
- abil = val_abil;
- break;
- case PM_WIZARD:
- abil = wiz_abil;
- break;
- default:
- abil = 0;
- break;
- }
+ abil = role_abil(Role_switch);
switch (Race_switch) {
case PM_ELF:
#ifdef WIN32_BUG
return (x = ((tmp <= 3) ? 3 : tmp));
#else
- return (schar) ((tmp <= 3) ? 3 : tmp);
+ return (schar) ((tmp <= 3) ? 3 : tmp);
#endif
} else if (x == A_CHA) {
if (tmp < 18
&& (youmonst.data->mlet == S_NYMPH || u.umonnum == PM_SUCCUBUS
|| u.umonnum == PM_INCUBUS))
return (schar) 18;
+ } else if (x == A_CON) {
+ if (uwep && uwep->oartifact == ART_OGRESMASHER)
+ return (schar) 25;
} else if (x == A_INT || x == A_WIS) {
/* yes, this may raise int/wis if player is sufficiently
* stupid. there are lower levels of cognition than "dunce".
/* lower limit for Str can also be 25 */
if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER)
lolimit = hilimit;
+ } else if (attrindx == A_CON) {
+ if (uwep && uwep->oartifact == ART_OGRESMASHER)
+ lolimit = hilimit;
}
/* this exception is hypothetical; the only other worn item affecting
Int or Wis is another helmet so can't be in use at the same time */