Xref: utzoo rec.games.hack:2784 comp.sources.games.bugs:425
Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!killer!ames!elroy!peregrine!uunet!mcvax!unido!ztivax!tumuc!lan!hartl
From: hartl@lan.informatik.tu-muenchen.dbp.de (Anton Hartl)
Newsgroups: rec.games.hack,comp.sources.games.bugs
Subject: Nethack 2.3 Bugs+Fixes+Enhancements
Message-ID: <256@infovax.lan.informatik.tu-muenchen.dbp.de>
Date: 12 Aug 88 09:20:51 GMT
Reply-To: hartl@lan.UUCP (Anton Hartl)
Organization: Inst. fuer Informatik, TU Muenchen, W. Germany
Lines: 671


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 
+ 
+ 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