[rec.games.hack] Nethack 2.3 Bugs+Fixes+Enhancements

hartl@lan.informatik.tu-muenchen.dbp.de (Anton Hartl) (08/12/88)

Nethack Bug Fixes + Enhancements
================================

1) BUG+FIX: If a nymph has stolen your badge/leash/blindfold (when applied)
  it remains applied. :-(

2) ENHANCEMENT:  To make the wand of probing and the stethoscope more
  useful (i.e. after a gremlin has sucked you :-(), the routine
  ustatusline now prints information about acquired attributes
  such as fire/cold/poison resistance.
  #define ATTRIBUTEPROBING in config.h if you want to know more about yourself.

3) ENHANCEMENT: Had you ever a fantastic game? And just in that
  moment nethack crashed? Or your machine crashed? @#$%^&*
  Here is the *solution*! With our patches applied, you will be able
  to restore those games on the last level you left. :-)
  #define ANTICRASH in config.h if you want to be resurrected.



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Anton "Ulysses" Hartl
	hartl@tumult.informatik.tu-muenchen.de (ARPA)
	...{!uunet,!unido}!tumult!hartl (UUCP)

Only those who attempt the absurd will achieve the impossible.
-------------------------------------------------------------------------------
Franz "Oin" Schmausser
	schmauss@lan.informatik.tu-muenchen.dbp.de
	schmauss%lan.informatik.tu-muenchen.dbp.de@{relay.cs.net,unido.uucp}

Monsters come from nowhere to hit YOU everywhere.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dept. of Computer Science, Technical University of Munich, Bavaria




---- snip ----- snip ----- snip ----- snip ----- snip ----- snip ----- snip ---

*** config.h.orig	Fri Aug 12 10:18:38 1988
--- config.h	Fri Aug 12 10:24:56 1988
***************
*** 231,236
  #define THEOLOGY	/* Smarter gods - The Unknown Hacker */
  #define	STOOGES		/* Three wild and crazy guys - Bruce Mewborne */
  #define SINKS		/* Kitchen sinks - Janet Walz */
  
  #ifdef MSDOS
  #define TERMLIB		/* enable use of termcap file c:\etc\termcap	*/

--- 231,238 -----
  #define THEOLOGY	/* Smarter gods - The Unknown Hacker */
  #define	STOOGES		/* Three wild and crazy guys - Bruce Mewborne */
  #define SINKS		/* Kitchen sinks - Janet Walz */
+ #define ANTICRASH	/* anti crash facility by Oin & Ulysses */
+ #define ATTRIBUTEPROBING	/* Enhanced probing code by Oin & Ulysses */
  
  #ifdef MSDOS
  #define TERMLIB		/* enable use of termcap file c:\etc\termcap	*/
*** lev.c.orig	Fri Aug 12 10:18:39 1988
--- lev.c	Fri Aug 12 10:23:23 1988
***************
*** 12,17
  extern int hackpid;
  extern xchar dlevel;
  extern char nul[];
  
  #ifndef NOWORM
  #include	"wseg.h"

--- 12,25 -----
  extern int hackpid;
  extern xchar dlevel;
  extern char nul[];
+ #ifdef ANTICRASH
+ extern char	save_game;
+ extern char	crash_recover;
+ extern struct permonst pm_wizard;
+ extern char	pl_character[PL_CSIZ];
+ extern char	fut_geno[60], genocided[60];
+ static boolean	freechain = TRUE;
+ #endif
  
  #ifndef NOWORM
  #include	"wseg.h"
***************
*** 106,111
  #ifdef DGK
  	if (count_only)	return(0);
  #endif
  	billobjs = 0;
  	fgold = 0;
  	ftrap = 0;

--- 114,159 -----
  #ifdef DGK
  	if (count_only)	return(0);
  #endif
