From: pfhovpu@voz.arg (Chris Subich)
Newsgroups: rec.games.roguelike.nethack
Subject: [slashem] Polymotph exhaustion
Date: Sat, 05 Jun 1999 20:24:39 GMT
Organization: Organization?  What organization!  I HAVE NONE!!!! :)
Lines: 96
Message-ID: <375936ce.5376204@news.mpinet.net>
NNTP-Posting-Host: 208.6.199.192
NNTP-Posting-Date: Sat, 05 Jun 1999 20:25:21 GMT
X-Trace: 928614321.427.83 N6YEBG2FMC7C0D006C qube-01.us-va.remarq.com
X-Complaints-To: newsabuse@remarQ.com
X-Newsreader: Forte Free Agent 1.11/32.235
Path: carrera.intergate.ca!newsfeed.bctel.net!cyclone.bc.net!news.maxwell.syr.edu!newsfeed.berkeley.edu!remarQ73!supernews.com!remarQ.com!remarQ69!news.remarQ.com!not-for-mail
Xref: carrera.intergate.ca rec.games.roguelike.nethack:28299

In the current Slash'em code, this little line [856 of rehumanize() in
polyself.c], has become the bane of doppelgangers everywhere:

u.uhp = (u.uhp/2) + 1;

And it is called for each and every rehumanization.


I have two problems with this code:  Firstly, it comes after the
actual rehumanization, causing the hp reduction to take place only
after the pause on the line "You revert to human form! -More-", which
is kind of depressing.

Secondly, this has made self-polymorphing virtually worthless in most
situations, even for the doppelganger, whose very ROLE is to
self-polymorph.  The polymorph-abuse punishment is taken care of in
the functions that call rehumanize(), such as losehp().  In most
cases, u.uhp and u.uhpmax are penalized by the monster's level, and
rnd(mons[u.umonnum].mlevel/5 + 1) is taken off in the case of
u.hpbase.

I propose changing:

     polyman("return to %s form!", uform);

 if (u.uhp < 1) {
     char kbuf[256];

     Sprintf(kbuf, "reverting to unhealthy %s form", uform);
     killer_format = KILLED_BY;
     killer = kbuf;
     done(DIED);
 }
 /* WAC Polymorph Exhaustion 1/2 HP to prevent abuse */
 u.uhp = (u.uhp/2) + 1;

To:

 if (u.mhp < 1 || (!Role_if(PM_DOPPELGAGNER) 
 && rn2(20) > ACCUR(A_CON)) { 
   /* Exhaustion for "forced" rehumaization & must pass con chack for 
    * non-doppelgangers */
   /* WAC Polymorph Exhaustion 1/2 HP to prevent abuse */
     u.uhp = (u.uhp/2) + 1;
}
 polyman("return to %s form!", uform);

 if (u.uhp < 1) {
     char kbuf[256];

     Sprintf(kbuf, "reverting to unhealthy %s form", uform);
     killer_format = KILLED_BY;
     killer = kbuf;
     done(DIED);

Also, you would have to change mhitu.c to set u.mhp = 0 before calling
rehumanize() calls if u.mhp < 1 is not checked previously.  The cases
that I have found are:

Straw/Wax/Peper Golem vs. fire - line 975
Iron golem vs Rust Monster - line 1324 & 536 of trap.c (rust trap)
Wood & Leather vs. decay - line 1339
Clay golem vs. cancellation - line 1412 & zap.c line 2041
Going kaboom - line 2568

(Method:  Searched through all .c files for rehumanize(), and then
checked for an unchanging or u.mhp check)

These should be changed anyway to set m.hp = 0 because there is a
small bug in that you revert to human form anyway even if you have
unchanging, because rehumanize() expacts the unchanging check to be
done on the caller's side unless u.mhp < 1.  The below is the only
unchanging check in the rehumanize() code, and polyman(), the function
that actually does the change, has no Unchanging checks at all.

/* KMH, balance patch -- you can't revert back while unchanging */
if (Unchanging && (u.mh < 1)) {
 killer_format = NO_KILLER_PREFIX;
 killer = "killed while stuck in creature form";
 done(DIED);
}

There is a small bug relating to unchanging, genocision, and
life-saving... It probably involves at least 2 unchanging bugs, and I
wouldn't know where to start. Try the following:

Polymorph into xorn & eat "AoUnchainging to get intrinsic.
Genocide xorns. (You stay as Xorn! "Feel dead inside?")
Wear "AoLS.
Die, & you come back as human w/ unchanging INtrinsic!


Chris
pfhovpu@voz.arg

(Address has been ROT13'd for your spammer's inconvienance.)
