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 28564e3da..0764ce2d3 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.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, @@ -21,6 +21,11 @@ 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 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 @@ -47,6 +52,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/src/dungeon.c b/src/dungeon.c index 275bd14ea..eff67af3a 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. */ @@ -176,6 +176,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); } g.mapseenchn = 0; @@ -2150,7 +2152,8 @@ int ledger_num; struct cemetery *bp, *bpnext; for (mptr = g.mapseenchn; mptr; mprev = mptr, mptr = mptr->next) - if (g.dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel == ledger_num) + if (g.dungeons[mptr->lev.dnum].ledger_start + mptr->lev.dlevel + == ledger_num) break; if (!mptr) @@ -2647,8 +2650,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 */ diff --git a/src/hack.c b/src/hack.c index 5f0da7986..399457e2c 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1780,7 +1780,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 */ @@ -1789,7 +1789,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 */ diff --git a/src/save.c b/src/save.c index e5e966e1d..bb88bf8a2 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: 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. */ @@ -284,15 +284,15 @@ register int fd, mode; #endif uid = (unsigned long) getuid(); bwrite(fd, (genericptr_t) &uid, sizeof uid); - bwrite(fd, (genericptr_t) &g.context, sizeof(struct context_info)); - bwrite(fd, (genericptr_t) &flags, sizeof(struct flag)); + bwrite(fd, (genericptr_t) &g.context, sizeof g.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? **/ @@ -321,14 +321,14 @@ register int fd, mode; g.migrating_objs = 0; g.migrating_mons = 0; } - bwrite(fd, (genericptr_t) g.mvitals, sizeof(g.mvitals)); + bwrite(fd, (genericptr_t) g.mvitals, sizeof g.mvitals); save_dungeon(fd, (boolean) !!perform_bwrite(mode), (boolean) !!release_data(mode)); savelevchn(fd, mode); bwrite(fd, (genericptr_t) &g.moves, sizeof g.moves); bwrite(fd, (genericptr_t) &g.monstermoves, sizeof g.monstermoves); - bwrite(fd, (genericptr_t) &g.quest_status, sizeof(struct q_score)); + bwrite(fd, (genericptr_t) &g.quest_status, sizeof g.quest_status); bwrite(fd, (genericptr_t) g.spl_book, sizeof(struct spell) * (MAXSPELL + 1)); save_artifacts(fd); @@ -390,7 +390,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 (g.hackpid != hpid) { Sprintf(whynot, "Level #0 pid (%d) doesn't match ours (%d)!", hpid, g.hackpid); @@ -407,11 +407,11 @@ savestateinlock() done(TRICKED); return; } - (void) write(fd, (genericptr_t) &g.hackpid, sizeof(g.hackpid)); + (void) write(fd, (genericptr_t) &g.hackpid, sizeof g.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); @@ -492,32 +492,31 @@ int mode; #endif if (lev >= 0 && lev <= maxledgerno()) g.level_info[lev].flags |= VISITED; - bwrite(fd, (genericptr_t) &g.hackpid, sizeof(g.hackpid)); + bwrite(fd, (genericptr_t) &g.hackpid, sizeof g.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, &g.level.bonesinfo); - savelevl(fd, - (boolean) ((sfsaveinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP)); - bwrite(fd, (genericptr_t) g.lastseentyp, sizeof(g.lastseentyp)); - bwrite(fd, (genericptr_t) &g.monstermoves, sizeof(g.monstermoves)); - bwrite(fd, (genericptr_t) &g.upstair, sizeof(stairway)); - bwrite(fd, (genericptr_t) &g.dnstair, sizeof(stairway)); - bwrite(fd, (genericptr_t) &g.upladder, sizeof(stairway)); - bwrite(fd, (genericptr_t) &g.dnladder, sizeof(stairway)); - bwrite(fd, (genericptr_t) &g.sstairs, sizeof(stairway)); - bwrite(fd, (genericptr_t) &g.updest, sizeof(dest_area)); - bwrite(fd, (genericptr_t) &g.dndest, sizeof(dest_area)); - bwrite(fd, (genericptr_t) &g.level.flags, sizeof(g.level.flags)); - bwrite(fd, (genericptr_t) g.doors, sizeof(g.doors)); + savelevl(fd, (boolean) ((sfsaveinfo.sfi1 & SFI1_RLECOMP) == SFI1_RLECOMP)); + bwrite(fd, (genericptr_t) g.lastseentyp, sizeof g.lastseentyp); + bwrite(fd, (genericptr_t) &g.monstermoves, sizeof g.monstermoves); + bwrite(fd, (genericptr_t) &g.upstair, sizeof (stairway)); + bwrite(fd, (genericptr_t) &g.dnstair, sizeof (stairway)); + bwrite(fd, (genericptr_t) &g.upladder, sizeof (stairway)); + bwrite(fd, (genericptr_t) &g.dnladder, sizeof (stairway)); + bwrite(fd, (genericptr_t) &g.sstairs, sizeof (stairway)); + bwrite(fd, (genericptr_t) &g.updest, sizeof (dest_area)); + bwrite(fd, (genericptr_t) &g.dndest, sizeof (dest_area)); + bwrite(fd, (genericptr_t) &g.level.flags, sizeof g.level.flags); + bwrite(fd, (genericptr_t) g.doors, sizeof g.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, &g.level.bonesinfo); @@ -583,21 +582,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; } @@ -901,12 +899,12 @@ register int fd, mode; for (tmplev = g.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 = g.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); } @@ -950,11 +948,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)) @@ -971,14 +969,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); @@ -989,26 +984,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); @@ -1059,7 +1046,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 @@ -1069,58 +1056,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)); @@ -1156,7 +1119,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; g.ftrap is the only trap chain so the 2nd arg is superfluous */ @@ -1172,7 +1135,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; @@ -1197,7 +1160,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; @@ -1216,7 +1179,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) g.plname, plsiztmp); bufon(fd); return; @@ -1242,11 +1205,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 */ @@ -1262,15 +1225,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; } @@ -1335,38 +1297,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(g.ftrap); - freeobjchn(fobj); - freeobjchn(g.level.buriedobjlist); - freeobjchn(g.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); @@ -1384,17 +1333,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 */ diff --git a/src/sp_lev.c b/src/sp_lev.c index 4237bf638..19e2cd24e 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -2023,11 +2023,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 (++g.mines_prize_count > 1) - impossible(prize_warning, "mines end"); + if (!g.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) { diff --git a/win/curses/cursmesg.c b/win/curses/cursmesg.c index 1548e2818..28c30ab74 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(g.toplines, message); + Strcpy(g.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(g.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. */