+ 
+ #ifdef ANTICRASH
+ 	if (!save_game)
+ 	{
+ 		int	tmp;
+ 
+ 		glo(-1);
+ 		if ((fd = creat(lock, 0644)) < 0)
+ 		{
+ 			done("tricked");
+ 		}
+ 		freechain = FALSE;
+ 		saveobjchn(fd, invent);
+ 		saveobjchn(fd, fcobj);
+ 		savemonchn(fd, fallen_down);
+ 		freechain = TRUE;
+ 		tmp = getuid();
+ 		bwrite(fd, (char *) &tmp, sizeof tmp);
+ 		bwrite(fd, (char *) &flags, sizeof(struct flag));
+ 		bwrite(fd, (char *) &dlevel, sizeof dlevel);
+ 		bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
+ 		bwrite(fd, (char *) level_exists, sizeof level_exists);
+ 		bwrite(fd, (char *) &moves, sizeof moves);
+ 		bwrite(fd, (char *) &u, sizeof(struct you));
+ #ifdef SPELLS
+ 		bwrite(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
+ #endif
+ 		if(u.ustuck)
+ 			bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
+ 		bwrite(fd, (char *) pl_character, sizeof pl_character);
+ 		bwrite(fd, (char *) genocided, sizeof genocided);
+ 		bwrite(fd, (char *) fut_geno, sizeof fut_geno);
+ #ifdef HARD
+ 		bwrite(fd, (char *) &pm_wizard, sizeof(struct permonst));
+ #endif
+ 		savenames(fd);
+ 		close(fd);
+ 	}
+ #endif /* ANTICRASH */
+ 
  	billobjs = 0;
  	fgold = 0;
  	ftrap = 0;
***************
*** 143,148
  #ifdef DGK
  		if (!count_only)
  #endif
  			free((char *) otmp);
  		otmp = otmp2;
  	}

--- 191,199 -----
  #ifdef DGK
  		if (!count_only)
  #endif
+ #ifdef ANTICRASH
+ 		if (freechain)
+ #endif
  			free((char *) otmp);
  		otmp = otmp2;
  	}
***************
*** 166,171
  		bwrite(fd, (char *) &xl, sizeof(int));
  		bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
  		if(mtmp->minvent) saveobjchn(fd,mtmp->minvent);
  		free((char *) mtmp);
  		mtmp = mtmp2;
  	}

--- 217,225 -----
  		bwrite(fd, (char *) &xl, sizeof(int));
  		bwrite(fd, (char *) mtmp, xl + sizeof(struct monst));
  		if(mtmp->minvent) saveobjchn(fd,mtmp->minvent);
+ #ifdef ANTICRASH
+ 		if (freechain)
+ #endif
  		free((char *) mtmp);
  		mtmp = mtmp2;
  	}
*** pri.c.orig	Fri Aug 12 10:18:39 1988
--- pri.c	Fri Aug 12 10:23:23 1988
***************
*** 482,487
  # else
  		u.ulevel, u.ugold, u.uhp, u.uhpmax, u.uac);
  # endif
  }
  #endif
  

--- 482,510 -----
  # else
  		u.ulevel, u.ugold, u.uhp, u.uhpmax, u.uac);
  # endif
+ #ifdef ATTRIBUTEPROBING
+ 	pline
+ 	(
+ 		"Your attributes are: %s%s%s%s%s%s%s%sprotection %+d",
+ 		((HPoison_resistance & INTRINSIC) == INTRINSIC)
+ 			? "poison resistance  " : "", 
+ 		((HFire_resistance & INTRINSIC) == INTRINSIC) 
+ 			? "fire resistance  " : "",
+ 		((HCold_resistance & INTRINSIC) == INTRINSIC)
+ 			? "cold resistance  " : "",
+ 		((HInvis & INTRINSIC) == INTRINSIC)
+ 			? "invisibility  " : "",
+ 		((HSee_invisible & INTRINSIC) == INTRINSIC)
+ 			? "see invisibles  " : "",
+ 		((Stealth & INTRINSIC) == INTRINSIC)
+ 			? "stealth  " : "",
+ 		((Fast & INTRINSIC) == INTRINSIC)
+ 			? "speed  " : "",
+ 		((HTelepat & INTRINSIC) == INTRINSIC)
+ 			? "telepathy  " : "",
+ 		Protection ? u.ublessed : 0
+ 	);
+ #endif
  }
  #endif
  
