]> granicus.if.org Git - nethack/commitdiff
more exploding magic pointers
authornethack.rankin <nethack.rankin>
Sun, 6 Feb 2005 04:44:36 +0000 (04:44 +0000)
committernethack.rankin <nethack.rankin>
Sun, 6 Feb 2005 04:44:36 +0000 (04:44 +0000)
     My simpler fix for dealing with stale pointers caused by magic bag
explosion didn't handle menu_loot() checking whether to merge a destroyed
object with a stack it had been split from (the case <Someone> didn't attempt to
address either).  That only needs a one-line change, but this also removes
the illusiion of generality that menu_loot() tried to maintain.  It always
operates on current_container and relies on calling in_container() and
out_container() which do the same, so passing a container argument to it
was not useful.  If that had been taken out first, <Someone>'s method of fixing
the original problem would have been simpler than mine but I'm not planning
to back out the earlier change.

     Also fix a minor post-3.4.3 bug with a container-contents-known flag
being set incorrectly.

src/pickup.c

index a6fd4c8cd3286081795f55b258b189f185369262..982db69b01cde07e65cd2067d7a9759f3296bf66 100644 (file)
@@ -33,7 +33,7 @@ STATIC_PTR int FDECL(ck_bag,(struct obj *));
 STATIC_PTR int FDECL(out_container,(struct obj *));
 STATIC_DCL long FDECL(mbag_item_gone, (int,struct obj *));
 STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
-STATIC_DCL int FDECL(menu_loot, (int, struct obj *, BOOLEAN_P));
+STATIC_DCL int FDECL(menu_loot, (int,BOOLEAN_P));
 STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *, BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
 STATIC_DCL boolean FDECL(able_to_loot, (int,int,BOOLEAN_P));
@@ -2169,7 +2169,7 @@ register int held;
                }
                if (loot_out) {
                    add_valid_menu_class(0);    /* reset */
-                   used |= menu_loot(0, current_container, FALSE) > 0;
+                   used |= menu_loot(0, FALSE) > 0;
                }
            } else {
                /* traditional code */
@@ -2197,15 +2197,14 @@ ask_again2:
                                     0, "nodot"))
                            used = 1;
                    } else if (menu_on_request < 0) {
-                       used |= menu_loot(menu_on_request,
-                                         current_container, FALSE) > 0;
+                       used |= menu_loot(menu_on_request, FALSE) > 0;
                    }
                    /*FALLTHRU*/
                case 'n':
                    break;
                case 'm':
                    menu_on_request = -2; /* triggers ALL_CLASSES */
-                   used |= menu_loot(menu_on_request, current_container, FALSE) > 0;
+                   used |= menu_loot(menu_on_request, FALSE) > 0;
                    break;
                case 'q':
                default:
@@ -2241,7 +2240,7 @@ ask_again2:
                case 'm':
                    add_valid_menu_class(0);      /* reset */
                    menu_on_request = -2; /* triggers ALL_CLASSES */
-                   used |= menu_loot(menu_on_request, current_container, TRUE) > 0;
+                   used |= menu_loot(menu_on_request, TRUE) > 0;
                    break;
                case 'q':
                default:
@@ -2270,7 +2269,7 @@ ask_again2:
 #endif
            add_valid_menu_class(0);      /* reset */
            if (flags.menu_style != MENU_TRADITIONAL) {
-               used |= menu_loot(0, current_container, TRUE) > 0;
+               used |= menu_loot(0, TRUE) > 0;
            } else {
                /* traditional code */
                menu_on_request = 0;
@@ -2285,8 +2284,7 @@ ask_again2:
                                    in_container, ck_bag, 0, "nodot");
                    used = 1;
                } else if (menu_on_request < 0) {
-                   used |= menu_loot(menu_on_request,
-                                     current_container, TRUE) > 0;
+                   used |= menu_loot(menu_on_request, TRUE) > 0;
                }
            }
        }
@@ -2303,17 +2301,16 @@ ask_again2:
        return used;
 }
 
-/* Loot container (take things out, put things in), using a menu. */
+/* Loot current_container (take things out, put things in), using a menu. */
 STATIC_OVL int
-menu_loot(retry, container, put_in)
+menu_loot(retry, put_in)
 int retry;
-struct obj *container;
 boolean put_in;
 {
     int n, i, n_looted = 0;
     boolean all_categories = TRUE, loot_everything = FALSE;
     char buf[BUFSZ];
-    const char *takeout = "Take out", *putin = "Put in";
+    const char *action = put_in ? "Put in" : "Take out";
     struct obj *otmp, *otmp2;
     menu_item *pick_list;
     int mflags, res;
@@ -2323,10 +2320,10 @@ boolean put_in;
        all_categories = (retry == -2);
     } else if (flags.menu_style == MENU_FULL) {
        all_categories = FALSE;
-       Sprintf(buf,"%s what type of objects?", put_in ? putin : takeout);
+       Sprintf(buf, "%s what type of objects?", action);
        mflags = put_in ? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN :
                          ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN;
-       n = query_category(buf, put_in ? invent : container->cobj,
+       n = query_category(buf, put_in ? invent : current_container->cobj,
                           mflags, &pick_list, PICK_ANY);
        if (!n) return 0;
        for (i = 0; i < n; i++) {
@@ -2341,8 +2338,8 @@ boolean put_in;
     }
 
     if (loot_everything) {
-       container->cknown = 1;
-       for (otmp = container->cobj; otmp; otmp = otmp2) {
+       current_container->cknown = 1;
+       for (otmp = current_container->cobj; otmp; otmp = otmp2) {
            otmp2 = otmp->nobj;
            res = out_container(otmp);
            if (res < 0) break;
@@ -2350,9 +2347,9 @@ boolean put_in;
     } else {
        mflags = INVORDER_SORT;
        if (put_in && flags.invlet_constant) mflags |= USE_INVLET;
-       if (takeout) container->cknown = 1;
-       Sprintf(buf,"%s what?", put_in ? putin : takeout);
-       n = query_objlist(buf, put_in ? invent : container->cobj,
+       if (!put_in) current_container->cknown = 1;
+       Sprintf(buf, "%s what?", action);
+       n = query_objlist(buf, put_in ? invent : current_container->cobj,
                          mflags, &pick_list, PICK_ANY,
                          all_categories ? allow_all : allow_category);
        if (n) {
@@ -2366,7 +2363,11 @@ boolean put_in;
                    }
                    res = put_in ? in_container(otmp) : out_container(otmp);
                    if (res < 0) {
-                       if (otmp != pick_list[i].item.a_obj) {
+                       if (!current_container) {
+                           /* otmp caused current_container to explode;
+                              both are now gone */
+                           otmp = 0;           /* and break loop */
+                       } else if (otmp && otmp != pick_list[i].item.a_obj) {
                            /* split occurred, merge again */
                            (void) merged(&pick_list[i].item.a_obj, &otmp);
                        }