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