]> granicus.if.org Git - nethack/commitdiff
Merge branch 'NetHack-3.6'
authornhmall <nhmall@nethack.org>
Mon, 27 May 2019 20:38:09 +0000 (16:38 -0400)
committernhmall <nhmall@nethack.org>
Mon, 27 May 2019 20:38:09 +0000 (16:38 -0400)
1  2 
src/ball.c
src/end.c

diff --cc src/ball.c
Simple merge
diff --cc src/end.c
index 21a10c5e30a10d9f62b9046fdc1d4d505b719f89,67ae532f1ed81b72a5c2de9cca9fc351d366c1a0..daebeb9e2c1d4a1255026ac2ee0f2d09c2f85c5c
+++ b/src/end.c
@@@ -973,6 -997,55 +974,55 @@@ int what
  }
  #endif
  
 -     * We used to use dealloc_obj() on thrownobj and kickedobj but
+ /* deal with some objects which may be in an abnormal state at end of game */
+ STATIC_OVL void
+ done_object_cleanup()
+ {
+     int ox, oy;
+     /* might have been killed while using a disposable item, so make sure
+        it's gone prior to inventory disclosure and creation of bones */
+     inven_inuse(TRUE);
+     /*
+      * Hero can die when throwing an object (by hitting an adjacent
+      * gas spore, for instance, or being hit by mis-returning Mjollnir),
+      * or while in transit (from falling down stairs).  If that happens,
+      * some object(s) might be in limbo rather than on the map or in
+      * any inventory.  Saving bones with an active light source in limbo
+      * would trigger an 'object not local' panic.
+      *
 -    if (thrownobj && thrownobj->where == OBJ_FREE) {
 -        place_object(thrownobj, ox, oy);
 -        stackobj(thrownobj), thrownobj = 0;
++     * We used to use dealloc_obj() on g.thrownobj and g.kickedobj but
+      * that keeps them out of bones and could leave uball in a confused
+      * state (gone but still attached).  Place them on the map but
+      * bypass flooreffects().  That could lead to minor anomalies in
+      * bones, like undamaged paper at water or lava locations or piles
+      * not being knocked down holes, but it seems better to get this
+      * game over with than risk being tangled up in more and more details.
+      */
+     ox = u.ux + u.dx, oy = u.uy + u.dy;
+     if (!isok(ox, oy) || !accessible(ox, oy))
+         ox = u.ux, oy = u.uy;
+     /* put thrown or kicked object on map (for bones); location might
+        be incorrect (perhaps killed by divine lightning when throwing at
+        a temple priest?) but this should be better than just vanishing
+        (fragile stuff should be taken care of before getting here) */
 -    if (kickedobj && kickedobj->where == OBJ_FREE) {
 -        place_object(kickedobj, ox, oy);
 -        stackobj(kickedobj), kickedobj = 0;
++    if (g.thrownobj && g.thrownobj->where == OBJ_FREE) {
++        place_object(g.thrownobj, ox, oy);
++        stackobj(g.thrownobj), g.thrownobj = 0;
+     }
++    if (g.kickedobj && g.kickedobj->where == OBJ_FREE) {
++        place_object(g.kickedobj, ox, oy);
++        stackobj(g.kickedobj), g.kickedobj = 0;
+     }
+     /* if Punished hero dies during level change or dies or quits while
+        swallowed, uball and uchain will be in limbo; put them on floor
+        so bones will have them and object list cleanup finds them */
+     if (uchain && uchain->where == OBJ_FREE) {
+         placebc();
+     }
+     return;
+ }
  /* called twice; first to calculate total, then to list relevant items */
  STATIC_OVL void
  artifact_score(list, counting, endwin)
@@@ -1144,15 -1217,10 +1194,10 @@@ int how
      /* render vision subsystem inoperative */
      iflags.vision_inited = 0;
  
-     /* might have been killed while using a disposable item, so make sure
-        it's gone prior to inventory disclosure and creation of bones data */
-     inven_inuse(TRUE);
-     /* maybe not on object lists; if an active light source, would cause
-        big trouble (`obj_is_local' panic) for savebones() -> savelev() */
-     if (g.thrownobj && g.thrownobj->where == OBJ_FREE)
-         dealloc_obj(g.thrownobj);
-     if (g.kickedobj && g.kickedobj->where == OBJ_FREE)
-         dealloc_obj(g.kickedobj);
+     /* maybe use up active invent item(s), place thrown/kicked missile,
+        deal with ball and chain possibly being temporarily off the map */
 -    if (!program_state.panicking)
++    if (!g.program_state.panicking)
+         done_object_cleanup();
  
      /* remember time of death here instead of having bones, rip, and
         topten figure it out separately and possibly getting different
          int mnum = u.umonnum;
  
          if (!Upolyd) {
-             /* Base corpse on race when not poly'd since original
-              * u.umonnum is based on role, and all role monsters
-              * are human.
-              */
+             /* Base corpse on race when not poly'd since original u.umonnum
+                is based on role, and all role monsters are human. */
 -            mnum = (flags.female && urace.femalenum != NON_PM)
 -                       ? urace.femalenum
 -                       : urace.malenum;
 +            mnum = (flags.female && g.urace.femalenum != NON_PM)
 +                       ? g.urace.femalenum
 +                       : g.urace.malenum;
          }
 -        corpse = mk_named_object(CORPSE, &mons[mnum], u.ux, u.uy, plname);
 -        Sprintf(pbuf, "%s, ", plname);
 +        corpse = mk_named_object(CORPSE, &mons[mnum], u.ux, u.uy, g.plname);
 +        Sprintf(pbuf, "%s, ", g.plname);
          formatkiller(eos(pbuf), sizeof pbuf - strlen(pbuf), how, TRUE);
          make_grave(u.ux, u.uy, pbuf);
      }