diff --git a/dat/opthelp b/dat/opthelp index 938debeda..73945261a 100644 --- a/dat/opthelp +++ b/dat/opthelp @@ -50,6 +50,7 @@ null allow nulls to be sent to your terminal [True] delay code) if moving objects seem to teleport across rooms perm_invent keep inventory in a permanent window [False] pickup_thrown override pickup_types for thrown objects [True] +pickup_dropped evaluate pickup_types for dropped objects [True] pushweapon when wielding a new weapon, put your previously [False] wielded weapon into the secondary weapon slot quick_farsight usually skip the chance to browse the map when [False] diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index d778e72cb..16e45fa54 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -4387,6 +4387,17 @@ level (Unencumbered, Burdened, streSsed, straiNed, overTaxed, or overLoaded), you will be asked if you want to continue. (Default \(oqS\(cq). Persistent. +.lp pickup_dropped +If this option is on, items you dropped will be treated like normal items for +.op autopickup +purposes. If it is disabled, items you dropped will not be automatically +picked up, even if +.op autopickup +is on and they are in +.op pickup_types +or match a positive autopickup exception. +Default is on. +Persistent. .lp pickup_thrown If this option is on and .op autopickup diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 116ef004f..7f74e62b2 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -4809,6 +4809,15 @@ level (Unencumbered, Burdened, streSsed, straiNed, overTaxed, or overLoaded), you will be asked if you want to continue. (Default `S'). Persistent. %.lp +\item[\ib{pickup\verb+_+dropped}] +If this option is on, items you dropped will be treated like normal items for +``{\it autopickup\/}'' purposes. If it disabled, items you dropped will not be +automatically picked up, even if ``{\it autopickup\/}'' is on and they are in +``{\it pickup\verb+_+types\/}'' or +match an autopickup exception. +Default is on. +Persistent. +%.lp \item[\ib{pickup\verb+_+thrown}] If this option is on and ``{\it autopickup\/}'' is also on, try to pick up things that you threw, even if they aren't in diff --git a/include/flag.h b/include/flag.h index 19771a830..8fd5a07bb 100644 --- a/include/flag.h +++ b/include/flag.h @@ -47,6 +47,7 @@ struct flag { boolean nap; /* `timed_delay' option for display effects */ boolean null; /* OK to send nulls to the terminal */ boolean pickup; /* whether you pickup or move and look */ + boolean pickup_dropped; /* items you dropped may be autopicked */ boolean pickup_thrown; /* auto-pickup items you threw */ boolean pushweapon; /* When wielding, push old weapon into second slot */ boolean quick_farsight; /* True disables map browsing during random diff --git a/include/obj.h b/include/obj.h index 5a8de9a7a..7c430c38f 100644 --- a/include/obj.h +++ b/include/obj.h @@ -127,6 +127,7 @@ struct obj { Bitfield(greased, 1); /* covered with grease */ Bitfield(nomerge, 1); /* set temporarily to prevent merging */ Bitfield(was_thrown, 1); /* thrown by hero since last picked up */ + Bitfield(was_dropped, 1); /* dropped deliberately by the hero */ Bitfield(in_use, 1); /* for magic items before useup items */ Bitfield(bypass, 1); /* mark this as an object to be skipped by bhito() */ @@ -144,9 +145,9 @@ struct obj { Bitfield(eknown, 1); /* effect known for wands zapped or rings worn when * not seen yet after being picked up while blind * [maybe for remaining stack of used potion too] */ - /* 0 free bits */ + /* 7 free bits */ #else - /* 2 free bits */ + /* 1 free bit */ #endif int corpsenm; /* type of corpse is mons[corpsenm] */ diff --git a/include/optlist.h b/include/optlist.h index 91c0518ea..16be32b31 100644 --- a/include/optlist.h +++ b/include/optlist.h @@ -531,6 +531,9 @@ static int optfn_##a(int, int, boolean, char *, char *); NHOPTC(pickup_burden, Advanced, 20, opt_in, set_in_game, No, Yes, No, Yes, NoAlias, "maximum burden picked up before prompt") + NHOPTB(pickup_dropped, Behavior, 0, opt_out, set_in_game, + On, Yes, No, No, NoAlias, &flags.pickup_dropped, Term_False, + "consider dropped items for autopickup") NHOPTB(pickup_thrown, Behavior, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias, &flags.pickup_thrown, Term_False, "autopickup thrown items") diff --git a/src/bones.c b/src/bones.c index 0abdb4000..c6d79d830 100644 --- a/src/bones.c +++ b/src/bones.c @@ -108,6 +108,7 @@ resetobjs(struct obj *ochain, boolean restore) otmp->invlet = 0; otmp->no_charge = 0; otmp->was_thrown = 0; + otmp->was_dropped = 0; /* strip user-supplied names */ /* Statue and some corpse names are left intact, diff --git a/src/do.c b/src/do.c index f74b36b0c..86a81d8d0 100644 --- a/src/do.c +++ b/src/do.c @@ -760,6 +760,7 @@ drop(struct obj *obj) if (!IS_ALTAR(levl[u.ux][u.uy].typ) && flags.verbose) You("drop %s.", doname(obj)); } + obj->was_dropped = 1; dropx(obj); return ECMD_TIME; } diff --git a/src/invent.c b/src/invent.c index d05c93813..af0322c96 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1050,7 +1050,7 @@ addinv_core0(struct obj *obj, struct obj *other_obj, if (Has_contents(obj)) picked_container(obj); /* clear no_charge */ obj_was_thrown = obj->was_thrown; - obj->was_thrown = 0; /* not meaningful for invent */ + obj->was_thrown = obj->was_dropped = 0; /* not meaningful for invent */ if (gl.loot_reset_justpicked) { gl.loot_reset_justpicked = FALSE; diff --git a/src/options.c b/src/options.c index e8d758d95..57e32d457 100644 --- a/src/options.c +++ b/src/options.c @@ -8593,7 +8593,8 @@ doset_simple_menu(void) /* pickup_types is separated from autopickup due to the spelling of their names; emphasize what it means */ if (allopt[i].idx == opt_pickup_types - || allopt[i].idx == opt_pickup_thrown) + || allopt[i].idx == opt_pickup_thrown + || allopt[i].idx == opt_pickup_dropped) Strcat(buf, " (for autopickup)"); add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE, NO_COLOR, buf, MENU_ITEMFLAGS_NONE); diff --git a/src/pickup.c b/src/pickup.c index f1d0a733c..8a531668c 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -904,6 +904,12 @@ autopick_testobj(struct obj *otmp, boolean calc_costly) if (costly && !otmp->no_charge) return FALSE; + /* pickup_thrown/!pickup_dropped override pickup_types and exceptions */ + if (flags.pickup_thrown && otmp->was_thrown) + return TRUE; + if (!flags.pickup_dropped && otmp->was_dropped) + return FALSE; + /* check for pickup_types */ pickit = (!*otypes || strchr(otypes, otmp->oclass)); @@ -912,9 +918,6 @@ autopick_testobj(struct obj *otmp, boolean calc_costly) if (ape) pickit = ape->grab; - /* pickup_thrown overrides pickup_types and exceptions */ - if (!pickit) - pickit = (flags.pickup_thrown && otmp->was_thrown); return pickit; } @@ -3664,6 +3667,7 @@ tipcontainer(struct obj *box) /* or bag */ (void) add_to_container(targetbox, otmp); } } else if (highdrop) { + otmp->was_dropped = 1; /* might break or fall down stairs; handles altars itself */ hitfloor(otmp, TRUE); } else { @@ -3676,6 +3680,7 @@ tipcontainer(struct obj *box) /* or bag */ pline("%s%c", doname(otmp), nobj ? ',' : '.'); iflags.last_msg = PLNMSG_OBJNAM_ONLY; } + otmp->was_dropped = 1; dropy(otmp); if (iflags.last_msg != PLNMSG_OBJNAM_ONLY) terse = FALSE; /* terse formatting has been interrupted */