* Walk through the chain starting at objchn and ask for all objects
* with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
* whether the action in question (i.e., fn) has to be performed.
- * If allflag then no questions are asked. Mx gives the max number
- * of objects to be treated. Return the number of objects treated.
*/
int
-askchain(struct obj **objchn, /* *objchn might change */
- const char *olets, /* olets is an Obj Class char array */
- int allflag,
- int (*fn)(OBJ_P), int (*ckfn)(OBJ_P),
- int mx, const char *word)
+askchain(
+ struct obj **objchn, /* *objchn might change */
+ const char *olets, /* olets is an Obj Class char array */
+ int allflag, /* bypass prompting about individual items */
+ int (*fn)(OBJ_P), /* action to perform on selected items */
+ int (*ckfn)(OBJ_P), /* callback to decided if an item is selectable */
+ int mx, /* if non-0, maximum number of objects to process */
+ const char *word) /* name of the action */
{
struct obj *otmp, *otmpo;
char sym, ilet;
pline("No applicable objects.");
ret:
unsortloot(&sortedchn);
- bypass_objlist(*objchn, FALSE);
+ /* can't just clear bypass bit of items in objchn because the action
+ applied to selected ones might move them to a different chain */
+ /*bypass_objlist(*objchn, FALSE);*/
+ clear_bypasses();
return cnt;
}
}
int
-use_container(struct obj **objp,
- int held,
- boolean more_containers) /* True iff #loot multiple and this
- isn't last one */
+use_container(
+ struct obj **objp,
+ int held,
+ boolean more_containers) /* True iff #loot multiple and this isn't last */
{
struct obj *otmp, *obj = *objp;
boolean quantum_cat, cursed_mbag, loot_out, loot_in, loot_in_first,
} else {
c = in_or_out_menu(qbuf, g.current_container,
outmaybe, inokay,
- (boolean) (used != ECMD_OK), more_containers);
+ (boolean) (used != ECMD_OK),
+ more_containers);
}
} else { /* TRADITIONAL or COMBINATION */
xbuf[0] = '\0'; /* list of extra acceptable responses */
#include "hack.h"
static void m_lose_armor(struct monst *, struct obj *);
+static void clear_bypass(struct obj *);
static void m_dowear_type(struct monst *, long, boolean, boolean);
static int extra_pref(struct monst *, struct obj *);
newsym(mon->mx, mon->my);
}
-/* all objects with their bypass bit set should now be reset to normal */
+/* clear bypass bits for an object chain, plus contents if applicable */
+static void
+clear_bypass(struct obj *objchn)
+{
+ struct obj *o;
+
+ for (o = objchn; o; o = o->nobj) {
+ o->bypass = 0;
+ if (Has_contents(o))
+ clear_bypass(o->cobj);
+ }
+}
+
+/* all objects with their bypass bit set should now be reset to normal;
+ this can be a relatively expensive operation so is only called if
+ g.context.bypasses is set */
void
clear_bypasses(void)
{
- struct obj *otmp, *nobj;
struct monst *mtmp;
/*
* bypassed.
*/
- for (otmp = fobj; otmp; otmp = nobj) {
- nobj = otmp->nobj;
- if (otmp->bypass) {
- otmp->bypass = 0;
-
- /* bypass will have inhibited any stacking, but since it's
- * used for polymorph handling, the objects here probably
- * have been transformed and won't be stacked in the usual
- * manner afterwards; so don't bother with this.
- * [Changing the fobj chain mid-traversal would also be risky.]
- */
-#if 0
- if (objects[otmp->otyp].oc_merge) {
- xchar ox, oy;
-
- (void) get_obj_location(otmp, &ox, &oy, 0);
- stack_object(otmp);
- newsym(ox, oy);
- }
-#endif /*0*/
- }
- }
- for (otmp = g.invent; otmp; otmp = otmp->nobj)
- otmp->bypass = 0;
- for (otmp = g.migrating_objs; otmp; otmp = otmp->nobj)
- otmp->bypass = 0;
- for (otmp = g.level.buriedobjlist; otmp; otmp = otmp->nobj)
- otmp->bypass = 0;
- for (otmp = g.billobjs; otmp; otmp = otmp->nobj)
- otmp->bypass = 0;
+ clear_bypass(fobj);
+ clear_bypass(g.invent);
+ clear_bypass(g.migrating_objs);
+ clear_bypass(g.level.buriedobjlist);
+ clear_bypass(g.billobjs);
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
- for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
- otmp->bypass = 0;
+ clear_bypass(mtmp->minvent);
/* long worm created by polymorph has mon->mextra->mcorpsenm set
to PM_LONG_WORM to flag it as not being subject to further
polymorph (so polymorph zap won't hit monster to transform it
MCORPSENM(mtmp) = NON_PM;
}
for (mtmp = g.migrating_mons; mtmp; mtmp = mtmp->nmon) {
- for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
- otmp->bypass = 0;
+ clear_bypass(mtmp->minvent);
/* no MCORPSENM(mtmp)==PM_LONG_WORM check here; long worms can't
be just created by polymorph and migrating at the same time */
}
/* this is a no-op since mydogs is only non-Null during level change or
final ascension and we aren't called at those times, but be thorough */
for (mtmp = g.mydogs; mtmp; mtmp = mtmp->nmon)
- for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
- otmp->bypass = 0;
-
- /* ball can be "floating", not on any chain */
+ clear_bypass(mtmp->minvent);
+ /* ball and chain can be "floating", not on any object chain (when
+ hero is swallowed by an engulfing monster, for instance) */
if (uball)
uball->bypass = 0;
+ if (uchain)
+ uchain->bypass = 0;
- /* g.billobjs and g.mydogs chains don't matter here */
g.context.bypasses = FALSE;
}