From d3b9d28f066df6262d1bd725e7856153aedbc5d2 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sun, 3 Feb 2008 06:42:25 +0000 Subject: [PATCH] exercise/abuse while polyd (trunk only) Three years ago reported that even though exercise of attributes other than wisdom is suppressed while the hero is polymorphed, attribute gains or losses due to pre-existing exercise can still take place in that situation. Since it's an entirely different set of attrs which will be replaced upon rehumanizing, there's not much point. (The same is actually true for wisdom, but I didn't change how exercise works for it.) Adopt his one-liner fix: old exercise won't cause attribute changes while polymorphed; it will silently fade as it does when its magnitude is insufficient to trigger a change. While checking that out, I noticed that exerchk() was using `/= 2' to fade out old exercise/abuse. That will produce platform-dependent results for negative values (ie, for the abuse case) since C's integer division doesn't specify whether to truncate towards zero or towards negative infinity. In particular, -1 / 2 could yield -1 rather than 0 as the code expected. (Its impact on play was negligible though.) This reduces the code for displaying the messages which accompany attribute gain/loss. A few were repharsed in order to simplify that. --- doc/fixes35.0 | 1 + src/attrib.c | 72 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index cf138ce96..aef033933 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -278,6 +278,7 @@ potion thrown by monster which hit a long worm's tail gave feedback about hitting its head implement energy vortex's previously unused energy drain attack changing alignment type resets alignment record to 0 (nomimally aligned) +while polymorphed, suppress attribute gain/lose earned by pre-poly exercise Platform- and/or Interface-Specific Fixes diff --git a/src/attrib.c b/src/attrib.c index eb1fd8811..d402fc21d 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)attrib.c 3.5 2008/01/21 */ +/* SCCS Id: @(#)attrib.c 3.5 2008/02/02 */ /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -440,10 +440,21 @@ exerper() } } +/* exercise/abuse text (must be in attribute order, not botl order); + phrased as "You must have been [][0]." or "You haven't been [][1]." */ +static NEARDATA const char * const exertext[A_MAX][2] = { + { "exercising diligently", "exercising properly" }, /* Str */ + { 0, 0 }, /* Int */ + { "very observant", "paying attention" }, /* Wis */ + { "working on your reflexes", "working on reflexes lately" }, /* Dex */ + { "leading a healthy life-style", "watching your health" }, /* Con */ + { 0, 0 }, /* Cha */ +}; + void exerchk() { - int i, mod_val; + int i, ax, mod_val, lolim, hilim; /* Check out the periodic accumulations */ exerper(); @@ -465,15 +476,30 @@ exerchk() * increase/decrease, you lose some of the * accumulated effects. */ - for(i = 0; i < A_MAX; AEXE(i++) /= 2) { + for (i = 0; i < A_MAX; ++i) { + ax = AEXE(i); + /* nothing to do here if no exercise or abuse has occurred + (Int and Cha always fall into this category) */ + if (!ax) continue; /* ok to skip nextattrib */ - if(ABASE(i) >= 18 || !AEXE(i)) continue; - if(i == A_INT || i == A_CHA) continue;/* can't exercise these */ + mod_val = sgn(ax); /* +1 or -1; used below */ + /* no further effect for exercise if at max or abuse if at min; + can't exceed 18 via exercise even if actual max is higher */ + lolim = ATTRMIN(i); /* usually 3; might be higher */ + hilim = ATTRMAX(i); /* usually 18; maybe lower or higher */ + if (hilim > 18) hilim = 18; + if ((ax < 0) ? (ABASE(i) <= lolim) : (ABASE(i) >= hilim)) + goto nextattrib; + /* can't exercise non-Wisdom while polymorphed; previous + exercise/abuse gradually wears off without impact then */ + if (Upolyd && i != A_WIS) goto nextattrib; #ifdef DEBUG pline("exerchk: testing %s (%d).", - (i == A_STR) ? "Str" : (i == A_WIS) ? "Wis" : - (i == A_DEX) ? "Dex" : "Con", AEXE(i)); + (i == A_STR) ? "Str" : (i == A_INT) ? "Int?" : + (i == A_WIS) ? "Wis" : (i == A_DEX) ? "Dex" : + (i == A_CON) ? "Con" : (i == A_CHA) ? "Cha?" : "???", + ax); #endif /* * Law of diminishing returns (Part III): @@ -481,9 +507,8 @@ exerchk() * You don't *always* gain by exercising. * [MRS 92/10/28 - Treat Wisdom specially for balance.] */ - if(rn2(AVAL) > ((i != A_WIS) ? abs(AEXE(i)*2/3) : abs(AEXE(i)))) - continue; - mod_val = sgn(AEXE(i)); + if (rn2(AVAL) > ((i != A_WIS) ? (abs(ax) * 2 / 3) : abs(ax))) + goto nextattrib; #ifdef DEBUG pline("exerchk: changing %d.", i); @@ -493,32 +518,21 @@ exerchk() pline("exerchk: changed %d.", i); #endif /* if you actually changed an attrib - zero accumulation */ - AEXE(i) = 0; + AEXE(i) = ax = 0; /* then print an explanation */ - switch(i) { - case A_STR: You((mod_val >0) ? - "must have been exercising." : - "must have been abusing your body."); - break; - case A_WIS: You((mod_val >0) ? - "must have been very observant." : - "haven't been paying attention."); - break; - case A_DEX: You((mod_val >0) ? - "must have been working on your reflexes." : - "haven't been working on reflexes lately."); - break; - case A_CON: You((mod_val >0) ? - "must be leading a healthy life-style." : - "haven't been watching your health."); - break; - } + You("%s %s.", + (mod_val > 0) ? "must have been" : "haven't been", + exertext[i][(mod_val > 0) ? 0 : 1]); } } context.next_attrib_check += rn1(200,800); #ifdef DEBUG pline("exerchk: next check at %ld.", context.next_attrib_check); #endif + nextattrib: + /* this used to be ``AEXE(i) /= 2'' but that would produce + platform-dependent rounding/truncation for negative values */ + AEXE(i) = (abs(ax) / 2) * mod_val; } }