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:
nethack.rankin
2005-02-08 04:57:54 +00:00
parent 01373731e5
commit 556b64e797
4 changed files with 58 additions and 34 deletions
+2 -1
View File
@@ -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
View File
@@ -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
View 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. */ /* 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
View 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 */ /* 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;
} }