[comp.sources.d] Bugs in PC Hack 3.5.1

ins_akaa@jhunix.UUCP (03/01/87)

I have recently compiled PC Hack and made a few changes in it, in the process
running across a number of bugs that remained in it.  The bugs include:

1) If you are dragging a heavy iron ball on the ground and you try levitating
   up a stairway, the game will crash a move later.

2) If you are levitating, and zap a wand of digging downwards, you'll still
   fall into the hole you make.

3) Reading a scroll of food detection while you are confused is supposed to
   detect potions.  What it actually does is detect potions, except that 
   when counting the number of potions to show, it still counts food.  This
   can cause problems when there a different number of potions and foods on
   the board.

4) Saving a game with a hell hound in it (and, I believe, going up a level
   and then returning, though I haven't tried it this way) causes the hell
   hound to be replaced with a garbage character and its description to be
   replaced with garbage.

5) A scroll of destroy armor will fail to operate on your shield.  Since a
   shield is considered armor for other purposes (i.e. enchant armor) I assume
   this is a bug.

6) If you read a scroll of enchant weapon while confused, the program fails to
   check to see if you're actually wielding a weapon, which means that you can
   wield your armor and rustproof it with an enchant weapon scroll.

7) Enchant weapon read while confused, and a few other scrolls, fail to check
   for plural in stating what happens to the weapon.

8) If you look at the weapon damage table, it becomes apparent that in many 
   cases they are similar to the AD&D weapon damage tables.  However, the
   first column is damage vs. large and the second versus small, the opposite
   of the way it is in AD&D.  I have no idea if this was really intended this
   way (it might have been).

9) If you eat a lump of royal jelly and it increases your strength but does
   nothing else that would change the status line, the program fails to
   update the status line.

10) There doesn't seem to be any limit in how many hit points your pet can
    have.  Therefore the pet can get negative or zero hit points if it wraps
    around.  (past 127)
  
11) Wielding a dead cockatrice is safe, even if you aren't wearing gloves.
    (Gloves are still required to safely pick one up, though, and you can't
    remove the gloves while wielding it.) 

12) Doing an inventory of gold will produce the response "1 gold pieces"
    (instead of piece) if you only have 1.

13) Eating a dead bat sets confusion to 50, instead of adding 50.  If you
    are very confused, eating the bat could conceivably reduce your confusion.

14) If you are confused and read a scroll of fire, you are damaged by the
    scroll catching fire and burning your hands even if you are fire resistant.
--
"Oh blast, here we go again!"

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
(The NSA, CIA, and FBI conspire to smuggle Reagan drugs via Iran and Nicaragua.)

ins_akaa@jhunix.UUCP (03/13/87)

This is in comp.sources.d because I cannot post to comp.sources.bugs.

Some time back I posted a series of bugs in PC Hack 3.5.1 which I en-
countered.  Here are the bugs (and some more bugs) along with the fixes.
Most of them should also be applicable to the regular Unix Hack 1.0.3.
Note: I have given the names of the files as they are in PC Hack.  Quite
probably a number of them have different names in Unix Hack.

I have tested all these changes, except where indicated.

Note: I am typing this in by hand, and it's conceivable that some mistakes
may have crept in.

>1) If you are dragging a heavy iron ball on the ground and you try levitating
>   up a stairway, the game will crash a move later.

The problem is in do.c, in the function goto_level().
The lines which read
	if(Punished && !Levitation){
		pline("With great effort you climb the stairs.");
		placebc(1);
	}
should read
	if(Punished) {
		if(!Levitation) {
			pline("With great effort you climb the stairs.");
		placebc(1);
	}

>2) If you are levitating, and zap a wand of digging downwards, you'll still
>   fall into the hole you make.

The problem is in dighole() in apply.c.  The line
	if(!u.ustuck)
should read
	if(!u.ustuck && !Levitation)

>3) Reading a scroll of food detection while you are confused is supposed to
>   detect potions.  What it actually does is detect potions, except that 
>   when counting the number of potions to show, it still counts food.  This
>   can cause problems when there a different number of potions and foods on
>   the board.

Check read.c in the function doread(), in the case SCR_FOOD_DETECTION:
The line 
	if(obj->olet == FOOD_SYM)
should have the "FOOD_SYM" changed to "foodsym".

