[comp.sources.d] Hack bug

ins_akaa@jhunix.UUCP (04/14/87)

>You miss the large dog.  The large dog devours the tripe ration.  More--
>The large dog dies from hunger.

I can think of a way this could happen, but it seems rather unlikely.

The test in dog_move() to see if the dog died of hunger tests not only hunger,
but hit points as well.  Normally, this is only supposed to happen at this
point if the dog lost hit points from being confused from hunger, a few lines
above.  However, if the dog already has zero or fewer hit points when this
function is called, it will falsely report that the dog dies "of hunger".

There are two bugs which can cause this.  One is the fact that a monster that
loses hit points from a trap doesn't die even if its hit points go down below
zero.  (I recently posted what I think is the fix for this, but I have not
tried it.)

The second involves chameleons, and means that the dog in question must have
been a chameleon.  Checking newcham() in mon.c shows the following algorithm
for computing a monster's new hit points from its old:  
(Note: mtmp->data is the "new" monster and mdat the "old" one)
     hpn = mtmp->mhp;
     hpd = (mtmp->data->mlevel)*8;
     if(!hpd) hpd = 4;
     mtmp->data = mdat;
     mhp = (mdat->mlevel)*8;
     mtmp->mhp = 2 + (hpn*mhp)/hpd;
and the same for computing its new maximum from its old maximum.
This will result in the changing chameleons endlessly going up in hit points,
until the hit points reach 127.  At that point any further increase will make
the hit points negative, due to wraparound.

It gets worse for chameleons that are pets (or were formerly pets; i.e. when
found on a ghost level and belonging to the ghost), or that gained hit points
due to fighting other monsters from the player's use of a ring of conflict.
Since their hit points are high, they are especially prone to the hit points
wrapping around past 127.  (A 4 hit die, 100 hit point chameleon which turns
into something that's 6 hit dice is definitely going to go over 127).

The same applies to polymorphing your dog when well into the game (after the dog
accumulated lots of extra hit points) since polymorph calls the same routine.

The fix: 
     hpn = mtmp->mhp;
     hpd = (mtmp->data->mlevel)*8;    if(!hpd) hpd = 4;
     mhp = (mdat->mlevel)*8;    if(!mhp) mhp = 4;
/* The above if(!mhp) mhp = 4; was not in the original.  Its omission meant
   that something changing into a zero hit die monster, which has 1-4 hp,
   would have its new HP zero.  Thus the 2 which the original added on. */
     mtmp->mhp = (hpn*mhp)/hpd;
     if (mhp > hpd && mtmp->mhp < hpn) mtmp->mhp = 127;
/* Not totally foolproof.  A 2HD monster with 80 HP that changes into a 6HD
   monster that really should have 240 and actually should have 127, the
   maximum possible, will wind up having 113.  */
     if (!mtmp->mhp) mtmp->mhp = 1;
/* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
   0HD creature will require this statement */
     mtmp->data = mdat;
/* and the same for maximum hit points */
     hpn = mtmp->mhpmax;
     mtmp->mhpmax = (hpn*mhp)/hpd;
     if (mhp > hpd && mtmp->mhpmax < hpn) mtmp->mhp = 127;
     if (!mtmp->mhp) mtmp->mhp = 1;
DISCLAIMER: I think this is correct, but I have not tried this fix.
--
"An eclipse of the Earth occurs when you put your hands over your eyes."

Kenneth Arromdee
BITNET: G46I4701@JHUVM, INS_AKAA@JHUVMS, INS_AKAA@JHUNIX
ARPA: ins_akaa%jhunix@hopkins.ARPA
UUCP: {allegra!hopkins, seismo!umcp-cs, ihnp4!whuxcc} !jhunix!ins_akaa
Copyright 1987 by Ken Arromdee.  Distribution of this article by electronic
     means constitutes permission for its recipients to distribute it likewise.
(The NSA, CIA, and FBI conspire to smuggle Reagan drugs via Iran and Nicaragua.)

ins_ajas@jhunix.UUCP (04/15/87)

>     if (mhp > hpd && mtmp->mhp < hpn) mtmp->mhp = 127;
>/* Not totally foolproof.  A 2HD monster with 80 HP that changes into a 6HD
>   monster that really should have 240 and actually should have 127, the
>   maximum possible, will wind up having 113.  */

I goofed here... the monster would actually have -16 HP, which this statement
would catch and change to 127.  A better example would be a 2HD monster with
80 HP that changes to an 8HD monster which "should" have 320 (which cannot be
represented in a signed char), should have 127, and will actually end up
with 64.
--
"An eclipse of the Earth occurs when you put your hands over your eyes."

Kenneth Arromdee
BITNET: G46I4701@JHUVM, INS_AKAA@JHUVMS, INS_AKAA@JHUNIX
ARPA: ins_akaa%jhunix@hopkins.ARPA
UUCP: {allegra!hopkins, seismo!umcp-cs, ihnp4!whuxcc} !jhunix!ins_akaa
Copyright 1987 by Ken Arromdee.  Distribution of this article by electronic
     means constitutes permission for its recipients to distribute it likewise.
(The NSA, CIA, and FBI conspire to smuggle Reagan drugs via Iran and Nicaragua.)