]> granicus.if.org Git - nethack/commitdiff
yet more exploding magic pointers
authornethack.rankin <nethack.rankin>
Tue, 8 Feb 2005 04:57:54 +0000 (04:57 +0000)
committernethack.rankin <nethack.rankin>
Tue, 8 Feb 2005 04:57:54 +0000 (04:57 +0000)
     Revert mostly to <Someone>'s original approach for keeping track of whether
a container being applied or looted had been destroyed by the operation.
askchain() now knows not to attempt to re-merge an item that has been
destroyed (a theorhetical action since no stackable items can trigger a
magic bag explosion) like the earlier change to menu_loot().  Also have
use_container() clean up after itself so that current_container never has
an old pointer value left around.

include/extern.h
src/apply.c
src/invent.c
src/pickup.c

index 6ca4c60929aef9622a40e023ac79a94ea4db8d00..22a8ec9d7060d7a052f1641b2fe8639702ba25b7 100644 (file)
@@ -1553,7 +1553,8 @@ E int FDECL(query_objlist, (const char *, struct obj *, int,
 E struct obj *FDECL(pick_obj, (struct obj *));
 E int NDECL(encumber_msg);
 E int NDECL(doloot);
-E int FDECL(use_container, (struct obj *,int));
+E boolean FDECL(container_gone, (int (*)(OBJ_P)));
+E int FDECL(use_container, (struct obj **,int));
 E int FDECL(loot_mon, (struct monst *,int *,boolean *));
 E int NDECL(dotip);
 E const char *FDECL(safe_qbuf, (const char *,unsigned,
index 17312b8147dba97a0fe757735bbb5f9903fb2e61..5f0e3301b3c4ec05ef1a7fb4da34feedaa8ed323 100644 (file)
@@ -45,9 +45,6 @@ STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
 void FDECL( amii_speaker, ( struct obj *, char *, int ) );
 #endif
 
-/* managed by use_container(pickup.c) */
-extern struct obj *current_container;
-
 static const char no_elbow_room[] = "don't have enough elbow-room to maneuver.";
 
 #ifdef TOURIST
@@ -2969,10 +2966,7 @@ doapply()
        case SACK:
        case BAG_OF_HOLDING:
        case OILSKIN_SACK:
-               res = use_container(obj, 1);
-               /* magic bag might end up being destroyed;
-                  if so, current_container will be null */
-               obj = current_container;
+               res = use_container(&obj, 1);
                break;
        case BAG_OF_TRICKS:
                bagotricks(obj);
index 5b7d88810be5cb006f643acc1e0d2ee804298e6f..b2950569f00cb08b159e738820d89348426395c9 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)invent.c   3.5     2004/11/03      */
+/*     SCCS Id: @(#)invent.c   3.5     2005/02/07      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1422,7 +1422,11 @@ nextclass:
                case 'y':
                        tmp = (*fn)(otmp);
                        if(tmp < 0) {
-                           if (otmp != otmpo) {
+                           if (container_gone(fn)) {
+                               /* otmp caused magic bag to explode;
+                                  both are now gone */
+                               otmp = 0;               /* and return */
+                           } else if (otmp && otmp != otmpo) {
                                /* split occurred, merge again */
                                (void) merged(&otmpo, &otmp);
                            }
index eaa0389d7cc3bb70e9a8ed7527efe8e97172b04f..31cafd1234f6fb84290d4ef91e97c420831f017d 100644 (file)
@@ -58,8 +58,8 @@ STATIC_DCL void FDECL(tipcontainer, (struct obj *));
 
 /* A variable set in use_container(), to be used by the callback routines  */
 /* in_container() and out_container() from askchain() and use_container(). */
-/* Also used by menu_loot().  And by doapply(apply.c).                    */
-struct obj *current_container;
+/* Also used by menu_loot() and container_gone().                         */ 
+static NEARDATA struct obj *current_container;
 #define Icebox (current_container->otyp == ICE_BOX)
 
 static const char moderateloadmsg[] = "You have a little trouble lifting";
@@ -1508,7 +1508,7 @@ int x, y;
 int
 doloot()       /* loot a container on the floor or loot saddle from mon. */
 {
-    register struct obj *cobj, *nobj;
+    struct obj *cobj, *nobj;
     register int c = -1;
     int timepassed = 0;
     coord cc;
@@ -1567,8 +1567,9 @@ lootcont:
                }
 
                You("carefully open %s...", the(xname(cobj)));
-               timepassed |= use_container(cobj, 0);
-               if (multi < 0) return 1;                /* chest trap */
+               timepassed |= use_container(&cobj, 0);
+               /* might have triggered chest trap or magic bag explosion */
+               if (multi < 0 || !cobj) return 1;
            }
        }
        if (any) c = 'y';