>4) Saving a game with a hell hound in it (and, I believe, going up a level
>   and then returning, though I haven't tried it this way) causes the hell
>   hound to be replaced with a garbage character and its description to be
>   replaced with garbage.

This bug is MSDOS-specific.  I think.  Add the lines marked below, in
savemonchn() in lev.c:

	extern struct permonst li_dog, dog, la_dog;
	extern struct permonst hell_hound;     /* add */
...
		monsindex = -3;
	else if (permonstp == &hell_hound)	/* add */
		monsindex = -4;			/* add */

and in restmonchn() in save.c:

	extern struct permonst li_dog, dog, la_dog;
	extern struct permonst hell_hound;     /* add */
...
		mtmp->data = &la_dog;
	else if (monsindex == -4)		/* add */
		mtmp->data = &hell_hound;	/* add */

>5) A scroll of destroy armor will fail to operate on your shield.  Since a
>   shield is considered armor for other purposes (i.e. enchant armor) I assume
>   this is a bug.

In read.c, doread(), case SCR_DESTROY_ARMOR:
		
	} else if(uarms)				/* add */
		pline("Your shield crumbles away!");	/* add */
		useup(uarms);				/* add */
	} else {
		strange_feeling(scroll,"Your skin itches.");

>6) If you read a scroll of enchant weapon while confused, the program fails to
>   check to see if you're actually wielding a weapon, which means that you can
>   wield your armor and rustproof it with an enchant weapon scroll.
>7) Enchant weapon read while confused, and a few other scrolls, fail to check
>   for plural in stating what happens to the weapon.

The fix for SCR_ENCHANT_WEAPON:  change the lines
	pline("Your %s glows silver for a moment.",
		objects[uwep->otyp].oc_name);
to the following:
	pline("Your %s silver for a moment.", aobjnam(uwep,"glow"));
The change for SCR_DAMAGE_WEAPON is similar, except the color is purple.
No changes need to be made for SCR_ENCHANT_ARMOR or SCR_DESTROY_ARMOR
since plural armors are impossible.

>8) If you look at the weapon damage table, it becomes apparent that in many 
>   cases they are similar to the AD&D weapon damage tables.  However, the
>   first column is damage vs. large and the second versus small, the opposite
>   of the way it is in AD&D.  I have no idea if this was really intended this
>   way (it might have been).

The correction for damage vs. large/small is in objclass.h; switch 
wldam for wsdam, and vice versa, in the two lines containing them.

>9) If you eat a lump of royal jelly and it increases your strength but does
>   nothing else that would change the status line, the program fails to
>   update the status line.

Eat.c, function doeat(), add a line
		flags.botl = 1;
immediately below
	if(otmp->otyp == LUMP_OF_ROYAL_JELLY) {

>10) There doesn't seem to be any limit in how many hit points your pet can
>    have.  Therefore the pet can get negative or zero hit points if it wraps
>    around.  (past 127)

Add the following to hitmm() in fight.c:
			hit = 2;
		}
		if (magr->mhpmax <= 0) magr->mhpmax = 127);  /* add */
	}
	return(hit);

>11) Wielding a dead cockatrice is safe, even if you aren't wearing gloves.
>    (Gloves are still required to safely pick one up, though, and you can't
>    remove the gloves while wielding it.) 

Wield.c, in dowield():
			pline("You are empty handed.");
		}
	/* addition begins */
	} else if (!uarmg && wep->otyp == DEAD_COCKATRICE) {
		pline("You wield the dead cockatrice in your bare hands.");
		pline("You turn to stone ..."):
		killer="dead cockatrice";
		done(died);
	/* addition ends */
	} else if(uarms && wep->otyp == TWO_HANDED_SWORD)

>12) Doing an inventory of gold will produce the response "1 gold pieces"
>    (instead of piece) if you only have 1.

In invent.c, doprgold():  change the line
	pline("You are carrying %ld gold pieces.", u.ugold);
to
	pline("You are carrying %ld gold piece%s.",u.ugold,plur(u.ugold));

>13) Eating a dead bat sets confusion to 50, instead of adding 50.  If you
>    are very confused, eating the bat could conceivably reduce your confusion.

Fix is obvious; in eatcorpse() in eat.c change "Confusion = 50"
to "Confusion += 50".

>14) If you are confused and read a scroll of fire, you are damaged by the
>    scroll catching fire and burning your hands even if you are fire resistant.

Read.c, doread(), case SCR_FIRE:

	known = TRUE;
	if(confused) {
		if(Fire_resistance) {		/* add */
			pline("The scroll catches fire""); /* add */
			pline("You are uninjured!");	/* add */
		} else {			/* add */
		pline("The scroll catches fire and you burn your hands.");	
		losehp(1, "scroll of fire");
		}				/* add */

>15) Same as 14), but for burning scrolls from being hit by dragon fire (or
>    bouncing wands of fire).

