but then not switch back to the engulfed or underwater restricted view
#overview used hardcoded bold and inverse for highlighting; switch to the
'menu_headings' option value so player has some control
+for menustyle:full, the 'A' menu choice to auto-select everything now only
+ does so if no other choices have been picked; when any have (object
+ class or BUCX state or both), it auto-selects every item that matches
+ those choices (so still skips the second menu) rather than every item
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
long cnt;
struct obj *otmp, *otmp2;
menu_item *pick_list;
- boolean all_categories = TRUE;
- boolean drop_everything = FALSE;
+ boolean all_categories = TRUE, drop_everything = FALSE, autopick = FALSE;
if (retry) {
all_categories = (retry == -2);
if (!n)
goto drop_done;
for (i = 0; i < n; i++) {
- if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
+ if (pick_list[i].item.a_int == ALL_TYPES_SELECTED) {
all_categories = TRUE;
- else if (pick_list[i].item.a_int == 'A')
- drop_everything = TRUE;
- else
+ } else if (pick_list[i].item.a_int == 'A') {
+ drop_everything = autopick = TRUE;
+ } else {
add_valid_menu_class(pick_list[i].item.a_int);
+ drop_everything = FALSE;
+ }
}
free((genericptr_t) pick_list);
} else if (flags.menu_style == MENU_COMBINATION) {
}
}
- if (drop_everything) {
+ if (autopick) {
/*
* Dropping a burning potion of oil while levitating can cause
* an explosion which might destroy some of hero's inventory,
* Use the bypass bit to mark items already processed (hence
* not droppable) and rescan inventory until no unbypassed
* items remain.
+ *
+ * FIXME? if something explodes, or even breaks, we probably
+ * ought to halt the traversal or perhaps ask player whether
+ * to halt it.
*/
bypass_objlist(g.invent, FALSE); /* clear bypass bit for invent */
- while ((otmp = nxt_unbypassed_obj(g.invent)) != 0)
- n_dropped += drop(otmp);
+ while ((otmp = nxt_unbypassed_obj(g.invent)) != 0) {
+ if (drop_everything || all_categories || allow_category(otmp))
+ n_dropped += drop(otmp);
+ }
/* we might not have dropped everything (worn armor, welded weapon,
cursed loadstones), so reset any remaining inventory to normal */
bypass_objlist(g.invent, FALSE);
return res;
}
+/* '$'==1, 'a'-'z'==2..27, 'A'-'Z'==28..53, '#'==54, catchall 55 */
static int
invletter_value(char c)
{
return ('a' <= c && c <= 'z') ? (c - 'a' + 2)
- : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
- : (c == '$') ? 1
- : (c == '#') ? 1 + 52 + 1
- : 1 + 52 + 1 + 1; /* none of the above */
+ : ('A' <= c && c <= 'Z') ? (c - 'A' + 2 + 26)
+ : (c == '$') ? 1
+ : (c == '#') ? 1 + 52 + 1
+ : 1 + 52 + 1 + 1; /* none of the above (shouldn't happen) */
}
/* qsort comparison routine for sortloot() */
* instead of simple 'struct obj *' entries.
*/
Loot *
-sortloot(struct obj **olist, /* previous version might have changed *olist, we don't */
- unsigned mode, /* flags for sortloot_cmp() */
- boolean by_nexthere, /* T: traverse via obj->nexthere, F: via obj->nobj */
- boolean (*filterfunc)(OBJ_P))
+sortloot(
+ struct obj **olist, /* old version might have changed *olist, we don't */
+ unsigned mode, /* flags for sortloot_cmp() */
+ boolean by_nexthere, /* T: traverse via obj->nexthere, F: via obj->nobj */
+ boolean (*filterfunc)(struct obj *)) /* optional filter */
{
Loot *sliarray;
struct obj *o;
free((genericptr_t) *loot_array_p), *loot_array_p = (Loot *) 0;
}
-#if 0 /* 3.6.0 'revamp' */
+#if 0 /* 3.6.0 'revamp' -- simpler than current, but ultimately too simple */
void
-sortloot(struct obj **olist, unsigned mode, /* flags for sortloot_cmp() */
- boolean by_nexthere) /* T: traverse via obj->nexthere,
- F: via obj->nobj */
+sortloot(
+ struct obj **olist,
+ unsigned mode, /* flags for sortloot_cmp() */
+ boolean by_nexthere) /* T: traverse via obj->nexthere, F: via obj->nobj */
{
struct sortloot_item *sliarray, osli, nsli;
struct obj *o, **nxt_p;
* isn't nearly as inefficient as it may first appear.
*/
need_more_sorting = FALSE;
- for (otmp = g.invent, prev = 0; otmp;) {
+ for (otmp = g.invent, prev = 0; otmp; ) {
next = otmp->nobj;
if (next && inv_rank(next) < inv_rank(otmp)) {
need_more_sorting = TRUE;
itemflags = MENU_ITEMFLAGS_SKIPINVERT;
add_menu(win, &nul_glyphinfo, &any, invlet, 0, ATR_NONE,
(qflags & WORN_TYPES) ? "Auto-select every item being worn"
- : "Auto-select every item",
+ : "Auto-select every relevant item",
itemflags);
any = cg.zeroany;
menu_loot(int retry, boolean put_in)
{
int n, i, n_looted = 0;
- boolean all_categories = TRUE, loot_everything = FALSE;
+ boolean all_categories = TRUE, loot_everything = FALSE, autopick = FALSE;
char buf[BUFSZ];
const char *action = put_in ? "Put in" : "Take out";
struct obj *otmp, *otmp2;
if (!n)
return 0;
for (i = 0; i < n; i++) {
- if (pick_list[i].item.a_int == 'A')
- loot_everything = TRUE;
- else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
+ if (pick_list[i].item.a_int == 'A') {
+ loot_everything = autopick = TRUE;
+ } else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED) {
all_categories = TRUE;
- else
+ } else {
add_valid_menu_class(pick_list[i].item.a_int);
+ loot_everything = FALSE;
+ }
}
free((genericptr_t) pick_list);
}
- if (loot_everything) {
+ if (autopick) {
+ int (*inout_func)(struct obj *); /* in_container or out_container */
+ struct obj *firstobj;
+
if (!put_in) {
g.current_container->cknown = 1;
- for (otmp = g.current_container->cobj; otmp; otmp = otmp2) {
- otmp2 = otmp->nobj;
- res = out_container(otmp);
- if (res < 0)
- break;
- n_looted += res;
- }
+ inout_func = out_container;
+ firstobj = g.current_container->cobj;
} else {
- for (otmp = g.invent; otmp && g.current_container; otmp = otmp2) {
- otmp2 = otmp->nobj;
- res = in_container(otmp);
+ inout_func = in_container;
+ firstobj = g.invent;
+ }
+ /*
+ * Note: for put_in, current_container might be destroyed during
+ * mid-traversal by a magic bag explosion.
+ * Note too: items are processed in internal list order rather
+ * than menu display order ('sortpack') or 'sortloot' order;
+ * for put_in that should be item->invlet order so reasonable.
+ */
+ for (otmp = firstobj; otmp && g.current_container; otmp = otmp2) {
+ otmp2 = otmp->nobj;
+ if (loot_everything || all_categories || allow_category(otmp)) {
+ res = (*inout_func)(otmp);
if (res < 0)
break;
n_looted += res;