@@ -2067,12 +2068,21 @@ struct obj *box;
 
 #undef Icebox
 
+/* used by askchain() to check for magic bag explosion */
+boolean
+container_gone(fn)
+int FDECL((*fn), (OBJ_P));
+{
+    /* result is only meaningful while use_container() is executing */
+    return ((fn == in_container || fn == out_container) && !current_container);
+}
+
 int
-use_container(obj, held)
-register struct obj *obj;
-register int held;
+use_container(objp, held)
+struct obj **objp;
+int held;
 {
-       struct obj *curr, *otmp;
+       struct obj *curr, *otmp, *obj = *objp;
 #ifndef GOLDOBJ
        struct obj *u_gold = (struct obj *)0;
 #endif
@@ -2109,7 +2119,9 @@ register int held;
            return 1;
        }
        obj->lknown = 1;
+
        current_container = obj;        /* for use by in/out_container */
+       /* from here on out, all early returns go through containerdone */
 
        if (obj->spe == 1) {
            observe_quantum_cat(obj);
@@ -2145,23 +2157,28 @@ register int held;
                if (flags.menu_style == MENU_FULL) {
                    int t;
                    char menuprompt[BUFSZ];
-                   boolean outokay = (cnt != 0);
+                   boolean outokay = (cnt != 0),
+                           inokay = (invent != 0);
+
 #ifndef GOLDOBJ
-                   boolean inokay = (invent != 0) || (u.ugold != 0);
-#else
-                   boolean inokay = (invent != 0);
+                   if (u.ugold) inokay = TRUE;
 #endif
+                   if (!cnt) obj->cknown = 1;  /* will be giving emptymsg */
+
                    if (!outokay && !inokay) {
                        pline("%s", emptymsg);
                        You("don't have anything to put in.");
-                       if (used) obj->cknown = 1;
-                       return used;
+                       goto containerdone;
                    }
                    menuprompt[0] = '\0';
                    if (!cnt) Sprintf(menuprompt, "%s ", emptymsg);
                    Strcat(menuprompt, "Do what?");
-                   t = in_or_out_menu(menuprompt, current_container, outokay, inokay);
-                   if (t <= 0) return 0;
+                   t = in_or_out_menu(menuprompt, current_container,
+                                      outokay, inokay);
+                   if (t <= 0) {
+                       used = 0;
+                       goto containerdone;
+                   }
                    loot_out = (t & 0x01) != 0;
                    loot_in  = (t & 0x02) != 0;
                } else {        /* MENU_COMBINATION or MENU_PARTIAL */
@@ -2208,12 +2225,12 @@ ask_again2:
                    break;
                case 'q':
                default:
-                   if (used) obj->cknown = 1;
-                   return used;
+                   goto containerdone;
                }
            }
        } else {
            pline("%s", emptymsg);              /* <whatever> is empty. */
+           obj->cknown = 1;
        }
 
 #ifndef GOLDOBJ
@@ -2223,8 +2240,7 @@ ask_again2:
 #endif
            /* nothing to put in, but some feedback is necessary */
            You("don't have anything to put in.");
-           if (used) obj->cknown = 1;
-           return used;
+           goto containerdone;
        }
        if (flags.menu_style != MENU_FULL) {
            Sprintf(qbuf, "Do you wish to put %s in?", something);
@@ -2244,8 +2260,7 @@ ask_again2:
                    break;
                case 'q':
                default:
-                   if (used) obj->cknown = 1;
-                   return used;
+                   goto containerdone;
            }
        }
        /*
@@ -2298,6 +2313,16 @@ ask_again2:
            dealloc_obj(u_gold);
        }
 #endif
+
+ containerdone:
+       /* Not completely correct; if we put something in without knowing
+          whatever was already inside, now we suddenly do.  That can't be
+          helped unless we want to track things item by item and then deal
+          with containers whose contents are "partly known". */
+       if (used) obj->cknown = 1;
+
+       *objp = current_container;      /* might have become null */
+       current_container = 0;          /* avoid hanging on to stale pointer */
        return used;
 }