From: Pasi Kallinen Date: Fri, 17 Sep 2021 17:52:54 +0000 (+0300) Subject: Allow dropping just picked up items X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b30061b5adc6355a66b085f25ba4e36b68eccc41;p=nethack Allow dropping just picked up items When using a menu to drop or put in items into a container, allow putting in the item (or items) you picked up previously, by selecting the 'P' entry from the item class menu Inspired by the itemcat patch by Stanislav Traykov. Invalidates saves and bones. --- diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index baecd5e3f..b26f0df2b 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -729,6 +729,8 @@ drop all objects known to be uncursed. drop all objects known to be cursed. .PL DX drop all objects of unknown B/U/C status. +.PL DP +drop objects picked up last. .PL Da drop all objects, without asking for confirmation. .PL Di @@ -826,6 +828,8 @@ list all items known to be uncursed; list all items known to be cursed; .PL IX list all items whose bless/curse status is unknown; +.PL IP +list items picked up last; .PL I$ count your money. .PE diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 0818c8812..27c637bca 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -829,6 +829,7 @@ the bless\-ed/\-un\-curs\-ed/\-curs\-ed groups may be typed.\\ {\tt DU} --- drop all objects known to be uncursed.\\ {\tt DC} --- drop all objects known to be cursed.\\ {\tt DX} --- drop all objects of unknown B/U/C status.\\ +{\tt DP} --- drop objects picked up last.\\ {\tt Da} --- drop all objects, without asking for confirmation.\\ {\tt Di} --- examine your inventory before dropping anything.\\ {\tt Du} --- drop only unpaid objects (when in a shop).\\ @@ -903,6 +904,7 @@ for potions.\\ {\tt IU} --- list all items known to be uncursed;\\ {\tt IC} --- list all items known to be cursed;\\ {\tt IX} --- list all items whose bless/curse status is unknown;\\ +{\tt IP} --- list items picked up last;\\ {\tt I\$} --- count your money. %.ei %.ed diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 6c84ddbfc..a4f773b27 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1158,6 +1158,7 @@ new bigroom variant, a boulder maze vomiting on an altar provokes the deities wrath branch stairs have a different glyph, show up in yellow color in tty duration of confusion when drinking booze depends upon hunger state +using 'D' allows dropping items picked up previously Platform- and/or Interface-Specific New Features diff --git a/include/decl.h b/include/decl.h index 621057551..88eb54e3b 100644 --- a/include/decl.h +++ b/include/decl.h @@ -1094,6 +1094,8 @@ struct instance_globals { boolean class_filter; boolean bucx_filter; boolean shop_filter; + boolean picked_filter; + boolean loot_reset_justpicked; /* pline.c */ unsigned pline_flags; diff --git a/include/extern.h b/include/extern.h index 5ea0b0eb6..5e328c24b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1076,7 +1076,7 @@ extern void free_pickinv_cache(void); extern int count_unpaid(struct obj *); extern int count_buc(struct obj *, int, boolean(*)(struct obj *)); extern void tally_BUCX(struct obj *, boolean, int *, int *, int *, int *, - int *); + int *, int *); extern long count_contents(struct obj *, boolean, boolean, boolean, boolean); extern void carry_obj_effects(struct obj *); extern const char *currency(long); @@ -1950,6 +1950,9 @@ extern boolean allow_category(struct obj *); extern boolean is_worn_by_type(struct obj *); extern int ck_bag(struct obj *); extern void removed_from_icebox(struct obj *); +extern void reset_justpicked(struct obj *); +extern int count_justpicked(struct obj *); +extern struct obj *find_justpicked(struct obj *); extern int pickup(int); extern int pickup_object(struct obj *, long, boolean); extern int query_category(const char *, struct obj *, int, menu_item **, int); diff --git a/include/hack.h b/include/hack.h index aed071165..2e87e21e1 100644 --- a/include/hack.h +++ b/include/hack.h @@ -366,6 +366,7 @@ typedef struct sortloot_item Loot; #define BUC_CURSED 0x0200 #define BUC_UNCURSED 0x0400 #define BUC_UNKNOWN 0x0800 +#define JUSTPICKED 0x1000 #define BUC_ALLBKNOWN (BUC_BLESSED | BUC_CURSED | BUC_UNCURSED) #define BUCX_TYPES (BUC_ALLBKNOWN | BUC_UNKNOWN) #define ALL_TYPES_SELECTED -2 diff --git a/include/obj.h b/include/obj.h index 107931f74..cb99cfc2c 100644 --- a/include/obj.h +++ b/include/obj.h @@ -117,7 +117,8 @@ struct obj { Bitfield(cknown, 1); /* for containers (including statues): the contents * are known; also applicable to tins */ Bitfield(lknown, 1); /* locked/unlocked status is known */ - /* 4 free bits */ + Bitfield(pickup_prev, 1); /* was picked up previously */ + /* 3 free bits */ int corpsenm; /* type of corpse is mons[corpsenm] */ #define leashmon corpsenm /* gets m_id of attached pet */ diff --git a/include/patchlevel.h b/include/patchlevel.h index d00a857d8..862453b82 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -17,7 +17,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 40 +#define EDITLEVEL 41 /* * Development status possibilities. diff --git a/src/allmain.c b/src/allmain.c index 3b10ecc79..6270fada6 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -57,6 +57,7 @@ moveloop_preamble(boolean resuming) if (!resuming) { /* new game */ g.context.rndencode = rnd(9000); set_wear((struct obj *) 0); /* for side-effects of starting gear */ + reset_justpicked(g.invent); (void) pickup(1); /* autopickup at initial location */ /* only matters if someday a character is able to start with clairvoyance (wizard with cornuthaum perhaps?); without this, diff --git a/src/decl.c b/src/decl.c index e9de48cd1..a2ef2dca5 100644 --- a/src/decl.c +++ b/src/decl.c @@ -553,6 +553,8 @@ const struct instance_globals g_init = { UNDEFINED_VALUE, /* class_filter */ UNDEFINED_VALUE, /* bucx_filter */ UNDEFINED_VALUE, /* shop_filter */ + UNDEFINED_VALUE, /* picked_filter */ + UNDEFINED_VALUE, /* loot_reset_justpicked */ /* pline.c */ 0, /* pline_flags */ diff --git a/src/do.c b/src/do.c index aeba44118..0747fe098 100644 --- a/src/do.c +++ b/src/do.c @@ -12,6 +12,7 @@ static void polymorph_sink(void); static boolean teleport_sink(void); static void dosinkring(struct obj *); static int drop(struct obj *); +static int menudrop_split(struct obj *, int); static boolean engulfer_digests_food(struct obj *); static int wipeoff(void); static int menu_drop(int); @@ -825,15 +826,32 @@ doddrop(void) return result; } +static int +menudrop_split(struct obj *otmp, int cnt) +{ + if (cnt && cnt < otmp->quan) { + if (welded(otmp)) { + ; /* don't split */ + } else if (otmp->otyp == LOADSTONE && otmp->cursed) { + /* same kludge as getobj(), for canletgo()'s use */ + otmp->corpsenm = (int) cnt; /* don't split */ + } else { + otmp = splitobj(otmp, cnt); + } + } + return drop(otmp); +} + /* Drop things from the hero's inventory, using a menu. */ static int menu_drop(int retry) { int n, i, n_dropped = 0; - long cnt; struct obj *otmp, *otmp2; menu_item *pick_list; boolean all_categories = TRUE, drop_everything = FALSE, autopick = FALSE; + boolean drop_justpicked = FALSE; + long justpicked_quan = 0; if (retry) { all_categories = (retry == -2); @@ -842,7 +860,7 @@ menu_drop(int retry) n = query_category("Drop what type of items?", g.invent, (UNPAID_TYPES | ALL_TYPES | CHOOSE_ALL | BUC_BLESSED | BUC_CURSED | BUC_UNCURSED - | BUC_UNKNOWN | INCLUDE_VENOM), + | BUC_UNKNOWN | JUSTPICKED | INCLUDE_VENOM), &pick_list, PICK_ANY); if (!n) goto drop_done; @@ -851,6 +869,10 @@ menu_drop(int retry) all_categories = TRUE; } else if (pick_list[i].item.a_int == 'A') { drop_everything = autopick = TRUE; + } else if (pick_list[i].item.a_int == 'P') { + justpicked_quan = max(0, pick_list[i].count); + drop_justpicked = TRUE; + add_valid_menu_class(pick_list[i].item.a_int); } else { add_valid_menu_class(pick_list[i].item.a_int); drop_everything = FALSE; @@ -898,6 +920,11 @@ menu_drop(int retry) /* we might not have dropped everything (worn armor, welded weapon, cursed loadstones), so reset any remaining inventory to normal */ bypass_objlist(g.invent, FALSE); + } else if (drop_justpicked && count_justpicked(g.invent) == 1) { + /* drop the just picked item automatically, if only one stack */ + otmp = find_justpicked(g.invent); + if (otmp) + n_dropped += menudrop_split(otmp, justpicked_quan); } else { /* should coordinate with perm invent, maybe not show worn items */ n = query_objlist("What would you like to drop?", &g.invent, @@ -926,18 +953,7 @@ menu_drop(int retry) if (!otmp2 || !otmp2->bypass) continue; /* found next selected invent item */ - cnt = pick_list[i].count; - if (cnt < otmp->quan) { - if (welded(otmp)) { - ; /* don't split */ - } else if (otmp->otyp == LOADSTONE && otmp->cursed) { - /* same kludge as getobj(), for canletgo()'s use */ - otmp->corpsenm = (int) cnt; /* don't split */ - } else { - otmp = splitobj(otmp, cnt); - } - } - n_dropped += drop(otmp); + n_dropped += menudrop_split(otmp, pick_list[i].count); } bypass_objlist(g.invent, FALSE); /* reset g.invent to normal */ free((genericptr_t) pick_list); diff --git a/src/invent.c b/src/invent.c index afd5efe09..93e552870 100644 --- a/src/invent.c +++ b/src/invent.c @@ -719,6 +719,9 @@ merged(struct obj **potmp, struct obj **pobj) otmp = *potmp = oname(otmp, ONAME(obj)); obj_extract_self(obj); + if (obj->pickup_prev && otmp->where == OBJ_INVENT) + otmp->pickup_prev = 1; + /* really should merge the timeouts */ if (obj->lamplit) obj_merge_light_sources(obj, otmp); @@ -877,6 +880,11 @@ addinv_core0(struct obj *obj, struct obj *other_obj, obj_was_thrown = obj->was_thrown; obj->was_thrown = 0; /* not meaningful for invent */ + if (g.loot_reset_justpicked) { + g.loot_reset_justpicked = FALSE; + reset_justpicked(g.invent); + } + addinv_core1(obj); /* for addinv_before(); if something has been removed and is now being @@ -937,6 +945,7 @@ addinv_core0(struct obj *obj, struct obj *other_obj, && (throwing_weapon(obj) || is_ammo(obj))) setuqwep(obj); added: + obj->pickup_prev = 1; addinv_core2(obj); carry_obj_effects(obj); /* carrying affects the obj */ if (update_perm_invent) @@ -1164,6 +1173,7 @@ void freeinv(struct obj *obj) { extract_nobj(obj, &g.invent); + obj->pickup_prev = 0; freeinv_core(obj); update_inventory(); } @@ -1869,7 +1879,7 @@ ggetobj(const char *word, int (*fn)(OBJ_P), int mx, boolean takeoff, ident, allflag, m_seen; int itemcount; int oletct, iletct, unpaid, oc_of_sym; - char sym, *ip, olets[MAXOCLASSES + 5], ilets[MAXOCLASSES + 10]; + char sym, *ip, olets[MAXOCLASSES + 6], ilets[MAXOCLASSES + 11]; char extra_removeables[3 + 1]; /* uwep,uswapwep,uquiver */ char buf[BUFSZ] = DUMMY, qbuf[QBUFSZ]; @@ -1908,6 +1918,8 @@ ggetobj(const char *word, int (*fn)(OBJ_P), int mx, ilets[iletct++] = 'C'; if (count_buc(g.invent, BUC_UNKNOWN, ofilter)) ilets[iletct++] = 'X'; + if (count_justpicked(g.invent)) + ilets[iletct++] = 'P'; ilets[iletct++] = 'a'; } ilets[iletct++] = 'i'; @@ -1988,8 +2000,8 @@ ggetobj(const char *word, int (*fn)(OBJ_P), int mx, } else if (sym == 'u') { add_valid_menu_class('u'); ckfn = ckunpaid; - } else if (index("BUCX", sym)) { - add_valid_menu_class(sym); /* 'B','U','C',or 'X' */ + } else if (index("BUCXP", sym)) { + add_valid_menu_class(sym); /* 'B','U','C','X', or 'P' */ ckfn = ckvalidcat; } else if (sym == 'm') { m_seen = TRUE; @@ -2916,7 +2928,7 @@ count_buc(struct obj *list, int type, boolean (*filterfunc)(OBJ_P)) rather than looking for a specific type */ void tally_BUCX(struct obj *list, boolean by_nexthere, - int *bcp, int *ucp, int *ccp, int *xcp, int *ocp) + int *bcp, int *ucp, int *ccp, int *xcp, int *ocp, int *jcp) { /* Future extensions: * Skip current_container when list is invent, uchain when @@ -2937,6 +2949,8 @@ tally_BUCX(struct obj *list, boolean by_nexthere, ++(*ucp); continue; } + if (list->pickup_prev) + ++(*jcp); /* ordinary items */ if (!list->bknown) ++(*xcp); @@ -3109,6 +3123,9 @@ this_type_only(struct obj *obj) case 'X': res = !obj->bknown; break; + case 'P': + res = obj->pickup_prev; + break; default: break; /* use 'res' as-is */ } @@ -3124,7 +3141,7 @@ dotypeinv(void) int n, i = 0; char *extra_types, types[BUFSZ]; int class_count, oclass, unpaid_count, itemcount; - int bcnt, ccnt, ucnt, xcnt, ocnt; + int bcnt, ccnt, ucnt, xcnt, ocnt, jcnt; boolean billx = *u.ushops && doinvbill(0); menu_item *pick_list; boolean traditional = TRUE; @@ -3135,7 +3152,7 @@ dotypeinv(void) return 0; } unpaid_count = count_unpaid(g.invent); - tally_BUCX(g.invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt); + tally_BUCX(g.invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt, &jcnt); if (flags.menu_style != MENU_TRADITIONAL) { if (flags.menu_style == MENU_FULL @@ -3152,6 +3169,8 @@ dotypeinv(void) i |= BUC_CURSED; if (xcnt) i |= BUC_UNKNOWN; + if (jcnt) + i |= JUSTPICKED; i |= INCLUDE_VENOM; n = query_category(prompt, g.invent, i, &pick_list, PICK_ONE); if (!n) @@ -3180,6 +3199,8 @@ dotypeinv(void) types[class_count++] = 'C'; if (xcnt) types[class_count++] = 'X'; + if (jcnt) + types[class_count++] = 'P'; types[class_count] = '\0'; /* add everything not already included; user won't see these */ extra_types = eos(types); @@ -3236,7 +3257,7 @@ dotypeinv(void) return 0; } if (traditional) { - if (index("BUCX", c)) + if (index("BUCXP", c)) oclass = c; /* not a class but understood by this_type_only() */ else oclass = def_char_to_objclass(c); /* change to object class */ @@ -3260,6 +3281,9 @@ dotypeinv(void) case 'X': after = " whose blessed/uncursed/cursed status is unknown"; break; /* better phrasing is desirable */ + case 'P': + after = " you just picked up"; + break; default: /* 'c' is an object class, because we've already handled all the non-class letters which were put into 'types[]'; diff --git a/src/mkobj.c b/src/mkobj.c index 619ec33ae..1ee4d00e9 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -400,6 +400,7 @@ splitobj(struct obj *obj, long num) otmp->quan = num; otmp->owt = weight(otmp); /* -= obj->owt ? */ otmp->lua_ref_cnt = 0; + otmp->pickup_prev = 0; g.context.objsplit.parent_oid = obj->o_id; g.context.objsplit.child_oid = otmp->o_id; @@ -765,6 +766,7 @@ mksobj(int otyp, boolean init, boolean artif) unknow_object(otmp); /* set up dknown and known: non-0 for some things */ otmp->corpsenm = NON_PM; otmp->lua_ref_cnt = 0; + otmp->pickup_prev = 0; if (init) { switch (let) { diff --git a/src/pickup.c b/src/pickup.c index 49f5c3a05..efa8027ca 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -46,6 +46,7 @@ static boolean able_to_loot(int, int, boolean); static boolean reverse_loot(void); static boolean mon_beside(int, int); static int do_loot_cont(struct obj **, int, int); +static int doloot_core(void); static void tipcontainer(struct obj *); /* define for query_objlist() and autopickup() */ @@ -133,7 +134,7 @@ query_classes(char oclasses[], boolean *one_at_a_time, boolean *everything, boolean not_everything, filtered; char qbuf[QBUFSZ]; boolean m_seen; - int itemcount, bcnt, ucnt, ccnt, xcnt, ocnt; + int itemcount, bcnt, ucnt, ccnt, xcnt, ocnt, jcnt; oclasses[oclassct = 0] = '\0'; *one_at_a_time = *everything = m_seen = FALSE; @@ -159,7 +160,7 @@ query_classes(char oclasses[], boolean *one_at_a_time, boolean *everything, if (count_unpaid(objs)) ilets[iletct++] = 'u'; - tally_BUCX(objs, here, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt); + tally_BUCX(objs, here, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt, &jcnt); if (bcnt) ilets[iletct++] = 'B'; if (ucnt) @@ -168,6 +169,8 @@ query_classes(char oclasses[], boolean *one_at_a_time, boolean *everything, ilets[iletct++] = 'C'; if (xcnt) ilets[iletct++] = 'X'; + if (jcnt) + ilets[iletct++] = 'P'; ilets[iletct] = '\0'; if (iletct > 1) { @@ -203,8 +206,8 @@ query_classes(char oclasses[], boolean *one_at_a_time, boolean *everything, goto ask_again; } else if (sym == 'm') { m_seen = TRUE; - } else if (index("uBUCX", sym)) { - add_valid_menu_class(sym); /* 'u' or 'B','U','C',or 'X' */ + } else if (index("uBUCXP", sym)) { + add_valid_menu_class(sym); /* 'u' or 'B','U','C','X','P' */ filtered = TRUE; } else { oc_of_sym = def_char_to_objclass(sym); @@ -407,6 +410,7 @@ add_valid_menu_class(int c) if (c == 0) { /* reset */ vmc_count = 0; g.class_filter = g.bucx_filter = g.shop_filter = FALSE; + g.picked_filter = FALSE; } else if (!menu_class_present(c)) { g.valid_menu_classes[vmc_count++] = (char) c; /* categorize the new class */ @@ -417,6 +421,9 @@ add_valid_menu_class(int c) case 'X': g.bucx_filter = TRUE; break; + case 'P': + g.picked_filter = TRUE; + break; case 'u': g.shop_filter = TRUE; break; @@ -457,6 +464,8 @@ allow_category(struct obj *obj) ? (index(g.valid_menu_classes, COIN_CLASS) ? TRUE : FALSE) : g.shop_filter /* coins are never unpaid, but check anyway */ ? (obj->unpaid ? TRUE : FALSE) + : g.picked_filter + ? obj->pickup_prev : g.bucx_filter ? (index(g.valid_menu_classes, flags.goldX ? 'X' : 'U') ? TRUE : FALSE) @@ -500,6 +509,8 @@ allow_category(struct obj *obj) if (!index(g.valid_menu_classes, bucx)) return FALSE; } + if (g.picked_filter && !obj->pickup_prev) + return FALSE; /* obj didn't fail any of the filter checks, so accept */ return TRUE; } @@ -524,6 +535,41 @@ is_worn_by_type(struct obj *otmp) return (is_worn(otmp) && allow_category(otmp)) ? TRUE : FALSE; } +/* reset last-picked-up flags */ +void +reset_justpicked(struct obj *olist) +{ + struct obj *otmp; + + for (otmp = olist; otmp; otmp = otmp->nobj) + otmp->pickup_prev = 0; +} + +int +count_justpicked(struct obj *olist) +{ + struct obj *otmp; + int cnt = 0; + + for (otmp = olist; otmp; otmp = otmp->nobj) + if (otmp->pickup_prev) + cnt++; + + return cnt; +} + +struct obj * +find_justpicked(struct obj *olist) +{ + struct obj *otmp; + + for (otmp = olist; otmp; otmp = otmp->nobj) + if (otmp->pickup_prev) + return otmp; + + return (struct obj *) 0; +} + /* * Have the hero pick things from the ground * or a monster's inventory if swallowed. @@ -601,6 +647,7 @@ pickup(int what) /* should be a long */ nomul(0); } + reset_justpicked(g.invent); add_valid_menu_class(0); /* reset */ if (!u.uswallow) { objchain_p = &g.level.objects[u.ux][u.uy]; @@ -1083,6 +1130,7 @@ query_category(const char *qstr, /* query string */ do_buc_unknown = FALSE; int num_buc_types = 0; unsigned itemflags = MENU_ITEMFLAGS_NONE; + int num_justpicked = 0; *pick_list = (menu_item *) 0; if (!olist) @@ -1107,6 +1155,9 @@ query_category(const char *qstr, /* query string */ do_buc_unknown = TRUE; num_buc_types++; } + if (qflags & JUSTPICKED) { + num_justpicked = count_justpicked(olist); + } ccount = count_categories(olist, qflags); /* no point in actually showing a menu for a single category */ @@ -1246,6 +1297,19 @@ query_category(const char *qstr, /* query string */ add_menu(win, &nul_glyphinfo, &any, invlet, 0, ATR_NONE, "Items of unknown Bless/Curse status", itemflags); } + if (num_justpicked) { + char tmpbuf[BUFSZ]; + + if (num_justpicked == 1) + Sprintf(tmpbuf, "%s", doname(find_justpicked(olist))); + else + Sprintf(tmpbuf, "Items you just picked up"); + invlet = 'P'; + any = cg.zeroany; + any.a_int = 'P'; + add_menu(win, &nul_glyphinfo, &any, invlet, 0, ATR_NONE, + tmpbuf, itemflags); + } end_menu(win, qstr); n = select_menu(win, how, pick_list); query_done: @@ -1834,9 +1898,21 @@ do_loot_cont(struct obj **cobjp, return use_container(cobjp, 0, (boolean) (cindex < ccount)); } -/* loot a container on the floor or loot saddle from mon. */ +/* #loot extended command */ int doloot(void) +{ + int res; + + g.loot_reset_justpicked = TRUE; + res = doloot_core(); + g.loot_reset_justpicked = FALSE; + return res; +} + +/* loot a container on the floor or loot saddle from mon. */ +static int +doloot_core(void) { struct obj *cobj, *nobj; register int c = -1; @@ -2901,6 +2977,7 @@ menu_loot(int retry, boolean put_in) int n, i, n_looted = 0; boolean all_categories = TRUE, loot_everything = FALSE, autopick = FALSE; char buf[BUFSZ]; + boolean loot_justpicked = FALSE; const char *action = put_in ? "Put in" : "Take out"; struct obj *otmp, *otmp2; menu_item *pick_list; @@ -2912,7 +2989,8 @@ menu_loot(int retry, boolean put_in) } else if (flags.menu_style == MENU_FULL) { all_categories = FALSE; Sprintf(buf, "%s what type of objects?", action); - mflags = (ALL_TYPES | UNPAID_TYPES | BUCX_TYPES | CHOOSE_ALL); + mflags = (ALL_TYPES | UNPAID_TYPES | BUCX_TYPES | CHOOSE_ALL + | JUSTPICKED ); n = query_category(buf, put_in ? g.invent : g.current_container->cobj, mflags, &pick_list, PICK_ANY); if (!n) @@ -2920,6 +2998,10 @@ menu_loot(int retry, boolean put_in) for (i = 0; i < n; i++) { if (pick_list[i].item.a_int == 'A') { loot_everything = autopick = TRUE; + } else if (put_in && pick_list[i].item.a_int == 'P') { + loot_justpicked = TRUE; + count = max(0, pick_list[i].count); + add_valid_menu_class(pick_list[i].item.a_int); } else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED) { all_categories = TRUE; } else { @@ -2958,10 +3040,22 @@ menu_loot(int retry, boolean put_in) n_looted += res; } } + } else if (put_in && loot_justpicked && count_justpicked(g.invent) == 1) { + otmp = find_justpicked(g.invent); + if (otmp) { + n_looted = 1; + if (count > 0 && count < otmp->quan) { + otmp = splitobj(otmp, count); + } + (void) in_container(otmp); + /* return value doesn't matter, even if container blew up */ + } } else { mflags = INVORDER_SORT | INCLUDE_VENOM; if (put_in && flags.invlet_constant) mflags |= USE_INVLET; + if (put_in && loot_justpicked) + mflags |= JUSTPICKED; if (!put_in) g.current_container->cknown = 1; Sprintf(buf, "%s what?", action);