From 786b810293c0a63235e4a4e50901979454939aec Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sun, 6 Feb 2005 04:44:36 +0000 Subject: [PATCH] more exploding magic pointers 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 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, '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 | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/pickup.c b/src/pickup.c index a6fd4c8cd..982db69b0 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -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 a 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); }