The change is in zap.c.  I seem to have misplaced my original copy of zap.c.

>16) When you wield a dead cockatrice against monsters, you are told that
>    they turn to stone, but the monsters only leave normal corpses.

No quick fix.  In mon.c and fight.c, add
	extern boolean stonekludge;
somewhere in the top.  Then go to killed() in mon.c and change the one line
	if(!letter(tmp) || (index("mw",tmp) && !rn2(3))) tmp = 0;
to
if(!stonekludge && (!letter(tmp) || (index("mw",tmp) && !rn2(3)))) tmp = 0;
Then change
	if(index("NTVm&",mdat->mlet) || rn2(5)) {
to
	if(stonekludge) {
		register char typetmp;
		if index(mlarge,tmp))
			typetmp=ENORMOUS_ROCK;
		else typetmp = ROCK;
		mksobj_at(typetmp, x, y);
		if(cansee(x,y))
			atl(x,y,objects[typetmp].oc_olet);
	} else if index("NTVm&w",mdat->mlet) || rn2(5)) {

The change in fight.c is:  add the line "stonekludge = FALSE;" inside
the opening { of hmon().  Then under case DEAD_COCKATRICE:,
add "stonekludge = TRUE;" just above "killed(mtmp);".
	
>17) A cockatrice that hits another cockatrice turns it to stone.  However,
>    when you hit a cockatrice with a cockatrice corpse nothing happens.

In fight.c, hitmm() change
		if(magr->data->mlet == 'c' && !magr->cham) {
to
	if(magr->data->mlet == 'c' && mdef->data->mlet != 'c' && !magr->cham) {

>18) When you zap a wand of undead turning at a corpse to bring it back to
>    life, the corpse doesn't get erased from the screen.

In the function revive() in zap.c, move the delobj() call to just before
(instead of just after) the mkmon() call.

>19) A long worm that dies without leaving a corpse fails to print the 
>    worm tooth on the screen.

See #16.

>20) If you dig out of a monster while swallowed, the '@' sign representing you
>    is not printed on the screen.

I haven't fixed this one yet.  Sorry...

>21) If you try to drop a very large amount of gold (try, with 0 gold 
>    currently possessed, dropping 1 more than the maximum positive
>    "long") Hack will think you are dropping a negative amount of gold.
>    (This bug was recently mentioned on the net.)

In do.c, drop():
			pline("You didn't drop any gold pieces.");
		else if(amount < 0) {		/* add */
			u.ugold += amount;	/* add */
	pline("The LRS would be very interested to know you have that much."); /* add */
		}				/* add */

>22) For female characters the same message for nymphs stealing armor is
>    given ("The nymph seduces you and you start taking off your clothes").

In steal.c, add an "extern boolean female;" at the top.  Then in steal()
	
		if(female)			/* add */
	pline("%s charms you.  You gladly hand over your humble garments.",
	Monnam(mtmp));	/* add these */
		else 				/* add */
		pline("%s seduces you and %s off your %s.");

>23) Changing male/female in the middle of the game is permitted.

Options.c, parseoptions()

	if(!strncmp(opts,"male",4)) {
		if(from_env && female != negated)/* add */
			pline("That is not anatomically possible."); /* add */
		else				/* add */

And a similar change a few lines down, but with == instead of !=

>24) A cancelled rust monster can still rust your helmet, though not your 
>    armor.  Also, cancellation is very inconsistent, and a lot of monsters
>    cannot be cancelled.

In mhitu.c, mhitu(): change in case 'R':
	if(tmp && uarmh && !uarmh->rustfree &&
by replacing tmp with ctmp.  Also under case 's':, make the same change.

NOTE: For 'R' I haven't tested this.

There are several other instances, but whether or not they are really bugs
is debatable.

>25) A tame chameleon seems to die of hunger rather quickly, and so do tame
monsters that get polymorphed often.  (This seems to be the same bug.)

This one I have no idea about, and I am not even sure if it really exists, but
it does seem this way.

Also there is a sort-of bug: with a tame chameleon, or polymorphing a tame
monster, the extra hit points that your pet gains through experience get
lost after the change; the HP possessed after the change are the normal
HP for a monster of the resultant type.  I can't see any way to fix this.

(Note: to tame a chameleon you don't need a scroll of taming.  Just wait 
until it changes into a dog, then throw a tripe ration at it.)
--
"Oh blast, here we go again!"

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
(The NSA, CIA, and FBI conspire to smuggle Reagan drugs via Iran and Nicaragua.)