1 /* SCCS Id: @(#)pickup.c 3.4 2003/07/27 */
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 STATIC_DCL void FDECL(simple_look, (struct obj *,BOOLEAN_P));
13 STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
14 const char *,struct obj *,BOOLEAN_P,BOOLEAN_P,int *));
16 STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
17 const char *,struct obj *,BOOLEAN_P,int *));
19 STATIC_DCL void FDECL(check_here, (BOOLEAN_P));
20 STATIC_DCL boolean FDECL(n_or_more, (struct obj *));
21 STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *));
23 STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *));
25 STATIC_DCL int FDECL(autopick, (struct obj*, int, menu_item **));
26 STATIC_DCL int FDECL(count_categories, (struct obj *,int));
27 STATIC_DCL long FDECL(carry_count,
28 (struct obj *,struct obj *,long,BOOLEAN_P,int *,int *));
29 STATIC_DCL int FDECL(lift_object, (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(ck_bag,(struct obj *));
33 STATIC_PTR int FDECL(out_container,(struct obj *));
34 STATIC_DCL long FDECL(mbag_item_gone, (int,struct obj *));
35 STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
36 STATIC_DCL int FDECL(menu_loot, (int, struct obj *, BOOLEAN_P));
37 STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *, BOOLEAN_P, BOOLEAN_P));
38 STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
39 STATIC_DCL boolean FDECL(able_to_loot, (int, int));
40 STATIC_DCL boolean FDECL(mon_beside, (int, int));
42 /* define for query_objlist() and autopickup() */
43 #define FOLLOW(curr, flags) \
44 (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
47 * How much the weight of the given container will change when the given
48 * object is removed from it. This calculation must match the one used
49 * by weight() in mkobj.c.
51 #define DELTA_CWT(cont,obj) \
52 ((cont)->cursed ? (obj)->owt * 2 : \
53 1 + ((obj)->owt / ((cont)->blessed ? 4 : 2)))
54 #define GOLD_WT(n) (((n) + 50L) / 100L)
55 /* if you can figure this out, give yourself a hearty pat on the back... */
56 #define GOLD_CAPACITY(w,n) (((w) * -100L) - ((n) + 50L) - 1L)
58 static const char moderateloadmsg[] = "You have a little trouble lifting";
59 static const char nearloadmsg[] = "You have much trouble lifting";
60 static const char overloadmsg[] = "You have extreme difficulty lifting";
62 /* BUG: this lets you look at cockatrice corpses while blind without
64 /* much simpler version of the look-here code; used by query_classes() */
66 simple_look(otmp, here)
67 struct obj *otmp; /* list of objects */
68 boolean here; /* flag for type of obj list linkage */
70 /* Neither of the first two cases is expected to happen, since
71 * we're only called after multiple classes of objects have been
72 * detected, hence multiple objects must be present.
75 impossible("simple_look(null)");
76 } else if (!(here ? otmp->nexthere : otmp->nobj)) {
77 pline("%s", doname(otmp));
79 winid tmpwin = create_nhwindow(NHW_MENU);
80 putstr(tmpwin, 0, "");
82 putstr(tmpwin, 0, doname(otmp));
83 otmp = here ? otmp->nexthere : otmp->nobj;
85 display_nhwindow(tmpwin, TRUE);
86 destroy_nhwindow(tmpwin);
92 collect_obj_classes(ilets, otmp, here, incl_gold, filter, itemcount)
94 register struct obj *otmp;
95 boolean here, incl_gold;
96 boolean FDECL((*filter),(OBJ_P));
100 collect_obj_classes(ilets, otmp, here, filter, itemcount)
102 register struct obj *otmp;
104 boolean FDECL((*filter),(OBJ_P));
108 register int iletct = 0;
114 ilets[iletct++] = def_oc_syms[COIN_CLASS];
116 ilets[iletct] = '\0'; /* terminate ilets so that index() will work */
118 c = def_oc_syms[(int)otmp->oclass];
119 if (!index(ilets, c) && (!filter || (*filter)(otmp)))
120 ilets[iletct++] = c, ilets[iletct] = '\0';
122 otmp = here ? otmp->nexthere : otmp->nobj;
129 * Suppose some '?' and '!' objects are present, but '/' objects aren't:
130 * "a" picks all items without further prompting;
131 * "A" steps through all items, asking one by one;
132 * "?" steps through '?' items, asking, and ignores '!' ones;
133 * "/" becomes 'A', since no '/' present;
134 * "?a" or "a?" picks all '?' without further prompting;
135 * "/a" or "a/" becomes 'A' since there aren't any '/'
136 * (bug fix: 3.1.0 thru 3.1.3 treated it as "a");
137 * "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
138 * (ie, treated as if it had just been "?a").
142 query_classes(oclasses, one_at_a_time, everything, action, objs,
143 here, incl_gold, menu_on_demand)
145 boolean *one_at_a_time, *everything;
148 boolean here, incl_gold;
152 query_classes(oclasses, one_at_a_time, everything, action, objs,
153 here, menu_on_demand)
155 boolean *one_at_a_time, *everything;
162 char ilets[20], inbuf[BUFSZ];
163 int iletct, oclassct;
164 boolean not_everything;
169 oclasses[oclassct = 0] = '\0';
170 *one_at_a_time = *everything = m_seen = FALSE;
171 iletct = collect_obj_classes(ilets, objs, here,
175 (boolean FDECL((*),(OBJ_P))) 0, &itemcount);
178 } else if (iletct == 1) {
179 oclasses[0] = def_char_to_objclass(ilets[0]);
181 if (itemcount && menu_on_demand) {
182 ilets[iletct++] = 'm';
184 ilets[iletct] = '\0';
186 } else { /* more than one choice available */
187 const char *where = 0;
188 register char sym, oc_of_sym, *p;
189 /* additional choices */
190 ilets[iletct++] = ' ';
191 ilets[iletct++] = 'a';
192 ilets[iletct++] = 'A';
193 ilets[iletct++] = (objs == invent ? 'i' : ':');
194 if (menu_on_demand) {
195 ilets[iletct++] = 'm';
198 ilets[iletct] = '\0';
200 oclasses[oclassct = 0] = '\0';
201 *one_at_a_time = *everything = FALSE;
202 not_everything = FALSE;
203 Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
206 if (*inbuf == '\033') return FALSE;
208 for (p = inbuf; (sym = *p++); ) {
209 /* new A function (selective all) added by GAN 01/09/87 */
210 if (sym == ' ') continue;
211 else if (sym == 'A') *one_at_a_time = TRUE;
212 else if (sym == 'a') *everything = TRUE;
213 else if (sym == ':') {
214 simple_look(objs, here); /* dumb if objs==invent */
216 } else if (sym == 'i') {
217 (void) display_inventory((char *)0, TRUE);
219 } else if (sym == 'm') {
222 oc_of_sym = def_char_to_objclass(sym);
223 if (index(ilets,sym)) {
224 add_valid_menu_class(oc_of_sym);
225 oclasses[oclassct++] = oc_of_sym;
226 oclasses[oclassct] = '\0';
229 where = !strcmp(action,"pick up") ? "here" :
230 !strcmp(action,"take out") ?
233 There("are no %c's %s.", sym, where);
235 You("have no %c's.", sym);
236 not_everything = TRUE;
240 if (m_seen && menu_on_demand) {
241 *menu_on_demand = (*everything || !oclassct) ? -2 : -3;
244 if (!oclassct && (!*everything || not_everything)) {
245 /* didn't pick anything,
246 or tried to pick something that's not present */
247 *one_at_a_time = TRUE; /* force 'A' */
248 *everything = FALSE; /* inhibit 'a' */
254 /* look at the objects at our location, unless there are too many of them */
256 check_here(picked_some)
259 register struct obj *obj;
262 /* count the objects here */
263 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) {
268 /* If there are objects here, take a look. */
270 if (flags.run) nomul(0);
272 (void) look_here(ct, picked_some);
274 read_engr_at(u.ux,u.uy);
278 /* Value set by query_objlist() for n_or_more(). */
279 static long val_for_n_or_more;
281 /* query_objlist callback: return TRUE if obj's count is >= reference value */
286 if (obj == uchain) return FALSE;
287 return (obj->quan >= val_for_n_or_more);
290 /* List of valid menu classes for query_objlist() and allow_category callback */
291 static char valid_menu_classes[MAXOCLASSES + 2];
294 add_valid_menu_class(c)
297 static int vmc_count = 0;
299 if (c == 0) /* reset */
302 valid_menu_classes[vmc_count++] = (char)c;
303 valid_menu_classes[vmc_count] = '\0';
306 /* query_objlist callback: return TRUE if not uchain */
311 return (obj != uchain);
314 /* query_objlist callback: return TRUE */
327 if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
328 if (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
329 (index(valid_menu_classes, obj->oclass) != (char *)0))
331 else if (((index(valid_menu_classes,'U') != (char *)0) &&
332 (obj->oclass != COIN_CLASS && obj->bknown && !obj->blessed && !obj->cursed)))
334 else if (((index(valid_menu_classes,'B') != (char *)0) &&
335 (obj->oclass != COIN_CLASS && obj->bknown && obj->blessed)))
337 else if (((index(valid_menu_classes,'C') != (char *)0) &&
338 (obj->oclass != COIN_CLASS && obj->bknown && obj->cursed)))
340 else if (((index(valid_menu_classes,'X') != (char *)0) &&
341 (obj->oclass != COIN_CLASS && !obj->bknown)))
348 /* query_objlist callback: return TRUE if valid category (class), no uchain */
350 allow_cat_no_uchain(obj)
353 if ((obj != uchain) &&
354 (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
355 (index(valid_menu_classes, obj->oclass) != (char *)0)))
362 /* query_objlist callback: return TRUE if valid class and worn */
364 is_worn_by_type(otmp)
365 register struct obj *otmp;
367 return((boolean)(!!(otmp->owornmask &
368 (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP | W_SWAPWEP | W_QUIVER)))
369 && (index(valid_menu_classes, otmp->oclass) != (char *)0));
373 * Have the hero pick things from the ground
374 * or a monster's inventory if swallowed.
379 * <0 pickup count of something
381 * Returns 1 if tried to pick something up, whether
382 * or not it succeeded.
386 int what; /* should be a long */
388 int i, n, res, count, n_tried = 0, n_picked = 0;
389 menu_item *pick_list = (menu_item *) 0;
390 boolean autopickup = what > 0;
391 struct obj *objchain;
394 if (what < 0) /* pick N of something */
396 else /* pick anything */
400 struct trap *ttmp = t_at(u.ux, u.uy);
401 /* no auto-pick if no-pick move, nothing there, or in a pool */
402 if (autopickup && (flags.nopick || !OBJ_AT(u.ux, u.uy) ||
403 (is_pool(u.ux, u.uy) && !Underwater) || is_lava(u.ux, u.uy))) {
404 read_engr_at(u.ux, u.uy);
408 /* no pickup if levitating & not on air or water level */
409 if (!can_reach_floor()) {
410 if ((multi && !flags.run) || (autopickup && !flags.pickup))
411 read_engr_at(u.ux, u.uy);
414 if (ttmp && ttmp->tseen) {
415 /* Allow pickup from holes and trap doors that you escaped
416 * from because that stuff is teetering on the edge just
417 * like you, but not pits, because there is an elevation
418 * discrepancy with stuff in pits.
420 if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT) &&
421 (!u.utrap || (u.utrap && u.utraptype != TT_PIT))) {
422 read_engr_at(u.ux, u.uy);
426 /* multi && !flags.run means they are in the middle of some other
427 * action, or possibly paralyzed, sleeping, etc.... and they just
428 * teleported onto the object. They shouldn't pick it up.
430 if ((multi && !flags.run) || (autopickup && !flags.pickup)) {
434 if (notake(youmonst.data)) {
436 You("are physically incapable of picking anything up.");
442 /* if there's anything here, stop running */
443 if (OBJ_AT(u.ux,u.uy) && flags.run && flags.run != 8 && !flags.nopick) nomul(0);
446 add_valid_menu_class(0); /* reset */
448 objchain = level.objects[u.ux][u.uy];
449 traverse_how = BY_NEXTHERE;
451 objchain = u.ustuck->minvent;
452 traverse_how = 0; /* nobj */
455 * Start the actual pickup process. This is split into two main
456 * sections, the newer menu and the older "traditional" methods.
457 * Automatic pickup has been split into its own menu-style routine
458 * to make things less confusing.
461 n = autopick(objchain, traverse_how, &pick_list);
465 if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
467 /* use menus exclusively */
468 if (count) { /* looking for N of something */
470 Sprintf(buf, "Pick %d of what?", count);
471 val_for_n_or_more = count; /* set up callback selector */
472 n = query_objlist(buf, objchain,
473 traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT,
474 &pick_list, PICK_ONE, n_or_more);
475 /* correct counts, if any given */
476 for (i = 0; i < n; i++)
477 pick_list[i].count = count;
479 n = query_objlist("Pick up what?", objchain,
480 traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT|FEEL_COCKATRICE,
481 &pick_list, PICK_ANY, all_but_uchain);
485 for (n_picked = i = 0 ; i < n; i++) {
486 res = pickup_object(pick_list[i].item.a_obj,pick_list[i].count,
488 if (res < 0) break; /* can't continue */
491 if (pick_list) free((genericptr_t)pick_list);
494 /* old style interface */
497 boolean all_of_a_type, selective;
498 char oclasses[MAXOCLASSES];
499 struct obj *obj, *obj2;
501 oclasses[0] = '\0'; /* types to consider (empty for all) */
502 all_of_a_type = TRUE; /* take all of considered types */
503 selective = FALSE; /* ask for each item */
505 /* check for more than one object */
507 obj; obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj)
510 if (ct == 1 && count) {
511 /* if only one thing, then pick it */
513 lcount = min(obj->quan, (long)count);
515 if (pickup_object(obj, lcount, FALSE) > 0)
516 n_picked++; /* picked something */
519 } else if (ct >= 2) {
522 There("are %s objects here.",
523 (ct <= 10) ? "several" : "many");
524 if (!query_classes(oclasses, &selective, &all_of_a_type,
526 traverse_how == BY_NEXTHERE,
531 if (!via_menu) return (0);
532 n = query_objlist("Pick up what?",
534 traverse_how|(selective ? 0 : INVORDER_SORT),
535 &pick_list, PICK_ANY,
536 via_menu == -2 ? allow_all : allow_category);
541 for (obj = objchain; obj; obj = obj2) {
542 if (traverse_how == BY_NEXTHERE)
543 obj2 = obj->nexthere; /* perhaps obj will be picked up */
548 if (!selective && oclasses[0] && !index(oclasses,obj->oclass))
551 if (!all_of_a_type) {
553 Sprintf(qbuf, "Pick up %s?",
554 safe_qbuf("", sizeof("Pick up ?"), doname(obj),
555 an(simple_typename(obj->otyp)), "something"));
556 switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
557 case 'q': goto end_query; /* out 2 levels */
560 all_of_a_type = TRUE;
563 oclasses[0] = obj->oclass;
567 case '#': /* count was entered */
568 if (!yn_number) continue; /* 0 count => No */
569 lcount = (long) yn_number;
570 if (lcount > obj->quan) lcount = obj->quan;
576 if (lcount == -1L) lcount = obj->quan;
579 if ((res = pickup_object(obj, lcount, FALSE)) < 0) break;
583 ; /* semicolon needed by brain-damaged compilers */
587 if (!OBJ_AT(u.ux,u.uy)) u.uundetected = 0;
589 /* position may need updating (invisible hero) */
590 if (n_picked) newsym(u.ux,u.uy);
592 /* see whether there's anything else here, after auto-pickup is done */
593 if (autopickup) check_here(n_picked > 0);
595 return (n_tried > 0);
598 #ifdef AUTOPICKUP_EXCEPTIONS
600 is_autopickup_exception(obj, grab)
602 boolean grab; /* forced pickup, rather than forced leave behind? */
605 * Does the text description of this match an exception?
607 char *objdesc = makesingular(doname(obj));
608 struct autopickup_exception *ape = (grab) ?
609 iflags.autopickup_exceptions[AP_GRAB] :
610 iflags.autopickup_exceptions[AP_LEAVE];
612 if (pmatch(ape->pattern, objdesc)) return TRUE;
617 #endif /* AUTOPICKUP_EXCEPTIONS */
620 * Pick from the given list using flags.pickup_types. Return the number
621 * of items picked (not counts). Create an array that returns pointers
622 * and counts of the items to be picked up. If the number of items
623 * picked is zero, the pickup list is left alone. The caller of this
624 * function must free the pickup list.
627 autopick(olist, follow, pick_list)
628 struct obj *olist; /* the object list */
629 int follow; /* how to follow the object list */
630 menu_item **pick_list; /* list of objects and counts to pick up */
632 menu_item *pi; /* pick item */
635 const char *otypes = flags.pickup_types;
637 /* first count the number of eligible items */
638 for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
641 #ifndef AUTOPICKUP_EXCEPTIONS
642 if (!*otypes || index(otypes, curr->oclass))
644 if ((!*otypes || index(otypes, curr->oclass) ||
645 is_autopickup_exception(curr, TRUE)) &&
646 !is_autopickup_exception(curr, FALSE))
651 *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n);
652 for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
653 #ifndef AUTOPICKUP_EXCEPTIONS
654 if (!*otypes || index(otypes, curr->oclass)) {
656 if ((!*otypes || index(otypes, curr->oclass) ||
657 is_autopickup_exception(curr, TRUE)) &&
658 !is_autopickup_exception(curr, FALSE)) {
660 pi[n].item.a_obj = curr;
661 pi[n].count = curr->quan;
670 * Put up a menu using the given object list. Only those objects on the
671 * list that meet the approval of the allow function are displayed. Return
672 * a count of the number of items selected, as well as an allocated array of
673 * menu_items, containing pointers to the objects selected and counts. The
674 * returned counts are guaranteed to be in bounds and non-zero.
677 * BY_NEXTHERE - Follow object list via nexthere instead of nobj.
678 * AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
680 * USE_INVLET - Use object's invlet.
681 * INVORDER_SORT - Use hero's pack order.
682 * SIGNAL_NOMENU - Return -1 rather than 0 if nothing passes "allow".
685 query_objlist(qstr, olist, qflags, pick_list, how, allow)
686 const char *qstr; /* query string */
687 struct obj *olist; /* the list to pick from */
688 int qflags; /* options to control the query */
689 menu_item **pick_list; /* return list of items picked */
690 int how; /* type of query */
691 boolean FDECL((*allow), (OBJ_P));/* allow function */
695 struct obj *curr, *last;
698 boolean printed_type_name;
700 *pick_list = (menu_item *) 0;
701 if (!olist) return 0;
703 /* count the number of items allowed */
704 for (n = 0, last = 0, curr = olist; curr; curr = FOLLOW(curr, qflags))
705 if ((*allow)(curr)) {
710 if (n == 0) /* nothing to pick here */
711 return (qflags & SIGNAL_NOMENU) ? -1 : 0;
713 if (n == 1 && (qflags & AUTOSELECT_SINGLE)) {
714 *pick_list = (menu_item *) alloc(sizeof(menu_item));
715 (*pick_list)->item.a_obj = last;
716 (*pick_list)->count = last->quan;
720 win = create_nhwindow(NHW_MENU);
722 any.a_obj = (struct obj *) 0;
725 * Run through the list and add the objects to the menu. If
726 * INVORDER_SORT is set, we'll run through the list once for
727 * each type so we can group them. The allow function will only
728 * be called once per object in the list.
730 pack = flags.inv_order;
732 printed_type_name = FALSE;
733 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
734 if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE &&
735 will_feel_cockatrice(curr, FALSE)) {
736 destroy_nhwindow(win); /* stop the menu and revert */
737 (void) look_here(0, FALSE);
740 if ((!(qflags & INVORDER_SORT) || curr->oclass == *pack)
743 /* if sorting, print type name (once only) */
744 if (qflags & INVORDER_SORT && !printed_type_name) {
745 any.a_obj = (struct obj *) 0;
746 add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
747 let_to_name(*pack, FALSE), MENU_UNSELECTED);
748 printed_type_name = TRUE;
752 add_menu(win, obj_to_glyph(curr), &any,
753 qflags & USE_INVLET ? curr->invlet : 0,
754 def_oc_syms[(int)objects[curr->otyp].oc_class],
755 ATR_NONE, doname(curr), MENU_UNSELECTED);
759 } while (qflags & INVORDER_SORT && *pack);
762 n = select_menu(win, how, pick_list);
763 destroy_nhwindow(win);
769 /* fix up counts: -1 means no count used => pick all */
770 for (i = 0, mi = *pick_list; i < n; i++, mi++)
771 if (mi->count == -1L || mi->count > mi->item.a_obj->quan)
772 mi->count = mi->item.a_obj->quan;
774 n = 0; /* caller's don't expect -1 */
780 * allow menu-based category (class) selection (for Drop,take off etc.)
784 query_category(qstr, olist, qflags, pick_list, how)
785 const char *qstr; /* query string */
786 struct obj *olist; /* the list to pick from */
787 int qflags; /* behaviour modification flags */
788 menu_item **pick_list; /* return list of items picked */
789 int how; /* type of query */
796 boolean collected_type_name;
799 boolean do_unpaid = FALSE;
800 boolean do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE,
801 do_buc_unknown = FALSE;
802 int num_buc_types = 0;
804 *pick_list = (menu_item *) 0;
805 if (!olist) return 0;
806 if ((qflags & UNPAID_TYPES) && count_unpaid(olist)) do_unpaid = TRUE;
807 if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED)) {
811 if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) {
815 if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) {
819 if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) {
820 do_buc_unknown = TRUE;
824 ccount = count_categories(olist, qflags);
825 /* no point in actually showing a menu for a single category */
826 if (ccount == 1 && !do_unpaid && num_buc_types <= 1 && !(qflags & BILLED_TYPES)) {
827 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
828 if ((qflags & WORN_TYPES) &&
829 !(curr->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL|W_WEP|W_SWAPWEP|W_QUIVER)))
834 *pick_list = (menu_item *) alloc(sizeof(menu_item));
835 (*pick_list)->item.a_int = curr->oclass;
839 impossible("query_category: no single object match");
845 win = create_nhwindow(NHW_MENU);
847 pack = flags.inv_order;
848 if ((qflags & ALL_TYPES) && (ccount > 1)) {
851 any.a_int = ALL_TYPES_SELECTED;
852 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
853 (qflags & WORN_TYPES) ? "All worn types" : "All types",
859 collected_type_name = FALSE;
860 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
861 if (curr->oclass == *pack) {
862 if ((qflags & WORN_TYPES) &&
863 !(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
864 W_WEP | W_SWAPWEP | W_QUIVER)))
866 if (!collected_type_name) {
868 any.a_int = curr->oclass;
869 add_menu(win, NO_GLYPH, &any, invlet++,
870 def_oc_syms[(int)objects[curr->otyp].oc_class],
871 ATR_NONE, let_to_name(*pack, FALSE),
873 collected_type_name = TRUE;
879 impossible("query_category: too many categories");
883 /* unpaid items if there are any */
888 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
889 "Unpaid items", MENU_UNSELECTED);
891 /* billed items: checked by caller, so always include if BILLED_TYPES */
892 if (qflags & BILLED_TYPES) {
896 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
897 "Unpaid items already used up", MENU_UNSELECTED);
899 if (qflags & CHOOSE_ALL) {
903 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
904 (qflags & WORN_TYPES) ?
905 "Auto-select every item being worn" :
906 "Auto-select every item", MENU_UNSELECTED);
908 /* items with b/u/c/unknown if there are any */
913 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
914 "Items known to be Blessed", MENU_UNSELECTED);
920 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
921 "Items known to be Cursed", MENU_UNSELECTED);
927 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
928 "Items known to be Uncursed", MENU_UNSELECTED);
930 if (do_buc_unknown) {
934 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
935 "Items of unknown B/C/U status",
939 n = select_menu(win, how, pick_list);
940 destroy_nhwindow(win);
942 n = 0; /* caller's don't expect -1 */
947 count_categories(olist, qflags)
952 boolean counted_category;
956 pack = flags.inv_order;
958 counted_category = FALSE;
959 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
960 if (curr->oclass == *pack) {
961 if ((qflags & WORN_TYPES) &&
962 !(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
963 W_WEP | W_SWAPWEP | W_QUIVER)))
965 if (!counted_category) {
967 counted_category = TRUE;
976 /* could we carry `obj'? if not, could we carry some of it/them? */
978 carry_count(obj, container, count, telekinesis, wt_before, wt_after)
979 struct obj *obj, *container; /* object to pick up, bag it's coming out of */
982 int *wt_before, *wt_after;
984 boolean adjust_wt = container && carried(container),
985 is_gold = obj->oclass == COIN_CLASS;
989 long umoney = money_cnt(invent);
992 const char *verb, *prefx1, *prefx2, *suffx;
993 char obj_nambuf[BUFSZ], where[BUFSZ];
995 savequan = obj->quan;
1000 if (count != savequan) {
1002 obj->owt = (unsigned)weight(obj);
1004 wt = iw + (int)obj->owt;
1006 wt -= (container->otyp == BAG_OF_HOLDING) ?
1007 (int)DELTA_CWT(container, obj) : (int)obj->owt;
1009 if (is_gold) /* merged gold might affect cumulative weight */
1010 wt -= (GOLD_WT(u.ugold) + GOLD_WT(count) - GOLD_WT(u.ugold + count));
1012 /* This will go with silver+copper & new gold weight */
1013 if (is_gold) /* merged gold might affect cumulative weight */
1014 wt -= (GOLD_WT(umoney) + GOLD_WT(count) - GOLD_WT(umoney + count));
1016 if (count != savequan) {
1017 obj->quan = savequan;
1026 /* see how many we can lift */
1029 iw -= (int)GOLD_WT(u.ugold);
1031 qq = GOLD_CAPACITY((long)iw, u.ugold);
1034 qq = 50L - (u.ugold % 100L) - 1L;
1036 iw -= (int)GOLD_WT(umoney);
1038 qq = GOLD_CAPACITY((long)iw, umoney);
1041 qq = 50L - (umoney % 100L) - 1L;
1043 if (qq < 0L) qq += 100L;
1044 for ( ; qq <= count; qq += 100L) {
1046 obj->owt = (unsigned)GOLD_WT(qq);
1048 ow = (int)GOLD_WT(u.ugold + qq);
1050 ow = (int)GOLD_WT(umoney + qq);
1052 ow -= (container->otyp == BAG_OF_HOLDING) ?
1053 (int)DELTA_CWT(container, obj) : (int)obj->owt;
1054 if (iw + ow >= 0) break;
1060 if (qq < 0L) qq = 0L;
1061 else if (qq > count) qq = count;
1063 wt = iw + (int)GOLD_WT(u.ugold + qq);
1065 wt = iw + (int)GOLD_WT(umoney + qq);
1067 } else if (count > 1 || count < obj->quan) {
1069 * Ugh. Calc num to lift by changing the quan of of the
1070 * object and calling weight.
1072 * This works for containers only because containers
1073 * don't merge. -dean
1075 for (qq = 1L; qq <= count; qq++) {
1077 obj->owt = (unsigned)(ow = weight(obj));
1079 ow -= (container->otyp == BAG_OF_HOLDING) ?
1080 (int)DELTA_CWT(container, obj) : (int)obj->owt;
1087 /* there's only one, and we can't lift it */
1090 obj->quan = savequan;
1094 /* some message will be given */
1095 Strcpy(obj_nambuf, doname(obj));
1097 Sprintf(where, "in %s", the(xname(container)));
1100 Strcpy(where, "lying here");
1101 verb = telekinesis ? "acquire" : "lift";
1104 /* lint supppression */
1105 *obj_nambuf = *where = '\0';
1108 /* we can carry qq of them */
1111 You("can only %s %s of the %s %s.",
1112 verb, (qq == 1L) ? "one" : "some", obj_nambuf, where);
1117 if (!container) Strcpy(where, "here"); /* slightly shorter form */
1119 if (invent || u.ugold) {
1121 if (invent || umoney) {
1123 prefx1 = "you cannot ";
1125 suffx = " any more";
1127 prefx1 = (obj->quan == 1L) ? "it " : "even one ";
1128 prefx2 = "is too heavy for you to ";
1131 There("%s %s %s, but %s%s%s%s.",
1132 otense(obj, "are"), obj_nambuf, where,
1133 prefx1, prefx2, verb, suffx);
1135 /* *wt_after = iw; */
1139 /* determine whether character is able and player is willing to carry `obj' */
1142 lift_object(obj, container, cnt_p, telekinesis)
1143 struct obj *obj, *container; /* object to pick up, bag it's coming out of */
1145 boolean telekinesis;
1147 int result, old_wt, new_wt, prev_encumbr, next_encumbr;
1149 if (obj->otyp == BOULDER && In_sokoban(&u.uz)) {
1150 You("cannot get your %s around this %s.",
1151 body_part(HAND), xname(obj));
1154 if (obj->otyp == LOADSTONE ||
1155 (obj->otyp == BOULDER && throws_rocks(youmonst.data)))
1156 return 1; /* lift regardless of current situation */
1158 *cnt_p = carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt);
1160 result = -1; /* nothing lifted */
1162 } else if (obj->oclass != COIN_CLASS && inv_cnt() >= 52 &&
1163 !merge_choice(invent, obj)) {
1165 } else if (inv_cnt() >= 52 && !merge_choice(invent, obj)) {
1167 Your("knapsack cannot accommodate any more items.");
1168 result = -1; /* nothing lifted */
1171 prev_encumbr = near_capacity();
1172 if (prev_encumbr < flags.pickup_burden)
1173 prev_encumbr = flags.pickup_burden;
1174 next_encumbr = calc_capacity(new_wt - old_wt);
1175 if (next_encumbr > prev_encumbr) {
1177 result = 0; /* don't lift */
1180 long savequan = obj->quan;
1184 (next_encumbr > HVY_ENCUMBER) ? overloadmsg :
1185 (next_encumbr > MOD_ENCUMBER) ? nearloadmsg :
1187 Sprintf(eos(qbuf), " %s. Continue?",
1188 safe_qbuf(qbuf, sizeof(" . Continue?"),
1189 doname(obj), an(simple_typename(obj->otyp)), "something"));
1190 obj->quan = savequan;
1191 switch (ynq(qbuf)) {
1192 case 'q': result = -1; break;
1193 case 'n': result = 0; break;
1194 default: break; /* 'y' => result == 1 */
1196 clear_nhwindow(WIN_MESSAGE);
1201 if (obj->otyp == SCR_SCARE_MONSTER && result <= 0 && !container)
1206 /* To prevent qbuf overflow in prompts use planA only
1207 * if it fits, or planB if PlanA doesn't fit,
1208 * finally using the fallback as a last resort.
1209 * last_restort is expected to be very short.
1212 safe_qbuf(qbuf, padlength, planA, planB, last_resort)
1213 const char *qbuf, *planA, *planB, *last_resort;
1216 /* convert size_t (or int for ancient systems) to ordinary unsigned */
1217 unsigned len_qbuf = (unsigned)strlen(qbuf),
1218 len_planA = (unsigned)strlen(planA),
1219 len_planB = (unsigned)strlen(planB),
1220 len_lastR = (unsigned)strlen(last_resort);
1221 unsigned textleft = QBUFSZ - (len_qbuf + padlength);
1223 if (len_lastR >= textleft) {
1224 impossible("safe_qbuf: last_resort too large at %u characters.",
1228 return (len_planA < textleft) ? planA :
1229 (len_planB < textleft) ? planB : last_resort;
1233 * Pick up <count> of obj from the ground and add it to the hero's inventory.
1234 * Returns -1 if caller should break out of its loop, 0 if nothing picked
1235 * up, 1 if otherwise.
1238 pickup_object(obj, count, telekinesis)
1241 boolean telekinesis; /* not picking it up directly by hand */
1245 const char *where = (obj->ox == u.ux && obj->oy == u.uy) ?
1249 if (obj->quan < count) {
1250 impossible("pickup_object: count %ld > quan %ld?",
1255 /* In case of auto-pickup, where we haven't had a chance
1256 to look at it yet; affects docall(SCR_SCARE_MONSTER). */
1258 #ifdef INVISIBLE_OBJECTS
1259 if (!obj->oinvis || See_invisible)
1263 if (obj == uchain) { /* do not pick up attached chain */
1265 } else if (obj->oartifact && !touch_artifact(obj,&youmonst)) {
1268 } else if (obj->oclass == COIN_CLASS) {
1269 /* Special consideration for gold pieces... */
1270 long iw = (long)max_capacity() - GOLD_WT(u.ugold);
1271 long gold_capacity = GOLD_CAPACITY(iw, u.ugold);
1273 if (gold_capacity <= 0L) {
1275 "There %s %ld gold piece%s %s, but you cannot carry any more.",
1277 obj->quan, plur(obj->quan), where);
1279 } else if (gold_capacity < count) {
1280 You("can only %s %s of the %ld gold pieces lying %s.",
1281 telekinesis ? "acquire" : "carry",
1282 gold_capacity == 1L ? "one" : "some", obj->quan, where);
1283 pline("%s %ld gold piece%s.",
1284 nearloadmsg, gold_capacity, plur(gold_capacity));
1285 u.ugold += gold_capacity;
1286 obj->quan -= gold_capacity;
1287 costly_gold(obj->ox, obj->oy, gold_capacity);
1290 if ((nearload = near_capacity()) != 0)
1291 pline("%s %ld gold piece%s.",
1292 nearload < MOD_ENCUMBER ?
1293 moderateloadmsg : nearloadmsg,
1294 count, plur(count));
1296 prinv((char *) 0, obj, count);
1297 costly_gold(obj->ox, obj->oy, count);
1298 if (count == obj->quan)
1304 if (flags.run) nomul(0);
1307 } else if (obj->otyp == CORPSE) {
1308 if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
1309 && !Stone_resistance && !telekinesis) {
1310 if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1311 display_nhwindow(WIN_MESSAGE, FALSE);
1315 Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1316 pline("Touching %s is a fatal mistake.", kbuf);
1320 } else if (is_rider(&mons[obj->corpsenm])) {
1321 pline("At your %s, the corpse suddenly moves...",
1322 telekinesis ? "attempted acquisition" : "touch");
1323 (void) revive_corpse(obj);
1324 exercise(A_WIS, FALSE);
1327 } else if (obj->otyp == SCR_SCARE_MONSTER) {
1328 if (obj->blessed) obj->blessed = 0;
1329 else if (!obj->spe && !obj->cursed) obj->spe = 1;
1331 pline_The("scroll%s %s to dust as you %s %s up.",
1332 plur(obj->quan), otense(obj, "turn"),
1333 telekinesis ? "raise" : "pick",
1334 (obj->quan == 1L) ? "it" : "them");
1335 if (!(objects[SCR_SCARE_MONSTER].oc_name_known) &&
1336 !(objects[SCR_SCARE_MONSTER].oc_uname))
1338 useupf(obj, obj->quan);
1339 return 1; /* tried to pick something up and failed, but
1340 don't want to terminate pickup loop yet */
1344 if ((res = lift_object(obj, (struct obj *)0, &count, telekinesis)) <= 0)
1348 /* Whats left of the special case for gold :-) */
1349 if (obj->oclass == COIN_CLASS) flags.botl = 1;
1351 if (obj->quan != count && obj->otyp != LOADSTONE)
1352 obj = splitobj(obj, count);
1354 obj = pick_obj(obj);
1356 if (uwep && uwep == obj) mrg_to_wielded = TRUE;
1357 nearload = near_capacity();
1358 prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0,
1360 mrg_to_wielded = FALSE;
1365 * Do the actual work of picking otmp from the floor or monster's interior
1366 * and putting it in the hero's inventory. Take care of billing. Return a
1367 * pointer to the object where otmp ends up. This may be different
1368 * from otmp because of merging.
1370 * Gold never reaches this routine unless GOLDOBJ is defined.
1376 obj_extract_self(otmp);
1377 if (!u.uswallow && otmp != uball && costly_spot(otmp->ox, otmp->oy)) {
1378 char saveushops[5], fakeshop[2];
1380 /* addtobill cares about your location rather than the object's;
1381 usually they'll be the same, but not when using telekinesis
1382 (if ever implemented) or a grappling hook */
1383 Strcpy(saveushops, u.ushops);
1384 fakeshop[0] = *in_rooms(otmp->ox, otmp->oy, SHOPBASE);
1386 Strcpy(u.ushops, fakeshop);
1387 /* sets obj->unpaid if necessary */
1388 addtobill(otmp, TRUE, FALSE, FALSE);
1389 Strcpy(u.ushops, saveushops);
1390 /* if you're outside the shop, make shk notice */
1391 if (!index(u.ushops, *fakeshop))
1392 remote_burglary(otmp->ox, otmp->oy);
1394 if (otmp->no_charge) /* only applies to objects outside invent */
1395 otmp->no_charge = 0;
1396 newsym(otmp->ox, otmp->oy);
1397 return addinv(otmp); /* might merge it with other objects */
1401 * prints a message if encumbrance changed since the last check and
1402 * returns the new encumbrance value (from near_capacity()).
1407 static int oldcap = UNENCUMBERED;
1408 int newcap = near_capacity();
1410 if(oldcap < newcap) {
1412 case 1: Your("movements are slowed slightly because of your load.");
1414 case 2: You("rebalance your load. Movement is difficult.");
1416 case 3: You("%s under your heavy load. Movement is very hard.",
1417 stagger(youmonst.data, "stagger"));
1419 default: You("%s move a handspan with this load!",
1420 newcap == 4 ? "can barely" : "can't even");
1424 } else if(oldcap > newcap) {
1426 case 0: Your("movements are now unencumbered.");
1428 case 1: Your("movements are only slowed slightly by your load.");
1430 case 2: You("rebalance your load. Movement is still difficult.");
1432 case 3: You("%s under your load. Movement is still very hard.",
1433 stagger(youmonst.data, "stagger"));
1443 /* Is there a container at x,y. Optional: return count of containers at x,y */
1445 container_at(x, y, countem)
1449 struct obj *cobj, *nobj;
1450 int container_count = 0;
1452 for(cobj = level.objects[x][y]; cobj; cobj = nobj) {
1453 nobj = cobj->nexthere;
1454 if(Is_container(cobj)) {
1456 if (!countem) break;
1459 return container_count;
1466 if (!can_reach_floor()) {
1468 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
1469 rider_cant_reach(); /* not skilled enough to reach */
1472 You("cannot reach the %s.", surface(x, y));
1474 } else if (is_pool(x, y) || is_lava(x, y)) {
1475 /* at present, can't loot in water even when Underwater */
1476 You("cannot loot things that are deep in the %s.",
1477 is_lava(x, y) ? "lava" : "water");
1479 } else if (nolimbs(youmonst.data)) {
1480 pline("Without limbs, you cannot loot anything.");
1482 } else if (!freehand()) {
1483 pline("Without a free %s, you cannot loot anything.",
1495 for(i = -1; i <= 1; i++)
1496 for(j = -1; j <= 1; j++) {
1499 if(isok(nx, ny) && MON_AT(nx, ny))
1506 doloot() /* loot a container on the floor or loot saddle from mon. */
1508 register struct obj *cobj, *nobj;
1509 register int c = -1;
1512 boolean underfoot = TRUE;
1513 const char *dont_find_anything = "don't find anything";
1516 int prev_inquiry = 0;
1517 boolean prev_loot = FALSE;
1519 if (check_capacity((char *)0)) {
1520 /* "Can't do that while carrying so much stuff." */
1523 if (nohands(youmonst.data)) {
1524 You("have no hands!"); /* not `body_part(HAND)' */
1527 cc.x = u.ux; cc.y = u.uy;
1531 if (container_at(cc.x, cc.y, FALSE)) {
1532 boolean any = FALSE;
1534 if (!able_to_loot(cc.x, cc.y)) return 0;
1535 for (cobj = level.objects[cc.x][cc.y]; cobj; cobj = nobj) {
1536 nobj = cobj->nexthere;
1538 if (Is_container(cobj)) {
1539 Sprintf(qbuf, "There is %s here, loot it?",
1540 safe_qbuf("", sizeof("There is here, loot it?"),
1541 doname(cobj), an(simple_typename(cobj->otyp)),
1544 if (c == 'q') return (timepassed);
1545 if (c == 'n') continue;
1548 if (cobj->olocked) {
1549 pline("Hmmm, it seems to be locked.");
1552 if (cobj->otyp == BAG_OF_TRICKS) {
1554 You("carefully open the bag...");
1555 pline("It develops a huge set of teeth and bites you!");
1557 if (Half_physical_damage) tmp = (tmp+1) / 2;
1558 losehp(tmp, "carnivorous bag", KILLED_BY_AN);
1559 makeknown(BAG_OF_TRICKS);
1564 You("carefully open %s...", the(xname(cobj)));
1565 timepassed |= use_container(cobj, 0);
1566 if (multi < 0) return 1; /* chest trap */
1570 } else if (Confusion) {
1573 long contribution = rnd((int)min(LARGEST_INT,u.ugold));
1574 struct obj *goldob = mkgoldobj(contribution);
1577 /* Find a money object to mess with */
1578 for (goldob = invent; goldob; goldob = goldob->nobj) {
1579 if (goldob->oclass == COIN_CLASS) break;
1582 long contribution = rnd((int)min(LARGEST_INT, goldob->quan));
1583 if (contribution < goldob->quan)
1584 goldob = splitobj(goldob, contribution);
1587 if (IS_THRONE(levl[u.ux][u.uy].typ)){
1588 struct obj *coffers;
1590 /* find the original coffers chest, or any chest */
1591 for (pass = 2; pass > -1; pass -= 2)
1592 for (coffers = fobj; coffers; coffers = coffers->nobj)
1593 if (coffers->otyp == CHEST && coffers->spe == pass)
1594 goto gotit; /* two level break */
1597 verbalize("Thank you for your contribution to reduce the debt.");
1598 (void) add_to_container(coffers, goldob);
1599 coffers->owt = weight(coffers);
1601 struct monst *mon = makemon(courtmon(),
1602 u.ux, u.uy, NO_MM_FLAGS);
1605 mon->mgold += goldob->quan;
1607 pline("The exchequer accepts your contribution.");
1615 add_to_minv(mon, goldob);
1616 pline("The exchequer accepts your contribution.");
1624 pline("Ok, now there is loot here.");
1627 } else if (IS_GRAVE(levl[cc.x][cc.y].typ)) {
1628 You("need to dig up the grave to effectively loot it...");
1631 * 3.3.1 introduced directional looting for some things.
1633 if (c != 'y' && mon_beside(u.ux, u.uy)) {
1634 if (!get_adjacent_loc("Loot in what direction?", "Invalid loot location",
1635 u.ux, u.uy, &cc)) return 0;
1636 if (cc.x == u.ux && cc.y == u.uy) {
1638 if (container_at(cc.x, cc.y, FALSE))
1643 You("%s to loot on the %s.", dont_find_anything,
1644 ceiling(cc.x, cc.y));
1648 mtmp = m_at(cc.x, cc.y);
1649 if (mtmp) timepassed = loot_mon(mtmp, &prev_inquiry, &prev_loot);
1651 /* Preserve pre-3.3.1 behaviour for containers.
1652 * Adjust this if-block to allow container looting
1653 * from one square away to change that in the future.
1656 if (container_at(cc.x, cc.y, FALSE)) {
1658 You_cant("loot anything %sthere with %s in the way.",
1659 prev_inquiry ? "else " : "", mon_nam(mtmp));
1662 You("have to be at a container to loot it.");
1665 You("%s %sthere to loot.", dont_find_anything,
1666 (prev_inquiry || prev_loot) ? "else " : "");
1670 } else if (c != 'y' && c != 'n') {
1671 You("%s %s to loot.", dont_find_anything,
1672 underfoot ? "here" : "there");
1674 return (timepassed);
1677 /* loot_mon() returns amount of time passed.
1680 loot_mon(mtmp, passed_info, prev_loot)
1691 /* 3.3.1 introduced the ability to remove saddle from a steed */
1692 /* *passed_info is set to TRUE if a loot query was given. */
1693 /* *prev_loot is set to TRUE if something was actually acquired in here. */
1694 if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
1696 if (passed_info) *passed_info = 1;
1697 Sprintf(qbuf, "Do you want to remove the saddle from %s?",
1698 x_monnam(mtmp, ARTICLE_THE, (char *)0, SUPPRESS_SADDLE, FALSE));
1699 if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
1700 if (nolimbs(youmonst.data)) {
1701 You_cant("do that without limbs."); /* not body_part(HAND) */
1705 You("can't. The saddle seems to be stuck to %s.",
1706 x_monnam(mtmp, ARTICLE_THE, (char *)0,
1707 SUPPRESS_SADDLE, FALSE));
1709 /* the attempt costs you time */
1712 obj_extract_self(otmp);
1713 if ((unwornmask = otmp->owornmask) != 0L) {
1714 mtmp->misc_worn_check &= ~unwornmask;
1715 otmp->owornmask = 0L;
1716 update_mon_intrinsics(mtmp, otmp, FALSE, FALSE);
1718 otmp = hold_another_object(otmp, "You drop %s!", doname(otmp),
1720 timepassed = rnd(3);
1721 if (prev_loot) *prev_loot = TRUE;
1722 } else if (c == 'q') {
1727 /* 3.4.0 introduced the ability to pick things up from within swallower's stomach */
1729 int count = passed_info ? *passed_info : 0;
1730 timepassed = pickup(count);
1736 * Decide whether an object being placed into a magic bag will cause
1737 * it to explode. If the object is a bag itself, check recursively.
1740 mbag_explodes(obj, depthin)
1744 /* these won't cause an explosion when they're empty */
1745 if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS) &&
1749 /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
1750 if ((Is_mbag(obj) || obj->otyp == WAN_CANCELLATION) &&
1751 (rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin))
1753 else if (Has_contents(obj)) {
1756 for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
1757 if (mbag_explodes(otmp, depthin+1)) return TRUE;
1762 /* A variable set in use_container(), to be used by the callback routines */
1763 /* in_container(), and out_container() from askchain() and use_container(). */
1764 static NEARDATA struct obj *current_container;
1765 #define Icebox (current_container->otyp == ICE_BOX)
1767 /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
1770 register struct obj *obj;
1772 boolean floor_container = !carried(current_container);
1773 boolean was_unpaid = FALSE;
1776 if (!current_container) {
1777 impossible("<in> no current_container?");
1779 } else if (obj == uball || obj == uchain) {
1780 You("must be kidding.");
1782 } else if (obj == current_container) {
1783 pline("That would be an interesting topological exercise.");
1785 } else if (obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
1786 Norep("You cannot %s %s you are wearing.",
1787 Icebox ? "refrigerate" : "stash", something);
1789 } else if ((obj->otyp == LOADSTONE) && obj->cursed) {
1791 pline_The("stone%s won't leave your person.", plur(obj->quan));
1793 } else if (obj->otyp == AMULET_OF_YENDOR ||
1794 obj->otyp == CANDELABRUM_OF_INVOCATION ||
1795 obj->otyp == BELL_OF_OPENING ||
1796 obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1797 /* Prohibit Amulets in containers; if you allow it, monsters can't
1798 * steal them. It also becomes a pain to check to see if someone
1799 * has the Amulet. Ditto for the Candelabrum, the Bell and the Book.
1801 pline("%s cannot be confined in such trappings.", The(xname(obj)));
1803 } else if (obj->otyp == LEASH && obj->leashmon != 0) {
1804 pline("%s attached to your pet.", Tobjnam(obj, "are"));
1806 } else if (obj == uwep) {
1811 setuwep((struct obj *) 0);
1812 if (uwep) return 0; /* unwielded, died, rewielded */
1813 } else if (obj == uswapwep) {
1814 setuswapwep((struct obj *) 0);
1815 if (uswapwep) return 0; /* unwielded, died, rewielded */
1816 } else if (obj == uquiver) {
1817 setuqwep((struct obj *) 0);
1818 if (uquiver) return 0; /* unwielded, died, rewielded */
1821 if (obj->otyp == CORPSE) {
1822 if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
1823 && !Stone_resistance) {
1824 if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1825 display_nhwindow(WIN_MESSAGE, FALSE);
1829 Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1830 pline("Touching %s is a fatal mistake.", kbuf);
1837 /* boxes, boulders, and big statues can't fit into any container */
1838 if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER ||
1839 (obj->otyp == STATUE && bigmonst(&mons[obj->corpsenm]))) {
1841 * xname() uses a static result array. Save obj's name
1842 * before current_container's name is computed. Don't
1843 * use the result of strcpy() within You() --- the order
1844 * of evaluation of the parameters is undefined.
1846 Strcpy(buf, the(xname(obj)));
1847 You("cannot fit %s into %s.", buf,
1848 the(xname(current_container)));
1854 if (obj_is_burning(obj)) /* this used to be part of freeinv() */
1855 (void) snuff_lit(obj);
1857 if (floor_container && costly_spot(u.ux, u.uy)) {
1858 if (current_container->no_charge && !obj->unpaid) {
1859 /* don't sell when putting the item into your own container */
1861 } else if (obj->oclass != COIN_CLASS) {
1862 /* sellobj() will take an unpaid item off the shop bill
1863 * note: coins are handled later */
1864 was_unpaid = obj->unpaid ? TRUE : FALSE;
1865 sellobj_state(SELL_DELIBERATE);
1866 sellobj(obj, u.ux, u.uy);
1867 sellobj_state(SELL_NORMAL);
1870 if (Icebox && !age_is_relative(obj)) {
1871 obj->age = monstermoves - obj->age; /* actual age */
1872 /* stop any corpse timeouts when frozen */
1873 if (obj->otyp == CORPSE && obj->timed) {
1874 long rot_alarm = stop_timer(ROT_CORPSE, (genericptr_t)obj);
1875 (void) stop_timer(REVIVE_MON, (genericptr_t)obj);
1876 /* mark a non-reviving corpse as such */
1877 if (rot_alarm) obj->norevive = 1;
1879 } else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
1880 /* explicitly mention what item is triggering the explosion */
1882 "As you put %s inside, you are blasted by a magical explosion!",
1884 /* did not actually insert obj yet */
1885 if (was_unpaid) addtobill(obj, FALSE, FALSE, TRUE);
1886 obfree(obj, (struct obj *)0);
1887 delete_contents(current_container);
1888 if (!floor_container)
1889 useup(current_container);
1890 else if (obj_here(current_container, u.ux, u.uy))
1891 useupf(current_container, obj->quan);
1893 panic("in_container: bag not found.");
1895 losehp(d(6,6),"magical explosion", KILLED_BY_AN);
1896 current_container = 0; /* baggone = TRUE; */
1899 if (current_container) {
1900 Strcpy(buf, the(xname(current_container)));
1901 You("put %s into %s.", doname(obj), buf);
1903 /* gold in container always needs to be added to credit */
1904 if (floor_container && obj->oclass == COIN_CLASS)
1905 sellobj(obj, current_container->ox, current_container->oy);
1906 (void) add_to_container(current_container, obj);
1907 current_container->owt = weight(current_container);
1909 /* gold needs this, and freeinv() many lines above may cause
1910 * the encumbrance to disappear from the status, so just always
1911 * update status immediately.
1915 return(current_container ? 1 : -1);
1922 return current_container && obj != current_container;
1925 /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
1928 register struct obj *obj;
1930 register struct obj *otmp;
1931 boolean is_gold = (obj->oclass == COIN_CLASS);
1935 if (!current_container) {
1936 impossible("<out> no current_container?");
1938 } else if (is_gold) {
1939 obj->owt = weight(obj);
1942 if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0;
1944 if (obj->otyp == CORPSE) {
1945 if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
1946 && !Stone_resistance) {
1947 if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1948 display_nhwindow(WIN_MESSAGE, FALSE);
1952 Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1953 pline("Touching %s is a fatal mistake.", kbuf);
1961 if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0)
1964 if (obj->quan != count && obj->otyp != LOADSTONE)
1965 obj = splitobj(obj, count);
1967 /* Remove the object from the list. */
1968 obj_extract_self(obj);
1969 current_container->owt = weight(current_container);
1971 if (Icebox && !age_is_relative(obj)) {
1972 obj->age = monstermoves - obj->age; /* actual age */
1973 if (obj->otyp == CORPSE)
1974 start_corpse_timeout(obj);
1976 /* simulated point of time */
1978 if(!obj->unpaid && !carried(current_container) &&
1979 costly_spot(current_container->ox, current_container->oy)) {
1980 obj->ox = current_container->ox;
1981 obj->oy = current_container->oy;
1982 addtobill(obj, FALSE, FALSE, FALSE);
1984 if (is_pick(obj) && !obj->unpaid && *u.ushops && shop_keeper(*u.ushops))
1985 verbalize("You sneaky cad! Get out of here with that pick!");
1988 loadlev = near_capacity();
1990 (loadlev < MOD_ENCUMBER ?
1991 "You have a little trouble removing" :
1992 "You have much trouble removing") : (char *)0,
1999 bot(); /* update character's gold piece count immediately */
2004 /* an object inside a cursed bag of holding is being destroyed */
2006 mbag_item_gone(held, item)
2014 pline("%s %s vanished!", Doname2(item), otense(item, "have"));
2016 You("%s %s disappear!", Blind ? "notice" : "see", doname(item));
2018 if (*u.ushops && (shkp = shop_keeper(*u.ushops)) != 0) {
2019 if (held ? (boolean) item->unpaid : costly_spot(u.ux, u.uy))
2020 loss = stolen_value(item, u.ux, u.uy,
2021 (boolean)shkp->mpeaceful, TRUE);
2023 obfree(item, (struct obj *) 0);
2028 observe_quantum_cat(box)
2031 static NEARDATA const char sc[] = "Schroedinger's Cat";
2032 struct obj *deadcat;
2033 struct monst *livecat;
2036 box->spe = 0; /* box->owt will be updated below */
2037 if (get_obj_location(box, &ox, &oy, 0))
2038 box->ox = ox, box->oy = oy; /* in case it's being carried */
2040 /* this isn't really right, since any form of observation
2041 (telepathic or monster/object/food detection) ought to
2042 force the determination of alive vs dead state; but basing
2043 it just on opening the box is much simpler to cope with */
2044 livecat = rn2(2) ? makemon(&mons[PM_HOUSECAT],
2045 box->ox, box->oy, NO_MINVENT) : 0;
2047 livecat->mpeaceful = 1;
2048 set_malign(livecat);
2049 if (!canspotmon(livecat))
2050 You("think %s brushed your %s.", something, body_part(FOOT));
2052 pline("%s inside the box is still alive!", Monnam(livecat));
2053 (void) christen_monst(livecat, sc);
2055 deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
2056 box->ox, box->oy, sc);
2058 obj_extract_self(deadcat);
2059 (void) add_to_container(box, deadcat);
2061 pline_The("%s inside the box is dead!",
2062 Hallucination ? rndmonnam() : "housecat");
2064 box->owt = weight(box);
2071 use_container(obj, held)
2072 register struct obj *obj;
2075 struct obj *curr, *otmp;
2077 struct obj *u_gold = (struct obj *)0;
2079 boolean one_by_one, allflag, quantum_cat = FALSE,
2080 loot_out = FALSE, loot_in = FALSE;
2081 char select[MAXOCLASSES+1];
2082 char qbuf[BUFSZ], emptymsg[BUFSZ], pbuf[QBUFSZ];
2084 int cnt = 0, used = 0,
2088 if (nohands(youmonst.data)) {
2089 You("have no hands!"); /* not `body_part(HAND)' */
2091 } else if (!freehand()) {
2092 You("have no free %s.", body_part(HAND));
2096 pline("%s to be locked.", Tobjnam(obj, "seem"));
2097 if (held) You("must put it down to unlock.");
2099 } else if (obj->otrapped) {
2100 if (held) You("open %s...", the(xname(obj)));
2101 (void) chest_trap(obj, HAND, FALSE);
2102 /* even if the trap fails, you've used up this turn */
2103 if (multi >= 0) { /* in case we didn't become paralyzed */
2109 current_container = obj; /* for use by in/out_container */
2111 if (obj->spe == 1) {
2112 observe_quantum_cat(obj);
2114 quantum_cat = TRUE; /* for adjusting "it's empty" message */
2116 /* Count the number of contained objects. Sometimes toss objects if */
2117 /* a cursed magic bag. */
2118 for (curr = obj->cobj; curr; curr = otmp) {
2120 if (Is_mbag(obj) && obj->cursed && !rn2(13)) {
2121 obj_extract_self(curr);
2122 loss += mbag_item_gone(held, curr);
2129 if (loss) /* magic bag lost some shop goods */
2130 You("owe %ld %s for lost merchandise.", loss, currency(loss));
2131 obj->owt = weight(obj); /* in case any items were lost */
2134 Sprintf(emptymsg, "%s is %sempty.", Yname2(obj),
2135 quantum_cat ? "now " : "");
2137 if (cnt || flags.menu_style == MENU_FULL) {
2138 Strcpy(qbuf, "Do you want to take something out of ");
2139 Sprintf(eos(qbuf), "%s?",
2140 safe_qbuf(qbuf, 1, yname(obj), ysimple_name(obj), "it"));
2141 if (flags.menu_style != MENU_TRADITIONAL) {
2142 if (flags.menu_style == MENU_FULL) {
2144 char menuprompt[BUFSZ];
2145 boolean outokay = (cnt != 0);
2147 boolean inokay = (invent != 0) || (u.ugold != 0);
2149 boolean inokay = (invent != 0);
2151 if (!outokay && !inokay) {
2152 pline("%s", emptymsg);
2153 You("don't have anything to put in.");
2156 menuprompt[0] = '\0';
2157 if (!cnt) Sprintf(menuprompt, "%s ", emptymsg);
2158 Strcat(menuprompt, "Do what?");
2159 t = in_or_out_menu(menuprompt, current_container, outokay, inokay);
2160 if (t <= 0) return 0;
2161 loot_out = (t & 0x01) != 0;
2162 loot_in = (t & 0x02) != 0;
2163 } else { /* MENU_COMBINATION or MENU_PARTIAL */
2164 loot_out = (yn_function(qbuf, "ynq", 'n') == 'y');
2167 add_valid_menu_class(0); /* reset */
2168 used |= menu_loot(0, current_container, FALSE) > 0;
2171 /* traditional code */
2173 menu_on_request = 0;
2174 add_valid_menu_class(0); /* reset */
2175 Strcpy(pbuf, ":ynq");
2176 if (cnt) Strcat(pbuf, "m");
2177 switch (yn_function(qbuf, pbuf, 'n')) {
2179 container_contents(current_container, FALSE, FALSE);
2182 if (query_classes(select, &one_by_one, &allflag,
2183 "take out", current_container->cobj,
2188 &menu_on_request)) {
2189 if (askchain((struct obj **)¤t_container->cobj,
2190 (one_by_one ? (char *)0 : select),
2191 allflag, out_container,
2192 (int FDECL((*),(OBJ_P)))0,
2195 } else if (menu_on_request < 0) {
2196 used |= menu_loot(menu_on_request,
2197 current_container, FALSE) > 0;
2203 menu_on_request = -2; /* triggers ALL_CLASSES */
2204 used |= menu_loot(menu_on_request, current_container, FALSE) > 0;
2212 pline("%s", emptymsg); /* <whatever> is empty. */
2216 if (!invent && u.ugold == 0) {
2220 /* nothing to put in, but some feedback is necessary */
2221 You("don't have anything to put in.");
2224 if (flags.menu_style != MENU_FULL) {
2225 Sprintf(qbuf, "Do you wish to put %s in?", something);
2226 Strcpy(pbuf, ynqchars);
2227 if (flags.menu_style == MENU_TRADITIONAL && invent && inv_cnt() > 0)
2229 switch (yn_function(qbuf, pbuf, 'n')) {
2236 add_valid_menu_class(0); /* reset */
2237 menu_on_request = -2; /* triggers ALL_CLASSES */
2238 used |= menu_loot(menu_on_request, current_container, TRUE) > 0;
2246 * Gone: being nice about only selecting food if we know we are
2247 * putting things in an ice chest.
2253 * Hack: gold is not in the inventory, so make a gold object
2254 * and put it at the head of the inventory list.
2256 u_gold = mkgoldobj(u.ugold); /* removes from u.ugold */
2257 u_gold->in_use = TRUE;
2258 u.ugold = u_gold->quan; /* put the gold back */
2259 assigninvlet(u_gold); /* might end up as NOINVSYM */
2260 u_gold->nobj = invent;
2264 add_valid_menu_class(0); /* reset */
2265 if (flags.menu_style != MENU_TRADITIONAL) {
2266 used |= menu_loot(0, current_container, TRUE) > 0;
2268 /* traditional code */
2269 menu_on_request = 0;
2270 if (query_classes(select, &one_by_one, &allflag, "put in",
2275 &menu_on_request)) {
2276 (void) askchain((struct obj **)&invent,
2277 (one_by_one ? (char *)0 : select), allflag,
2278 in_container, ck_bag, 0, "nodot");
2280 } else if (menu_on_request < 0) {
2281 used |= menu_loot(menu_on_request,
2282 current_container, TRUE) > 0;
2288 if (u_gold && invent && invent->oclass == COIN_CLASS) {
2289 /* didn't stash [all of] it */
2291 invent = u_gold->nobj;
2292 u_gold->in_use = FALSE;
2293 dealloc_obj(u_gold);
2299 /* Loot a container (take things out, put things in), using a menu. */
2301 menu_loot(retry, container, put_in)
2303 struct obj *container;
2306 int n, i, n_looted = 0;
2307 boolean all_categories = TRUE, loot_everything = FALSE;
2309 const char *takeout = "Take out", *putin = "Put in";
2310 struct obj *otmp, *otmp2;
2311 menu_item *pick_list;
2316 all_categories = (retry == -2);
2317 } else if (flags.menu_style == MENU_FULL) {
2318 all_categories = FALSE;
2319 Sprintf(buf,"%s what type of objects?", put_in ? putin : takeout);
2320 mflags = put_in ? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN :
2321 ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN;
2322 n = query_category(buf, put_in ? invent : container->cobj,
2323 mflags, &pick_list, PICK_ANY);
2325 for (i = 0; i < n; i++) {
2326 if (pick_list[i].item.a_int == 'A')
2327 loot_everything = TRUE;
2328 else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
2329 all_categories = TRUE;
2331 add_valid_menu_class(pick_list[i].item.a_int);
2333 free((genericptr_t) pick_list);
2336 if (loot_everything) {
2337 for (otmp = container->cobj; otmp; otmp = otmp2) {
2339 res = out_container(otmp);
2343 mflags = INVORDER_SORT;
2344 if (put_in && flags.invlet_constant) mflags |= USE_INVLET;
2345 Sprintf(buf,"%s what?", put_in ? putin : takeout);
2346 n = query_objlist(buf, put_in ? invent : container->cobj,
2347 mflags, &pick_list, PICK_ANY,
2348 all_categories ? allow_all : allow_category);
2351 for (i = 0; i < n; i++) {
2352 otmp = pick_list[i].item.a_obj;
2353 count = pick_list[i].count;
2354 if (count > 0 && count < otmp->quan) {
2355 otmp = splitobj(otmp, count);
2356 /* special split case also handled by askchain() */
2358 res = put_in ? in_container(otmp) : out_container(otmp);
2360 if (otmp != pick_list[i].item.a_obj) {
2361 /* split occurred, merge again */
2362 (void) merged(&pick_list[i].item.a_obj, &otmp);
2367 free((genericptr_t)pick_list);
2374 in_or_out_menu(prompt, obj, outokay, inokay)
2377 boolean outokay, inokay;
2381 menu_item *pick_list;
2384 const char *menuselector = iflags.lootabc ? "abc" : "oib";
2387 win = create_nhwindow(NHW_MENU);
2391 Sprintf(buf,"Take %s out of %s", something, the(xname(obj)));
2392 add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE,
2393 buf, MENU_UNSELECTED);
2398 Sprintf(buf,"Put %s into %s", something, the(xname(obj)));
2399 add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE, buf, MENU_UNSELECTED);
2402 if (outokay && inokay) {
2404 add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE,
2405 "Both of the above", MENU_UNSELECTED);
2407 end_menu(win, prompt);
2408 n = select_menu(win, PICK_ONE, &pick_list);
2409 destroy_nhwindow(win);
2411 n = pick_list[0].item.a_int;
2412 free((genericptr_t) pick_list);