*** steal.c.orig	Fri Aug 12 10:18:39 1988
--- steal.c	Fri Aug 12 10:23:23 1988
***************
*** 77,83
  	}
  	tmp = 0;
  	for(otmp = invent; otmp; otmp = otmp->nobj) if(otmp != uarm2)
! 		tmp += ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1);
  	tmp = rn2(tmp);
  	for(otmp = invent; otmp; otmp = otmp->nobj) if(otmp != uarm2)
  		if((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1))

--- 77,83 -----
  	}
  	tmp = 0;
  	for(otmp = invent; otmp; otmp = otmp->nobj) if(otmp != uarm2)
! 		tmp += ((otmp->owornmask & (W_ARMOR | W_RING | W_TOOL)) ? 5 : 1);
  	tmp = rn2(tmp);
  	for(otmp = invent; otmp; otmp = otmp->nobj) if(otmp != uarm2)
  		if((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING | W_TOOL)) ? 5 : 1))
***************
*** 80,86
  		tmp += ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1);
  	tmp = rn2(tmp);
  	for(otmp = invent; otmp; otmp = otmp->nobj) if(otmp != uarm2)
! 		if((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1))
  			< 0) break;
  	if(!otmp) {
  		impossible("Steal fails!");

--- 80,86 -----
  		tmp += ((otmp->owornmask & (W_ARMOR | W_RING | W_TOOL)) ? 5 : 1);
  	tmp = rn2(tmp);
  	for(otmp = invent; otmp; otmp = otmp->nobj) if(otmp != uarm2)
! 		if((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING | W_TOOL)) ? 5 : 1))
  			< 0) break;
  	if(!otmp) {
  		impossible("Steal fails!");
***************
*** 88,94
  	}
  	if(otmp->o_id == stealoid)
  		return(0);
