From cf89253358a86372c41e1c7c55b240ceea64524a Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 11 Dec 2018 01:27:20 -0800 Subject: [PATCH 1/7] an() bit --- src/objnam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objnam.c b/src/objnam.c index ce828c355..6a805852d 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 objnam.c $NHDT-Date: 1544492043 2018/12/11 01:34:03 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.229 $ */ +/* NetHack 3.6 objnam.c $NHDT-Date: 1544520422 2018/12/11 09:27:02 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.230 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1220,7 +1220,7 @@ unsigned doname_flags; Strcpy(tmpbuf, prefix + 2); /* set prefix[] to "", "a ", or "an " */ (void) just_an(prefix, *tmpbuf ? tmpbuf : bp); - /* apprend remainder of original prefix */ + /* append remainder of original prefix */ Strcat(prefix, tmpbuf); } @@ -1629,7 +1629,7 @@ const char *str; impossible("Alphabet soup: 'an(%s)'.", str ? "\"\"" : ""); return strcpy(buf, "an []"); } - just_an(buf, str); + (void) just_an(buf, str); return strcat(buf, str); } From 9952049a752b6e310791740814cf3aea78d2951e Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Dec 2018 01:54:33 -0800 Subject: [PATCH 2/7] fix #H7677 - guard placed twice at <0,0> "Placing monster over another?" warning was triggered for vault guard by an earlier change which made m_detach() stop removing monsters at <0,*> from level.monsters[][]. So one guard would replace another at <0,0> for however many guards were created, and memory for all but the last one would be lost. This involved a lot of flailing about and the patch includes various things would could have been discarded. One or two extended monster sanity checks are included, plus a couple of debugpline()'s for tracking guard movement. --- doc/fixes36.2 | 1 + src/mon.c | 29 +++++++++++---- src/steed.c | 8 +++- src/vault.c | 101 ++++++++++++++++++++++++++++++-------------------- 4 files changed, 90 insertions(+), 49 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 9e6b004bb..51e6bfa69 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -293,6 +293,7 @@ changing Sting's description to be "(weapon in hand) (light blue aura)" was fix bit-use collision between WC2_TERM_SIZE and WC2_RESET_STATUS in include/winprocs.h following a recent merge fix foxen pluralization again after underflow remedy reintroduced the problem +fix "placing monster over another?" warning for vault guards tty: turn off an optimization that is the suspected cause of Windows reported partial status lines following level changes tty: ensure that current status fields are always copied to prior status diff --git a/src/mon.c b/src/mon.c index a22db1a1a..74edcccd7 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1543455827 2018/11/29 01:43:47 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.272 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1544608467 2018/12/12 09:54:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.273 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -48,8 +48,6 @@ struct monst *mtmp; boolean chk_geno; const char *msg; { - if (DEADMONSTER(mtmp)) - return; if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS]) { impossible("illegal mon data %s; mnum=%d (%s)", fmt_ptr((genericptr_t) mtmp->data), mtmp->mnum, msg); @@ -61,6 +59,13 @@ const char *msg; mtmp->mnum, mndx, msg); mtmp->mnum = mndx; } + if (DEADMONSTER(mtmp)) { + /* bad if not fmons list or if not vault guard */ + if (strcmp(msg, "fmon") || !mtmp->isgd) + impossible("dead monster on %s; %s at <%d,%d>", + msg, mons[mndx].mname, mtmp->mx, mtmp->my); + return; + } if (chk_geno && (mvitals[mndx].mvflags & G_GENOD) != 0) impossible("genocided %s in play (%s)", mons[mndx].mname, msg); } @@ -85,8 +90,9 @@ mon_sanity_check() for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { sanity_check_single_mon(mtmp, TRUE, "fmon"); - if (DEADMONSTER(mtmp)) + if (DEADMONSTER(mtmp) && !mtmp->isgd) continue; + x = mtmp->mx, y = mtmp->my; if (!isok(x, y) && !(mtmp->isgd && x == 0 && y == 0)) { impossible("mon (%s) claims to be at <%d,%d>?", @@ -713,10 +719,17 @@ movemon() break; } nmtmp = mtmp->nmon; - /* one dead monster needs to perform a move after death: - vault guard whose temporary corridor is still on the map */ - if (mtmp->isgd && !mtmp->mx && DEADMONSTER(mtmp)) + /* one dead monster needs to perform a move after death: vault + guard whose temporary corridor is still on the map; live + guards who have led the hero back to civilization get moved + off the map too; gd_move() decides whether the temporary + corridor can be removed and guard discarded (via clearing + mon->isgd flag so that dmonsfree() will get rid of mon) */ + if (mtmp->isgd && !mtmp->mx) { + /* parked at <0,0>; eventually isgd should get set to false */ (void) gd_move(mtmp); + continue; + } if (DEADMONSTER(mtmp)) continue; @@ -1766,7 +1779,7 @@ struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */ mtmp->mtrapped = 0; mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */ relobj(mtmp, 0, FALSE); - if (onmap) { + if (onmap || mtmp == level.monsters[0][0]) { if (mtmp->wormno) remove_worm(mtmp); else diff --git a/src/steed.c b/src/steed.c index 65e5ebbae..9eaf8f4c0 100644 --- a/src/steed.c +++ b/src/steed.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 steed.c $NHDT-Date: 1543543362 2018/11/30 02:02:42 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.59 $ */ +/* NetHack 3.6 steed.c $NHDT-Date: 1544608468 2018/12/12 09:54:28 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.60 $ */ /* Copyright (c) Kevin Hugo, 1998-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -742,6 +742,12 @@ place_monster(mon, x, y) struct monst *mon; int x, y; { + /* normal map bounds are <1..COLNO-1,0..ROWNO-1> but sometimes + vault guards (either living or dead) are parked at <0,0> */ + if (!isok(x, y) && (x != 0 || y != 0 || !mon->isgd)) { + impossible("trying to place monster at <%d,%d>", x, y); + x = y = 0; + } if (mon == u.usteed /* special case is for convoluted vault guard handling */ || (DEADMONSTER(mon) && !(mon->isgd && x == 0 && y == 0))) { diff --git a/src/vault.c b/src/vault.c index 7e47577e2..0e811d117 100644 --- a/src/vault.c +++ b/src/vault.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 vault.c $NHDT-Date: 1542765368 2018/11/21 01:56:08 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.55 $ */ +/* NetHack 3.6 vault.c $NHDT-Date: 1544608469 2018/12/12 09:54:29 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.57 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -10,6 +10,7 @@ STATIC_DCL struct monst *NDECL(findgd); STATIC_DCL boolean FDECL(clear_fcorr, (struct monst *, BOOLEAN_P)); STATIC_DCL void FDECL(blackout, (int, int)); STATIC_DCL void FDECL(restfakecorr, (struct monst *)); +STATIC_DCL void FDECL(parkguard, (struct monst *)); STATIC_DCL boolean FDECL(in_fcorridor, (struct monst *, int, int)); STATIC_DCL void FDECL(move_gold, (struct obj *, int)); STATIC_DCL void FDECL(wallify_vault, (struct monst *)); @@ -22,8 +23,8 @@ struct monst *mtmp; if (!mtmp->mextra) mtmp->mextra = newmextra(); if (!EGD(mtmp)) { - EGD(mtmp) = (struct egd *) alloc(sizeof(struct egd)); - (void) memset((genericptr_t) EGD(mtmp), 0, sizeof(struct egd)); + EGD(mtmp) = (struct egd *) alloc(sizeof (struct egd)); + (void) memset((genericptr_t) EGD(mtmp), 0, sizeof (struct egd)); } } @@ -38,6 +39,9 @@ struct monst *mtmp; mtmp->isgd = 0; } +/* try to remove the temporary corridor (from vault to rest of map) being + maintained by guard 'grd'; if guard is still in it, removal will fail, + to be tried again later */ STATIC_OVL boolean clear_fcorr(grd, forceshow) struct monst *grd; @@ -53,10 +57,14 @@ boolean forceshow; if (!on_level(&egrd->gdlevel, &u.uz)) return TRUE; + /* note: guard remains on 'fmons' list (alive or dead, at off-map + coordinate <0,0>), until temporary corridor from vault back to + civilization has been removed */ while ((fcbeg = egrd->fcbeg) < egrd->fcend) { fcx = egrd->fakecorr[fcbeg].fx; fcy = egrd->fakecorr[fcbeg].fy; - if ((DEADMONSTER(grd) || !in_fcorridor(grd, u.ux, u.uy)) && egrd->gddone) + if ((DEADMONSTER(grd) || !in_fcorridor(grd, u.ux, u.uy)) + && egrd->gddone) forceshow = TRUE; if ((u.ux == fcx && u.uy == fcy && !DEADMONSTER(grd)) || (!forceshow && couldsee(fcx, fcy)) @@ -137,6 +145,26 @@ struct monst *grd; } } +/* move guard--dead to alive--to <0,0> until temporary corridor is removed */ +STATIC_OVL void +parkguard(grd) +struct monst *grd; +{ + /* either guard is dead or will now be treated as if so; + monster traversal loops should skip it */ + if (grd == context.polearm.hitmon) + context.polearm.hitmon = 0; + if (grd->mx) { + remove_monster(grd->mx, grd->my); + newsym(grd->mx, grd->my); + place_monster(grd, 0, 0); + /* [grd->mx,my just got set to 0,0 by place_monster(), so this + just sets EGD(grd)->ogx,ogy to 0,0 too; is that what we want?] */ + EGD(grd)->ogx = grd->mx; + EGD(grd)->ogy = grd->my; + } +} + /* called in mon.c */ boolean grddead(grd) @@ -147,16 +175,8 @@ struct monst *grd; if (!dispose) { /* destroy guard's gold; drop any other inventory */ relobj(grd, 0, FALSE); - /* guard is dead; monster traversal loops should skip it */ grd->mhp = 0; - if (grd == context.polearm.hitmon) - context.polearm.hitmon = 0; - /* see comment by newpos in gd_move() */ - remove_monster(grd->mx, grd->my); - newsym(grd->mx, grd->my); - place_monster(grd, 0, 0); - EGD(grd)->ogx = grd->mx; - EGD(grd)->ogy = grd->my; + parkguard(grd); dispose = clear_fcorr(grd, TRUE); } if (dispose) @@ -226,13 +246,12 @@ invault() u.uinvault = 0; return; } - vaultroom -= ROOMOFFSET; guard = findgd(); if (++u.uinvault % VAULT_GUARD_TIME == 0 && !guard) { /* if time ok and no guard now. */ - char buf[BUFSZ] = DUMMY; + char buf[BUFSZ]; register int x, y, dd, gx, gy; int lx = 0, ly = 0; long umoney; @@ -387,6 +406,7 @@ invault() nomul(0); unmul((char *) 0); } + buf[0] = '\0'; trycount = 5; do { getlin(Deaf ? "You are required to supply your name. -" @@ -401,7 +421,7 @@ invault() } if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos") - || !strcmpi(buf, "Creosote")) { + || !strcmpi(buf, "Creosote")) { /* Discworld */ if (!mvitals[PM_CROESUS].died) { if (Deaf) { if (!Blind) @@ -468,9 +488,9 @@ invault() EGD(guard)->fcbeg = 0; EGD(guard)->fakecorr[0].fx = x; EGD(guard)->fakecorr[0].fy = y; - if (IS_WALL(levl[x][y].typ)) + if (IS_WALL(levl[x][y].typ)) { EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ; - else { /* the initial guard location is a dug door */ + } else { /* the initial guard location is a dug door */ int vlt = EGD(guard)->vroom; xchar lowx = rooms[vlt].lx, hix = rooms[vlt].hx; xchar lowy = rooms[vlt].ly, hiy = rooms[vlt].hy; @@ -603,27 +623,29 @@ register struct monst *grd; int x, y, nx, ny, m, n; int dx, dy, gx, gy, fci; uchar typ; + struct rm *crm; struct fakecorridor *fcp; register struct egd *egrd = EGD(grd); - struct rm *crm; - boolean goldincorridor = FALSE, - u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE, - grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE; - boolean disappear_msg_seen = FALSE, semi_dead = (DEADMONSTER(grd)); - long umoney = money_cnt(invent); - register boolean u_carry_gold = ((umoney + hidden_gold()) > 0L); - boolean see_guard, newspot = FALSE; + long umoney = 0L; + boolean goldincorridor = FALSE, u_in_vault = FALSE, grd_in_vault = FALSE, + disappear_msg_seen = FALSE, semi_dead = DEADMONSTER(grd), + u_carry_gold = FALSE, newspot = FALSE, see_guard; if (!on_level(&(egrd->gdlevel), &u.uz)) return -1; nx = ny = m = n = 0; + if (semi_dead || !grd->mx || egrd->gddone) { + egrd->gddone = 1; + goto cleanup; + } + debugpline1("gd_move: %s guard", grd->mpeaceful ? "peaceful" : "hostile"); + + u_in_vault = vault_occupied(u.urooms) ? TRUE : FALSE; + grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT) ? TRUE : FALSE; if (!u_in_vault && !grd_in_vault) wallify_vault(grd); + if (!grd->mpeaceful) { - if (semi_dead) { - egrd->gddone = 1; - goto newpos; - } if (!u_in_vault && (grd_in_vault || (in_fcorridor(grd, grd->mx, grd->my) && !in_fcorridor(grd, u.ux, u.uy)))) { @@ -647,6 +669,9 @@ register struct monst *grd; grd->mpeaceful = 0; return -1; } + + umoney = money_cnt(invent); + u_carry_gold = umoney > 0L || hidden_gold() > 0L; if (egrd->fcend == 1) { if (u_in_vault && (u_carry_gold || um_dist(grd->mx, grd->my, 1))) { if (egrd->warncnt == 3 && !Deaf) @@ -696,7 +721,6 @@ register struct monst *grd; } else { if (!Deaf) verbalize("Well, begone."); - wallify_vault(grd); egrd->gddone = 1; goto cleanup; } @@ -881,7 +905,7 @@ proceed: fcp->fy = ny; fcp->ftyp = typ; newpos: - gd_mv_monaway(grd, nx,ny); + gd_mv_monaway(grd, nx, ny); if (egrd->gddone) { /* The following is a kludge. We need to keep */ /* the guard around in order to be able to make */ @@ -893,17 +917,14 @@ newpos: /* At the end of the process, the guard is killed */ /* in restfakecorr(). */ cleanup: - x = grd->mx; - y = grd->my; - + x = grd->mx, y = grd->my; see_guard = canspotmon(grd); + parkguard(grd); /* move to <0,0> */ wallify_vault(grd); - remove_monster(grd->mx, grd->my); - newsym(grd->mx, grd->my); - place_monster(grd, 0, 0); - egrd->ogx = grd->mx; - egrd->ogy = grd->my; restfakecorr(grd); + debugpline2("gd_move: %scleanup%s", + grd->isgd ? "" : "final ", + grd->isgd ? " attempt" : ""); if (!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) { if (!disappear_msg_seen && see_guard) pline("Suddenly, %s disappears.", noit_mon_nam(grd)); From fdec3704fd51e546fb588e8dcea7bbb228cff11d Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Dec 2018 15:42:46 -0800 Subject: [PATCH 3/7] mon_sanity_check tweak A change I included with the vault guard fix was triggering fuzzer panics about dead monsters on the fmons list. I'm not quite sure why; I couldn't reproduce it interactively. [Perhaps caused by hero killing a monster and then getting another move before monsters get their turn, but trying to do that still didn't trip the dead monster sanity check.] Suppress that check so that the fuzzer can run amok. Also, a waiting-to-exit vault guard could move extra times, uselessly since ''hero hasn't left temporary corridor yet'' is why he's waiting, if there were any monsters fast enough to get extra moves before the hero's next turn. --- src/mon.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mon.c b/src/mon.c index 74edcccd7..de037e42b 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1544608467 2018/12/12 09:54:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.273 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1544658160 2018/12/12 23:42:40 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.274 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -60,10 +60,12 @@ const char *msg; mtmp->mnum = mndx; } if (DEADMONSTER(mtmp)) { +#if 0 /* bad if not fmons list or if not vault guard */ if (strcmp(msg, "fmon") || !mtmp->isgd) impossible("dead monster on %s; %s at <%d,%d>", msg, mons[mndx].mname, mtmp->mx, mtmp->my); +#endif return; } if (chk_geno && (mvitals[mndx].mvflags & G_GENOD) != 0) @@ -89,6 +91,7 @@ mon_sanity_check() struct monst *mtmp, *m; for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { + /* dead monsters should still have sane data */ sanity_check_single_mon(mtmp, TRUE, "fmon"); if (DEADMONSTER(mtmp) && !mtmp->isgd) continue; @@ -727,7 +730,10 @@ movemon() mon->isgd flag so that dmonsfree() will get rid of mon) */ if (mtmp->isgd && !mtmp->mx) { /* parked at <0,0>; eventually isgd should get set to false */ - (void) gd_move(mtmp); + if (monstermoves > mtmp->mlstmv) { + (void) gd_move(mtmp); + mtmp->mlstmv = monstermoves; + } continue; } if (DEADMONSTER(mtmp)) From 30ddfb01dbbfe3b1cfbe689c1f6a23de6f6cb746 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Dec 2018 17:54:53 -0800 Subject: [PATCH 4/7] place_monster() warning bit --- src/steed.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/steed.c b/src/steed.c index 9eaf8f4c0..a90a0ce86 100644 --- a/src/steed.c +++ b/src/steed.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 steed.c $NHDT-Date: 1544608468 2018/12/12 09:54:28 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.60 $ */ +/* NetHack 3.6 steed.c $NHDT-Date: 1544666049 2018/12/13 01:54:09 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.61 $ */ /* Copyright (c) Kevin Hugo, 1998-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -756,7 +756,7 @@ int x, y; return; } if (level.monsters[x][y]) - impossible("placing monster over another?"); + impossible("placing monster over another at <%d,%d>?", x, y); mon->mx = x, mon->my = y; level.monsters[x][y] = mon; } From a63b9f29a5f8beace02ae4bc69b924a8c9758fe4 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Dec 2018 17:55:43 -0800 Subject: [PATCH 5/7] fuzzing hero boost I watched the fuzzer run for a bit and noticed that Str and most other characteristics were steadily dropping until they hit 3 and not being recovered, so I gave the defenseless hero a chance to benefit from blessed restore ability occasionally. It hasn't helped much. Str and Con both still drop to 3. [If I had to guess, I'd go with side-effect of polymorphing, but not an intended one.] --- src/end.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/end.c b/src/end.c index cbc312598..e90745cdb 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1544003110 2018/12/05 09:45:10 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.156 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1544666123 2018/12/13 01:55:23 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.157 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -577,13 +577,13 @@ VA_DECL(const char *, str) ? "Program initialization has failed." : "Suddenly, the dungeon collapses."); #ifndef MICRO -#if defined(NOTIFY_NETHACK_BUGS) +#ifdef NOTIFY_NETHACK_BUGS if (!wizard) raw_printf("Report the following error to \"%s\" or at \"%s\".", DEVTEAM_EMAIL, DEVTEAM_URL); else if (program_state.something_worth_saving) raw_print("\nError save file being written.\n"); -#else +#else /* !NOTIFY_NETHACK_BUGS */ if (!wizard) { const char *maybe_rebuild = !program_state.something_worth_saving ? "." @@ -599,7 +599,7 @@ VA_DECL(const char *, str) raw_printf("Report error to \"%s\"%s", WIZARD_NAME, maybe_rebuild); } -#endif +#endif /* ?NOTIFY_NETHACK_BUGS */ /* XXX can we move this above the prints? Then we'd be able to * suppress "it may be possible to rebuild" based on dosave0() * or say it's NOT possible to rebuild. */ @@ -611,7 +611,7 @@ VA_DECL(const char *, str) raw_printf("%s", sysopt.recover); } } -#endif +#endif /* !MICRO */ { char buf[BUFSZ]; @@ -1055,7 +1055,16 @@ int how; if (iflags.debug_fuzzer) { if (!(program_state.panicking || how == PANICKED)) { savelife(how); - killer.name[0] = 0; + /* periodically restore characteristics and lost exp levels */ + if (!rn2(10)) { + struct obj *potion = mksobj(POT_RESTORE_ABILITY, TRUE, FALSE); + + bless(potion); + (void) peffects(potion); /* always -1 for restore ability */ + /* not useup(); we haven't put this potion into inventory */ + obfree(potion, (struct obj *) 0); + } + killer.name[0] = '\0'; killer.format = 0; return; } From 59dcf73ad86be8175e246c173d0ecf427fbfb782 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Dec 2018 18:49:12 -0800 Subject: [PATCH 6/7] interactive !pickup_types To use 'O' to clear a value from pickup_types with menustyle Traditional or Combination, you needed to give a value starting with 'a' (for 'all'). Accept space(s) too, similar to removing an object or monster name. --- src/options.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/options.c b/src/options.c index 3a190b9c1..d0358caf0 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1544396581 2018/12/09 23:03:01 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.340 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1544669347 2018/12/13 02:49:07 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.343 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2008. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2986,12 +2986,17 @@ boolean tinitial, tfrom_file; use_menu = TRUE; if (flags.menu_style == MENU_TRADITIONAL || flags.menu_style == MENU_COMBINATION) { + boolean wasspace; + use_menu = FALSE; Sprintf(qbuf, "New %s: [%s am] (%s)", fullname, ocl, *tbuf ? tbuf : "all"); getlin(qbuf, abuf); + wasspace = (abuf[0] == ' '); /* before mungspaces */ op = mungspaces(abuf); - if (abuf[0] == '\0' || abuf[0] == '\033') + if (wasspace && !abuf[0]) + ; /* one or more spaces will remove old value */ + else if (!abuf[0] || abuf[0] == '\033') op = tbuf; /* restore */ else if (abuf[0] == 'm') use_menu = TRUE; From 05c253b6d85259e208270acc1cafd75772de44f9 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 12 Dec 2018 18:55:06 -0800 Subject: [PATCH 7/7] show autopickup in ^X feedback Gathers all the autopickup information in one place: Auto-pickup is { off | on { for 'classes' [plus thrown] | all types } [, with exceptions] }. --- doc/fixes36.2 | 1 + include/extern.h | 3 ++- src/cmd.c | 18 +++++++++++++++++- src/options.c | 5 ++--- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 51e6bfa69..26305aacf 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -406,6 +406,7 @@ for ^X and enlightenment, display the information in a menu rather than a '<' (menu_previous_page) and '^' (menu_first_page) menu keys; needed for interfaces (tty) without text popup scrollbar support; end of game disclosure of attributes remains single-forward-pass +for ^X, include current state of 'autopickup' NetHack Community Patches (or Variation) Included diff --git a/include/extern.h b/include/extern.h index 81b792aa9..1c88ca32f 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1544401264 2018/12/10 00:21:04 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.666 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1544669659 2018/12/13 02:54:19 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.667 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1729,6 +1729,7 @@ E int FDECL(fruitadd, (char *, struct fruit *)); E int FDECL(choose_classes_menu, (const char *, int, BOOLEAN_P, char *, char *)); E boolean FDECL(parsebindings, (char *)); +E void FDECL(oc_to_str, (char *, char *)); E void FDECL(add_menu_cmd_alias, (CHAR_P, CHAR_P)); E char FDECL(get_menu_cmd_key, (CHAR_P)); E char FDECL(map_menu_cmd, (CHAR_P)); diff --git a/src/cmd.c b/src/cmd.c index 67170cec7..5f484bebf 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1544050555 2018/12/05 22:55:55 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.314 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1544669664 2018/12/13 02:54:24 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.315 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2019,6 +2019,22 @@ int final; enl_msg(Your_wallet, "contains ", "contained ", buf, ""); } } + + if (flags.pickup) { + char ocl[MAXOCLASSES + 1]; + + Strcpy(buf, "on"); + oc_to_str(flags.pickup_types, ocl); + Sprintf(eos(buf), " for %s%s%s", + *ocl ? "'" : "", *ocl ? ocl : "all types", *ocl ? "'" : ""); + if (flags.pickup_thrown && *ocl) /* *ocl: don't show if 'all types' */ + Strcat(buf, " plus thrown"); + if (iflags.autopickup_exceptions[AP_GRAB] + || iflags.autopickup_exceptions[AP_LEAVE]) + Strcat(buf, ", with exceptions"); + } else + Strcpy(buf, "off"); + enl_msg("Auto-pickup ", "is ", "was ", buf, ""); } /* characteristics: expanded version of bottom line strength, dexterity, &c */ diff --git a/src/options.c b/src/options.c index d0358caf0..6419c55f0 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 options.c $NHDT-Date: 1544669347 2018/12/13 02:49:07 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.343 $ */ +/* NetHack 3.6 options.c $NHDT-Date: 1544669666 2018/12/13 02:54:26 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.344 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2008. */ /* NetHack may be freely redistributed. See license for details. */ @@ -557,7 +557,6 @@ STATIC_DCL int NDECL(count_menucolors); STATIC_DCL boolean FDECL(parse_role_opts, (BOOLEAN_P, const char *, char *, char **)); -STATIC_DCL void FDECL(oc_to_str, (char *, char *)); STATIC_DCL void FDECL(doset_add_menu, (winid, const char *, int)); STATIC_DCL void FDECL(opts_add_others, (winid, const char *, int, char *, int)); @@ -4086,7 +4085,7 @@ static NEARDATA const char *sortltype[] = { "none", "loot", "full" }; * Convert the given string of object classes to a string of default object * symbols. */ -STATIC_OVL void +void oc_to_str(src, dest) char *src, *dest; {