yet more exploding magic pointers
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.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
73
src/pickup.c
73
src/pickup.c
@@ -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
|
||||
|
||||
int
|
||||
use_container(obj, held)
|
||||
register struct obj *obj;
|
||||
register int held;
|
||||
/* used by askchain() to check for magic bag explosion */
|
||||
boolean
|
||||
container_gone(fn)
|
||||
int FDECL((*fn), (OBJ_P));
|
||||
{
|
||||
struct obj *curr, *otmp;
|
||||
/* result is only meaningful while use_container() is executing */
|
||||
return ((fn == in_container || fn == out_container) && !current_container);
|
||||
}
|
||||
|
||||
int
|
||||
use_container(objp, held)
|
||||
struct obj **objp;
|
||||
int held;
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user