From c5d6ac55616384217be9c2c59b044b4842d8aa15 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 25 May 2019 00:42:29 -0400 Subject: [PATCH 1/8] whitespace bit --- src/hack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hack.c b/src/hack.c index a4385673a..6f2489197 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1782,7 +1782,7 @@ domove_core() if (u.usteed) u.usteed->mx = u.ux, u.usteed->my = u.uy; You("stop. %s can't move diagonally.", upstart(y_monnam(mtmp))); - } else if (u_with_boulder + } else if (u_with_boulder && !(verysmall(mtmp->data) && (!mtmp->minvent || (curr_mon_load(mtmp) <= 600)))) { /* can't swap places when pet won't fit there with the boulder */ @@ -1791,7 +1791,7 @@ domove_core() u.usteed->mx = u.ux, u.usteed->my = u.uy; You("stop. %s won't fit into the same spot that you're at.", upstart(y_monnam(mtmp))); - } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0) + } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0) && bad_rock(mtmp->data, u.ux0, y) && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) { /* can't swap places when pet won't fit thru the opening */ From 6bd2f4979cb9397b3207d87a4a7d69d8578b1241 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 25 May 2019 07:37:08 -0700 Subject: [PATCH 2/8] curses memory leak Back in February, my e991dd1b0c4192495c7e9092c10fa83bb6d81a24 added ESC (when there's no input) as an early return for curses' getline, but it neglected to clean up some allocated memory. --- doc/fixes36.3 | 3 ++- win/curses/cursmesg.c | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 28564e3da..5ad8f325d 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.15 $ $NHDT-Date: 1558686805 2019/05/24 08:33:25 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.18 $ $NHDT-Date: 1558794988 2019/05/25 14:36:28 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -47,6 +47,7 @@ curses: when display windows get reconfigured (after setting align_status, messages rather than most recent N. [Still room for improvement; when feasible it combines short lines, resulting in N messages on fewer than N lines and leaving some of the available lines blank.] +curses: plug memory leak when getting a line of input is cancelled by ESC tty: re-do one optimization used when status conditions have all been removed and remove another that tried to check whether condition text to be displayed next was the same as the existing value; sometimes new diff --git a/win/curses/cursmesg.c b/win/curses/cursmesg.c index 0d67cff1c..13c3109ba 100644 --- a/win/curses/cursmesg.c +++ b/win/curses/cursmesg.c @@ -86,7 +86,7 @@ curses_message_win_puts(const char *message, boolean recursed) scroll_window(MESSAGE_WIN); mx = width; my--; - strcpy(toplines, message); + Strcpy(toplines, message); } return; } @@ -466,10 +466,10 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) char *tmpstr; /* for free() */ int maxy, maxx; /* linewrap / scroll */ int ch; - WINDOW *win = curses_get_nhwin(MESSAGE_WIN); int border_space = 0; int len; /* of answer string */ boolean border = curses_window_has_border(MESSAGE_WIN); + WINDOW *win = curses_get_nhwin(MESSAGE_WIN); orig_cursor = curs_set(0); @@ -485,6 +485,7 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) maxy = height - 1 + border_space; maxx = width - 1 + border_space; + /* +2? buffer already includes room for terminator; +1: "prompt answer" */ tmpbuf = (char *) alloc((unsigned) ((int) strlen(prompt) + buffer + 2)); maxlines = buffer / width * 2; Strcpy(tmpbuf, prompt); @@ -585,7 +586,7 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) /* if there isn't any input yet, return ESC */ if (len == 0) { Strcpy(answer, "\033"); - return; + goto alldone; } /* otherwise, discard current input and start over; first need to blank it from the screen */ @@ -609,27 +610,19 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) break; case ERR: /* should not happen */ *answer = '\0'; - free(tmpbuf); - free(linestarts); - curs_set(orig_cursor); - curses_toggle_color_attr(win, NONE, A_BOLD, OFF); - return; + goto alldone; case '\r': case '\n': - free(linestarts); (void) strncpy(answer, p_answer, buffer); answer[buffer - 1] = '\0'; Strcpy(toplines, tmpbuf); mesg_add_line(tmpbuf); - free(tmpbuf); - curs_set(orig_cursor); - curses_toggle_color_attr(win, NONE, A_BOLD, OFF); if (++my > maxy) { scroll_window(MESSAGE_WIN); my--; } mx = border_space; - return; + goto alldone; case '\177': /* DEL/Rubout */ case KEY_DC: /* delete-character */ case '\b': /* ^H (Backspace: '\011') */ @@ -666,6 +659,13 @@ curses_message_win_getline(const char *prompt, char *answer, int buffer) p_answer[len] = '\0'; } } + + alldone: + free(linestarts); + free(tmpbuf); + curses_toggle_color_attr(win, NONE, A_BOLD, OFF); + curs_set(orig_cursor); + return; } /* Scroll lines upward in given window, or clear window if only one line. */ From 8a5ffa4085c104a651cb532abf65ad8dbcfe74b1 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 25 May 2019 11:58:32 -0400 Subject: [PATCH 3/8] do not mark multiple luckstones as the prize in mines-end if one of the random objects happened to be a luckstone then it and the explicit one got marked as a prize. Following this change, only one will be marked as the prize, but a follow-up on the order of things in mines.des may be warranted to ensure it is the explicitly placed luckstone. --- doc/fixes36.3 | 2 ++ src/sp_lev.c | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 28564e3da..ebbf1c95b 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -21,6 +21,8 @@ xans fly, but could not reach your feet if you flew adjust vortex database entry to be consistent with fire and energy vortices when co-located with a boulder you could sometimes swap places with pets of any size +on rare occasions, multiple mines-end luckstones were being marked as the + prize and triggering an impossible() on a public server Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/sp_lev.c b/src/sp_lev.c index cd952108c..dbab1dfdc 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -2044,11 +2044,13 @@ struct mkroom *croom; might be short-circuited if a monster brings object to hero) */ if (Is_mineend_level(&u.uz)) { if (otmp->otyp == iflags.mines_prize_type) { - otmp->record_achieve_special = MINES_PRIZE; - /* prevent stacking; cleared when achievement is recorded */ - otmp->nomerge = 1; - if (++mines_prize_count > 1) - impossible(prize_warning, "mines end"); + if (!mines_prize_count++) { + /* Note: the first luckstone on lev will become the prize + even if its not the explicit one, but random */ + otmp->record_achieve_special = MINES_PRIZE; + /* prevent stacking; cleared when achievement is recorded */ + otmp->nomerge = 1; + } } } else if (Is_sokoend_level(&u.uz)) { if (otmp->otyp == iflags.soko_prize_type1) { From 2562144503dfbcc53fd00c785cf2d8f2aa08ae93 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Sat, 25 May 2019 19:15:53 +0300 Subject: [PATCH 4/8] Make sure the correct luckstone is the prize The first generated luckstone is marked as the prize in mines' end. Make sure we generate the intended one first, before any other (possibly randomly generated) luckstones. --- dat/mines.des | 34 +++++++++++++++++----------------- doc/fixes36.3 | 1 + 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/dat/mines.des b/dat/mines.des index 19a829bda..1ef2031f5 100644 --- a/dat/mines.des +++ b/dat/mines.des @@ -1042,6 +1042,7 @@ OBJECT:('!',"booze"),(10,09) OBJECT:('!',"object detection"),(10,09) # Objects # The Treasure chamber... +OBJECT:('*',"luckstone"),(70,05) OBJECT:('*',"diamond"),(69,04) OBJECT:'*',(69,04) OBJECT:('*',"diamond"),(69,04) @@ -1058,7 +1059,6 @@ OBJECT:('*',"ruby"),(70,05) OBJECT:('*',"amethyst"),(70,05) OBJECT:'*',(70,05) OBJECT:('*',"amethyst"),(70,05) -OBJECT:('*',"luckstone"),(70,05) # Scattered gems... OBJECT:'*',random OBJECT:'*',random @@ -1147,24 +1147,24 @@ STAIR:(42,8),up WALLIFY # Objects -OBJECT:('*',"diamond"),random -OBJECT:'*',random -OBJECT:('*',"diamond"),random -OBJECT:'*',random -OBJECT:('*',"emerald"),random -OBJECT:'*',random -OBJECT:('*',"emerald"),random -OBJECT:'*',random -OBJECT:('*',"emerald"),random -OBJECT:'*',random -OBJECT:('*',"ruby"),random -OBJECT:'*',random -OBJECT:('*',"ruby"),random -OBJECT:('*',"amethyst"),random -OBJECT:'*',random -OBJECT:('*',"amethyst"),random OBJECT:('*',"luckstone"),$place[0] OBJECT:('*',"flint"),$place[1] +OBJECT:('*',"diamond"),random +OBJECT:'*',random +OBJECT:('*',"diamond"),random +OBJECT:'*',random +OBJECT:('*',"emerald"),random +OBJECT:'*',random +OBJECT:('*',"emerald"),random +OBJECT:'*',random +OBJECT:('*',"emerald"),random +OBJECT:'*',random +OBJECT:('*',"ruby"),random +OBJECT:'*',random +OBJECT:('*',"ruby"),random +OBJECT:('*',"amethyst"),random +OBJECT:'*',random +OBJECT:('*',"amethyst"),random OBJECT:'?',random OBJECT:'?',random OBJECT:'?',random diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 42fe406b0..edb1062eb 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -23,6 +23,7 @@ when co-located with a boulder you could sometimes swap places with pets of any size on rare occasions, multiple mines-end luckstones were being marked as the prize and triggering an impossible() on a public server +make sure the correct luckstone is the prize in mine's end Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository From f5bc41cc53175242631b8eac3a9b3742e79f2483 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 25 May 2019 12:25:05 -0400 Subject: [PATCH 5/8] refer to the same level the same way in fixes file --- doc/fixes36.3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index edb1062eb..41c2e8b89 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -21,7 +21,7 @@ xans fly, but could not reach your feet if you flew adjust vortex database entry to be consistent with fire and energy vortices when co-located with a boulder you could sometimes swap places with pets of any size -on rare occasions, multiple mines-end luckstones were being marked as the +on rare occasions, multiple mine's end luckstones were being marked as the prize and triggering an impossible() on a public server make sure the correct luckstone is the prize in mine's end From 5cc730196570f75736e33ec1c6594889bf8b375f Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 25 May 2019 23:43:42 -0700 Subject: [PATCH 6/8] free overview->final_resting_place The #overview command can provide some feedback about levels loaded from bones files; that data wasn't being released at end of game. (There are two copies of that data, one set always in memory with the overview data [final_resting_place field in the 'mapseen' data], and another set with portions attached to each relevant level [via level.bonesinfo]. Neither set was being properly freed; this only addresses one of them, so far. The per-level data can probably be eliminated--for post-3.6--since DUNGEON_OVERVIEW isn't a conditional feature as it was when that was implemented.) --- doc/fixes36.3 | 3 ++- src/dungeon.c | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 41c2e8b89..41ef3f97e 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.18 $ $NHDT-Date: 1558794988 2019/05/25 14:36:28 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.22 $ $NHDT-Date: 1558853011 2019/05/26 06:43:31 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -24,6 +24,7 @@ when co-located with a boulder you could sometimes swap places with pets of on rare occasions, multiple mine's end luckstones were being marked as the prize and triggering an impossible() on a public server make sure the correct luckstone is the prize in mine's end +free dungeon overview's bones information at end of game Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/dungeon.c b/src/dungeon.c index 08722645b..d473e1c2e 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dungeon.c $NHDT-Date: 1554341477 2019/04/04 01:31:17 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.92 $ */ +/* NetHack 3.6 dungeon.c $NHDT-Date: 1558853012 2019/05/26 06:43:32 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.94 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -181,6 +181,8 @@ boolean perform_write, free_data; next_ms = curr_ms->next; if (curr_ms->custom) free((genericptr_t) curr_ms->custom); + if (curr_ms->final_resting_place) + savecemetery(fd, FREE_SAVE, &curr_ms->final_resting_place); free((genericptr_t) curr_ms); } mapseenchn = 0; @@ -2155,7 +2157,8 @@ int ledger_num; struct cemetery *bp, *bpnext; for (mptr = mapseenchn; mptr; mprev = mptr, mptr = mptr->next) - if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel == ledger_num) + if (dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel + == ledger_num) break; if (!mptr) @@ -2652,8 +2655,7 @@ recalc_mapseen() } /*ARGUSED*/ -/* valley and sanctum levels get automatic annotation once temple is entered - */ +/* valley and sanctum levels get automatic annotation once temple is entered */ void mapseen_temple(priest) struct monst *priest UNUSED; /* currently unused; might be useful someday */ From ba6edbe5dcfbd27c03683e4d7aebf9593b24c5a7 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 26 May 2019 00:11:53 -0700 Subject: [PATCH 7/8] save.c cleanup Mostly 'sizeof' usage. This has been sitting around for a while and I wanted to get it out of the way before making some other save.c changes. --- src/save.c | 166 +++++++++++++++++++++-------------------------------- 1 file changed, 64 insertions(+), 102 deletions(-) diff --git a/src/save.c b/src/save.c index c3ce6d06f..b955bde9b 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 save.c $NHDT-Date: 1554591225 2019/04/06 22:53:45 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.117 $ */ +/* NetHack 3.6 save.c $NHDT-Date: 1558854699 2019/05/26 07:11:39 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.118 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -287,15 +287,15 @@ register int fd, mode; #endif uid = (unsigned long) getuid(); bwrite(fd, (genericptr_t) &uid, sizeof uid); - bwrite(fd, (genericptr_t) &context, sizeof(struct context_info)); - bwrite(fd, (genericptr_t) &flags, sizeof(struct flag)); + bwrite(fd, (genericptr_t) &context, sizeof context); + bwrite(fd, (genericptr_t) &flags, sizeof flags); #ifdef SYSFLAGS - bwrite(fd, (genericptr_t) &sysflags, sizeof(struct sysflag)); + bwrite(fd, (genericptr_t) &sysflags, sysflags); #endif urealtime.finish_time = getnow(); urealtime.realtime += (long) (urealtime.finish_time - urealtime.start_timing); - bwrite(fd, (genericptr_t) &u, sizeof(struct you)); + bwrite(fd, (genericptr_t) &u, sizeof u); bwrite(fd, yyyymmddhhmmss(ubirthday), 14); bwrite(fd, (genericptr_t) &urealtime.realtime, sizeof urealtime.realtime); bwrite(fd, yyyymmddhhmmss(urealtime.start_timing), 14); /** Why? **/ @@ -324,14 +324,14 @@ register int fd, mode; migrating_objs = 0; migrating_mons = 0; } - bwrite(fd, (genericptr_t) mvitals, sizeof(mvitals)); + bwrite(fd, (genericptr_t) mvitals, sizeof mvitals); save_dungeon(fd, (boolean) !!perform_bwrite(mode), (boolean) !!release_data(mode)); savelevchn(fd, mode); bwrite(fd, (genericptr_t) &moves, sizeof moves); bwrite(fd, (genericptr_t) &monstermoves, sizeof monstermoves); - bwrite(fd, (genericptr_t) &quest_status, sizeof(struct q_score)); + bwrite(fd, (genericptr_t) &quest_status, sizeof quest_status); bwrite(fd, (genericptr_t) spl_book, sizeof(struct spell) * (MAXSPELL + 1)); save_artifacts(fd); @@ -394,7 +394,7 @@ savestateinlock() if (tricked_fileremoved(fd, whynot)) return; - (void) read(fd, (genericptr_t) &hpid, sizeof(hpid)); + (void) read(fd, (genericptr_t) &hpid, sizeof hpid); if (hackpid != hpid) { Sprintf(whynot, "Level #0 pid (%d) doesn't match ours (%d)!", hpid, hackpid); @@ -411,11 +411,11 @@ savestateinlock() done(TRICKED); return; } - (void) write(fd, (genericptr_t) &hackpid, sizeof(hackpid)); + (void) write(fd, (genericptr_t) &hackpid, sizeof hackpid); if (flags.ins_chkpt) { int currlev = ledger_no(&u.uz); - (void) write(fd, (genericptr_t) &currlev, sizeof(currlev)); + (void) write(fd, (genericptr_t) &currlev, sizeof currlev); save_savefile_name(fd); store_version(fd); store_savefileinfo(fd); @@ -496,32 +496,31 @@ int mode; #endif if (lev >= 0 && lev <= maxledgerno()) level_info[lev].flags |= VISITED; - bwrite(fd, (genericptr_t) &hackpid, sizeof(hackpid)); + bwrite(fd, (genericptr_t) &hackpid, sizeof hackpid); #ifdef TOS tlev = lev; tlev &= 0x00ff; - bwrite(fd, (genericptr_t) &tlev, sizeof(tlev)); + bwrite(fd, (genericptr_t) &tlev, sizeof tlev); #else - bwrite(fd, (genericptr_t) &lev, sizeof(lev)); + bwrite(fd, (genericptr_t) &lev, sizeof lev); #endif savecemetery(fd, mode, &level.bonesinfo); - savelevl(fd, - (boolean) ((sfsaveinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP)); - bwrite(fd, (genericptr_t) lastseentyp, sizeof(lastseentyp)); - bwrite(fd, (genericptr_t) &monstermoves, sizeof(monstermoves)); - bwrite(fd, (genericptr_t) &upstair, sizeof(stairway)); - bwrite(fd, (genericptr_t) &dnstair, sizeof(stairway)); - bwrite(fd, (genericptr_t) &upladder, sizeof(stairway)); - bwrite(fd, (genericptr_t) &dnladder, sizeof(stairway)); - bwrite(fd, (genericptr_t) &sstairs, sizeof(stairway)); - bwrite(fd, (genericptr_t) &updest, sizeof(dest_area)); - bwrite(fd, (genericptr_t) &dndest, sizeof(dest_area)); - bwrite(fd, (genericptr_t) &level.flags, sizeof(level.flags)); - bwrite(fd, (genericptr_t) doors, sizeof(doors)); + savelevl(fd, (boolean) ((sfsaveinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP)); + bwrite(fd, (genericptr_t) lastseentyp, sizeof lastseentyp); + bwrite(fd, (genericptr_t) &monstermoves, sizeof monstermoves); + bwrite(fd, (genericptr_t) &upstair, sizeof (stairway)); + bwrite(fd, (genericptr_t) &dnstair, sizeof (stairway)); + bwrite(fd, (genericptr_t) &upladder, sizeof (stairway)); + bwrite(fd, (genericptr_t) &dnladder, sizeof (stairway)); + bwrite(fd, (genericptr_t) &sstairs, sizeof (stairway)); + bwrite(fd, (genericptr_t) &updest, sizeof (dest_area)); + bwrite(fd, (genericptr_t) &dndest, sizeof (dest_area)); + bwrite(fd, (genericptr_t) &level.flags, sizeof level.flags); + bwrite(fd, (genericptr_t) doors, sizeof doors); save_rooms(fd); /* no dynamic memory to reclaim */ -/* from here on out, saving also involves allocated memory cleanup */ -skip_lots: + /* from here on out, saving also involves allocated memory cleanup */ + skip_lots: /* this comes before the map, so need cleanup here if we skipped */ if (mode == FREE_SAVE) savecemetery(fd, mode, &level.bonesinfo); @@ -587,21 +586,20 @@ boolean rlecomp; goto writeout; } } else { - /* the run has been broken, - * write out run-length encoding */ - writeout: - bwrite(fd, (genericptr_t) &match, sizeof(uchar)); - bwrite(fd, (genericptr_t) rgrm, sizeof(struct rm)); + /* run has been broken, write out run-length encoding */ + writeout: + bwrite(fd, (genericptr_t) &match, sizeof (uchar)); + bwrite(fd, (genericptr_t) rgrm, sizeof (struct rm)); /* start encoding again. we have at least 1 rm - * in the next run, viz. this one. */ + in the next run, viz. this one. */ match = 1; rgrm = prm; } } } if (match > 0) { - bwrite(fd, (genericptr_t) &match, sizeof(uchar)); - bwrite(fd, (genericptr_t) rgrm, sizeof(struct rm)); + bwrite(fd, (genericptr_t) &match, sizeof (uchar)); + bwrite(fd, (genericptr_t) rgrm, sizeof (struct rm)); } return; } @@ -905,12 +903,12 @@ register int fd, mode; for (tmplev = sp_levchn; tmplev; tmplev = tmplev->next) cnt++; if (perform_bwrite(mode)) - bwrite(fd, (genericptr_t) &cnt, sizeof(int)); + bwrite(fd, (genericptr_t) &cnt, sizeof cnt); for (tmplev = sp_levchn; tmplev; tmplev = tmplev2) { tmplev2 = tmplev->next; if (perform_bwrite(mode)) - bwrite(fd, (genericptr_t) tmplev, sizeof(s_level)); + bwrite(fd, (genericptr_t) tmplev, sizeof *tmplev); if (release_data(mode)) free((genericptr_t) tmplev); } @@ -954,11 +952,11 @@ register int fd, mode; for (tmp_dam = damageptr; tmp_dam; tmp_dam = tmp_dam->next) xl++; if (perform_bwrite(mode)) - bwrite(fd, (genericptr_t) &xl, sizeof(xl)); + bwrite(fd, (genericptr_t) &xl, sizeof xl); while (xl--) { if (perform_bwrite(mode)) - bwrite(fd, (genericptr_t) damageptr, sizeof(*damageptr)); + bwrite(fd, (genericptr_t) damageptr, sizeof *damageptr); tmp_dam = damageptr; damageptr = damageptr->next; if (release_data(mode)) @@ -975,14 +973,11 @@ struct obj *otmp; { int buflen, zerobuf = 0; - buflen = sizeof(struct obj); - bwrite(fd, (genericptr_t) &buflen, sizeof(int)); + buflen = (int) sizeof (struct obj); + bwrite(fd, (genericptr_t) &buflen, sizeof buflen); bwrite(fd, (genericptr_t) otmp, buflen); if (otmp->oextra) { - if (ONAME(otmp)) - buflen = strlen(ONAME(otmp)) + 1; - else - buflen = 0; + buflen = ONAME(otmp) ? (int) strlen(ONAME(otmp)) + 1 : 0; bwrite(fd, (genericptr_t) &buflen, sizeof buflen); if (buflen > 0) bwrite(fd, (genericptr_t) ONAME(otmp), buflen); @@ -993,26 +988,18 @@ struct obj *otmp; else bwrite(fd, (genericptr_t) &zerobuf, sizeof zerobuf); - if (OMID(otmp)) - buflen = sizeof(unsigned); - else - buflen = 0; + buflen = OMID(otmp) ? (int) sizeof (unsigned) : 0; bwrite(fd, (genericptr_t) &buflen, sizeof buflen); if (buflen > 0) bwrite(fd, (genericptr_t) OMID(otmp), buflen); - if (OLONG(otmp)) - buflen = sizeof(long); - else - buflen = 0; + /* TODO: post 3.6.x, get rid of this */ + buflen = OLONG(otmp) ? (int) sizeof (long) : 0; bwrite(fd, (genericptr_t) &buflen, sizeof buflen); if (buflen > 0) bwrite(fd, (genericptr_t) OLONG(otmp), buflen); - if (OMAILCMD(otmp)) - buflen = strlen(OMAILCMD(otmp)) + 1; - else - buflen = 0; + buflen = OMAILCMD(otmp) ? (int) strlen(OMAILCMD(otmp)) + 1 : 0; bwrite(fd, (genericptr_t) &buflen, sizeof buflen); if (buflen > 0) bwrite(fd, (genericptr_t) OMAILCMD(otmp), buflen); @@ -1063,7 +1050,7 @@ register struct obj *otmp; otmp = otmp2; } if (perform_bwrite(mode)) - bwrite(fd, (genericptr_t) &minusone, sizeof(int)); + bwrite(fd, (genericptr_t) &minusone, sizeof (int)); } STATIC_OVL void @@ -1073,58 +1060,34 @@ struct monst *mtmp; { int buflen; - buflen = sizeof(struct monst); - bwrite(fd, (genericptr_t) &buflen, sizeof(int)); + buflen = (int) sizeof (struct monst); + bwrite(fd, (genericptr_t) &buflen, sizeof buflen); bwrite(fd, (genericptr_t) mtmp, buflen); if (mtmp->mextra) { - if (MNAME(mtmp)) - buflen = strlen(MNAME(mtmp)) + 1; - else - buflen = 0; + buflen = MNAME(mtmp) ? (int) strlen(MNAME(mtmp)) + 1 : 0; bwrite(fd, (genericptr_t) &buflen, sizeof buflen); if (buflen > 0) bwrite(fd, (genericptr_t) MNAME(mtmp), buflen); - - if (EGD(mtmp)) - buflen = sizeof(struct egd); - else - buflen = 0; - bwrite(fd, (genericptr_t) &buflen, sizeof(int)); + buflen = EGD(mtmp) ? (int) sizeof (struct egd) : 0; + bwrite(fd, (genericptr_t) &buflen, sizeof buflen); if (buflen > 0) bwrite(fd, (genericptr_t) EGD(mtmp), buflen); - - if (EPRI(mtmp)) - buflen = sizeof(struct epri); - else - buflen = 0; - bwrite(fd, (genericptr_t) &buflen, sizeof(int)); + buflen = EPRI(mtmp) ? (int) sizeof (struct epri) : 0; + bwrite(fd, (genericptr_t) &buflen, sizeof buflen); if (buflen > 0) bwrite(fd, (genericptr_t) EPRI(mtmp), buflen); - - if (ESHK(mtmp)) - buflen = sizeof(struct eshk); - else - buflen = 0; + buflen = ESHK(mtmp) ? (int) sizeof (struct eshk) : 0; bwrite(fd, (genericptr_t) &buflen, sizeof(int)); if (buflen > 0) bwrite(fd, (genericptr_t) ESHK(mtmp), buflen); - - if (EMIN(mtmp)) - buflen = sizeof(struct emin); - else - buflen = 0; + buflen = EMIN(mtmp) ? (int) sizeof (struct emin) : 0; bwrite(fd, (genericptr_t) &buflen, sizeof(int)); if (buflen > 0) bwrite(fd, (genericptr_t) EMIN(mtmp), buflen); - - if (EDOG(mtmp)) - buflen = sizeof(struct edog); - else - buflen = 0; + buflen = EDOG(mtmp) ? (int) sizeof (struct edog) : 0; bwrite(fd, (genericptr_t) &buflen, sizeof(int)); if (buflen > 0) bwrite(fd, (genericptr_t) EDOG(mtmp), buflen); - /* mcorpsenm is inline int rather than pointer to something, so doesn't need to be preceded by a length field */ bwrite(fd, (genericptr_t) &MCORPSENM(mtmp), sizeof MCORPSENM(mtmp)); @@ -1160,7 +1123,7 @@ register struct monst *mtmp; mtmp = mtmp2; } if (perform_bwrite(mode)) - bwrite(fd, (genericptr_t) &minusone, sizeof(int)); + bwrite(fd, (genericptr_t) &minusone, sizeof (int)); } /* save traps; ftrap is the only trap chain so the 2nd arg is superfluous */ @@ -1176,7 +1139,7 @@ int mode; while (trap) { trap2 = trap->ntrap; if (perform_bwrite(mode)) - bwrite(fd, (genericptr_t) trap, sizeof (struct trap)); + bwrite(fd, (genericptr_t) trap, sizeof *trap); if (release_data(mode)) dealloc_trap(trap); trap = trap2; @@ -1201,7 +1164,7 @@ int fd, mode; while (f1) { f2 = f1->nextf; if (f1->fid >= 0 && perform_bwrite(mode)) - bwrite(fd, (genericptr_t) f1, sizeof (struct fruit)); + bwrite(fd, (genericptr_t) f1, sizeof *f1); if (release_data(mode)) dealloc_fruit(f1); f1 = f2; @@ -1220,7 +1183,7 @@ int fd; bufoff(fd); /* bwrite() before bufon() uses plain write() */ - bwrite(fd, (genericptr_t) &plsiztmp, sizeof(plsiztmp)); + bwrite(fd, (genericptr_t) &plsiztmp, sizeof plsiztmp); bwrite(fd, (genericptr_t) plname, plsiztmp); bufon(fd); return; @@ -1246,11 +1209,11 @@ int fd, mode; no need to modify msg[] since terminator isn't written */ if (msglen > BUFSZ - 1) msglen = BUFSZ - 1; - bwrite(fd, (genericptr_t) &msglen, sizeof(msglen)); + bwrite(fd, (genericptr_t) &msglen, sizeof msglen); bwrite(fd, (genericptr_t) msg, msglen); ++msgcount; } - bwrite(fd, (genericptr_t) &minusone, sizeof(int)); + bwrite(fd, (genericptr_t) &minusone, sizeof (int)); } debugpline1("Stored %d messages into savefile.", msgcount); /* note: we don't attempt to handle release_data() here */ @@ -1266,15 +1229,14 @@ int fd; * sfsaveinfo (decl.c) describes the savefile info that actually * gets written into the savefile, and is used to determine the * save file being written. - + * * sfrestinfo (decl.c) describes the savefile info that is * being used to read the information from an existing savefile. - * */ bufoff(fd); /* bwrite() before bufon() uses plain write() */ - bwrite(fd, (genericptr_t) &sfsaveinfo, (unsigned) (sizeof sfsaveinfo)); + bwrite(fd, (genericptr_t) &sfsaveinfo, (unsigned) sizeof sfsaveinfo); bufon(fd); return; } From d06b99d3925e7333b8a1a6c7b31333d3ff01fed2 Mon Sep 17 00:00:00 2001 From: PatR Date: Sun, 26 May 2019 00:40:40 -0700 Subject: [PATCH 8/8] free level.bonesinfo Bones information for the current level was freed during save but not at end of game. Have freedynamicdata() call savelev(,,FREE_SAVE) to throw away current level instead of trying to duplicate the actions that performs. --- doc/fixes36.3 | 3 ++- src/save.c | 36 ++++++++++++------------------------ 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 41ef3f97e..0764ce2d3 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.22 $ $NHDT-Date: 1558853011 2019/05/26 06:43:31 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.23 $ $NHDT-Date: 1558856435 2019/05/26 07:40:35 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -25,6 +25,7 @@ on rare occasions, multiple mine's end luckstones were being marked as the prize and triggering an impossible() on a public server make sure the correct luckstone is the prize in mine's end free dungeon overview's bones information at end of game +free current level's bones information at end of game Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/save.c b/src/save.c index b955bde9b..d9d3662fd 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 save.c $NHDT-Date: 1558854699 2019/05/26 07:11:39 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.118 $ */ +/* NetHack 3.6 save.c $NHDT-Date: 1558856435 2019/05/26 07:40:35 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.119 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2009. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1301,38 +1301,25 @@ freedynamicdata() msgtype_free(); tmp_at(DISP_FREEMEM, 0); /* temporary display effects */ #ifdef FREE_ALL_MEMORY +#define free_current_level() savelev(-1, -1, FREE_SAVE) #define freeobjchn(X) (saveobjchn(0, X, FREE_SAVE), X = 0) #define freemonchn(X) (savemonchn(0, X, FREE_SAVE), X = 0) -#define freetrapchn(X) (savetrapchn(0, X, FREE_SAVE), X = 0) #define freefruitchn() savefruitchn(0, FREE_SAVE) #define freenames() savenames(0, FREE_SAVE) #define free_killers() save_killers(0, FREE_SAVE) #define free_oracles() save_oracles(0, FREE_SAVE) #define free_waterlevel() save_waterlevel(0, FREE_SAVE) -#define free_worm() save_worm(0, FREE_SAVE) #define free_timers(R) save_timers(0, FREE_SAVE, R) -#define free_light_sources(R) save_light_sources(0, FREE_SAVE, R); -#define free_engravings() save_engravings(0, FREE_SAVE) -#define freedamage() savedamage(0, FREE_SAVE) +#define free_light_sources(R) save_light_sources(0, FREE_SAVE, R) #define free_animals() mon_animal_list(FALSE) /* move-specific data */ dmonsfree(); /* release dead monsters */ /* level-specific data */ - free_timers(RANGE_LEVEL); - free_light_sources(RANGE_LEVEL); - clear_regions(); - freemonchn(fmon); - free_worm(); /* release worm segment information */ - freetrapchn(ftrap); - freeobjchn(fobj); - freeobjchn(level.buriedobjlist); - freeobjchn(billobjs); - free_engravings(); - freedamage(); + free_current_level(); - /* game-state data */ + /* game-state data [ought to reorganize savegamestate() to handle this] */ free_killers(); free_timers(RANGE_GLOBAL); free_light_sources(RANGE_GLOBAL); @@ -1350,17 +1337,18 @@ freedynamicdata() /* some pointers in iflags */ if (iflags.wc_font_map) - free(iflags.wc_font_map); + free((genericptr_t) iflags.wc_font_map), iflags.wc_font_map = 0; if (iflags.wc_font_message) - free(iflags.wc_font_message); + free((genericptr_t) iflags.wc_font_message), + iflags.wc_font_message = 0; if (iflags.wc_font_text) - free(iflags.wc_font_text); + free((genericptr_t) iflags.wc_font_text), iflags.wc_font_text = 0; if (iflags.wc_font_menu) - free(iflags.wc_font_menu); + free((genericptr_t) iflags.wc_font_menu), iflags.wc_font_menu = 0; if (iflags.wc_font_status) - free(iflags.wc_font_status); + free((genericptr_t) iflags.wc_font_status), iflags.wc_font_status = 0; if (iflags.wc_tile_file) - free(iflags.wc_tile_file); + free((genericptr_t) iflags.wc_tile_file), iflags.wc_tile_file = 0; free_autopickup_exceptions(); /* miscellaneous */