1 /* NetHack 3.6 pickup.c $NHDT-Date: 1445556881 2015/10/22 23:34:41 $ $NHDT-Branch: master $:$NHDT-Revision: 1.162 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
6 * Contains code for picking objects up, and container use.
11 #define CONTAINED_SYM '>' /* from invent.c */
13 STATIC_DCL void FDECL(simple_look, (struct obj *, BOOLEAN_P));
15 FDECL(query_classes, (char *, boolean *, boolean *, const char *,
16 struct obj *, BOOLEAN_P, int *));
17 STATIC_DCL boolean FDECL(fatal_corpse_mistake, (struct obj *, BOOLEAN_P));
18 STATIC_DCL void FDECL(check_here, (BOOLEAN_P));
19 STATIC_DCL boolean FDECL(n_or_more, (struct obj *));
20 STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *));
22 STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *));
24 STATIC_DCL int FDECL(autopick, (struct obj *, int, menu_item **));
25 STATIC_DCL int FDECL(count_categories, (struct obj *, int));
26 STATIC_DCL long FDECL(carry_count, (struct obj *, struct obj *, long,
27 BOOLEAN_P, int *, int *));
28 STATIC_DCL int FDECL(lift_object,
29 (struct obj *, struct obj *, long *, BOOLEAN_P));
30 STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *, int));
31 STATIC_PTR int FDECL(in_container, (struct obj *));
32 STATIC_PTR int FDECL(out_container, (struct obj *));
33 STATIC_DCL long FDECL(mbag_item_gone, (int, struct obj *));
34 STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
35 STATIC_DCL void NDECL(explain_container_prompt);
36 STATIC_DCL int FDECL(traditional_loot, (BOOLEAN_P));
37 STATIC_DCL int FDECL(menu_loot, (int, BOOLEAN_P));
38 STATIC_DCL char FDECL(in_or_out_menu, (const char *, struct obj *, BOOLEAN_P,
39 BOOLEAN_P, BOOLEAN_P));
40 STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
41 STATIC_DCL boolean FDECL(able_to_loot, (int, int, BOOLEAN_P));
42 STATIC_DCL boolean NDECL(reverse_loot);
43 STATIC_DCL boolean FDECL(mon_beside, (int, int));
44 STATIC_DCL int FDECL(do_loot_cont, (struct obj **));
45 STATIC_DCL void FDECL(tipcontainer, (struct obj *));
47 /* define for query_objlist() and autopickup() */
48 #define FOLLOW(curr, flags) \
49 (((flags) &BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
52 * How much the weight of the given container will change when the given
53 * object is removed from it. This calculation must match the one used
54 * by weight() in mkobj.c.
56 #define DELTA_CWT(cont, obj) \
57 ((cont)->cursed ? (obj)->owt * 2 : (cont)->blessed \
58 ? ((obj)->owt + 3) / 4 \
59 : ((obj)->owt + 1) / 2)
60 #define GOLD_WT(n) (((n) + 50L) / 100L)
61 /* if you can figure this out, give yourself a hearty pat on the back... */
62 #define GOLD_CAPACITY(w, n) (((w) * -100L) - ((n) + 50L) - 1L)
64 /* A variable set in use_container(), to be used by the callback routines */
65 /* in_container() and out_container() from askchain() and use_container(). */
66 /* Also used by menu_loot() and container_gone(). */
67 static NEARDATA struct obj *current_container;
68 #define Icebox (current_container->otyp == ICE_BOX)
70 static const char moderateloadmsg[] = "You have a little trouble lifting";
71 static const char nearloadmsg[] = "You have much trouble lifting";
72 static const char overloadmsg[] = "You have extreme difficulty lifting";
74 /* BUG: this lets you look at cockatrice corpses while blind without
76 /* much simpler version of the look-here code; used by query_classes() */
78 simple_look(otmp, here)
79 struct obj *otmp; /* list of objects */
80 boolean here; /* flag for type of obj list linkage */
82 /* Neither of the first two cases is expected to happen, since
83 * we're only called after multiple classes of objects have been
84 * detected, hence multiple objects must be present.
87 impossible("simple_look(null)");
88 } else if (!(here ? otmp->nexthere : otmp->nobj)) {
91 winid tmpwin = create_nhwindow(NHW_MENU);
92 putstr(tmpwin, 0, "");
94 putstr(tmpwin, 0, doname(otmp));
95 otmp = here ? otmp->nexthere : otmp->nobj;
97 display_nhwindow(tmpwin, TRUE);
98 destroy_nhwindow(tmpwin);
103 collect_obj_classes(ilets, otmp, here, filter, itemcount)
105 register struct obj *otmp;
107 boolean FDECL((*filter), (OBJ_P));
110 register int iletct = 0;
114 ilets[iletct] = '\0'; /* terminate ilets so that index() will work */
116 c = def_oc_syms[(int) otmp->oclass].sym;
117 if (!index(ilets, c) && (!filter || (*filter)(otmp)))
118 ilets[iletct++] = c, ilets[iletct] = '\0';
120 otmp = here ? otmp->nexthere : otmp->nobj;
127 * Suppose some '?' and '!' objects are present, but '/' objects aren't:
128 * "a" picks all items without further prompting;
129 * "A" steps through all items, asking one by one;
130 * "?" steps through '?' items, asking, and ignores '!' ones;
131 * "/" becomes 'A', since no '/' present;
132 * "?a" or "a?" picks all '?' without further prompting;
133 * "/a" or "a/" becomes 'A' since there aren't any '/'
134 * (bug fix: 3.1.0 thru 3.1.3 treated it as "a");
135 * "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
136 * (ie, treated as if it had just been "?a").
139 query_classes(oclasses, one_at_a_time, everything, action, objs, here,
142 boolean *one_at_a_time, *everything;
148 char ilets[30], inbuf[BUFSZ]; /* FIXME: hardcoded ilets[] length */
149 int iletct, oclassct;
150 boolean not_everything;
155 oclasses[oclassct = 0] = '\0';
156 *one_at_a_time = *everything = m_seen = FALSE;
157 iletct = collect_obj_classes(ilets, objs, here,
158 (boolean FDECL((*), (OBJ_P))) 0, &itemcount);
161 } else if (iletct == 1) {
162 oclasses[0] = def_char_to_objclass(ilets[0]);
164 if (itemcount && menu_on_demand) {
165 ilets[iletct++] = 'm';
167 ilets[iletct] = '\0';
169 } else { /* more than one choice available */
170 const char *where = 0;
171 register char sym, oc_of_sym, *p;
172 /* additional choices */
173 ilets[iletct++] = ' ';
174 ilets[iletct++] = 'a';
175 ilets[iletct++] = 'A';
176 ilets[iletct++] = (objs == invent ? 'i' : ':');
177 if (menu_on_demand) {
178 ilets[iletct++] = 'm';
181 ilets[iletct] = '\0';
183 oclasses[oclassct = 0] = '\0';
184 *one_at_a_time = *everything = FALSE;
185 not_everything = FALSE;
186 Sprintf(qbuf, "What kinds of thing do you want to %s? [%s]", action,
189 if (*inbuf == '\033')
192 for (p = inbuf; (sym = *p++);) {
193 /* new A function (selective all) added by GAN 01/09/87 */
197 *one_at_a_time = TRUE;
200 else if (sym == ':') {
201 simple_look(objs, here); /* dumb if objs==invent */
202 /* if we just scanned the contents of a container
203 then mark it as having known contents */
204 if (objs->where == OBJ_CONTAINED)
205 objs->ocontainer->cknown = 1;
207 } else if (sym == 'i') {
208 (void) display_inventory((char *) 0, TRUE);
210 } else if (sym == 'm') {
213 oc_of_sym = def_char_to_objclass(sym);
214 if (index(ilets, sym)) {
215 add_valid_menu_class(oc_of_sym);
216 oclasses[oclassct++] = oc_of_sym;
217 oclasses[oclassct] = '\0';
221 !strcmp(action, "pick up")
223 : !strcmp(action, "take out") ? "inside" : "";
225 There("are no %c's %s.", sym, where);
227 You("have no %c's.", sym);
228 not_everything = TRUE;
232 if (m_seen && menu_on_demand) {
233 *menu_on_demand = (*everything || !oclassct) ? -2 : -3;
236 if (!oclassct && (!*everything || not_everything)) {
237 /* didn't pick anything,
238 or tried to pick something that's not present */
239 *one_at_a_time = TRUE; /* force 'A' */
240 *everything = FALSE; /* inhibit 'a' */
246 /* check whether hero is bare-handedly touching a cockatrice corpse */
248 fatal_corpse_mistake(obj, remotely)
252 if (uarmg || remotely || obj->otyp != CORPSE
253 || !touch_petrifies(&mons[obj->corpsenm]) || Stone_resistance)
256 if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) {
257 display_nhwindow(WIN_MESSAGE, FALSE); /* --More-- */
261 pline("Touching %s is a fatal mistake.",
262 corpse_xname(obj, (const char *) 0, CXN_SINGULAR | CXN_ARTICLE));
263 instapetrify(killer_xname(obj));
267 /* attempting to manipulate a Rider's corpse triggers its revival */
269 rider_corpse_revival(obj, remotely)
273 if (!obj || obj->otyp != CORPSE || !is_rider(&mons[obj->corpsenm]))
276 pline("At your %s, the corpse suddenly moves...",
277 remotely ? "attempted acquisition" : "touch");
278 (void) revive_corpse(obj);
279 exercise(A_WIS, FALSE);
283 /* look at the objects at our location, unless there are too many of them */
285 check_here(picked_some)
288 register struct obj *obj;
291 /* count the objects here */
292 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) {
297 /* If there are objects here, take a look. */
302 (void) look_here(ct, picked_some);
304 read_engr_at(u.ux, u.uy);
308 /* Value set by query_objlist() for n_or_more(). */
309 static long val_for_n_or_more;
311 /* query_objlist callback: return TRUE if obj's count is >= reference value */
318 return (boolean) (obj->quan >= val_for_n_or_more);
321 /* list of valid menu classes for query_objlist() and allow_category callback
322 (with room for all object classes, 'u'npaid, BUCX, and terminator) */
323 static char valid_menu_classes[MAXOCLASSES + 1 + 4 + 1];
324 static boolean class_filter, bucx_filter, shop_filter;
327 add_valid_menu_class(c)
330 static int vmc_count = 0;
332 if (c == 0) { /* reset */
334 class_filter = bucx_filter = shop_filter = FALSE;
336 valid_menu_classes[vmc_count++] = (char) c;
337 /* categorize the new class */
341 case 'C': /*FALLTHRU*/
353 valid_menu_classes[vmc_count] = '\0';
356 /* query_objlist callback: return TRUE if not uchain */
361 return (boolean) (obj != uchain);
364 /* query_objlist callback: return TRUE */
368 struct obj *obj UNUSED;
377 /* unpaid and BUC checks don't apply to coins */
378 if (obj->oclass == COIN_CLASS)
379 return index(valid_menu_classes, COIN_CLASS) ? TRUE : FALSE;
381 if (Role_if(PM_PRIEST))
384 * There are three types of filters possible and the first and
385 * third can have more than one entry:
386 * 1) object class (armor, potion, &c);
387 * 2) unpaid shop item;
388 * 3) bless/curse state (blessed, uncursed, cursed, BUC-unknown).
389 * When only one type is present, the situation is simple:
390 * to be accepted, obj's status must match one of the entries.
391 * When more than one type is present, the obj will now only
392 * be accepted when it matches one entry of each type.
393 * So ?!B will accept blessed scrolls or potions, and [u will
394 * accept unpaid armor. (In 3.4.3, an object was accepted by
395 * this filter if it met any entry of any type, so ?!B resulted
396 * in accepting all scrolls and potions regardless of bless/curse
397 * state plus all blessed non-scroll, non-potion objects.)
399 /* if class is expected but obj's class is not in the list, reject */
400 if (class_filter && !index(valid_menu_classes, obj->oclass))
402 /* if unpaid is expected and obj isn't unpaid, reject (treat a container
403 holding any unpaid object as unpaid even if isn't unpaid itself) */
404 if (shop_filter && !obj->unpaid
405 && !(Has_contents(obj) && count_unpaid(obj->cobj) > 0))
407 /* check for particular bless/curse state */
409 /* first categorize this object's bless/curse state */
411 !obj->bknown ? 'X' : obj->blessed ? 'B' : obj->cursed ? 'C' : 'U';
413 /* if its category is not in the list, reject */
414 if (!index(valid_menu_classes, bucx))
417 /* obj didn't fail any of the filter checks, so accept */
422 /* query_objlist callback: return TRUE if valid category (class), no uchain */
424 allow_cat_no_uchain(obj)
428 && ((index(valid_menu_classes,'u') && obj->unpaid)
429 || index(valid_menu_classes, obj->oclass)))
436 /* query_objlist callback: return TRUE if valid class and worn */
438 is_worn_by_type(otmp)
439 register struct obj *otmp;
441 return (boolean) (!!(otmp->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON))
442 && index(valid_menu_classes, otmp->oclass) != 0);
446 * Have the hero pick things from the ground
447 * or a monster's inventory if swallowed.
452 * <0 pickup count of something
454 * Returns 1 if tried to pick something up, whether
455 * or not it succeeded.
459 int what; /* should be a long */
461 int i, n, res, count, n_tried = 0, n_picked = 0;
462 menu_item *pick_list = (menu_item *) 0;
463 boolean autopickup = what > 0;
464 struct obj *objchain;
467 /* we might have arrived here while fainted or sleeping, via
468 random teleport or levitation timeout; if so, skip check_here
469 and read_engr_at in addition to bypassing autopickup itself
470 [probably ought to check whether hero is using a cockatrice
471 corpse for a pillow here... (also at initial faint/sleep)] */
472 if (autopickup && multi < 0 && unconscious())
475 if (what < 0) /* pick N of something */
477 else /* pick anything */
481 struct trap *ttmp = t_at(u.ux, u.uy);
482 /* no auto-pick if no-pick move, nothing there, or in a pool */
483 if (autopickup && (context.nopick || !OBJ_AT(u.ux, u.uy)
484 || (is_pool(u.ux, u.uy) && !Underwater)
485 || is_lava(u.ux, u.uy))) {
486 read_engr_at(u.ux, u.uy);
490 /* no pickup if levitating & not on air or water level */
491 if (!can_reach_floor(TRUE)) {
492 if ((multi && !context.run) || (autopickup && !flags.pickup)
493 || (ttmp && uteetering_at_seen_pit(ttmp)))
494 read_engr_at(u.ux, u.uy);
497 /* multi && !context.run means they are in the middle of some other
498 * action, or possibly paralyzed, sleeping, etc.... and they just
499 * teleported onto the object. They shouldn't pick it up.
501 if ((multi && !context.run) || (autopickup && !flags.pickup)) {
505 if (notake(youmonst.data)) {
507 You("are physically incapable of picking anything up.");
513 /* if there's anything here, stop running */
514 if (OBJ_AT(u.ux, u.uy) && context.run && context.run != 8
519 add_valid_menu_class(0); /* reset */
521 objchain = level.objects[u.ux][u.uy];
522 traverse_how = BY_NEXTHERE;
524 objchain = u.ustuck->minvent;
525 traverse_how = 0; /* nobj */
528 * Start the actual pickup process. This is split into two main
529 * sections, the newer menu and the older "traditional" methods.
530 * Automatic pickup has been split into its own menu-style routine
531 * to make things less confusing.
534 n = autopick(objchain, traverse_how, &pick_list);
538 if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
539 /* use menus exclusively */
540 if (count) { /* looking for N of something */
542 Sprintf(buf, "Pick %d of what?", count);
543 val_for_n_or_more = count; /* set up callback selector */
544 n = query_objlist(buf, objchain, traverse_how | AUTOSELECT_SINGLE
546 &pick_list, PICK_ONE, n_or_more);
547 /* correct counts, if any given */
548 for (i = 0; i < n; i++)
549 pick_list[i].count = count;
551 n = query_objlist("Pick up what?", objchain,
552 traverse_how | AUTOSELECT_SINGLE | INVORDER_SORT
554 &pick_list, PICK_ANY, all_but_uchain);
558 for (n_picked = i = 0; i < n; i++) {
559 res = pickup_object(pick_list[i].item.a_obj, pick_list[i].count,
562 break; /* can't continue */
566 free((genericptr_t) pick_list);
569 /* old style interface */
572 boolean all_of_a_type, selective;
573 char oclasses[MAXOCLASSES];
574 struct obj *obj, *obj2;
576 oclasses[0] = '\0'; /* types to consider (empty for all) */
577 all_of_a_type = TRUE; /* take all of considered types */
578 selective = FALSE; /* ask for each item */
580 /* check for more than one object */
581 for (obj = objchain; obj;
582 obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj)
585 if (ct == 1 && count) {
586 /* if only one thing, then pick it */
588 lcount = min(obj->quan, (long) count);
590 if (pickup_object(obj, lcount, FALSE) > 0)
591 n_picked++; /* picked something */
594 } else if (ct >= 2) {
597 There("are %s objects here.", (ct <= 10) ? "several" : "many");
598 if (!query_classes(oclasses, &selective, &all_of_a_type,
600 traverse_how == BY_NEXTHERE, &via_menu)) {
604 "Pick up what?", objchain,
605 traverse_how | (selective ? 0 : INVORDER_SORT),
606 &pick_list, PICK_ANY,
607 via_menu == -2 ? allow_all : allow_category);
612 for (obj = objchain; obj; obj = obj2) {
613 if (traverse_how == BY_NEXTHERE)
614 obj2 = obj->nexthere; /* perhaps obj will be picked up */
619 if (!selective && oclasses[0] && !index(oclasses, obj->oclass))
622 if (!all_of_a_type) {
625 (void) safe_qbuf(qbuf, "Pick up ", "?", obj, doname,
626 ansimpleoname, something);
627 switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
629 goto end_query; /* out 2 levels */
633 all_of_a_type = TRUE;
636 oclasses[0] = obj->oclass;
640 case '#': /* count was entered */
642 continue; /* 0 count => No */
643 lcount = (long) yn_number;
644 if (lcount > obj->quan)
655 if ((res = pickup_object(obj, lcount, FALSE)) < 0)
660 ; /* semicolon needed by brain-damaged compilers */
664 if (hides_under(youmonst.data))
665 (void) hideunder(&youmonst);
667 /* position may need updating (invisible hero) */
671 /* check if there's anything else here after auto-pickup is done */
673 check_here(n_picked > 0);
675 return (n_tried > 0);
679 is_autopickup_exception(obj, grab)
681 boolean grab; /* forced pickup, rather than forced leave behind? */
684 * Does the text description of this match an exception?
686 char *objdesc = makesingular(doname(obj));
687 struct autopickup_exception *ape =
688 (grab) ? iflags.autopickup_exceptions[AP_GRAB]
689 : iflags.autopickup_exceptions[AP_LEAVE];
691 if (regex_match(objdesc, ape->regex))
699 * Pick from the given list using flags.pickup_types. Return the number
700 * of items picked (not counts). Create an array that returns pointers
701 * and counts of the items to be picked up. If the number of items
702 * picked is zero, the pickup list is left alone. The caller of this
703 * function must free the pickup list.
706 autopick(olist, follow, pick_list)
707 struct obj *olist; /* the object list */
708 int follow; /* how to follow the object list */
709 menu_item **pick_list; /* list of objects and counts to pick up */
711 menu_item *pi; /* pick item */
715 const char *otypes = flags.pickup_types;
717 /* first count the number of eligible items */
718 for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) {
719 pickit = (!*otypes || index(otypes, curr->oclass));
720 /* check for "always pick up */
722 pickit = is_autopickup_exception(curr, TRUE);
723 /* then for "never pick up */
725 pickit = !is_autopickup_exception(curr, FALSE);
726 /* pickup_thrown overrides pickup_types and exceptions */
728 pickit = (flags.pickup_thrown && curr->was_thrown);
729 /* finally, do we count this object? */
735 *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n);
736 for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) {
737 pickit = (!*otypes || index(otypes, curr->oclass));
739 pickit = is_autopickup_exception(curr, TRUE);
741 pickit = !is_autopickup_exception(curr, FALSE);
743 pickit = (flags.pickup_thrown && curr->was_thrown);
745 pi[n].item.a_obj = curr;
746 pi[n].count = curr->quan;
755 * Put up a menu using the given object list. Only those objects on the
756 * list that meet the approval of the allow function are displayed. Return
757 * a count of the number of items selected, as well as an allocated array of
758 * menu_items, containing pointers to the objects selected and counts. The
759 * returned counts are guaranteed to be in bounds and non-zero.
762 * BY_NEXTHERE - Follow object list via nexthere instead of nobj.
763 * AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
765 * USE_INVLET - Use object's invlet.
766 * INVORDER_SORT - Use hero's pack order.
767 * INCLUDE_HERO - Showing engulfer's invent; show hero too.
768 * SIGNAL_NOMENU - Return -1 rather than 0 if nothing passes "allow".
769 * SIGNAL_ESCAPE - Return -1 rather than 0 if player uses ESC to
773 query_objlist(qstr, olist, qflags, pick_list, how, allow)
774 const char *qstr; /* query string */
775 struct obj *olist; /* the list to pick from */
776 int qflags; /* options to control the query */
777 menu_item **pick_list; /* return list of items picked */
778 int how; /* type of query */
779 boolean FDECL((*allow), (OBJ_P)); /* allow function */
783 struct obj *curr, *last, fake_hero_object;
787 boolean printed_type_name, sorted = (qflags & INVORDER_SORT) != 0,
788 engulfer = (qflags & INCLUDE_HERO) != 0;
790 *pick_list = (menu_item *) 0;
791 if (!olist && !engulfer)
794 /* count the number of items allowed */
795 for (n = 0, last = 0, curr = olist; curr; curr = FOLLOW(curr, qflags))
796 if ((*allow)(curr)) {
803 /* don't autoselect swallowed hero if it's the only choice */
804 qflags &= ~AUTOSELECT_SINGLE;
807 if (n == 0) /* nothing to pick here */
808 return (qflags & SIGNAL_NOMENU) ? -1 : 0;
810 if (n == 1 && (qflags & AUTOSELECT_SINGLE)) {
811 *pick_list = (menu_item *) alloc(sizeof(menu_item));
812 (*pick_list)->item.a_obj = last;
813 (*pick_list)->count = last->quan;
817 oarray = objarr_init(actualn);
818 /* Add objects to the array */
820 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
821 if ((*allow)(curr)) {
822 objarr_set(curr, i++, oarray, (flags.sortloot == 'f'
823 || (flags.sortloot == 'l'
824 && !(qflags & USE_INVLET))));
828 win = create_nhwindow(NHW_MENU);
833 * Run through the list and add the objects to the menu. If
834 * INVORDER_SORT is set, we'll run through the list once for
835 * each type so we can group them. The allow function will only
836 * be called once per object in the list.
838 pack = flags.inv_order;
840 printed_type_name = FALSE;
841 for (i = 0; i < actualn; i++) {
843 if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE
844 && will_feel_cockatrice(curr, FALSE)) {
845 destroy_nhwindow(win); /* stop the menu and revert */
846 (void) look_here(0, FALSE);
849 if ((!sorted || curr->oclass == *pack) && (*allow)(curr)) {
850 /* if sorting, print type name (once only) */
851 if (sorted && !printed_type_name) {
853 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
854 let_to_name(*pack, FALSE,
856 && iflags.menu_head_objsym),
858 printed_type_name = TRUE;
862 add_menu(win, obj_to_glyph(curr), &any,
863 (qflags & USE_INVLET) ? curr->invlet : 0,
864 def_oc_syms[(int) objects[curr->otyp].oc_class].sym,
865 ATR_NONE, doname_with_price(curr), MENU_UNSELECTED);
869 } while (sorted && *pack);
876 if (sorted && n > 1) {
877 Sprintf(buf, "%s Creatures",
878 is_animal(u.ustuck->data) ? "Swallowed" : "Engulfed");
879 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf,
882 fake_hero_object = zeroobj;
883 fake_hero_object.quan = 1L; /* not strictly necessary... */
884 any.a_obj = &fake_hero_object;
885 add_menu(win, mon_to_glyph(&youmonst), &any,
886 /* fake inventory letter, no group accelerator */
887 CONTAINED_SYM, 0, ATR_NONE, an(self_lookat(buf)),
892 n = select_menu(win, how, pick_list);
893 destroy_nhwindow(win);
899 /* fix up counts: -1 means no count used => pick all;
900 if fake_hero_object was picked, discard that choice */
901 for (i = k = 0, mi = *pick_list; i < n; i++, mi++) {
902 if (mi->item.a_obj == &fake_hero_object)
904 if (mi->count == -1L || mi->count > mi->item.a_obj->quan)
905 mi->count = mi->item.a_obj->quan;
907 (*pick_list)[k] = *mi;
911 /* fake_hero was only choice so discard whole list */
912 free((genericptr_t) *pick_list);
916 /* other stuff plus fake_hero; last slot is now unused */
917 (*pick_list)[k].item = zeroany;
918 (*pick_list)[k].count = 0L;
922 /* -1 is used for SIGNAL_NOMENU, so callers don't expect it
923 to indicate that the player declined to make a choice */
924 n = (qflags & SIGNAL_ESCAPE) ? -2 : 0;
930 * allow menu-based category (class) selection (for Drop,take off etc.)
934 query_category(qstr, olist, qflags, pick_list, how)
935 const char *qstr; /* query string */
936 struct obj *olist; /* the list to pick from */
937 int qflags; /* behaviour modification flags */
938 menu_item **pick_list; /* return list of items picked */
939 int how; /* type of query */
946 boolean collected_type_name;
949 boolean do_unpaid = FALSE;
950 boolean do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE,
951 do_buc_unknown = FALSE;
952 int num_buc_types = 0;
954 *pick_list = (menu_item *) 0;
957 if ((qflags & UNPAID_TYPES) && count_unpaid(olist))
959 if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED)) {
963 if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) {
967 if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) {
971 if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) {
972 do_buc_unknown = TRUE;
976 ccount = count_categories(olist, qflags);
977 /* no point in actually showing a menu for a single category */
978 if (ccount == 1 && !do_unpaid && num_buc_types <= 1
979 && !(qflags & BILLED_TYPES)) {
980 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
981 if ((qflags & WORN_TYPES)
982 && !(curr->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON)))
987 *pick_list = (menu_item *) alloc(sizeof(menu_item));
988 (*pick_list)->item.a_int = curr->oclass;
991 debugpline0("query_category: no single object match");
996 win = create_nhwindow(NHW_MENU);
998 pack = flags.inv_order;
999 if ((qflags & ALL_TYPES) && (ccount > 1)) {
1002 any.a_int = ALL_TYPES_SELECTED;
1003 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
1004 (qflags & WORN_TYPES) ? "All worn types" : "All types",
1010 collected_type_name = FALSE;
1011 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
1012 if (curr->oclass == *pack) {
1013 if ((qflags & WORN_TYPES)
1014 && !(curr->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON)))
1016 if (!collected_type_name) {
1018 any.a_int = curr->oclass;
1020 win, NO_GLYPH, &any, invlet++,
1021 def_oc_syms[(int) objects[curr->otyp].oc_class].sym,
1022 ATR_NONE, let_to_name(*pack, FALSE,
1024 && iflags.menu_head_objsym),
1026 collected_type_name = TRUE;
1031 if (invlet >= 'u') {
1032 impossible("query_category: too many categories");
1036 /* unpaid items if there are any */
1041 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, "Unpaid items",
1044 /* billed items: checked by caller, so always include if BILLED_TYPES */
1045 if (qflags & BILLED_TYPES) {
1049 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
1050 "Unpaid items already used up", MENU_UNSELECTED);
1052 if (qflags & CHOOSE_ALL) {
1056 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
1057 (qflags & WORN_TYPES) ? "Auto-select every item being worn"
1058 : "Auto-select every item",
1061 /* items with b/u/c/unknown if there are any */
1066 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
1067 "Items known to be Blessed", MENU_UNSELECTED);
1073 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
1074 "Items known to be Cursed", MENU_UNSELECTED);
1080 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
1081 "Items known to be Uncursed", MENU_UNSELECTED);
1083 if (do_buc_unknown) {
1087 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
1088 "Items of unknown B/C/U status", MENU_UNSELECTED);
1090 end_menu(win, qstr);
1091 n = select_menu(win, how, pick_list);
1092 destroy_nhwindow(win);
1094 n = 0; /* caller's don't expect -1 */
1099 count_categories(olist, qflags)
1104 boolean counted_category;
1108 pack = flags.inv_order;
1110 counted_category = FALSE;
1111 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
1112 if (curr->oclass == *pack) {
1113 if ((qflags & WORN_TYPES)
1114 && !(curr->owornmask & (W_ARMOR | W_ACCESSORY | W_WEAPON)))
1116 if (!counted_category) {
1118 counted_category = TRUE;
1127 /* could we carry `obj'? if not, could we carry some of it/them? */
1129 carry_count(obj, container, count, telekinesis, wt_before, wt_after)
1130 struct obj *obj, *container; /* object to pick up, bag it's coming out of */
1132 boolean telekinesis;
1133 int *wt_before, *wt_after;
1135 boolean adjust_wt = container && carried(container),
1136 is_gold = obj->oclass == COIN_CLASS;
1137 int wt, iw, ow, oow;
1138 long qq, savequan, umoney;
1140 const char *verb, *prefx1, *prefx2, *suffx;
1141 char obj_nambuf[BUFSZ], where[BUFSZ];
1143 savequan = obj->quan;
1145 umoney = money_cnt(invent);
1146 iw = max_capacity();
1148 if (count != savequan) {
1150 obj->owt = (unsigned) weight(obj);
1152 wt = iw + (int) obj->owt;
1154 wt -= (container->otyp == BAG_OF_HOLDING)
1155 ? (int) DELTA_CWT(container, obj)
1157 /* This will go with silver+copper & new gold weight */
1158 if (is_gold) /* merged gold might affect cumulative weight */
1159 wt -= (GOLD_WT(umoney) + GOLD_WT(count) - GOLD_WT(umoney + count));
1160 if (count != savequan) {
1161 obj->quan = savequan;
1170 /* see how many we can lift */
1172 iw -= (int) GOLD_WT(umoney);
1174 qq = GOLD_CAPACITY((long) iw, umoney);
1177 qq = 50L - (umoney % 100L) - 1L;
1180 for (; qq <= count; qq += 100L) {
1182 obj->owt = (unsigned) GOLD_WT(qq);
1183 ow = (int) GOLD_WT(umoney + qq);
1184 ow -= (container->otyp == BAG_OF_HOLDING)
1185 ? (int) DELTA_CWT(container, obj)
1196 else if (qq > count)
1198 wt = iw + (int) GOLD_WT(umoney + qq);
1199 } else if (count > 1 || count < obj->quan) {
1201 * Ugh. Calc num to lift by changing the quan of of the
1202 * object and calling weight.
1204 * This works for containers only because containers
1205 * don't merge. -dean
1207 for (qq = 1L; qq <= count; qq++) {
1209 obj->owt = (unsigned) (ow = weight(obj));
1211 ow -= (container->otyp == BAG_OF_HOLDING)
1212 ? (int) DELTA_CWT(container, obj)
1220 /* there's only one, and we can't lift it */
1223 obj->quan = savequan;
1227 /* some message will be given */
1228 Strcpy(obj_nambuf, doname(obj));
1230 Sprintf(where, "in %s", the(xname(container)));
1233 Strcpy(where, "lying here");
1234 verb = telekinesis ? "acquire" : "lift";
1237 /* lint suppression */
1238 *obj_nambuf = *where = '\0';
1241 /* we can carry qq of them */
1244 You("can only %s %s of the %s %s.", verb,
1245 (qq == 1L) ? "one" : "some", obj_nambuf, where);
1251 Strcpy(where, "here"); /* slightly shorter form */
1252 if (invent || umoney) {
1253 prefx1 = "you cannot ";
1255 suffx = " any more";
1257 prefx1 = (obj->quan == 1L) ? "it " : "even one ";
1258 prefx2 = "is too heavy for you to ";
1261 There("%s %s %s, but %s%s%s%s.", otense(obj, "are"), obj_nambuf, where,
1262 prefx1, prefx2, verb, suffx);
1264 /* *wt_after = iw; */
1268 /* determine whether character is able and player is willing to carry `obj' */
1271 lift_object(obj, container, cnt_p, telekinesis)
1272 struct obj *obj, *container; /* object to pick up, bag it's coming out of */
1274 boolean telekinesis;
1276 int result, old_wt, new_wt, prev_encumbr, next_encumbr;
1278 if (obj->otyp == BOULDER && Sokoban) {
1279 You("cannot get your %s around this %s.", body_part(HAND),
1283 /* override weight consideration for loadstone picked up by anybody
1284 and for boulder picked up by hero poly'd into a giant; override
1285 availability of open inventory slot iff not already carrying one */
1286 if (obj->otyp == LOADSTONE
1287 || (obj->otyp == BOULDER && throws_rocks(youmonst.data))) {
1288 if (inv_cnt(FALSE) < 52 || !carrying(obj->otyp)
1289 || merge_choice(invent, obj))
1290 return 1; /* lift regardless of current situation */
1291 /* if we reach here, we're out of slots and already have at least
1292 one of these, so treat this one more like a normal item */
1293 You("are carrying too much stuff to pick up %s %s.",
1294 (obj->quan == 1L) ? "another" : "more", simpleonames(obj));
1299 carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt);
1301 result = -1; /* nothing lifted */
1302 } else if (obj->oclass != COIN_CLASS
1303 /* [exception for gold coins will have to change
1304 if silver/copper ones ever get implemented] */
1305 && inv_cnt(FALSE) >= 52 && !merge_choice(invent, obj)) {
1306 Your("knapsack cannot accommodate any more items.");
1307 result = -1; /* nothing lifted */
1310 prev_encumbr = near_capacity();
1311 if (prev_encumbr < flags.pickup_burden)
1312 prev_encumbr = flags.pickup_burden;
1313 next_encumbr = calc_capacity(new_wt - old_wt);
1314 if (next_encumbr > prev_encumbr) {
1316 result = 0; /* don't lift */
1319 long savequan = obj->quan;
1322 Strcpy(qbuf, (next_encumbr > HVY_ENCUMBER)
1324 : (next_encumbr > MOD_ENCUMBER)
1328 (void) strsubst(qbuf, "lifting", "removing");
1330 (void) safe_qbuf(qbuf, qbuf, ". Continue?", obj, doname,
1331 ansimpleoname, something);
1332 obj->quan = savequan;
1333 switch (ynq(qbuf)) {
1341 break; /* 'y' => result == 1 */
1343 clear_nhwindow(WIN_MESSAGE);
1348 if (obj->otyp == SCR_SCARE_MONSTER && result <= 0 && !container)
1354 * Pick up <count> of obj from the ground and add it to the hero's inventory.
1355 * Returns -1 if caller should break out of its loop, 0 if nothing picked
1356 * up, 1 if otherwise.
1359 pickup_object(obj, count, telekinesis)
1362 boolean telekinesis; /* not picking it up directly by hand */
1366 if (obj->quan < count) {
1367 impossible("pickup_object: count %ld > quan %ld?", count, obj->quan);
1371 /* In case of auto-pickup, where we haven't had a chance
1372 to look at it yet; affects docall(SCR_SCARE_MONSTER). */
1376 if (obj == uchain) { /* do not pick up attached chain */
1378 } else if (obj->oartifact && !touch_artifact(obj, &youmonst)) {
1380 } else if (obj->otyp == CORPSE) {
1381 if (fatal_corpse_mistake(obj, telekinesis)
1382 || rider_corpse_revival(obj, telekinesis))
1384 } else if (obj->otyp == SCR_SCARE_MONSTER) {
1387 else if (!obj->spe && !obj->cursed)
1390 pline_The("scroll%s %s to dust as you %s %s up.", plur(obj->quan),
1391 otense(obj, "turn"), telekinesis ? "raise" : "pick",
1392 (obj->quan == 1L) ? "it" : "them");
1393 if (!(objects[SCR_SCARE_MONSTER].oc_name_known)
1394 && !(objects[SCR_SCARE_MONSTER].oc_uname))
1396 useupf(obj, obj->quan);
1397 return 1; /* tried to pick something up and failed, but
1398 don't want to terminate pickup loop yet */
1402 if ((res = lift_object(obj, (struct obj *) 0, &count, telekinesis)) <= 0)
1405 /* Whats left of the special case for gold :-) */
1406 if (obj->oclass == COIN_CLASS)
1408 if (obj->quan != count && obj->otyp != LOADSTONE)
1409 obj = splitobj(obj, count);
1411 obj = pick_obj(obj);
1413 if (uwep && uwep == obj)
1414 mrg_to_wielded = TRUE;
1415 nearload = near_capacity();
1416 prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0, obj,
1418 mrg_to_wielded = FALSE;
1423 * Do the actual work of picking otmp from the floor or monster's interior
1424 * and putting it in the hero's inventory. Take care of billing. Return a
1425 * pointer to the object where otmp ends up. This may be different
1426 * from otmp because of merging.
1432 obj_extract_self(otmp);
1433 if (!u.uswallow && otmp != uball && costly_spot(otmp->ox, otmp->oy)) {
1434 char saveushops[5], fakeshop[2];
1436 /* addtobill cares about your location rather than the object's;
1437 usually they'll be the same, but not when using telekinesis
1438 (if ever implemented) or a grappling hook */
1439 Strcpy(saveushops, u.ushops);
1440 fakeshop[0] = *in_rooms(otmp->ox, otmp->oy, SHOPBASE);
1442 Strcpy(u.ushops, fakeshop);
1443 /* sets obj->unpaid if necessary */
1444 addtobill(otmp, TRUE, FALSE, FALSE);
1445 Strcpy(u.ushops, saveushops);
1446 /* if you're outside the shop, make shk notice */
1447 if (!index(u.ushops, *fakeshop))
1448 remote_burglary(otmp->ox, otmp->oy);
1450 newsym(otmp->ox, otmp->oy);
1451 return addinv(otmp); /* might merge it with other objects */
1455 * prints a message if encumbrance changed since the last check and
1456 * returns the new encumbrance value (from near_capacity()).
1461 static int oldcap = UNENCUMBERED;
1462 int newcap = near_capacity();
1464 if (oldcap < newcap) {
1467 Your("movements are slowed slightly because of your load.");
1470 You("rebalance your load. Movement is difficult.");
1473 You("%s under your heavy load. Movement is very hard.",
1474 stagger(youmonst.data, "stagger"));
1477 You("%s move a handspan with this load!",
1478 newcap == 4 ? "can barely" : "can't even");
1482 } else if (oldcap > newcap) {
1485 Your("movements are now unencumbered.");
1488 Your("movements are only slowed slightly by your load.");
1491 You("rebalance your load. Movement is still difficult.");
1494 You("%s under your load. Movement is still very hard.",
1495 stagger(youmonst.data, "stagger"));
1505 /* Is there a container at x,y. Optional: return count of containers at x,y */
1507 container_at(x, y, countem)
1511 struct obj *cobj, *nobj;
1512 int container_count = 0;
1514 for (cobj = level.objects[x][y]; cobj; cobj = nobj) {
1515 nobj = cobj->nexthere;
1516 if (Is_container(cobj)) {
1522 return container_count;
1526 able_to_loot(x, y, looting)
1528 boolean looting; /* loot vs tip */
1530 const char *verb = looting ? "loot" : "tip";
1532 if (!can_reach_floor(TRUE)) {
1533 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
1534 rider_cant_reach(); /* not skilled enough to reach */
1536 cant_reach_floor(x, y, FALSE, TRUE);
1538 } else if ((is_pool(x, y) && (looting || !Underwater)) || is_lava(x, y)) {
1539 /* at present, can't loot in water even when Underwater;
1540 can tip underwater, but not when over--or stuck in--lava */
1541 You("cannot %s things that are deep in the %s.", verb,
1542 is_lava(x, y) ? "lava" : "water");
1544 } else if (nolimbs(youmonst.data)) {
1545 pline("Without limbs, you cannot %s anything.", verb);
1547 } else if (looting && !freehand()) {
1548 pline("Without a free %s, you cannot loot anything.",
1560 for (i = -1; i <= 1; i++)
1561 for (j = -1; j <= 1; j++) {
1564 if (isok(nx, ny) && MON_AT(nx, ny))
1574 struct obj *cobj = *cobjp;
1577 if (cobj->olocked) {
1579 cobj->lknown ? "It is" : "Hmmm, it turns out to be");
1585 if (cobj->otyp == BAG_OF_TRICKS) {
1587 You("carefully open the bag...");
1588 pline("It develops a huge set of teeth and bites you!");
1590 losehp(Maybe_Half_Phys(tmp), "carnivorous bag", KILLED_BY_AN);
1591 makeknown(BAG_OF_TRICKS);
1595 You("%sopen %s...", (!cobj->cknown || !cobj->lknown) ? "carefully " : "",
1597 return use_container(cobjp, 0);
1600 /* loot a container on the floor or loot saddle from mon. */
1604 struct obj *cobj, *nobj;
1605 register int c = -1;
1608 boolean underfoot = TRUE;
1609 const char *dont_find_anything = "don't find anything";
1612 int prev_inquiry = 0;
1613 boolean prev_loot = FALSE;
1616 if (check_capacity((char *) 0)) {
1617 /* "Can't do that while carrying so much stuff." */
1620 if (nohands(youmonst.data)) {
1621 You("have no hands!"); /* not `body_part(HAND)' */
1625 if (rn2(6) && reverse_loot())
1628 pline("Being confused, you find nothing to loot.");
1629 return 1; /* costs a turn */
1630 } /* else fallthrough to normal looting */
1637 if ((num_conts = container_at(cc.x, cc.y, TRUE)) > 0) {
1638 boolean anyfound = FALSE;
1640 if (!able_to_loot(cc.x, cc.y, TRUE))
1643 if (num_conts > 1) {
1644 /* use a menu to loot many containers */
1648 menu_item *pick_list = NULL;
1651 win = create_nhwindow(NHW_MENU);
1654 for (cobj = level.objects[cc.x][cc.y]; cobj;
1655 cobj = cobj->nexthere)
1656 if (Is_container(cobj)) {
1658 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
1659 doname(cobj), MENU_UNSELECTED);
1661 end_menu(win, "Loot which containers?");
1662 n = select_menu(win, PICK_ANY, &pick_list);
1663 destroy_nhwindow(win);
1666 for (i = 0; i < n; i++) {
1667 timepassed |= do_loot_cont(&pick_list[i].item.a_obj);
1668 if (multi < 0 || !pick_list[i].item.a_obj) {
1669 free((genericptr_t) pick_list);
1675 free((genericptr_t) pick_list);
1679 for (cobj = level.objects[cc.x][cc.y]; cobj; cobj = nobj) {
1680 nobj = cobj->nexthere;
1682 if (Is_container(cobj)) {
1683 c = ynq(safe_qbuf(qbuf, "There is ", " here, loot it?",
1684 cobj, doname, ansimpleoname,
1692 timepassed |= do_loot_cont(&cobj);
1693 /* might have triggered chest trap or magic bag explosion
1695 if (multi < 0 || !cobj)
1702 } else if (IS_GRAVE(levl[cc.x][cc.y].typ)) {
1703 You("need to dig up the grave to effectively loot it...");
1706 * 3.3.1 introduced directional looting for some things.
1708 if (c != 'y' && mon_beside(u.ux, u.uy)) {
1709 if (!get_adjacent_loc("Loot in what direction?",
1710 "Invalid loot location", u.ux, u.uy, &cc))
1712 if (cc.x == u.ux && cc.y == u.uy) {
1714 if (container_at(cc.x, cc.y, FALSE))
1719 You("%s to loot on the %s.", dont_find_anything,
1720 ceiling(cc.x, cc.y));
1724 mtmp = m_at(cc.x, cc.y);
1726 timepassed = loot_mon(mtmp, &prev_inquiry, &prev_loot);
1727 /* always use a turn when choosing a direction is impaired,
1728 even if you've successfully targetted a saddled creature
1729 and then answered "no" to the "remove its saddle?" prompt */
1730 if (Confusion || Stunned)
1733 /* Preserve pre-3.3.1 behaviour for containers.
1734 * Adjust this if-block to allow container looting
1735 * from one square away to change that in the future.
1738 if (container_at(cc.x, cc.y, FALSE)) {
1740 You_cant("loot anything %sthere with %s in the way.",
1741 prev_inquiry ? "else " : "", mon_nam(mtmp));
1744 You("have to be at a container to loot it.");
1747 You("%s %sthere to loot.", dont_find_anything,
1748 (prev_inquiry || prev_loot) ? "else " : "");
1752 } else if (c != 'y' && c != 'n') {
1753 You("%s %s to loot.", dont_find_anything,
1754 underfoot ? "here" : "there");
1759 /* called when attempting to #loot while confused */
1763 struct obj *goldob = 0, *coffers, *otmp, boxdummy;
1766 int n, x = u.ux, y = u.uy;
1769 /* n objects: 1/(n+1) chance per object plus 1/(n+1) to fall off end
1771 for (n = inv_cnt(TRUE), otmp = invent; otmp; --n, otmp = otmp->nobj)
1773 prinv("You find old loot:", otmp, 0L);
1779 /* find a money object to mess with */
1780 for (goldob = invent; goldob; goldob = goldob->nobj)
1781 if (goldob->oclass == COIN_CLASS) {
1782 contribution = ((long) rnd(5) * goldob->quan + 4L) / 5L;
1783 if (contribution < goldob->quan)
1784 goldob = splitobj(goldob, contribution);
1790 if (!IS_THRONE(levl[x][y].typ)) {
1792 /* the dropped gold might have fallen to lower level */
1794 pline("Ok, now there is loot here.");
1796 /* find original coffers chest if present, otherwise use nearest one
1799 for (coffers = fobj; coffers; coffers = coffers->nobj)
1800 if (coffers->otyp == CHEST) {
1801 if (coffers->spe == 2)
1802 break; /* a throne room chest */
1804 || distu(coffers->ox, coffers->oy)
1805 < distu(otmp->ox, otmp->oy))
1806 otmp = coffers; /* remember closest ordinary chest */
1812 verbalize("Thank you for your contribution to reduce the debt.");
1814 (void) add_to_container(coffers, goldob);
1815 coffers->owt = weight(coffers);
1816 coffers->cknown = 0;
1817 if (!coffers->olocked) {
1818 boxdummy = zeroobj, boxdummy.otyp = SPE_WIZARD_LOCK;
1819 (void) boxlock(coffers, &boxdummy);
1821 } else if (levl[x][y].looted != T_LOOTED &&
1822 (mon = makemon(courtmon(), x, y, NO_MM_FLAGS)) != 0) {
1824 add_to_minv(mon, goldob);
1825 pline("The exchequer accepts your contribution.");
1827 levl[x][y].looted = T_LOOTED;
1829 You("drop %s.", doname(goldob));
1836 /* loot_mon() returns amount of time passed.
1839 loot_mon(mtmp, passed_info, prev_loot)
1849 /* 3.3.1 introduced the ability to remove saddle from a steed */
1850 /* *passed_info is set to TRUE if a loot query was given. */
1851 /* *prev_loot is set to TRUE if something was actually acquired in here.
1853 if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
1858 qbuf, "Do you want to remove the saddle from %s?",
1859 x_monnam(mtmp, ARTICLE_THE, (char *) 0, SUPPRESS_SADDLE, FALSE));
1860 if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
1861 if (nolimbs(youmonst.data)) {
1862 You_cant("do that without limbs."); /* not body_part(HAND) */
1866 You("can't. The saddle seems to be stuck to %s.",
1867 x_monnam(mtmp, ARTICLE_THE, (char *) 0, SUPPRESS_SADDLE,
1869 /* the attempt costs you time */
1872 obj_extract_self(otmp);
1873 if ((unwornmask = otmp->owornmask) != 0L) {
1874 mtmp->misc_worn_check &= ~unwornmask;
1875 otmp->owornmask = 0L;
1876 update_mon_intrinsics(mtmp, otmp, FALSE, FALSE);
1878 otmp = hold_another_object(otmp, "You drop %s!", doname(otmp),
1880 timepassed = rnd(3);
1883 } else if (c == 'q') {
1887 /* 3.4.0 introduced the ability to pick things up from within swallower's
1890 int count = passed_info ? *passed_info : 0;
1891 timepassed = pickup(count);
1897 * Decide whether an object being placed into a magic bag will cause
1898 * it to explode. If the object is a bag itself, check recursively.
1901 mbag_explodes(obj, depthin)
1905 /* these won't cause an explosion when they're empty */
1906 if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS)
1910 /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
1911 if ((Is_mbag(obj) || obj->otyp == WAN_CANCELLATION)
1912 && (rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin))
1914 else if (Has_contents(obj)) {
1917 for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
1918 if (mbag_explodes(otmp, depthin + 1))
1924 /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
1927 register struct obj *obj;
1929 boolean floor_container = !carried(current_container);
1930 boolean was_unpaid = FALSE;
1933 if (!current_container) {
1934 impossible("<in> no current_container?");
1936 } else if (obj == uball || obj == uchain) {
1937 You("must be kidding.");
1939 } else if (obj == current_container) {
1940 pline("That would be an interesting topological exercise.");
1942 } else if (obj->owornmask & (W_ARMOR | W_ACCESSORY)) {
1943 Norep("You cannot %s %s you are wearing.",
1944 Icebox ? "refrigerate" : "stash", something);
1946 } else if ((obj->otyp == LOADSTONE) && obj->cursed) {
1948 pline_The("stone%s won't leave your person.", plur(obj->quan));
1950 } else if (obj->otyp == AMULET_OF_YENDOR
1951 || obj->otyp == CANDELABRUM_OF_INVOCATION
1952 || obj->otyp == BELL_OF_OPENING
1953 || obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1954 /* Prohibit Amulets in containers; if you allow it, monsters can't
1955 * steal them. It also becomes a pain to check to see if someone
1956 * has the Amulet. Ditto for the Candelabrum, the Bell and the Book.
1958 pline("%s cannot be confined in such trappings.", The(xname(obj)));
1960 } else if (obj->otyp == LEASH && obj->leashmon != 0) {
1961 pline("%s attached to your pet.", Tobjnam(obj, "are"));
1963 } else if (obj == uwep) {
1968 setuwep((struct obj *) 0);
1970 return 0; /* unwielded, died, rewielded */
1971 } else if (obj == uswapwep) {
1972 setuswapwep((struct obj *) 0);
1974 return 0; /* unwielded, died, rewielded */
1975 } else if (obj == uquiver) {
1976 setuqwep((struct obj *) 0);
1978 return 0; /* unwielded, died, rewielded */
1981 if (fatal_corpse_mistake(obj, FALSE))
1984 /* boxes, boulders, and big statues can't fit into any container */
1985 if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER
1986 || (obj->otyp == STATUE && bigmonst(&mons[obj->corpsenm]))) {
1988 * xname() uses a static result array. Save obj's name
1989 * before current_container's name is computed. Don't
1990 * use the result of strcpy() within You() --- the order
1991 * of evaluation of the parameters is undefined.
1993 Strcpy(buf, the(xname(obj)));
1994 You("cannot fit %s into %s.", buf, the(xname(current_container)));
2000 if (obj_is_burning(obj)) /* this used to be part of freeinv() */
2001 (void) snuff_lit(obj);
2003 if (floor_container && costly_spot(u.ux, u.uy)) {
2004 if (current_container->no_charge && !obj->unpaid) {
2005 /* don't sell when putting the item into your own container */
2007 } else if (obj->oclass != COIN_CLASS) {
2008 /* sellobj() will take an unpaid item off the shop bill
2009 * note: coins are handled later */
2010 was_unpaid = obj->unpaid ? TRUE : FALSE;
2011 sellobj_state(SELL_DELIBERATE);
2012 sellobj(obj, u.ux, u.uy);
2013 sellobj_state(SELL_NORMAL);
2016 if (Icebox && !age_is_relative(obj)) {
2017 obj->age = monstermoves - obj->age; /* actual age */
2018 /* stop any corpse timeouts when frozen */
2019 if (obj->otyp == CORPSE && obj->timed) {
2020 long rot_alarm = stop_timer(ROT_CORPSE, obj_to_any(obj));
2021 (void) stop_timer(REVIVE_MON, obj_to_any(obj));
2022 /* mark a non-reviving corpse as such */
2026 } else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
2027 /* explicitly mention what item is triggering the explosion */
2028 pline("As you put %s inside, you are blasted by a magical explosion!",
2030 /* did not actually insert obj yet */
2032 addtobill(obj, FALSE, FALSE, TRUE);
2033 obfree(obj, (struct obj *) 0);
2034 delete_contents(current_container);
2035 if (!floor_container)
2036 useup(current_container);
2037 else if (obj_here(current_container, u.ux, u.uy))
2038 useupf(current_container, current_container->quan);
2040 panic("in_container: bag not found.");
2042 losehp(d(6, 6), "magical explosion", KILLED_BY_AN);
2043 current_container = 0; /* baggone = TRUE; */
2046 if (current_container) {
2047 Strcpy(buf, the(xname(current_container)));
2048 You("put %s into %s.", doname(obj), buf);
2050 /* gold in container always needs to be added to credit */
2051 if (floor_container && obj->oclass == COIN_CLASS)
2052 sellobj(obj, current_container->ox, current_container->oy);
2053 (void) add_to_container(current_container, obj);
2054 current_container->owt = weight(current_container);
2056 /* gold needs this, and freeinv() many lines above may cause
2057 * the encumbrance to disappear from the status, so just always
2058 * update status immediately.
2062 return (current_container ? 1 : -1);
2069 return current_container && obj != current_container;
2072 /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
2075 register struct obj *obj;
2077 register struct obj *otmp;
2078 boolean is_gold = (obj->oclass == COIN_CLASS);
2082 if (!current_container) {
2083 impossible("<out> no current_container?");
2085 } else if (is_gold) {
2086 obj->owt = weight(obj);
2089 if (obj->oartifact && !touch_artifact(obj, &youmonst))
2092 if (fatal_corpse_mistake(obj, FALSE))
2096 if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0)
2099 if (obj->quan != count && obj->otyp != LOADSTONE)
2100 obj = splitobj(obj, count);
2102 /* Remove the object from the list. */
2103 obj_extract_self(obj);
2104 current_container->owt = weight(current_container);
2106 if (Icebox && !age_is_relative(obj)) {
2107 obj->age = monstermoves - obj->age; /* actual age */
2108 if (obj->otyp == CORPSE)
2109 start_corpse_timeout(obj);
2111 /* simulated point of time */
2113 if (!obj->unpaid && !carried(current_container)
2114 && costly_spot(current_container->ox, current_container->oy)) {
2115 obj->ox = current_container->ox;
2116 obj->oy = current_container->oy;
2117 addtobill(obj, FALSE, FALSE, FALSE);
2120 pick_pick(obj); /* shopkeeper feedback */
2123 loadlev = near_capacity();
2125 ? (loadlev < MOD_ENCUMBER ? "You have a little trouble removing"
2126 : "You have much trouble removing")
2131 bot(); /* update character's gold piece count immediately */
2136 /* an object inside a cursed bag of holding is being destroyed */
2138 mbag_item_gone(held, item)
2146 pline("%s %s vanished!", Doname2(item), otense(item, "have"));
2148 You("%s %s disappear!", Blind ? "notice" : "see", doname(item));
2150 if (*u.ushops && (shkp = shop_keeper(*u.ushops)) != 0) {
2151 if (held ? (boolean) item->unpaid : costly_spot(u.ux, u.uy))
2152 loss = stolen_value(item, u.ux, u.uy, (boolean) shkp->mpeaceful,
2155 obfree(item, (struct obj *) 0);
2160 observe_quantum_cat(box)
2163 static NEARDATA const char sc[] = "Schroedinger's Cat";
2164 struct obj *deadcat;
2165 struct monst *livecat;
2168 box->spe = 0; /* box->owt will be updated below */
2169 if (get_obj_location(box, &ox, &oy, 0))
2170 box->ox = ox, box->oy = oy; /* in case it's being carried */
2172 /* this isn't really right, since any form of observation
2173 (telepathic or monster/object/food detection) ought to
2174 force the determination of alive vs dead state; but basing
2175 it just on opening the box is much simpler to cope with */
2177 ? makemon(&mons[PM_HOUSECAT], box->ox, box->oy, NO_MINVENT)
2180 livecat->mpeaceful = 1;
2181 set_malign(livecat);
2182 if (!canspotmon(livecat))
2183 You("think %s brushed your %s.", something, body_part(FOOT));
2185 pline("%s inside the box is still alive!", Monnam(livecat));
2186 (void) christen_monst(livecat, sc);
2189 mk_named_object(CORPSE, &mons[PM_HOUSECAT], box->ox, box->oy, sc);
2191 obj_extract_self(deadcat);
2192 (void) add_to_container(box, deadcat);
2194 pline_The("%s inside the box is dead!",
2195 Hallucination ? rndmonnam(NULL) : "housecat");
2197 box->owt = weight(box);
2203 /* used by askchain() to check for magic bag explosion */
2206 int FDECL((*fn), (OBJ_P));
2208 /* result is only meaningful while use_container() is executing */
2209 return ((fn == in_container || fn == out_container)
2210 && !current_container);
2214 explain_container_prompt()
2216 static const char *const explaintext[] = {
2217 "Container actions:", "", " : -- Look: examine contents",
2218 " o -- Out: take things out", " i -- In: put things in",
2219 " b -- Both: first take things out, then put things in",
2220 " r -- Reversed: put things in, then take things out",
2221 " s -- Stash: put one item in", " q -- Quit: do nothing",
2222 " ? -- Help: display this text.", "", 0
2224 const char *const *txtpp;
2227 /* "Do what with <container>? [:oibrsq or ?] (q)" */
2228 if ((win = create_nhwindow(NHW_TEXT)) != WIN_ERR) {
2229 for (txtpp = explaintext; *txtpp; ++txtpp)
2230 putstr(win, 0, *txtpp);
2231 display_nhwindow(win, FALSE);
2232 destroy_nhwindow(win);
2239 if (nohands(youmonst.data)) {
2240 You("have no hands!"); /* not `body_part(HAND)' */
2242 } else if (!freehand()) {
2243 You("have no free %s.", body_part(HAND));
2249 static const char stashable[] = { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
2252 use_container(objp, held)
2256 struct obj *curr, *otmp, *obj = *objp;
2257 boolean quantum_cat, cursed_mbag, loot_out, loot_in, loot_in_first,
2258 stash_one, inokay, outokay, outmaybe;
2259 char c, emptymsg[BUFSZ], qbuf[QBUFSZ], pbuf[QBUFSZ], xbuf[QBUFSZ];
2268 pline("%s locked.", Tobjnam(obj, "are"));
2270 You("must put it down to unlock.");
2273 } else if (obj->otrapped) {
2275 You("open %s...", the(xname(obj)));
2277 (void) chest_trap(obj, HAND, FALSE);
2278 /* even if the trap fails, you've used up this turn */
2279 if (multi >= 0) { /* in case we didn't become paralyzed */
2281 multi_reason = "opening a container";
2288 current_container = obj; /* for use by in/out_container */
2289 /* from here on out, all early returns go through containerdone */
2291 /* check for Schroedinger's Cat */
2292 quantum_cat = SchroedingersBox(current_container);
2294 observe_quantum_cat(current_container);
2297 /* sometimes toss objects if a cursed magic bag */
2298 cursed_mbag = (Is_mbag(current_container) && current_container->cursed
2299 && Has_contents(current_container));
2303 for (curr = current_container->cobj; curr; curr = otmp) {
2306 obj_extract_self(curr);
2307 loss += mbag_item_gone(held, curr);
2312 You("owe %ld %s for lost merchandise.", loss, currency(loss));
2313 current_container->owt = weight(current_container);
2315 inokay = (invent != 0
2316 && !(invent == current_container && !current_container->nobj));
2317 outokay = Has_contents(current_container);
2318 if (!outokay) /* preformat the empty-container message */
2319 Sprintf(emptymsg, "%s is %sempty.", Ysimple_name2(current_container),
2320 (quantum_cat || cursed_mbag) ? "now " : "");
2323 * What-to-do prompt's list of possible actions:
2324 * always include the look-inside choice (':');
2325 * include the take-out choice ('o') if container
2326 * has anything in it or if player doesn't yet know
2327 * that it's empty (latter can change on subsequent
2328 * iterations if player picks ':' response);
2329 * include the put-in choices ('i','s') if hero
2330 * carries any inventory (including gold);
2331 * include do-both when 'o' is available, even if
2332 * inventory is empty--taking out could alter that;
2333 * include do-both-reversed when 'i' is available,
2334 * even if container is empty--for similar reason;
2335 * always include the quit choice ('q').
2336 * include the help choice (" or ?") if `cmdassist'
2337 * run-time option is set;
2338 * (Player can pick any of (o,i,b,r,s,?) even when
2339 * they're not listed among the available actions.)
2341 * Do what with <the/your/Shk's container>? [:oibrsq or ?] (q)
2343 * <The/Your/Shk's container> is empty. Do what with it? [:irsq or ?]
2345 for (;;) { /* repeats if '?' or ":' gets chosen */
2346 outmaybe = (outokay || !current_container->cknown);
2348 (void) safe_qbuf(qbuf, (char *) 0, " is empty. Do what with it?",
2349 current_container, Yname2, Ysimple_name2,
2352 (void) safe_qbuf(qbuf, "Do what with ", "?", current_container,
2353 yname, ysimple_name, "it");
2354 /* ask player about what to do with this container */
2355 if (flags.menu_style == MENU_FULL) {
2356 if (!inokay && !outmaybe) {
2357 /* nothing to take out, nothing to put in;
2358 trying to do both will yield proper feedback */
2361 c = in_or_out_menu(qbuf, current_container, outmaybe, inokay,
2364 } else { /* TRADITIONAL, COMBINATION, or PARTIAL */
2365 xbuf[0] = '\0'; /* list of extra acceptable responses */
2366 Strcpy(pbuf, ":"); /* look inside */
2367 Strcat(outmaybe ? pbuf : xbuf, "o"); /* take out */
2368 Strcat(inokay ? pbuf : xbuf, "i"); /* put in */
2369 Strcat(outmaybe ? pbuf : xbuf, "b"); /* both */
2370 Strcat(inokay ? pbuf : xbuf, "rs"); /* reversed, stash */
2371 Strcat(pbuf, "q"); /* quit */
2372 if (iflags.cmdassist)
2373 Strcat(pbuf, " or ?"); /* help */
2377 Strcat(strcat(pbuf, "\033"), xbuf);
2378 c = yn_function(qbuf, pbuf, 'q');
2379 } /* FULL vs other modes */
2382 explain_container_prompt();
2383 } else if (c == ':') { /* note: will set obj->cknown */
2384 if (!current_container->cknown)
2385 used = 1; /* gaining info */
2386 container_contents(current_container, FALSE, FALSE, TRUE);
2389 } /* loop until something other than '?' or ':' is picked */
2391 if (c == 'q') /* [not strictly needed; falling through works] */
2393 loot_out = (c == 'o' || c == 'b' || c == 'r');
2394 loot_in = (c == 'i' || c == 'b' || c == 'r');
2395 loot_in_first = (c == 'r'); /* both, reversed */
2396 stash_one = (c == 's');
2398 /* out-only or out before in */
2399 if (loot_out && !loot_in_first) {
2400 if (!Has_contents(current_container)) {
2401 pline1(emptymsg); /* <whatever> is empty. */
2402 if (!current_container->cknown)
2404 current_container->cknown = 1;
2406 add_valid_menu_class(0); /* reset */
2407 if (flags.menu_style == MENU_TRADITIONAL)
2408 used |= traditional_loot(FALSE);
2410 used |= (menu_loot(0, FALSE) > 0);
2414 if ((loot_in || stash_one)
2415 && (!invent || (invent == current_container && !invent->nobj))) {
2416 You("don't have anything%s to %s.", invent ? " else" : "",
2417 stash_one ? "stash" : "put in");
2418 loot_in = stash_one = FALSE;
2422 * Gone: being nice about only selecting food if we know we are
2423 * putting things in an ice chest.
2426 add_valid_menu_class(0); /* reset */
2427 if (flags.menu_style == MENU_TRADITIONAL)
2428 used |= traditional_loot(TRUE);
2430 used |= (menu_loot(0, TRUE) > 0);
2431 } else if (stash_one) {
2432 /* put one item into container */
2433 if ((otmp = getobj(stashable, "stash")) != 0) {
2434 if (in_container(otmp)) {
2437 /* couldn't put selected item into container for some
2438 reason; might need to undo splitobj() */
2439 for (curr = invent; curr; curr = curr->nobj)
2440 if (curr->nobj == otmp)
2442 if (curr && curr->invlet == otmp->invlet)
2443 (void) merged(&curr, &otmp);
2447 /* putting something in might have triggered magic bag explosion */
2448 if (!current_container)
2452 if (loot_out && loot_in_first) {
2453 if (!Has_contents(current_container)) {
2454 pline1(emptymsg); /* <whatever> is empty. */
2455 if (!current_container->cknown)
2457 current_container->cknown = 1;
2459 add_valid_menu_class(0); /* reset */
2460 if (flags.menu_style == MENU_TRADITIONAL)
2461 used |= traditional_loot(FALSE);
2463 used |= (menu_loot(0, FALSE) > 0);
2469 /* Not completely correct; if we put something in without knowing
2470 whatever was already inside, now we suddenly do. That can't
2471 be helped unless we want to track things item by item and then
2472 deal with containers whose contents are "partly known". */
2473 if (current_container)
2474 current_container->cknown = 1;
2478 *objp = current_container; /* might have become null */
2479 current_container = 0; /* avoid hanging on to stale pointer */
2483 /* loot current_container (take things out or put things in), by prompting */
2485 traditional_loot(put_in)
2488 int FDECL((*actionfunc), (OBJ_P)), FDECL((*checkfunc), (OBJ_P));
2489 struct obj **objlist;
2490 char selection[MAXOCLASSES + 1];
2492 boolean one_by_one, allflag;
2493 int used = 0, menu_on_request = 0;
2498 actionfunc = in_container;
2501 action = "take out";
2502 objlist = &(current_container->cobj);
2503 actionfunc = out_container;
2504 checkfunc = (int FDECL((*), (OBJ_P))) 0;
2507 if (query_classes(selection, &one_by_one, &allflag, action, *objlist,
2508 FALSE, &menu_on_request)) {
2509 if (askchain(objlist, (one_by_one ? (char *) 0 : selection), allflag,
2510 actionfunc, checkfunc, 0, action))
2512 } else if (menu_on_request < 0) {
2513 used = (menu_loot(menu_on_request, put_in) > 0);
2518 /* loot current_container (take things out or put things in), using a menu */
2520 menu_loot(retry, put_in)
2524 int n, i, n_looted = 0;
2525 boolean all_categories = TRUE, loot_everything = FALSE;
2527 const char *action = put_in ? "Put in" : "Take out";
2528 struct obj *otmp, *otmp2;
2529 menu_item *pick_list;
2534 all_categories = (retry == -2);
2535 } else if (flags.menu_style == MENU_FULL) {
2536 all_categories = FALSE;
2537 Sprintf(buf, "%s what type of objects?", action);
2539 ? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN
2540 : ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN;
2541 n = query_category(buf, put_in ? invent : current_container->cobj,
2542 mflags, &pick_list, PICK_ANY);
2545 for (i = 0; i < n; i++) {
2546 if (pick_list[i].item.a_int == 'A')
2547 loot_everything = TRUE;
2548 else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
2549 all_categories = TRUE;
2551 add_valid_menu_class(pick_list[i].item.a_int);
2553 free((genericptr_t) pick_list);
2556 if (loot_everything) {
2557 current_container->cknown = 1;
2558 for (otmp = current_container->cobj; otmp; otmp = otmp2) {
2560 res = out_container(otmp);
2565 mflags = INVORDER_SORT;
2566 if (put_in && flags.invlet_constant)
2567 mflags |= USE_INVLET;
2569 current_container->cknown = 1;
2570 Sprintf(buf, "%s what?", action);
2571 n = query_objlist(buf, put_in ? invent : current_container->cobj,
2572 mflags, &pick_list, PICK_ANY,
2573 all_categories ? allow_all : allow_category);
2576 for (i = 0; i < n; i++) {
2577 otmp = pick_list[i].item.a_obj;
2578 count = pick_list[i].count;
2579 if (count > 0 && count < otmp->quan) {
2580 otmp = splitobj(otmp, count);
2581 /* special split case also handled by askchain() */
2583 res = put_in ? in_container(otmp) : out_container(otmp);
2585 if (!current_container) {
2586 /* otmp caused current_container to explode;
2587 both are now gone */
2588 otmp = 0; /* and break loop */
2589 } else if (otmp && otmp != pick_list[i].item.a_obj) {
2590 /* split occurred, merge again */
2591 (void) merged(&pick_list[i].item.a_obj, &otmp);
2596 free((genericptr_t) pick_list);
2603 in_or_out_menu(prompt, obj, outokay, inokay, alreadyused)
2606 boolean outokay, inokay, alreadyused;
2608 /* underscore is not a choice; it's used to skip element [0] */
2609 static const char lootchars[] = "_:oibrsq", abc_chars[] = "_:abcdeq";
2612 menu_item *pick_list;
2615 const char *menuselector = flags.lootabc ? abc_chars : lootchars;
2618 win = create_nhwindow(NHW_MENU);
2621 any.a_int = 1; /* ':' */
2622 Sprintf(buf, "Look inside %s", thesimpleoname(obj));
2623 add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE, buf,
2626 any.a_int = 2; /* 'o' */
2627 Sprintf(buf, "take %s out", something);
2628 add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
2629 buf, MENU_UNSELECTED);
2632 any.a_int = 3; /* 'i' */
2633 Sprintf(buf, "put %s in", something);
2634 add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
2635 buf, MENU_UNSELECTED);
2638 any.a_int = 4; /* 'b' */
2639 Sprintf(buf, "%stake out, then put in", inokay ? "both; " : "");
2640 add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
2641 buf, MENU_UNSELECTED);
2644 any.a_int = 5; /* 'r' */
2645 Sprintf(buf, "%sput in, then take out",
2646 outokay ? "both reversed; " : "");
2647 add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
2648 buf, MENU_UNSELECTED);
2649 any.a_int = 6; /* 's' */
2650 Sprintf(buf, "stash one item into %s", thesimpleoname(obj));
2651 add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE,
2652 buf, MENU_UNSELECTED);
2654 any.a_int = 7; /* 'q' */
2655 Strcpy(buf, alreadyused ? "done" : "do nothing");
2656 add_menu(win, NO_GLYPH, &any, menuselector[any.a_int], 0, ATR_NONE, buf,
2659 end_menu(win, prompt);
2660 n = select_menu(win, PICK_ONE, &pick_list);
2661 destroy_nhwindow(win);
2663 n = pick_list[0].item.a_int;
2664 free((genericptr_t) pick_list);
2665 return lootchars[n]; /* :,o,i,b,r,s,q */
2667 return 'q'; /* quit */
2670 static const char tippables[] = { ALL_CLASSES, TOOL_CLASS, 0 };
2672 /* #tip command -- empty container contents onto floor */
2676 struct obj *cobj, *nobj;
2679 char c, buf[BUFSZ], qbuf[BUFSZ];
2680 const char *spillage = 0;
2683 * doesn't require free hands;
2684 * limbs are needed to tip floor containers
2687 /* at present, can only tip things at current spot, not adjacent ones */
2688 cc.x = u.ux, cc.y = u.uy;
2690 /* check floor container(s) first; at most one will be accessed */
2691 if ((boxes = container_at(cc.x, cc.y, TRUE)) > 0) {
2692 Sprintf(buf, "You can't tip %s while carrying so much.",
2693 !flags.verbose ? "a container" : (boxes > 1) ? "one" : "it");
2694 if (!check_capacity(buf) && able_to_loot(cc.x, cc.y, FALSE)) {
2695 if (boxes > 1 && (flags.menu_style != MENU_TRADITIONAL
2696 || iflags.menu_requested)) {
2697 /* use menu to pick a container to tip */
2701 menu_item *pick_list = NULL;
2702 struct obj dummyobj, *otmp;
2705 win = create_nhwindow(NHW_MENU);
2708 for (cobj = level.objects[cc.x][cc.y], i = 0; cobj;
2709 cobj = cobj->nexthere)
2710 if (Is_container(cobj)) {
2713 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
2714 doname(cobj), MENU_UNSELECTED);
2718 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
2719 "", MENU_UNSELECTED);
2720 any.a_obj = &dummyobj;
2721 /* use 'i' for inventory unless there are so many
2722 containers that it's already being used */
2723 i = (i <= 'i' - 'a' && !flags.lootabc) ? 'i' : 0;
2724 add_menu(win, NO_GLYPH, &any, i, 0, ATR_NONE,
2725 "tip something being carried", MENU_SELECTED);
2727 end_menu(win, "Tip which container?");
2728 n = select_menu(win, PICK_ONE, &pick_list);
2729 destroy_nhwindow(win);
2731 * Deal with quirk of preselected item in pick-one menu:
2732 * n == 0 => picked preselected entry, toggling it off;
2733 * n == 1 => accepted preselected choice via SPACE or RETURN;
2734 * n == 2 => picked something other than preselected entry;
2735 * n == -1 => cancelled via ESC;
2737 otmp = (n <= 0) ? (struct obj *) 0 : pick_list[0].item.a_obj;
2738 if (n > 1 && otmp == &dummyobj)
2739 otmp = pick_list[1].item.a_obj;
2741 free((genericptr_t) pick_list);
2742 if (otmp && otmp != &dummyobj) {
2748 /* else pick-from-invent below */
2750 for (cobj = level.objects[cc.x][cc.y]; cobj; cobj = nobj) {
2751 nobj = cobj->nexthere;
2752 if (!Is_container(cobj))
2754 c = ynq(safe_qbuf(qbuf, "There is ", " here, tip it?",
2756 doname, ansimpleoname, "container"));
2762 /* can only tip one container at a time */
2769 /* either no floor container(s) or couldn't tip one or didn't tip any */
2770 cobj = getobj(tippables, "tip");
2775 if (Is_container(cobj) || cobj->otyp == HORN_OF_PLENTY) {
2779 /* assorted other cases */
2780 if (Is_candle(cobj) && cobj->lamplit) {
2781 /* note "wax" even for tallow candles to avoid giving away info */
2783 } else if ((cobj->otyp == POT_OIL && cobj->lamplit)
2784 || (cobj->otyp == OIL_LAMP && cobj->age != 0L)
2785 || (cobj->otyp == MAGIC_LAMP && cobj->spe != 0)) {
2787 /* todo: reduce potion's remaining burn timer or oil lamp's fuel */
2788 } else if (cobj->otyp == CAN_OF_GREASE && cobj->spe > 0) {
2789 /* charged consumed below */
2790 spillage = "grease";
2791 } else if (cobj->otyp == FOOD_RATION || cobj->otyp == CRAM_RATION
2792 || cobj->otyp == LEMBAS_WAFER) {
2793 spillage = "crumbs";
2794 } else if (cobj->oclass == VENOM_CLASS) {
2799 if (is_pool(u.ux, u.uy))
2800 Sprintf(buf, " and gradually %s", vtense(spillage, "dissipate"));
2801 else if (is_lava(u.ux, u.uy))
2802 Sprintf(buf, " and immediately %s away",
2803 vtense(spillage, "burn"));
2804 pline("Some %s %s onto the %s%s.", spillage,
2805 vtense(spillage, "spill"), surface(u.ux, u.uy), buf);
2806 /* shop usage message comes after the spill message */
2807 if (cobj->otyp == CAN_OF_GREASE && cobj->spe > 0) {
2808 consume_obj_charge(cobj, TRUE);
2810 /* something [useless] happened */
2813 /* anything not covered yet */
2814 if (cobj->oclass == POTION_CLASS) /* can't pour potions... */
2815 pline_The("%s %s securely sealed.", xname(cobj), otense(cobj, "are"));
2816 else if (cobj->otyp == STATUE)
2817 pline("Nothing interesting happens.");
2819 pline1(nothing_happens);
2825 struct obj *box; /* or bag */
2827 xchar ox = u.ux, oy = u.uy; /* #tip only works at hero's location */
2828 boolean empty_it = FALSE,
2829 /* Shop handling: can't rely on the container's own unpaid
2830 or no_charge status because contents might differ with it.
2831 A carried container's contents will be flagged as unpaid
2832 or not, as appropriate, and need no special handling here.
2833 Items owned by the hero get sold to the shop without
2834 confirmation as with other uncontrolled drops. A floor
2835 container's contents will be marked no_charge if owned by
2836 hero, otherwise they're owned by the shop. By passing
2837 the contents through shop billing, they end up getting
2838 treated the same as in the carried case. We do so one
2839 item at a time instead of doing whole container at once
2840 to reduce the chance of exhausting shk's billing capacity. */
2841 maybeshopgoods = !carried(box) && costly_spot(ox, oy);
2843 /* caveat: this assumes that cknown, lknown, olocked, and otrapped
2844 fields haven't been overloaded to mean something special for the
2845 non-standard "container" horn of plenty */
2848 pline("It's locked.");
2849 } else if (box->otrapped) {
2850 /* we're not reaching inside but we're still handling it... */
2851 (void) chest_trap(box, HAND, FALSE);
2852 /* even if the trap fails, you've used up this turn */
2853 if (multi >= 0) { /* in case we didn't become paralyzed */
2855 multi_reason = "tipping a container";
2858 } else if (box->otyp == BAG_OF_TRICKS || box->otyp == HORN_OF_PLENTY) {
2859 boolean bag = box->otyp == BAG_OF_TRICKS;
2860 int old_spe = box->spe, seen = 0;
2862 if (maybeshopgoods && !box->no_charge)
2863 addtobill(box, FALSE, FALSE, TRUE);
2864 /* apply this bag/horn until empty or monster/object creation fails
2865 (if the latter occurs, force the former...) */
2867 if (!(bag ? bagotricks(box, TRUE, &seen)
2868 : hornoplenty(box, TRUE)))
2870 } while (box->spe > 0);
2872 if (box->spe < old_spe) {
2874 pline((seen == 0) ? "Nothing seems to happen."
2875 : (seen == 1) ? "A monster appears."
2876 : "Monsters appear!");
2877 /* check_unpaid wants to see a non-zero charge count */
2879 check_unpaid_usage(box, TRUE);
2880 box->spe = 0; /* empty */
2883 if (maybeshopgoods && !box->no_charge)
2884 subfrombill(box, shop_keeper(*in_rooms(ox, oy, SHOPBASE)));
2885 } else if (SchroedingersBox(box)) {
2886 char yourbuf[BUFSZ];
2888 observe_quantum_cat(box);
2889 if (!Has_contents(box)) /* evidently a live cat came out */
2890 /* container type of "large box" is inferred */
2891 pline("%sbox is now empty.", Shk_Your(yourbuf, box));
2892 else /* holds cat corpse or other random stuff */
2895 } else if (!Has_contents(box)) {
2897 pline("It's empty.");
2903 struct obj *otmp, *nobj;
2904 boolean verbose = FALSE, highdrop = !can_reach_floor(TRUE),
2905 altarizing = IS_ALTAR(levl[ox][oy].typ),
2906 cursed_mbag = (Is_mbag(box) && box->cursed);
2907 int held = carried(box);
2911 highdrop = altarizing = FALSE;
2914 box->cobj->nobj ? "Objects spill" : "An object spills",
2915 !(highdrop || altarizing) ? ':' : '.');
2916 for (otmp = box->cobj; otmp; otmp = nobj) {
2918 obj_extract_self(otmp);
2919 if (cursed_mbag && !rn2(13)) {
2920 loss += mbag_item_gone(held, otmp);
2921 /* abbreviated drop format is no longer appropriate */
2926 if (maybeshopgoods) {
2927 addtobill(otmp, FALSE, FALSE, TRUE);
2928 iflags.suppress_price++; /* doname formatting */
2932 /* might break or fall down stairs; handles altars itself */
2938 pline("%s %s to the %s.", Doname2(otmp),
2939 otense(otmp, "drop"), surface(ox, oy));
2941 pline("%s%c", doname(otmp), nobj ? ',' : '.');
2945 iflags.suppress_price--; /* reset */
2947 if (loss) /* magic bag lost some shop goods */
2948 You("owe %ld %s for lost merchandise.", loss, currency(loss));
2949 box->owt = weight(box); /* mbag_item_gone() doesn't update this */
2951 (void) encumber_msg();