! 	if((otmp->owornmask & (W_ARMOR | W_RING))){
  		switch(otmp->olet) {
  		case RING_SYM:
  			ringoff(otmp);

--- 88,94 -----
  	}
  	if(otmp->o_id == stealoid)
  		return(0);
! 	if((otmp->owornmask & (W_ARMOR | W_RING | W_TOOL))){
  		switch(otmp->olet) {
  		case TOOL_SYM:
  		  switch(otmp->otyp){
***************
*** 90,95
  		return(0);
  	if((otmp->owornmask & (W_ARMOR | W_RING))){
  		switch(otmp->olet) {
  		case RING_SYM:
  			ringoff(otmp);
  			break;

--- 90,117 -----
  		return(0);
  	if((otmp->owornmask & (W_ARMOR | W_RING | W_TOOL))){
  		switch(otmp->olet) {
+ 		case TOOL_SYM:
+ 		  switch(otmp->otyp){
+ 		  case BLINDFOLD:
+ 			if (Blindfolded && otmp->owornmask) {
+ 			      Blindfolded = 0;
+ 			      otmp->owornmask = 0;
+ 			      if (!Blinded)
+ 				Blinded = 1;	/* see on nexte */
+ 			}
+ 			break;
+ 
+ 		  case BADGE:
+ 			if (Badged && otmp->owornmask) {
+ 			    Badged = 0;
+ 			    otmp->owornmask = 0;
+ 			}
+ 			break;
+ 		  default:
+ 			break;
+ 		  }
+ 		  break; /* esac TOOL_SYM */
+ 
  		case RING_SYM:
  			ringoff(otmp);
  			break;
***************
*** 145,150
  	}
  	else if(otmp == uwep) setuwep((struct obj *) 0);
  
  	if(Punished && otmp == uball){
  		Punished = 0;
  		freeobj(uchain);

--- 167,200 -----
  	}
  	else if(otmp == uwep) setuwep((struct obj *) 0);
  
+ #ifdef WALKIES
+ 	if (otmp->olet == TOOL_SYM && otmp->otyp == LEASH)
+ 	{
+ 	    register struct monst *ltmp = fmon;
+ 	    extern char *lmonnam();
+ 
+ 	    while(ltmp && !ltmp->mleashed)
+ 		    ltmp = ltmp->nmon;
+ 
+ 	    if(ltmp) {
+ 	      char	dfn[BUFSZ];
+ 
+ 	      strcpy(dfn,
+ #ifdef RPH
+     /* a hack to include the dogs full name.  +4 elminates */
+     /* the 'the' at the start of the name */
+ 			lmonnam(ltmp) + 4);
+ #else
+ 			ltmp->data->mname);
+ #endif
+ 
+ 	      ltmp->mleashed = 0;
+ 	      if (next_to(ltmp))
+ 		pline("%s removes the leash from your %s.",
+ 		  Monnam(mtmp), dfn);
+ 	    }
+ 	}
+ #endif
  	if(Punished && otmp == uball){
  		Punished = 0;
  		freeobj(uchain);
*** unixmain.c.orig	Fri Aug 12 10:18:40 1988
--- unixmain.c	Fri Aug 12 10:23:24 1988
***************
*** 15,20
  extern char *getlogin(), *getenv();
  extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
  
  int (*afternmv)();
  int (*occupation)();
  

--- 15,24 -----
  extern char *getlogin(), *getenv();
  extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
  
+ #ifdef ANTICRASH
+ extern char	crash_recover;
+ #endif
+ 
  int (*afternmv)();
  int (*occupation)();
  
***************
*** 179,185
  		askname();
  	plnamesuffix();		/* strip suffix from name; calls askname() */
  				/* again if suffix was whole name */
! 				/* accepts any suffix */
  #ifdef WIZARD
  	if(!wizard) {
  #endif

--- 183,191 -----
  		askname();
  	plnamesuffix();		/* strip suffix from name; calls askname() */
  				/* again if suffix was whole name */
! #ifdef ANTICRASH
! 	setftty();
! #endif
  #ifdef WIZARD
  	if(!wizard) {
  #endif
***************
*** 222,227
  		}
  	}
  #endif /* WIZARD /**/
  	setftty();
  	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
  	regularize(SAVEF+5);		/* avoid . or / in name */

--- 228,234 -----
  		}
  	}
  #endif /* WIZARD /**/
+ #ifndef ANTICRASH
  	setftty();
  #endif
  	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
***************
*** 223,228
  	}
  #endif /* WIZARD /**/
  	setftty();
  	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
  	regularize(SAVEF+5);		/* avoid . or / in name */
  	if((fd = open(SAVEF,0)) >= 0 &&

--- 230,236 -----
  #endif /* WIZARD /**/
  #ifndef ANTICRASH
  	setftty();
+ #endif
  	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
  	regularize(SAVEF+5);		/* avoid . or / in name */
  #ifdef ANTICRASH
***************
*** 225,230
  	setftty();
  	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
  	regularize(SAVEF+5);		/* avoid . or / in name */
  	if((fd = open(SAVEF,0)) >= 0 &&
  	   (uptodate(fd) || unlink(SAVEF) == 666)) {
  		(void) signal(SIGINT,done1);

--- 233,248 -----
  #endif
  	(void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
  	regularize(SAVEF+5);		/* avoid . or / in name */
+ #ifdef ANTICRASH
+ 	if (crash_recover)
+ 	{
+ 		pline("Hello %s%s, welcome to %s!", 
+ 			(Badged) ? "Officer " : "", plname, gamename);
+ 		(void) signal(SIGINT,done1);
+ 		flags.move = 0;
+ 	}
+ 	else
+ #endif
  	if((fd = open(SAVEF,0)) >= 0 &&
  	   (uptodate(fd) || unlink(SAVEF) == 666)) {
  		(void) signal(SIGINT,done1);
*** unixunix.c.orig	Fri Aug 12 10:18:40 1988
--- unixunix.c	Fri Aug 12 10:23:24 1988
***************
*** 27,32
  extern char *getenv();
  extern time_t time();
  
  setrandom()
  {
  	(void) srand((int) time ((time_t *) 0));

--- 27,41 -----
  extern char *getenv();
  extern time_t time();
  
+ #ifdef ANTICRASH
+ extern char	crash_recover;
+ extern struct permonst pm_wizard;
+ extern char	pl_character[PL_CSIZ];
+ extern char	fut_geno[60], genocided[60];
+ extern char	crash_recover;
+ extern boolean	level_exists[MAXLEVEL+1];
+ #endif
+ 
  setrandom()
  {
  	(void) srand((int) time ((time_t *) 0));
***************
*** 170,175
    		if(!(kill(lockedpid, 0) == -1 && errno == ESRCH))
  #endif
  			return(0);
  	}
  	(void) close(fd);
  	for(i = 1; i <= MAXLEVEL; i++) {		/* try to remove all */

--- 179,188 -----
    		if(!(kill(lockedpid, 0) == -1 && errno == ESRCH))
  #endif
  			return(0);
+ #ifdef ANTICRASH
+ 		if (recover_from_crash())
+ 			return(0);
+ #endif
  	}
  	(void) close(fd);
  	for(i = 1; i <= MAXLEVEL; i++) {		/* try to remove all */
***************
*** 229,234
  		if(veryold(fd))	/* if true, this closes fd and unlinks lock */
  			goto gotlock;
  		(void) close(fd);
  	} while(i < locknum);
  
  	(void) unlink(LLOCK);

--- 242,254 -----
  		if(veryold(fd))	/* if true, this closes fd and unlinks lock */
  			goto gotlock;
  		(void) close(fd);
+ #ifdef ANTICRASH
+ 		if (crash_recover)
+ 		{
+ 			(void) unlink(LLOCK);
+ 			return;
+ 		}
+ #endif
  	} while(i < locknum);
  
  	(void) unlink(LLOCK);
***************
*** 433,435
  	while((lp = index(s, '.')) || (lp = index(s, '/')))
  		*lp = '_';
  }

--- 453,584 -----
  	while((lp = index(s, '.')) || (lp = index(s, '/')))
  		*lp = '_';
  }
+ 
+ 
+ #ifdef ANTICRASH
+ 
+ #undef FMASK
+ #include <sys/file.h>
+ 
+ recover_from_crash()
+ {
+ 	int	fd;
+ 	char	answer, readchar();
+ 
+ 	glo(-1);
+ 	if ((fd = open(lock, O_RDONLY)) < 0)
+ 		return(0);
+ 
+ 	pline("Your last dungeon visit unfortunately ended in a disaster!");
+ 	pline("Do you want to recover the crashed game? ");
+ 	answer = readchar();
+ 	if (answer == 'Y' || answer == 'y')
+ 		return(recover_level(fd));
+ 	else
+ 		return(0);
+ }
+ 
+ recover_level(fd)
+ int	fd;
+ {
+ 	int	tmp;
+ 	unsigned	mid;
+ 	struct obj	*otmp;
+ 	extern struct obj	*restobjchn();
+ 	extern struct monst	*restmonchn();
+ 
+ 	invent = restobjchn(fd);
+ 	for (otmp = invent; otmp; otmp = otmp->nobj)
+ 		if(otmp->owornmask)
+ 			setworn(otmp, otmp->owornmask);
+ 	fcobj = restobjchn(fd);
+ 	fallen_down = restmonchn(fd);
+ 	mread(fd, (char *) &tmp, sizeof tmp);
+ #ifdef WIZARD
+ 	if (!wizard)
+ #endif
+ 	if (tmp != getuid()) 
+ 	{	
+ 		/* strange ... */
+ 		(void) close(fd);
+ 		puts("Saved game was not yours.");
+ 		return(0);
+ 	}
+ 	mread(fd, (char *) &flags, sizeof(struct flag));
+ #ifdef DGK
+ 	/* Some config file OPTIONS take precedence over those in save file.
+ 	 */
+ 	flags.rawio = oldflags.rawio;
+ 	flags.DECRainbow = oldflags.DECRainbow;
+ 	flags.IBMBIOS = oldflags.IBMBIOS;
+ #endif
+ 	mread(fd, (char *) &dlevel, sizeof dlevel);
+ 	mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
+ 	mread(fd, (char *) level_exists, sizeof level_exists);
+ 	mread(fd, (char *) &moves, sizeof moves);
+ 	mread(fd, (char *) &u, sizeof(struct you));
+ #ifdef SPELLS
+ 	mread(fd, (char *) spl_book, sizeof(struct spell) * (MAXSPELL + 1));
+ #endif
+ 	if (u.ustuck)
+ 		mread(fd, (char *) &mid, sizeof mid);
+ 	mread(fd, (char *) pl_character, sizeof pl_character);
+ 	mread(fd, (char *) genocided, sizeof genocided);
+ 	mread(fd, (char *) fut_geno, sizeof fut_geno);
+ #ifdef HARD
+ 	{
+ 		/* Save name pointer from being munged -- tom@uw-warp */
+ 		char *name = pm_wizard.mname;
+ 		mread(fd, (char *) &pm_wizard, sizeof(struct permonst));
+ 		pm_wizard.mname = name;
+ 	}
+ #endif
+ 	restnames(fd);
+ 	if (Punished) 
+ 	{
+ 		for (otmp = fobj; otmp; otmp = otmp->nobj)
+ 			if (otmp->olet == CHAIN_SYM)
+ 				goto chainfnd;
+ 		panic("Cannot find the iron chain?");
+ chainfnd:
+ 		uchain = otmp;
+ 		if (!uball)
+ 		{
+ 			for (otmp = fobj; otmp; otmp = otmp->nobj)
+ 				if (otmp->olet == BALL_SYM && otmp->spe)
+ 					goto ballfnd;
+ 			panic("Cannot find the iron ball?");
+ ballfnd:
+ 			uball = otmp;
+ 		}
+ 	}
+ 	if (u.ustuck) 
+ 	{
+ 		register struct monst *mtmp;
+ 
+ 		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
+ 			if (mtmp->m_id == mid)
+ 				goto monfnd;
+ 		panic("Cannot find the monster ustuck.");
+ monfnd:
+ 		u.ustuck = mtmp;
+ 	}
+ 	close(fd);
+ 
+ 	glo(dlevel);
+ 	if ((fd = open(lock, O_RDONLY)) < 0)
+ 		return(0);
+ 	getlev(fd, 0, 0);
+ 	close(fd);
+ 
+ 	initrack();
+ 	flags.nscrinh = 0;
+ 	setsee();
+ 	seeobjs();
+ 	docrt();
+ 
+ 	crash_recover = TRUE;
+ 	return(1);
+ }
+ 
+ #endif

institut@csli.STANFORD.EDU (LSA Summer Institute Account) (08/17/88)

The original posting was too long to edit, but the first thing it
mentioned was that if a nymph steals certain items while they are
applied, you will still get the effects of that item (e.g., if you
apply the leash and she steals it, the dog will still stay within a
couple of spaces of you), or at least that's how I understood it.

So what happens if you apply the blindfold, she steals it, and
then you can't take it off (blind for rest of game?)...


========================================================================
Tom Wylie
send email to wylie@score.stanford.edu,  NOT THE ADDRESS ABOVE!!!
(this ain't my account, I just use it for bboards)
I'm the only gamer on the staff, so any opinions can only be my own.