]> granicus.if.org Git - nethack/commitdiff
mapping/detection hangup handling (trunk only)
authornethack.rankin <nethack.rankin>
Tue, 29 Nov 2011 03:28:07 +0000 (03:28 +0000)
committernethack.rankin <nethack.rankin>
Tue, 29 Nov 2011 03:28:07 +0000 (03:28 +0000)
     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.

doc/fixes35.0
include/patchlevel.h
include/you.h
src/detect.c
src/restore.c

index 2896757c93d1f55a3d70992954a4d07b8523c339..1de294c31e9e7fcabe12978a41174c63437e59b8 100644 (file)
@@ -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 <foo> detection performed while
+       underwater could put hero on top of the water after restore
 
 
 Platform- and/or Interface-Specific Fixes
index 2fee2b03f82c39389a26bb846591e7c243160fd6..b832531579c19b0b96909489b5194b97d8711a8c 100644 (file)
@@ -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"
index 2ff81782dafdd322c94d05f8865f33df5f8d0252..9b3e0743d13d1f76ee4c333cae04dab9006e4290 100644 (file)
@@ -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' */
 
index 3e6424bd2290efa60c028f355261789e26e07cb4..a06a62e7e4219eb957b0db2808650efbbd688286 100644 (file)
@@ -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
index 4d5136f7a1d92a074bf02429e12f18de8fce9fb1..9e2def56d7a92db575e24d160af565b6c9d158a2 100644 (file)
@@ -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 */