December 10, 1999 This is a patch that will take an unmodified 3.2.2 distribution and make it Year-2000 ready, as well as fix several bugs that could cause the game to crash. *** ../NetHack322/include/patchlevel.h Mon Dec 9 17:22:52 1996 --- include/patchlevel.h Wed Dec 8 21:02:28 1999 *************** *** 1,14 **** ! /* SCCS Id: @(#)patchlevel.h 3.2 96/11/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ ! /* NetHack 3.2.2 */ #define VERSION_MAJOR 3 #define VERSION_MINOR 2 /* * PATCHLEVEL is updated for each release. */ ! #define PATCHLEVEL 2 /* * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. --- 1,14 ---- ! /* SCCS Id: @(#)patchlevel.h 3.2 99/12/10 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ ! /* NetHack 3.2.3 */ #define VERSION_MAJOR 3 #define VERSION_MINOR 2 /* * PATCHLEVEL is updated for each release. */ ! #define PATCHLEVEL 3 /* * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. *************** *** 16,22 **** #define EDITLEVEL 0 #define COPYRIGHT_BANNER_A \ ! "NetHack, Copyright 1985-1996" #define COPYRIGHT_BANNER_B \ " By Stichting Mathematisch Centrum and M. Stephenson." --- 16,22 ---- #define EDITLEVEL 0 #define COPYRIGHT_BANNER_A \ ! "NetHack, Copyright 1985-1999" #define COPYRIGHT_BANNER_B \ " By Stichting Mathematisch Centrum and M. Stephenson." *************** *** 24,30 **** #define COPYRIGHT_BANNER_C \ " See license for details." ! #if 0 /* * If two successive patchlevels have compatible data files (fat chance), * defining this with the value of the older one will allow its bones and --- 24,30 ---- #define COPYRIGHT_BANNER_C \ " See license for details." ! #if 1 /* * If two successive patchlevels have compatible data files (fat chance), * defining this with the value of the older one will allow its bones and *************** *** 38,44 **** #endif /*****************************************************************************/ ! /* Version 3.2.2 */ /* Patch 2, December 10, 1996 * fix the `recover' utility --- 38,58 ---- #endif /*****************************************************************************/ ! /* Version 3.2.3 */ ! ! /* Patch 3, December 10, 1999 ! * Released simultaneously with 3.3.0 for the benefit of ! * ports and platforms that were unable to get working ! * versions of 3.3.0 ready prior to the year 2000. It ! * consisted of just a few bug fixes and offered no new ! * functionality changes over 3.2.2. ! * ! * Y2K fix: use 4 digit year values for the dates in the score file ! * updated COPYRIGHT_BANNER_A to reflect year of release ! * Fatal Mac bug removed ! * DOS Makefile problem removed ! * several bugs that could potentially trigger crashes removed ! */ /* Patch 2, December 10, 1996 * fix the `recover' utility *** ../NetHack322/src/end.c Mon Nov 4 09:01:04 1996 --- src/end.c Wed Dec 8 19:49:42 1999 *************** *** 535,543 **** --- 535,546 ---- /* clean up unneeded windows */ if (have_windows) { + wait_synch(); + display_nhwindow(WIN_MESSAGE, TRUE); destroy_nhwindow(WIN_MAP); destroy_nhwindow(WIN_STATUS); destroy_nhwindow(WIN_MESSAGE); + WIN_MESSAGE = WIN_STATUS = WIN_MAP = WIN_ERR; if(!done_stopprint || flags.tombstone) endwin = create_nhwindow(NHW_TEXT); *** ../NetHack322/src/mail.c Mon Dec 9 17:44:04 1996 --- src/mail.c Wed Dec 8 21:00:32 1999 *************** *** 434,447 **** { char *junk[]={ "Please disregard previous letter.", ! "Welcome to NetHack 3.2.2!", #ifdef AMIGA "Only Amiga makes it possible.", "CATS have all the answers.", #endif ! "Report bugs to nethack-bugs@linc.cis.upenn.edu" }; pline("It reads: \"%s\"", junk[rn2(SIZE(junk))]); } --- 434,450 ---- { char *junk[]={ "Please disregard previous letter.", ! "Welcome to NetHack 3.2.3!", #ifdef AMIGA "Only Amiga makes it possible.", "CATS have all the answers.", #endif ! "Report bugs to " }; + if (Blind) + pline("Unfortunately you cannot see what it says."); + else pline("It reads: \"%s\"", junk[rn2(SIZE(junk))]); } *** ../NetHack322/src/mkmaze.c Mon Nov 4 09:01:26 1996 --- src/mkmaze.c Wed Dec 8 19:49:44 1999 *************** *** 919,924 **** --- 919,926 ---- if (!wportal) set_wportal(); vision_recalc(2); + /* keep attached ball&chain separate from bubble objects */ + if (Punished) unplacebc(); /* * Pick up everything inside of a bubble then fill all bubble *************** *** 1021,1026 **** --- 1023,1030 ---- FALSE); } + /* put attached ball&chain back */ + if (Punished) placebc(); vision_full_recalc = 1; } *************** *** 1321,1327 **** if (MON_AT(cons->x, cons->y)) { mnexto(m_at(cons->x,cons->y)); } - if (Punished) placebc(); /* do this for now */ break; } --- 1325,1330 ---- *** ../NetHack322/src/music.c Tue Mar 12 10:03:48 1996 --- src/music.c Wed Dec 8 19:49:44 1999 *************** *** 244,249 **** --- 244,251 ---- goto do_pit; #endif case ALTAR : + if (Is_astralevel(&u.uz) || Is_sanctum(&u.uz)) break; + if (cansee(x,y)) pline_The("altar falls into a chasm."); goto do_pit; *** ../NetHack322/src/pager.c Tue May 14 15:01:10 1996 --- src/pager.c Wed Dec 8 19:49:44 1999 *************** *** 507,513 **** /* Finally, print out our explanation. */ if (found) { ! pline(out_str); /* check the data file for information about this thing */ if (found == 1 && !quick && flags.help) { char temp_buf[BUFSZ]; --- 507,513 ---- /* Finally, print out our explanation. */ if (found) { ! pline("%s", out_str); /* check the data file for information about this thing */ if (found == 1 && !quick && flags.help) { char temp_buf[BUFSZ]; *** ../NetHack322/src/pray.c Tue Aug 13 12:30:56 1996 --- src/pray.c Wed Dec 8 19:49:44 1999 *************** *** 248,254 **** break; case TROUBLE_STUCK_IN_WALL: Your("surroundings change."); ! tele(); break; case TROUBLE_CURSED_LEVITATION: if (uarmf && uarmf->otyp==LEVITATION_BOOTS --- 248,255 ---- break; case TROUBLE_STUCK_IN_WALL: Your("surroundings change."); ! /* no control, but works on no-teleport levels */ ! (void) safe_teleds(); break; case TROUBLE_CURSED_LEVITATION: if (uarmf && uarmf->otyp==LEVITATION_BOOTS *** ../NetHack322/src/sp_lev.c Mon Nov 25 17:43:02 1996 --- src/sp_lev.c Wed Dec 8 19:49:44 1999 *************** *** 739,744 **** --- 739,745 ---- schar x, y; char class; aligntyp amask; + coord cc; struct permonst *pm; if (rn2(100) < m->chance) { *************** *** 785,791 **** else get_location(&x, &y, DRY|WET); } ! if(m->align != -12) mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful); --- 786,794 ---- else get_location(&x, &y, DRY|WET); } ! /* try to find a close place if someone else is already there */ ! if (MON_AT(x,y) && enexto(&cc, x, y, pm)) ! x = cc.x, y = cc.y; if(m->align != -12) mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful); *************** *** 1058,1063 **** --- 1061,1067 ---- schar sproom,x,y; aligntyp amask; boolean croom_is_temple = TRUE; + int oldtyp; x = a->x; y = a->y; *************** *** 1073,1078 **** --- 1077,1087 ---- croom_is_temple = FALSE; } + /* check for existing features */ + oldtyp = levl[x][y].typ; + if (oldtyp == STAIRS || oldtyp == LADDER) + return; + a->x = x; a->y = y; *************** *** 1092,1097 **** --- 1101,1111 ---- if (a->shrine == -11) a->shrine = rn2(1); /* handle random case */ + if (oldtyp == FOUNTAIN) + level.flags.nfountains--; + else if (oldtyp == SINK) + level.flags.nsinks--; + if (!croom_is_temple || !a->shrine) return; if (a->shrine) { /* Is it a shrine or sanctum? */ *************** *** 1150,1155 **** --- 1164,1176 ---- } else { get_location(&x, &y, DRY); } + /* Don't cover up an existing feature (particularly randomly + placed stairs). However, if the _same_ feature is already + here, it came from the map drawing and we still need to + update the special counters. */ + if (IS_FURNITURE(levl[x][y].typ) && levl[x][y].typ != typ) + return; + levl[x][y].typ = typ; if (typ == FOUNTAIN) level.flags.nfountains++; *** ../NetHack322/src/trap.c Mon Oct 21 21:41:38 1996 --- src/trap.c Wed Dec 8 19:49:44 1999 *************** *** 1793,1798 **** --- 1793,1801 ---- { int invc = inv_cnt(); + /* [TODO: drop u.ugold separately or insert it into inventory chain] */ + if (invc == 0) return FALSE; /* nothing to drop */ + while (near_capacity() > (Punished ? UNENCUMBERED : SLT_ENCUMBER)) { register struct obj *obj, *otmp = (struct obj *)0; register int i = rn2(invc); *** ../NetHack322/src/version.c Mon Jun 24 12:35:24 1996 --- src/version.c Wed Dec 8 19:49:44 1999 *************** *** 1,4 **** ! /* SCCS Id: @(#)version.c 3.2 96/06/22 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ --- 1,4 ---- ! /* SCCS Id: @(#)version.c 3.2 99/05/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ *************** *** 82,97 **** int fd; const char *name; { ! struct version_info vers_info; ! boolean verbose = name ? TRUE : FALSE; ! ! (void) read(fd, (genericptr_t) &vers_info, sizeof vers_info); ! minit(); /* ZEROCOMP */ ! if (!check_version(&vers_info, name, verbose)) { ! if (verbose) wait_synch(); ! return FALSE; } ! return TRUE; } void --- 82,105 ---- int fd; const char *name; { ! int rlen; ! struct version_info vers_info; ! boolean verbose = name ? TRUE : FALSE; ! ! rlen = read(fd, (genericptr_t) &vers_info, sizeof vers_info); ! minit(); /* ZEROCOMP */ ! if (rlen == 0) { ! if (verbose) { ! pline("File \"%s\" is empty?", name); ! wait_synch(); } ! return FALSE; ! } ! if (!check_version(&vers_info, name, verbose)) { ! if (verbose) wait_synch(); ! return FALSE; ! } ! return TRUE; } void *** ../NetHack322/src/hacklib.c Mon May 6 16:06:24 1996 --- src/hacklib.c Sun Nov 28 11:55:32 1999 *************** *** 35,40 **** --- 35,41 ---- void setrandom (void) int getyear (void) char * yymmdd (time_t) + long yyyymmdd (time_t) int phase_of_the_moon (void) boolean friday_13th (void) int night (void) *************** *** 395,401 **** * * The time is used for: * - seed for rand() ! * - year on tombstone and yymmdd in record file * - phase of the moon (various monsters react to NEW_MOON or FULL_MOON) * - night and midnight (the undead are dangerous at midnight) * - determination of what files are "very old" --- 396,402 ---- * * The time is used for: * - seed for rand() ! * - year on tombstone and yyyymmdd in record file * - phase of the moon (various monsters react to NEW_MOON or FULL_MOON) * - night and midnight (the undead are dangerous at midnight) * - determination of what files are "very old" *************** *** 457,467 **** return(1900 + getlt()->tm_year); } char * yymmdd(date) time_t date; { ! Static char datestr[7]; struct tm *lt; if (date == 0) --- 458,469 ---- return(1900 + getlt()->tm_year); } + /* This routine is no longer used since in 2000 it will yield "100mmdd". */ char * yymmdd(date) time_t date; { ! Static char datestr[10]; struct tm *lt; if (date == 0) *************** *** 476,481 **** --- 478,512 ---- Sprintf(datestr, "%02d%02d%02d", lt->tm_year, lt->tm_mon + 1, lt->tm_mday); return(datestr); + } + + long + yyyymmdd(date) + time_t date; + { + long datenum; + struct tm *lt; + + if (date == 0) + lt = getlt(); + else + #if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || defined(BSD) + lt = localtime((long *)(&date)); + #else + lt = localtime(&date); + #endif + + /* just in case somebody's localtime supplies (year % 100) + rather than the expected (year - 1900) */ + if (lt->tm_year < 70) + datenum = (long)lt->tm_year + 2000L; + else + datenum = (long)lt->tm_year + 1900L; + /* yyyy --> yyyymm */ + datenum = datenum * 100L + (long)(lt->tm_mon + 1); + /* yyyymm --> yyyymmdd */ + datenum = datenum * 100L + (long)lt->tm_mday; + return datenum; } /* *** ../NetHack322/src/topten.c Mon Nov 25 17:41:40 1996 --- src/topten.c Sun Nov 28 11:55:32 1999 *************** *** 48,54 **** int deathdnum, deathlev; int maxlvl, hp, maxhp, deaths; int ver_major, ver_minor, patchlevel; ! char deathdate[8], birthdate[8]; /* see readentry about size */ int uid; char plchar; char sex; --- 48,54 ---- int deathdnum, deathlev; int maxlvl, hp, maxhp, deaths; int ver_major, ver_minor, patchlevel; ! long deathdate, birthdate; int uid; char plchar; char sex; *************** *** 126,160 **** struct toptenentry *tt; { #ifdef NO_SCAN_BRACK ! static char *fmt = "%d %d %d %ld %d %d %d %d %d %d %6s %6s %d%*c%c%c %s %s%*c"; #else ! static char *fmt = "%d.%d.%d %ld %d %d %d %d %d %d %6s %6s %d %c%c %[^,],%[^\n]%*c"; #endif - #ifdef __BEOS__ - /* - Test for a bug in Be's *scanf functions. This exists in at least - versions DR8.2 and earlier. We should eventually be able to - remove this special code.. - - The bug is that a read of a sized string field, e.g. %6s, leaves - the last character of the string to be read again. The work-round - is to increase the read size by 1. This means that deathdate and - birthdate need a size of 8 (7 chars + 1 NULL) instead of a size - 7 (6 chars + 1 NULL). - */ - static boolean tested_scanf_bug = FALSE; - - if (!tested_scanf_bug) { - char s1[16], s2[16]; - - tested_scanf_bug = TRUE; - (void) sscanf("123456 789012", "%6s %6s", s1, s2); - if (strcmp(s2, "789012") != 0) - fmt = "%d.%d.%d %ld %d %d %d %d %d %d %7s %7s %d %c%c %[^,],%[^\n]%*c"; - } - #endif /* __BEOS__ */ - #ifdef UPDATE_RECORD_IN_PLACE /* note: fscanf() below must read the record's terminating newline */ final_fpos = tt->fpos = ftell(rfile); --- 126,136 ---- struct toptenentry *tt; { #ifdef NO_SCAN_BRACK ! static char *fmt = "%d %d %d %ld %d %d %d %d %d %d %ld %ld %d%*c%c%c %s %s%*c"; #else ! static char *fmt = "%d.%d.%d %ld %d %d %d %d %d %d %ld %ld %d %c%c %[^,],%[^\n]%*c"; #endif #ifdef UPDATE_RECORD_IN_PLACE /* note: fscanf() below must read the record's terminating newline */ final_fpos = tt->fpos = ftell(rfile); *************** *** 164,170 **** &tt->ver_major, &tt->ver_minor, &tt->patchlevel, &tt->points, &tt->deathdnum, &tt->deathlev, &tt->maxlvl, &tt->hp, &tt->maxhp, &tt->deaths, ! tt->deathdate, tt->birthdate, &tt->uid, &tt->plchar, &tt->sex, tt->name, tt->death) != TTFIELDS) #undef TTFIELDS --- 140,146 ---- &tt->ver_major, &tt->ver_minor, &tt->patchlevel, &tt->points, &tt->deathdnum, &tt->deathlev, &tt->maxlvl, &tt->hp, &tt->maxhp, &tt->deaths, ! &tt->deathdate, &tt->birthdate, &tt->uid, &tt->plchar, &tt->sex, tt->name, tt->death) != TTFIELDS) #undef TTFIELDS *************** *** 177,182 **** --- 153,164 ---- } #endif } + + /* check old score entries for Y2K problem and fix whenever found */ + if (tt->points > 0) { + if (tt->birthdate < 19000000L) tt->birthdate += 19000000L; + if (tt->deathdate < 19000000L) tt->deathdate += 19000000L; + } } static void *************** *** 187,195 **** #ifdef NO_SCAN_BRACK nsb_mung_line(tt->name); nsb_mung_line(tt->death); ! (void) fprintf(rfile,"%d %d %d %ld %d %d %d %d %d %d %6s %6s %d %c%c %s %s\n", #else ! (void) fprintf(rfile,"%d.%d.%d %ld %d %d %d %d %d %d %6s %6s %d %c%c %s,%s\n", #endif tt->ver_major, tt->ver_minor, tt->patchlevel, tt->points, tt->deathdnum, tt->deathlev, --- 169,177 ---- #ifdef NO_SCAN_BRACK nsb_mung_line(tt->name); nsb_mung_line(tt->death); ! (void) fprintf(rfile,"%d %d %d %ld %d %d %d %d %d %d %ld %ld %d %c%c %s %s\n", #else ! (void) fprintf(rfile,"%d.%d.%d %ld %d %d %d %d %d %d %ld %ld %d %c%c %s,%s\n", #endif tt->ver_major, tt->ver_minor, tt->patchlevel, tt->points, tt->deathdnum, tt->deathlev, *************** *** 295,302 **** (void) strncat(t0->death, killer, DTHSZ); break; } ! Strcpy(t0->birthdate, yymmdd(u.ubirthday)); ! Strcpy(t0->deathdate, yymmdd(0L)); t0->tt_next = 0; #ifdef UPDATE_RECORD_IN_PLACE t0->fpos = -1L; --- 277,284 ---- (void) strncat(t0->death, killer, DTHSZ); break; } ! t0->birthdate = yyyymmdd(u.ubirthday); ! t0->deathdate = yyyymmdd((time_t)0L); t0->tt_next = 0; #ifdef UPDATE_RECORD_IN_PLACE t0->fpos = -1L; *************** *** 476,482 **** t1->uid = t1->deathdnum = t1->deathlev = 0; t1->maxlvl = t1->hp = t1->maxhp = t1->deaths = 0; t1->plchar = t1->sex = '-'; ! Strcpy(t1->birthdate, strcpy(t1->deathdate, yymmdd(0L))); Strcpy(t1->name, "@"); Strcpy(t1->death, "\n"); writeentry(rfile, t1); --- 458,464 ---- t1->uid = t1->deathdnum = t1->deathlev = 0; t1->maxlvl = t1->hp = t1->maxhp = t1->deaths = 0; t1->plchar = t1->sex = '-'; ! t1->birthdate = t1->deathdate = yyyymmdd((time_t)0L); Strcpy(t1->name, "@"); Strcpy(t1->death, "\n"); writeentry(rfile, t1); *** ../NetHack322/sys/mac/macwin.c Mon Jun 17 17:34:30 1996 --- sys/mac/macwin.c Sun Nov 28 11:55:32 1999 *************** *** 2389,2394 **** --- 2389,2398 ---- { EventRecord anEvent ; + /* KMH -- Don't proceed if the window system isn't set up */ + if (!iflags.window_inited) + return; + if ( ( inSelect == WIN_ERR && iflags . window_inited && ! in_topl_mode ( ) ) == mBarDimmed ) if ( mBarDimmed ) { *** ../NetHack322/sys/msdos/Makefile.GCC Sat Oct 26 13:53:18 1996 --- sys/msdos/Makefile.GCC Sun Nov 28 12:25:52 1999 *************** *** 754,760 **** alloc.o: $(CONFIG_H) alloc.c $(CC) $(CFLAGS) -oalloc.o alloc.c ! drawing.o: $(CONFIG_H) drawing.c pcvideo.h $(CC) $(CFLAGS) -odrawing.o drawing.c decl.o: $(CONFIG_H) decl.c --- 754,760 ---- alloc.o: $(CONFIG_H) alloc.c $(CC) $(CFLAGS) -oalloc.o alloc.c ! drawing.o: $(CONFIG_H) drawing.c $(INCL)\pcvideo.h $(CC) $(CFLAGS) -odrawing.o drawing.c decl.o: $(CONFIG_H) decl.c *** ../NetHack322/README Mon Nov 25 17:42:18 1996 --- README Wed Dec 8 21:35:14 1999 *************** *** 170,176 **** If you have problems building the game, or you find bugs in it, the development team may be reached as ! nethack-bugs@linc.cis.upenn.edu Please be sure to include your machine type, OS, and patchlevel. --- 170,176 ---- If you have problems building the game, or you find bugs in it, the development team may be reached as ! nethack-bugs@nethack.org Please be sure to include your machine type, OS, and patchlevel.