From: nethack.rankin Date: Tue, 29 Nov 2011 03:28:07 +0000 (+0000) Subject: mapping/detection hangup handling (trunk only) X-Git-Tag: MOVE2GIT~149 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e072ebd3fa2e921a876f2afb890bd40ed8585fb6;p=nethack mapping/detection hangup handling (trunk only) Noticed while looking at the magic mapping code: u.uinwater is cleared during mapping and detection so that map updating isn't suppressed due to underwater vision restrictions, and it was possible for a hangup save to take place before that state field was reset. After restore, the hero would end up standing on water, then fall in on the next turn. This saves it in struct `u' rather than in a local variable, so that the stored value is accessible during restore. The u.uburied flag was being ignored, but presumeably it would also impose severe vision restrictions if it ever gets implemented, so it is now saved, temporarily cleared, and restored along with u.uinwater during monster/object/gold/trap detection and magic mapping. --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 2896757c9..1de294c31 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -398,6 +398,8 @@ wand/scroll/spell of light now hurts gremlins (lamp/candle light doesn't) ditto for hero in gremlin form (camera too) autosearch finds and transforms secret doors and corridors even while blind, but it wasn't updating the map to show them unless the hero could see +panic save made during magic mapping or detection performed while + underwater could put hero on top of the water after restore Platform- and/or Interface-Specific Fixes diff --git a/include/patchlevel.h b/include/patchlevel.h index 2fee2b03f..b83253157 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -13,7 +13,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 49 +#define EDITLEVEL 50 #define COPYRIGHT_BANNER_A \ "NetHack, Copyright 1985-2011" diff --git a/include/you.h b/include/you.h index 2ff81782d..9b3e0743d 100644 --- a/include/you.h +++ b/include/you.h @@ -1,5 +1,4 @@ /* NetHack 3.5 you.h $Date$ $Revision$ */ -/* SCCS Id: @(#)you.h 3.5 2006/03/01 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -228,6 +227,14 @@ struct Align { extern const struct Align aligns[]; /* table of available alignments */ +/* hangup handling; sometimes u.uinwater is overridden, and we need to + be able to reset it in the event of restoring from a hangup save; + save/override/restore takes place during normal execution, so this + isn't dependent upon current port's signal handling capability */ +struct huphack { + Bitfield(hup_uinwater,1); + Bitfield(hup_uburied,1); +}; /*** Information about the player ***/ struct you { @@ -361,6 +368,7 @@ struct you { xchar skill_record[P_SKILL_LIMIT]; /* skill advancements */ struct skills weapon_skills[P_NUM_SKILLS]; boolean twoweap; /* KMH -- Using two-weapon combat */ + struct huphack save; /* hup_{uinwater,uburied} */ }; /* end of `struct you' */ diff --git a/src/detect.c b/src/detect.c index 3e6424bd2..a06a62e7e 100644 --- a/src/detect.c +++ b/src/detect.c @@ -166,7 +166,6 @@ register struct obj *sobj; { register struct obj *obj; register struct monst *mtmp; - int uw = u.uinwater; struct obj *temp; boolean stale; @@ -234,7 +233,8 @@ register struct obj *sobj; outgoldmap: cls(); - u.uinwater = 0; + u.save.hup_uinwater = u.uinwater, u.save.hup_uburied = u.uburied; + u.uinwater = u.uburied = 0; /* Discover gold locations. */ for (obj = fobj; obj; obj = obj->nobj) { if (sobj->blessed && (temp = o_material(obj, GOLD))) { @@ -277,13 +277,12 @@ outgoldmap: break; } } - newsym(u.ux,u.uy); + u.uinwater = u.save.hup_uinwater, u.uburied = u.save.hup_uburied; You_feel("very greedy, and sense gold!"); exercise(A_WIS, TRUE); display_nhwindow(WIN_MAP, TRUE); docrt(); - u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); return(0); @@ -301,7 +300,6 @@ register struct obj *sobj; boolean confused = (Confusion || (sobj && sobj->cursed)), stale; char oclass = confused ? POTION_CLASS : FOOD_CLASS; const char *what = confused ? something : "food"; - int uw = u.uinwater; stale = clear_stale_map(oclass, 0); @@ -353,7 +351,8 @@ register struct obj *sobj; struct obj *temp; known = TRUE; cls(); - u.uinwater = 0; + u.save.hup_uinwater = u.uinwater, u.save.hup_uburied = u.uburied; + u.uinwater = u.uburied = 0; for (obj = fobj; obj; obj = obj->nobj) if ((temp = o_in(obj, oclass)) != 0) { if (temp != obj) { @@ -372,19 +371,19 @@ register struct obj *sobj; break; /* skip rest of this monster's inventory */ } newsym(u.ux,u.uy); + u.uinwater = u.save.hup_uinwater, u.uburied = u.save.hup_uburied; if (sobj) { if (sobj->blessed) { - Your("%s %s to tingle and you smell %s.", body_part(NOSE), - u.uedibility ? "continues" : "starts", what); + Your("%s %s to tingle and you smell %s.", body_part(NOSE), + u.uedibility ? "continues" : "starts", what); u.uedibility = 1; } else Your("%s tingles and you smell %s.", body_part(NOSE), what); - } - else You("sense %s.", what); + } else + You("sense %s.", what); display_nhwindow(WIN_MAP, TRUE); exercise(A_WIS, TRUE); docrt(); - u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); } @@ -411,7 +410,6 @@ int class; /* an object class, 0 for all */ int ct = 0, ctu = 0; register struct obj *obj, *otmp = (struct obj *)0; register struct monst *mtmp; - int uw = u.uinwater; int sym, boulder = 0; if (class < 0 || class >= MAXOCLASSES) { @@ -484,7 +482,8 @@ int class; /* an object class, 0 for all */ cls(); - u.uinwater = 0; + u.save.hup_uinwater = u.uinwater, u.save.hup_uburied = u.uburied; + u.uinwater = u.uburied = 0; /* * Map all buried objects first. */ @@ -561,6 +560,7 @@ int class; /* an object class, 0 for all */ } newsym(u.ux,u.uy); + u.uinwater = u.save.hup_uinwater, u.uburied = u.save.hup_uburied; You("detect the %s of %s.", ct ? "presence" : "absence", stuff); display_nhwindow(WIN_MAP, TRUE); /* @@ -569,7 +569,6 @@ int class; /* an object class, 0 for all */ */ docrt(); /* this will correctly reset vision */ - u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); return 0; @@ -717,7 +716,7 @@ register struct obj *sobj; register struct trap *ttmp; struct monst *mon; int door, glyph, tr; - int uw = u.uinwater, cursed_src = sobj && sobj->cursed; + int cursed_src = sobj && sobj->cursed; boolean found = FALSE; coord cc; @@ -767,7 +766,8 @@ register struct obj *sobj; outtrapmap: cls(); - u.uinwater = 0; + u.save.hup_uinwater = u.uinwater, u.save.hup_uburied = u.uburied; + u.uinwater = u.uburied = 0; /* show chest traps first, so that subsequent floor trap display will override if both types are present at the same location */ @@ -792,12 +792,12 @@ outtrapmap: glyph = glyph_at(u.ux, u.uy); if (!(glyph_is_trap(glyph) || glyph_is_object(glyph))) newsym(u.ux, u.uy); + u.uinwater = u.save.hup_uinwater, u.uburied = u.save.hup_uburied; You_feel("%s.", cursed_src ? "very greedy" : "entrapped"); /* wait for user to respond, then reset map display to normal */ display_nhwindow(WIN_MAP, TRUE); docrt(); - u.uinwater = uw; if (Underwater) under_water(2); if (u.uburied) under_ground(2); return(0); @@ -1004,19 +1004,19 @@ void do_mapping() { register int zx, zy; - int uw = u.uinwater; - u.uinwater = 0; + u.save.hup_uinwater = u.uinwater, u.save.hup_uburied = u.uburied; + u.uinwater = u.uburied = 0; for (zx = 1; zx < COLNO; zx++) for (zy = 0; zy < ROWNO; zy++) show_map_spot(zx, zy); - exercise(A_WIS, TRUE); - u.uinwater = uw; + u.uinwater = u.save.hup_uinwater, u.uburied = u.save.hup_uburied; if (!level.flags.hero_memory || Underwater) { flush_screen(1); /* flush temp screen */ display_nhwindow(WIN_MAP, TRUE); /* wait */ docrt(); } + exercise(A_WIS, TRUE); } void diff --git a/src/restore.c b/src/restore.c index 4d5136f7a..9e2def56d 100644 --- a/src/restore.c +++ b/src/restore.c @@ -857,6 +857,11 @@ register int fd; */ reset_restpref(); + /* some fixups in case this was a hangup save */ + u.uinvulnerable = 0; + if (u.save.hup_uinwater) u.uinwater = 1, u.save.hup_uinwater = 0; + if (u.save.hup_uburied) u.uburied = 1, u.save.hup_uburied = 0; + restlevelstate(stuckid, steedid); program_state.something_worth_saving = 1; /* useful data now exists */