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:
+2
-1
@@ -1553,7 +1553,8 @@ E int FDECL(query_objlist, (const char *, struct obj *, int,
|
|||||||
E struct obj *FDECL(pick_obj, (struct obj *));
|
E struct obj *FDECL(pick_obj, (struct obj *));
|
||||||
E int NDECL(encumber_msg);
|
E int NDECL(encumber_msg);
|
||||||
E int NDECL(doloot);
|
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 FDECL(loot_mon, (struct monst *,int *,boolean *));
|
||||||
E int NDECL(dotip);
|
E int NDECL(dotip);
|
||||||
E const char *FDECL(safe_qbuf, (const char *,unsigned,
|
E const char *FDECL(safe_qbuf, (const char *,unsigned,
|
||||||
|
|||||||
+1
-7
@@ -45,9 +45,6 @@ STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
|
|||||||
void FDECL( amii_speaker, ( struct obj *, char *, int ) );
|
void FDECL( amii_speaker, ( struct obj *, char *, int ) );
|
||||||
#endif
|
#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.";
|
static const char no_elbow_room[] = "don't have enough elbow-room to maneuver.";
|
||||||
|
|
||||||
#ifdef TOURIST
|
#ifdef TOURIST
|
||||||
@@ -2969,10 +2966,7 @@ doapply()
|
|||||||
case SACK:
|
case SACK:
|
||||||
case BAG_OF_HOLDING:
|
case BAG_OF_HOLDING:
|
||||||
case OILSKIN_SACK:
|
case OILSKIN_SACK:
|
||||||
res = use_container(obj, 1);
|
res = use_container(&obj, 1);
|
||||||
/* magic bag might end up being destroyed;
|
|
||||||
if so, current_container will be null */
|
|
||||||
obj = current_container;
|
|
||||||
break;
|
break;
|
||||||
case BAG_OF_TRICKS:
|
case BAG_OF_TRICKS:
|
||||||
bagotricks(obj);
|
bagotricks(obj);
|
||||||
|
|||||||
+6
-2
@@ -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. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -1422,7 +1422,11 @@ nextclass:
|
|||||||
case 'y':
|
case 'y':
|
||||||
tmp = (*fn)(otmp);
|
tmp = (*fn)(otmp);
|
||||||
if(tmp < 0) {
|
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 */
|
/* split occurred, merge again */
|
||||||
(void) merged(&otmpo, &otmp);
|
(void) merged(&otmpo, &otmp);
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-24
@@ -58,8 +58,8 @@ STATIC_DCL void FDECL(tipcontainer, (struct obj *));
|
|||||||
|
|
||||||
/* A variable set in use_container(), to be used by the callback routines */
|
/* A variable set in use_container(), to be used by the callback routines */
|
||||||
/* in_container() and out_container() from askchain() and use_container(). */
|
/* in_container() and out_container() from askchain() and use_container(). */
|
||||||
/* Also used by menu_loot(). And by doapply(apply.c). */
|
/* Also used by menu_loot() and container_gone(). */
|
||||||
struct obj *current_container;
|
static NEARDATA struct obj *current_container;
|
||||||
#define Icebox (current_container->otyp == ICE_BOX)
|
#define Icebox (current_container->otyp == ICE_BOX)
|
||||||
|
|
||||||
static const char moderateloadmsg[] = "You have a little trouble lifting";
|
static const char moderateloadmsg[] = "You have a little trouble lifting";
|
||||||
@@ -1508,7 +1508,7 @@ int x, y;
|
|||||||
int
|
int
|
||||||
doloot() /* loot a container on the floor or loot saddle from mon. */
|
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;
|
register int c = -1;
|
||||||
int timepassed = 0;
|
int timepassed = 0;
|
||||||
coord cc;
|
coord cc;
|
||||||
@@ -1567,8 +1567,9 @@ lootcont:
|
|||||||
}
|
}
|
||||||
|
|
||||||
You("carefully open %s...", the(xname(cobj)));
|
You("carefully open %s...", the(xname(cobj)));
|
||||||
timepassed |= use_container(cobj, 0);
|
timepassed |= use_container(&cobj, 0);
|
||||||
if (multi < 0) return 1; /* chest trap */
|
/* might have triggered chest trap or magic bag explosion */
|
||||||
|
if (multi < 0 || !cobj) return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (any) c = 'y';
|
if (any) c = 'y';
|
||||||
@@ -2067,12 +2068,21 @@ struct obj *box;
|
|||||||
|
|
||||||
#undef Icebox
|
#undef Icebox
|
||||||
|
|
||||||
int
|
/* used by askchain() to check for magic bag explosion */
|
||||||
use_container(obj, held)
|
boolean
|
||||||
register struct obj *obj;
|
container_gone(fn)
|
||||||
register int held;
|
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
|
#ifndef GOLDOBJ
|
||||||
struct obj *u_gold = (struct obj *)0;
|
struct obj *u_gold = (struct obj *)0;
|
||||||
#endif
|
#endif
|
||||||
@@ -2109,7 +2119,9 @@ register int held;
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
obj->lknown = 1;
|
obj->lknown = 1;
|
||||||
|
|
||||||
current_container = obj; /* for use by in/out_container */
|
current_container = obj; /* for use by in/out_container */
|
||||||
|
/* from here on out, all early returns go through containerdone */
|
||||||
|
|
||||||
if (obj->spe == 1) {
|
if (obj->spe == 1) {
|
||||||
observe_quantum_cat(obj);
|
observe_quantum_cat(obj);
|
||||||
@@ -2145,23 +2157,28 @@ register int held;
|
|||||||
if (flags.menu_style == MENU_FULL) {
|
if (flags.menu_style == MENU_FULL) {
|
||||||
int t;
|
int t;
|
||||||
char menuprompt[BUFSZ];
|
char menuprompt[BUFSZ];
|
||||||
boolean outokay = (cnt != 0);
|
boolean outokay = (cnt != 0),
|
||||||
|
inokay = (invent != 0);
|
||||||
|
|
||||||
#ifndef GOLDOBJ
|
#ifndef GOLDOBJ
|
||||||
boolean inokay = (invent != 0) || (u.ugold != 0);
|
if (u.ugold) inokay = TRUE;
|
||||||
#else
|
|
||||||
boolean inokay = (invent != 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
if (!cnt) obj->cknown = 1; /* will be giving emptymsg */
|
||||||
|
|
||||||
if (!outokay && !inokay) {
|
if (!outokay && !inokay) {
|
||||||
pline("%s", emptymsg);
|
pline("%s", emptymsg);
|
||||||
You("don't have anything to put in.");
|
You("don't have anything to put in.");
|
||||||
if (used) obj->cknown = 1;
|
goto containerdone;
|
||||||
return used;
|
|
||||||
}
|
}
|
||||||
menuprompt[0] = '\0';
|
menuprompt[0] = '\0';
|
||||||
if (!cnt) Sprintf(menuprompt, "%s ", emptymsg);
|
if (!cnt) Sprintf(menuprompt, "%s ", emptymsg);
|
||||||
Strcat(menuprompt, "Do what?");
|
Strcat(menuprompt, "Do what?");
|
||||||
t = in_or_out_menu(menuprompt, current_container, outokay, inokay);
|
t = in_or_out_menu(menuprompt, current_container,
|
||||||
if (t <= 0) return 0;
|
outokay, inokay);
|
||||||
|
if (t <= 0) {
|
||||||
|
used = 0;
|
||||||
|
goto containerdone;
|
||||||
|
}
|
||||||
loot_out = (t & 0x01) != 0;
|
loot_out = (t & 0x01) != 0;
|
||||||
loot_in = (t & 0x02) != 0;
|
loot_in = (t & 0x02) != 0;
|
||||||
} else { /* MENU_COMBINATION or MENU_PARTIAL */
|
} else { /* MENU_COMBINATION or MENU_PARTIAL */
|
||||||
@@ -2208,12 +2225,12 @@ ask_again2:
|
|||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
default:
|
default:
|
||||||
if (used) obj->cknown = 1;
|
goto containerdone;
|
||||||
return used;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pline("%s", emptymsg); /* <whatever> is empty. */
|
pline("%s", emptymsg); /* <whatever> is empty. */
|
||||||
|
obj->cknown = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef GOLDOBJ
|
#ifndef GOLDOBJ
|
||||||
@@ -2223,8 +2240,7 @@ ask_again2:
|
|||||||
#endif
|
#endif
|
||||||
/* nothing to put in, but some feedback is necessary */
|
/* nothing to put in, but some feedback is necessary */
|
||||||
You("don't have anything to put in.");
|
You("don't have anything to put in.");
|
||||||
if (used) obj->cknown = 1;
|
goto containerdone;
|
||||||
return used;
|
|
||||||
}
|
}
|
||||||
if (flags.menu_style != MENU_FULL) {
|
if (flags.menu_style != MENU_FULL) {
|
||||||
Sprintf(qbuf, "Do you wish to put %s in?", something);
|
Sprintf(qbuf, "Do you wish to put %s in?", something);
|
||||||
@@ -2244,8 +2260,7 @@ ask_again2:
|
|||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
default:
|
default:
|
||||||
if (used) obj->cknown = 1;
|
goto containerdone;
|
||||||
return used;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -2298,6 +2313,16 @@ ask_again2:
|
|||||||
dealloc_obj(u_gold);
|
dealloc_obj(u_gold);
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user