1 /* SCCS Id: @(#)pickup.c 3.3 2000/03/01 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 /*
6 * Contains code for picking objects up, and container use.
7 */
8
9 #include "hack.h"
10
11 STATIC_DCL void FDECL(simple_look, (struct obj *,BOOLEAN_P));
12 STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
13 const char *,struct obj *,BOOLEAN_P,BOOLEAN_P,int *));
14 STATIC_DCL void FDECL(check_here, (BOOLEAN_P));
15 STATIC_DCL boolean FDECL(n_or_more, (struct obj *));
16 STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *));
17 #if 0 /* not used */
18 STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *));
19 #endif
20 STATIC_DCL int FDECL(autopick, (struct obj*, int, menu_item **));
21 STATIC_DCL int FDECL(count_categories, (struct obj *,int));
22 STATIC_DCL long FDECL(carry_count,
23 (struct obj *,struct obj *,long,BOOLEAN_P,int *,int *));
24 STATIC_DCL int FDECL(lift_object, (struct obj *,struct obj *,long *,BOOLEAN_P));
25 STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *,int));
26 STATIC_PTR int FDECL(in_container,(struct obj *));
27 STATIC_PTR int FDECL(ck_bag,(struct obj *));
28 STATIC_PTR int FDECL(out_container,(struct obj *));
29 STATIC_DCL int FDECL(menu_loot, (int, struct obj *, BOOLEAN_P));
30 STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *));
31 STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
32 STATIC_DCL boolean FDECL(able_to_loot, (int, int));
33 STATIC_DCL boolean FDECL(mon_beside, (int, int));
34
35 /* define for query_objlist() and autopickup() */
36 #define FOLLOW(curr, flags) \
37 (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
38
39 /*
40 * How much the weight of the given container will change when the given
41 * object is removed from it. This calculation must match the one used
42 * by weight() in mkobj.c.
43 */
44 #define DELTA_CWT(cont,obj) \
45 ((cont)->cursed ? (obj)->owt * 2 : \
46 1 + ((obj)->owt / ((cont)->blessed ? 4 : 2)))
47 #define GOLD_WT(n) (((n) + 50L) / 100L)
48 /* if you can figure this out, give yourself a hearty pat on the back... */
49 #define GOLD_CAPACITY(w,n) (((w) * -100L) - ((n) + 50L) - 1L)
50
51 static const char moderateloadmsg[] = "You have a little trouble lifting";
52 static const char nearloadmsg[] = "You have much trouble lifting";
53 static const char overloadmsg[] = "You have extreme difficulty lifting";
54
55 /* BUG: this lets you look at cockatrice corpses while blind without
56 touching them */
57 /* much simpler version of the look-here code; used by query_classes() */
58 STATIC_OVL void
simple_look(otmp,here)59 simple_look(otmp, here)
60 struct obj *otmp; /* list of objects */
61 boolean here; /* flag for type of obj list linkage */
62 {
63 /* Neither of the first two cases is expected to happen, since
64 * we're only called after multiple classes of objects have been
65 * detected, hence multiple objects must be present.
66 */
67 if (!otmp) {
68 impossible("simple_look(null)");
69 } else if (!(here ? otmp->nexthere : otmp->nobj)) {
70 pline("%s", doname(otmp));
71 } else {
72 winid tmpwin = create_nhwindow(NHW_MENU);
73 putstr(tmpwin, 0, "");
74 do {
75 putstr(tmpwin, 0, doname(otmp));
76 otmp = here ? otmp->nexthere : otmp->nobj;
77 } while (otmp);
78 display_nhwindow(tmpwin, TRUE);
79 destroy_nhwindow(tmpwin);
80 }
81 }
82
83 int
collect_obj_classes(ilets,otmp,here,incl_gold,filter)84 collect_obj_classes(ilets, otmp, here, incl_gold, filter)
85 char ilets[];
86 register struct obj *otmp;
87 boolean here, incl_gold;
88 boolean FDECL((*filter),(OBJ_P));
89 {
90 register int iletct = 0;
91 register char c;
92
93 if (incl_gold)
94 ilets[iletct++] = def_oc_syms[GOLD_CLASS];
95 ilets[iletct] = '\0'; /* terminate ilets so that index() will work */
96 while (otmp) {
97 c = def_oc_syms[(int)otmp->oclass];
98 if (!index(ilets, c) && (!filter || (*filter)(otmp)))
99 ilets[iletct++] = c, ilets[iletct] = '\0';
100 otmp = here ? otmp->nexthere : otmp->nobj;
101 }
102
103 return iletct;
104 }
105
106 /*
107 * Suppose some '?' and '!' objects are present, but '/' objects aren't:
108 * "a" picks all items without further prompting;
109 * "A" steps through all items, asking one by one;
110 * "?" steps through '?' items, asking, and ignores '!' ones;
111 * "/" becomes 'A', since no '/' present;
112 * "?a" or "a?" picks all '?' without further prompting;
113 * "/a" or "a/" becomes 'A' since there aren't any '/'
114 * (bug fix: 3.1.0 thru 3.1.3 treated it as "a");
115 * "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
116 * (ie, treated as if it had just been "?a").
117 */
118 STATIC_OVL boolean
query_classes(oclasses,one_at_a_time,everything,action,objs,here,incl_gold,menu_on_demand)119 query_classes(oclasses, one_at_a_time, everything, action, objs,
120 here, incl_gold, menu_on_demand)
121 char oclasses[];
122 boolean *one_at_a_time, *everything;
123 const char *action;
124 struct obj *objs;
125 boolean here, incl_gold;
126 int *menu_on_demand;
127 {
128 char ilets[20], inbuf[BUFSZ];
129 int iletct, oclassct;
130 boolean not_everything;
131 char qbuf[QBUFSZ];
132 boolean m_seen;
133
134 oclasses[oclassct = 0] = '\0';
135 *one_at_a_time = *everything = m_seen = FALSE;
136 iletct = collect_obj_classes(ilets, objs, here, incl_gold,
137 (boolean FDECL((*),(OBJ_P))) 0);
138 if (iletct == 0) {
139 return FALSE;
140 } else if (iletct == 1) {
141 oclasses[0] = def_char_to_objclass(ilets[0]);
142 oclasses[1] = '\0';
143 } else { /* more than one choice available */
144 const char *where = 0;
145 register char sym, oc_of_sym, *p;
146 /* additional choices */
147 ilets[iletct++] = ' ';
148 ilets[iletct++] = 'a';
149 ilets[iletct++] = 'A';
150 ilets[iletct++] = (objs == invent ? 'i' : ':');
151 if (menu_on_demand) {
152 ilets[iletct++] = 'm';
153 *menu_on_demand = 0;
154 }
155 ilets[iletct] = '\0';
156 ask_again:
157 oclasses[oclassct = 0] = '\0';
158 *one_at_a_time = *everything = FALSE;
159 not_everything = FALSE;
160 Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
161 action, ilets);
162 getlin(qbuf,inbuf);
163 if (*inbuf == '\033') return FALSE;
164
165 for (p = inbuf; (sym = *p++); ) {
166 /* new A function (selective all) added by GAN 01/09/87 */
167 if (sym == ' ') continue;
168 else if (sym == 'A') *one_at_a_time = TRUE;
169 else if (sym == 'a') *everything = TRUE;
170 else if (sym == ':') {
171 simple_look(objs, here); /* dumb if objs==invent */
172 goto ask_again;
173 } else if (sym == 'i') {
174 (void) display_inventory((char *)0, TRUE);
175 goto ask_again;
176 } else if (sym == 'm') {
177 m_seen = TRUE;
178 } else {
179 oc_of_sym = def_char_to_objclass(sym);
180 if (index(ilets,sym)) {
181 add_valid_menu_class(oc_of_sym);
182 oclasses[oclassct++] = oc_of_sym;
183 oclasses[oclassct] = '\0';
184 } else {
185 if (!where)
186 where = !strcmp(action,"pick up") ? "here" :
187 !strcmp(action,"take out") ?
188 "inside" : "";
189 if (*where)
190 There("are no %c's %s.", sym, where);
191 else
192 You("have no %c's.", sym);
193 not_everything = TRUE;
194 }
195 }
196 }
197 if (m_seen && menu_on_demand) {
198 *menu_on_demand = (*everything || !oclassct) ? -2 : -3;
199 return FALSE;
200 }
201 if (!oclassct && (!*everything || not_everything)) {
202 /* didn't pick anything,
203 or tried to pick something that's not present */
204 *one_at_a_time = TRUE; /* force 'A' */
205 *everything = FALSE; /* inhibit 'a' */
206 }
207 }
208 return TRUE;
209 }
210
211 /* look at the objects at our location, unless there are too many of them */
212 STATIC_OVL void
check_here(picked_some)213 check_here(picked_some)
214 boolean picked_some;
215 {
216 register struct obj *obj;
217 register int ct = 0;
218
219 /* count the objects here */
220 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) {
221 if (obj != uchain)
222 ct++;
223 }
224
225 /* If there are objects here, take a look. */
226 if (ct) {
227 if (flags.run) nomul(0);
228 flush_screen(1);
229 (void) look_here(ct, picked_some);
230 } else {
231 read_engr_at(u.ux,u.uy);
232 }
233 }
234
235 /* Value set by query_objlist() for n_or_more(). */
236 static long val_for_n_or_more;
237
238 /* query_objlist callback: return TRUE if obj's count is >= reference value */
239 STATIC_OVL boolean
n_or_more(obj)240 n_or_more(obj)
241 struct obj *obj;
242 {
243 if (obj == uchain) return FALSE;
244 return (obj->quan >= val_for_n_or_more);
245 }
246
247 /* List of valid menu classes for query_objlist() and allow_category callback */
248 static char valid_menu_classes[MAXOCLASSES + 2];
249
250 void
add_valid_menu_class(c)251 add_valid_menu_class(c)
252 int c;
253 {
254 static int vmc_count = 0;
255
256 if (c == 0) /* reset */
257 vmc_count = 0;
258 else
259 valid_menu_classes[vmc_count++] = (char)c;
260 valid_menu_classes[vmc_count] = '\0';
261 }
262
263 /* query_objlist callback: return TRUE if not uchain */
264 STATIC_OVL boolean
all_but_uchain(obj)265 all_but_uchain(obj)
266 struct obj *obj;
267 {
268 return (obj != uchain);
269 }
270
271 /* query_objlist callback: return TRUE */
272 /*ARGSUSED*/
273 boolean
allow_all(obj)274 allow_all(obj)
275 struct obj *obj;
276 {
277 return TRUE;
278 }
279
280 boolean
allow_category(obj)281 allow_category(obj)
282 struct obj *obj;
283 {
284 if (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
285 (index(valid_menu_classes, obj->oclass) != (char *)0))
286 return TRUE;
287 else
288 return FALSE;
289 }
290
291 #if 0 /* not used */
292 /* query_objlist callback: return TRUE if valid category (class), no uchain */
293 STATIC_OVL boolean
294 allow_cat_no_uchain(obj)
295 struct obj *obj;
296 {
297 if ((obj != uchain) &&
298 (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
299 (index(valid_menu_classes, obj->oclass) != (char *)0)))
300 return TRUE;
301 else
302 return FALSE;
303 }
304 #endif
305
306 /* query_objlist callback: return TRUE if valid class and worn */
307 boolean
is_worn_by_type(otmp)308 is_worn_by_type(otmp)
309 register struct obj *otmp;
310 {
311 return((boolean)(!!(otmp->owornmask &
312 (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP | W_SWAPWEP | W_QUIVER)))
313 && (index(valid_menu_classes, otmp->oclass) != (char *)0));
314 }
315
316 /*
317 * Have the hero pick things from the ground.
318 *
319 * Arg what:
320 * >0 autopickup
321 * =0 interactive
322 * <0 pickup count of something
323 *
324 * Returns 1 if tried to pick something up, whether
325 * or not it succeeded.
326 */
327 int
pickup(what)328 pickup(what)
329 int what; /* should be a long */
330 {
331 int i, n, res, count, n_tried = 0, n_picked = 0;
332 menu_item *pick_list = (menu_item *) 0;
333 boolean autopickup = what > 0;
334
335 if (what < 0) /* pick N of something */
336 count = -what;
337 else /* pick anything */
338 count = 0;
339
340 /* no auto-pick if no-pick move, nothing there, or in a pool */
341 if (autopickup && (flags.nopick || !OBJ_AT(u.ux, u.uy) ||
342 (is_pool(u.ux, u.uy) && !Underwater) || is_lava(u.ux, u.uy))) {
343 read_engr_at(u.ux, u.uy);
344 return (0);
345 }
346
347 /* no pickup if levitating & not on air or water level */
348 if (!can_reach_floor()) {
349 if ((multi && !flags.run) || (autopickup && !flags.pickup))
350 read_engr_at(u.ux, u.uy);
351 return (0);
352 }
353
354 /* multi && !flags.run means they are in the middle of some other
355 * action, or possibly paralyzed, sleeping, etc.... and they just
356 * teleported onto the object. They shouldn't pick it up.
357 */
358 if ((multi && !flags.run) || (autopickup && !flags.pickup)) {
359 check_here(FALSE);
360 return (0);
361 }
362
363 if (notake(youmonst.data)) {
364 if (!autopickup)
365 You("are physically incapable of picking anything up.");
366 else
367 check_here(FALSE);
368 return (0);
369 }
370
371 /* if there's anything here, stop running */
372 if (OBJ_AT(u.ux,u.uy) && flags.run && !flags.nopick) nomul(0);
373
374 add_valid_menu_class(0); /* reset */
375 /*
376 * Start the actual pickup process. This is split into two main
377 * sections, the newer menu and the older "traditional" methods.
378 * Automatic pickup has been split into its own menu-style routine
379 * to make things less confusing.
380 */
381 if (autopickup) {
382 n = autopick(level.objects[u.ux][u.uy], BY_NEXTHERE, &pick_list);
383 goto menu_pickup;
384 }
385
386 if (flags.menu_style != MENU_TRADITIONAL) {
387 /* use menus exclusively */
388
389 if (count) { /* looking for N of something */
390 char buf[QBUFSZ];
391 Sprintf(buf, "Pick %d of what?", count);
392 val_for_n_or_more = count; /* set up callback selector */
393 n = query_objlist(buf, level.objects[u.ux][u.uy],
394 BY_NEXTHERE|AUTOSELECT_SINGLE|INVORDER_SORT,
395 &pick_list, PICK_ONE, n_or_more);
396 /* correct counts, if any given */
397 for (i = 0; i < n; i++)
398 pick_list[i].count = count;
399 } else {
400 n = query_objlist("Pick up what?", level.objects[u.ux][u.uy],
401 BY_NEXTHERE|AUTOSELECT_SINGLE|INVORDER_SORT,
402 &pick_list, PICK_ANY, all_but_uchain);
403 }
404 menu_pickup:
405 n_tried = n;
406 for (n_picked = i = 0 ; i < n; i++) {
407 res = pickup_object(pick_list[i].item.a_obj,pick_list[i].count,
408 FALSE);
409 if (res < 0) break; /* can't continue */
410 n_picked += res;
411 }
412 if (pick_list) free((genericptr_t)pick_list);
413
414 } else {
415 /* old style interface */
416 int ct = 0;
417 long lcount;
418 boolean all_of_a_type, selective;
419 char oclasses[MAXOCLASSES];
420 struct obj *obj, *obj2;
421
422 oclasses[0] = '\0'; /* types to consider (empty for all) */
423 all_of_a_type = TRUE; /* take all of considered types */
424 selective = FALSE; /* ask for each item */
425
426 /* check for more than one object */
427 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
428 ct++;
429
430 if (ct == 1 && count) {
431 /* if only one thing, then pick it */
432 obj = level.objects[u.ux][u.uy];
433 lcount = min(obj->quan, (long)count);
434 n_tried++;
435 if (pickup_object(obj, lcount, FALSE) > 0)
436 n_picked++; /* picked something */
437 goto end_query;
438
439 } else if (ct >= 2) {
440 int via_menu = 0;
441
442 There("are %s objects here.",
443 (ct <= 10) ? "several" : "many");
444 if (!query_classes(oclasses, &selective, &all_of_a_type,
445 "pick up", level.objects[u.ux][u.uy],
446 TRUE, FALSE, &via_menu)) {
447 if (!via_menu) return (0);
448 n = query_objlist("Pick up what?",
449 level.objects[u.ux][u.uy],
450 BY_NEXTHERE|(selective ? 0 : INVORDER_SORT),
451 &pick_list, PICK_ANY,
452 via_menu == -2 ? allow_all : allow_category);
453 goto menu_pickup;
454 }
455 }
456
457 for (obj = level.objects[u.ux][u.uy]; obj; obj = obj2) {
458 obj2 = obj->nexthere; /* perhaps obj will be picked up */
459 lcount = -1L;
460
461 if (!selective && oclasses[0] && !index(oclasses,obj->oclass))
462 continue;
463
464 if (!all_of_a_type) {
465 char qbuf[QBUFSZ];
466 Sprintf(qbuf, "Pick up %s?", doname(obj));
467 switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
468 case 'q': goto end_query; /* out 2 levels */
469 case 'n': continue;
470 case 'a':
471 all_of_a_type = TRUE;
472 if (selective) {
473 selective = FALSE;
474 oclasses[0] = obj->oclass;
475 oclasses[1] = '\0';
476 }
477 break;
478 case '#': /* count was entered */
479 if (!yn_number) continue; /* 0 count => No */
480 lcount = (long) yn_number;
481 if (lcount > obj->quan) lcount = obj->quan;
482 /* fall thru */
483 default: /* 'y' */
484 break;
485 }
486 }
487 if (lcount == -1L) lcount = obj->quan;
488
489 n_tried++;
490 if ((res = pickup_object(obj, lcount, FALSE)) < 0) break;
491 n_picked += res;
492 }
493 end_query:
494 ; /* semicolon needed by brain-damaged compilers */
495 }
496
497 /* position may need updating (invisible hero) */
498 if (n_picked) newsym(u.ux,u.uy);
499
500 /* see whether there's anything else here, after auto-pickup is done */
501 if (autopickup) check_here(n_picked > 0);
502 return (n_tried > 0);
503 }
504
505 /*
506 * Pick from the given list using flags.pickup_types. Return the number
507 * of items picked (not counts). Create an array that returns pointers
508 * and counts of the items to be picked up. If the number of items
509 * picked is zero, the pickup list is left alone. The caller of this
510 * function must free the pickup list.
511 */
512 STATIC_OVL int
autopick(olist,follow,pick_list)513 autopick(olist, follow, pick_list)
514 struct obj *olist; /* the object list */
515 int follow; /* how to follow the object list */
516 menu_item **pick_list; /* list of objects and counts to pick up */
517 {
518 menu_item *pi; /* pick item */
519 struct obj *curr;
520 int n;
521 const char *otypes = flags.pickup_types;
522
523 /* first count the number of eligible items */
524 for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
525 if (!*otypes || index(otypes, curr->oclass))
526 n++;
527
528 if (n) {
529 *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n);
530 for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
531 if (!*otypes || index(otypes, curr->oclass)) {
532 pi[n].item.a_obj = curr;
533 pi[n].count = curr->quan;
534 n++;
535 }
536 }
537 return n;
538 }
539
540
541 /*
542 * Put up a menu using the given object list. Only those objects on the
543 * list that meet the approval of the allow function are displayed. Return
544 * a count of the number of items selected, as well as an allocated array of
545 * menu_items, containing pointers to the objects selected and counts. The
546 * returned counts are guaranteed to be in bounds and non-zero.
547 *
548 * Query flags:
549 * BY_NEXTHERE - Follow object list via nexthere instead of nobj.
550 * AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
551 * use it.
552 * USE_INVLET - Use object's invlet.
553 * INVORDER_SORT - Use hero's pack order.
554 * SIGNAL_NOMENU - Return -1 rather than 0 if nothing passes "allow".
555 */
556 int
query_objlist(qstr,olist,qflags,pick_list,how,allow)557 query_objlist(qstr, olist, qflags, pick_list, how, allow)
558 const char *qstr; /* query string */
559 struct obj *olist; /* the list to pick from */
560 int qflags; /* options to control the query */
561 menu_item **pick_list; /* return list of items picked */
562 int how; /* type of query */
563 boolean FDECL((*allow), (OBJ_P));/* allow function */
564 {
565 int n;
566 winid win;
567 struct obj *curr, *last;
568 char *pack;
569 anything any;
570 boolean printed_type_name;
571
572 *pick_list = (menu_item *) 0;
573 if (!olist) return 0;
574
575 /* count the number of items allowed */
576 for (n = 0, last = 0, curr = olist; curr; curr = FOLLOW(curr, qflags))
577 if ((*allow)(curr)) {
578 last = curr;
579 n++;
580 }
581
582 if (n == 0) /* nothing to pick here */
583 return (qflags & SIGNAL_NOMENU) ? -1 : 0;
584
585 if (n == 1 && (qflags & AUTOSELECT_SINGLE)) {
586 *pick_list = (menu_item *) alloc(sizeof(menu_item));
587 (*pick_list)->item.a_obj = last;
588 (*pick_list)->count = last->quan;
589 return 1;
590 }
591
592 win = create_nhwindow(NHW_MENU);
593 start_menu(win);
594 any.a_obj = (struct obj *) 0;
595
596 /*
597 * Run through the list and add the objects to the menu. If
598 * INVORDER_SORT is set, we'll run through the list once for
599 * each type so we can group them. The allow function will only
600 * be called once per object in the list.
601 */
602 pack = flags.inv_order;
603 do {
604 printed_type_name = FALSE;
605 for (curr = olist; curr; curr = FOLLOW(curr, qflags))
606 if ((!(qflags & INVORDER_SORT) || curr->oclass == *pack)
607 && (*allow)(curr)) {
608
609 /* if sorting, print type name (once only) */
610 if (qflags & INVORDER_SORT && !printed_type_name) {
611 any.a_obj = (struct obj *) 0;
612 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_INVERSE,
613 let_to_name(*pack, FALSE), MENU_UNSELECTED);
614 printed_type_name = TRUE;
615 }
616
617 any.a_obj = curr;
618 add_menu(win, obj_to_glyph(curr), &any,
619 qflags & USE_INVLET ? curr->invlet : 0,
620 def_oc_syms[(int)objects[curr->otyp].oc_class],
621 ATR_NONE, doname(curr), MENU_UNSELECTED);
622 }
623 pack++;
624 } while (qflags & INVORDER_SORT && *pack);
625
626 end_menu(win, qstr);
627 n = select_menu(win, how, pick_list);
628 destroy_nhwindow(win);
629
630 if (n > 0) {
631 menu_item *mi;
632 int i;
633
634 /* fix up counts: -1 means no count used => pick all */
635 for (i = 0, mi = *pick_list; i < n; i++, mi++)
636 if (mi->count == -1L || mi->count > mi->item.a_obj->quan)
637 mi->count = mi->item.a_obj->quan;
638 } else if (n < 0) {
639 n = 0; /* caller's don't expect -1 */
640 }
641 return n;
642 }
643
644 /*
645 * allow menu-based category (class) selection (for Drop,take off etc.)
646 *
647 */
648 int
query_category(qstr,olist,qflags,pick_list,how)649 query_category(qstr, olist, qflags, pick_list, how)
650 const char *qstr; /* query string */
651 struct obj *olist; /* the list to pick from */
652 int qflags; /* behaviour modification flags */
653 menu_item **pick_list; /* return list of items picked */
654 int how; /* type of query */
655 {
656 int n;
657 winid win;
658 struct obj *curr;
659 char *pack;
660 anything any;
661 boolean collected_type_name;
662 char invlet;
663 int ccount;
664 boolean do_unpaid = FALSE;
665
666 *pick_list = (menu_item *) 0;
667 if (!olist) return 0;
668 if ((qflags & UNPAID_TYPES) && count_unpaid(olist)) do_unpaid = TRUE;
669
670 ccount = count_categories(olist, qflags);
671 /* no point in actually showing a menu for a single category */
672 if (ccount == 1 && !do_unpaid && !(qflags & BILLED_TYPES)) {
673 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
674 if ((qflags & WORN_TYPES) &&
675 !(curr->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL|W_WEP|W_SWAPWEP|W_QUIVER)))
676 continue;
677 break;
678 }
679 if (curr) {
680 *pick_list = (menu_item *) alloc(sizeof(menu_item));
681 (*pick_list)->item.a_int = curr->oclass;
682 return 1;
683 } else {
684 #ifdef DEBUG
685 impossible("query_category: no single object match");
686 #endif
687 }
688 return 0;
689 }
690
691 win = create_nhwindow(NHW_MENU);
692 start_menu(win);
693 pack = flags.inv_order;
694 if ((qflags & ALL_TYPES) && (ccount > 1)) {
695 invlet = 'a';
696 any.a_void = 0;
697 any.a_int = ALL_TYPES_SELECTED;
698 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
699 (qflags & WORN_TYPES) ? "All worn types" : "All types",
700 MENU_UNSELECTED);
701 invlet = 'b';
702 } else
703 invlet = 'a';
704 do {
705 collected_type_name = FALSE;
706 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
707 if (curr->oclass == *pack) {
708 if ((qflags & WORN_TYPES) &&
709 !(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
710 W_WEP | W_SWAPWEP | W_QUIVER)))
711 continue;
712 if (!collected_type_name) {
713 any.a_void = 0;
714 any.a_int = curr->oclass;
715 add_menu(win, NO_GLYPH, &any, invlet++,
716 def_oc_syms[(int)objects[curr->otyp].oc_class],
717 ATR_NONE, let_to_name(*pack, FALSE),
718 MENU_UNSELECTED);
719 collected_type_name = TRUE;
720 }
721 }
722 }
723 pack++;
724 if (invlet >= 'u') {
725 impossible("query_category: too many categories");
726 return 0;
727 }
728 } while (*pack);
729 /* unpaid items if there are any */
730 if (do_unpaid) {
731 invlet = 'u';
732 any.a_void = 0;
733 any.a_int = 'u';
734 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
735 "Unpaid items", MENU_UNSELECTED);
736 }
737 /* billed items: checked by caller, so always include if BILLED_TYPES */
738 if (qflags & BILLED_TYPES) {
739 invlet = 'x';
740 any.a_void = 0;
741 any.a_int = 'x';
742 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
743 "Unpaid items already used up", MENU_UNSELECTED);
744 }
745 if (qflags & CHOOSE_ALL) {
746 invlet = 'A';
747 any.a_void = 0;
748 any.a_int = 'A';
749 add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
750 (qflags & WORN_TYPES) ?
751 "Auto-select every item being worn" :
752 "Auto-select every item", MENU_UNSELECTED);
753 }
754 end_menu(win, qstr);
755 n = select_menu(win, how, pick_list);
756 destroy_nhwindow(win);
757 if (n < 0)
758 n = 0; /* caller's don't expect -1 */
759 return n;
760 }
761
762 STATIC_OVL int
count_categories(olist,qflags)763 count_categories(olist, qflags)
764 struct obj *olist;
765 int qflags;
766 {
767 char *pack;
768 boolean counted_category;
769 int ccount = 0;
770 struct obj *curr;
771
772 pack = flags.inv_order;
773 do {
774 counted_category = FALSE;
775 for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
776 if (curr->oclass == *pack) {
777 if ((qflags & WORN_TYPES) &&
778 !(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
779 W_WEP | W_SWAPWEP | W_QUIVER)))
780 continue;
781 if (!counted_category) {
782 ccount++;
783 counted_category = TRUE;
784 }
785 }
786 }
787 pack++;
788 } while (*pack);
789 return ccount;
790 }
791
792 /* could we carry `obj'? if not, could we carry some of it/them? */
793 STATIC_OVL
carry_count(obj,container,count,telekinesis,wt_before,wt_after)794 long carry_count(obj, container, count, telekinesis, wt_before, wt_after)
795 struct obj *obj, *container; /* object to pick up, bag it's coming out of */
796 long count;
797 boolean telekinesis;
798 int *wt_before, *wt_after;
799 {
800 boolean adjust_wt = container && carried(container),
801 is_gold = obj->oclass == GOLD_CLASS;
802 int wt, iw, ow, oow;
803 long qq, savequan;
804 unsigned saveowt;
805 const char *verb, *prefx1, *prefx2, *suffx;
806 char obj_nambuf[BUFSZ], where[BUFSZ];
807
808 savequan = obj->quan;
809 saveowt = obj->owt;
810 iw = max_capacity();
811 if (count != savequan) {
812 obj->quan = count;
813 obj->owt = (unsigned)weight(obj);
814 }
815 wt = iw + (int)obj->owt;
816 if (adjust_wt)
817 wt -= (container->otyp == BAG_OF_HOLDING) ?
818 (int)DELTA_CWT(container, obj) : (int)obj->owt;
819 if (is_gold) /* merged gold might affect cumulative weight */
820 wt -= (GOLD_WT(u.ugold) + GOLD_WT(count) - GOLD_WT(u.ugold + count));
821 if (count != savequan) {
822 obj->quan = savequan;
823 obj->owt = saveowt;
824 }
825 *wt_before = iw;
826 *wt_after = wt;
827 if (wt < 0)
828 return count;
829
830 /* see how many we can lift */
831 if (is_gold) {
832 iw -= (int)GOLD_WT(u.ugold);
833 if (!adjust_wt) {
834 qq = GOLD_CAPACITY((long)iw, u.ugold);
835 } else {
836 oow = 0;
837 qq = 50L - (u.ugold % 100L) - 1L;
838 if (qq < 0L) qq += 100L;
839 for ( ; qq <= count; qq += 100L) {
840 obj->quan = qq;
841 obj->owt = (unsigned)GOLD_WT(qq);
842 ow = (int)GOLD_WT(u.ugold + qq);
843 ow -= (container->otyp == BAG_OF_HOLDING) ?
844 (int)DELTA_CWT(container, obj) : (int)obj->owt;
845 if (iw + ow >= 0) break;
846 oow = ow;
847 }
848 iw -= oow;
849 qq -= 100L;
850 }
851 if (qq < 0L) qq = 0L;
852 else if (qq > count) qq = count;
853 wt = iw + (int)GOLD_WT(u.ugold + qq);
854 } else if (count > 1 || count < obj->quan) {
855 /*
856 * Ugh. Calc num to lift by changing the quan of of the
857 * object and calling weight.
858 *
859 * This works for containers only because containers
860 * don't merge. -dean
861 */
862 for (qq = 1L; qq <= count; qq++) {
863 obj->quan = qq;
864 obj->owt = (unsigned)(ow = weight(obj));
865 if (adjust_wt)
866 ow -= (container->otyp == BAG_OF_HOLDING) ?
867 (int)DELTA_CWT(container, obj) : (int)obj->owt;
868 if (iw + ow >= 0)
869 break;
870 wt = iw + ow;
871 }
872 --qq;
873 } else {
874 /* there's only one, and we can't lift it */
875 qq = 0L;
876 }
877 obj->quan = savequan;
878 obj->owt = saveowt;
879
880 if (qq < count) {
881 /* some message will be given */
882 Strcpy(obj_nambuf, doname(obj));
883 if (container) {
884 Sprintf(where, "in %s", the(xname(container)));
885 verb = "carry";
886 } else {
887 Strcpy(where, "lying here");
888 verb = telekinesis ? "acquire" : "lift";
889 }
890 } else {
891 /* lint supppression */
892 *obj_nambuf = *where = '\0';
893 verb = "";
894 }
895 /* we can carry qq of them */
896 if (qq > 0) {
897 if (qq < count)
898 You("can only %s %s of the %s %s.",
899 verb, (qq == 1L) ? "one" : "some", obj_nambuf, where);
900 *wt_after = wt;
901 return qq;
902 }
903
904 if (!container) Strcpy(where, "here"); /* slightly shorter form */
905 if (invent || u.ugold) {
906 prefx1 = "you cannot ";
907 prefx2 = "";
908 suffx = " any more";
909 } else {
910 prefx1 = (obj->quan == 1L) ? "it " : "even one ";
911 prefx2 = "is too heavy for you to ";
912 suffx = "";
913 }
914 There("%s %s %s, but %s%s%s%s.",
915 (obj->quan == 1L) ? "is" : "are", obj_nambuf, where,
916 prefx1, prefx2, verb, suffx);
917
918 /* *wt_after = iw; */
919 return 0L;
920 }
921
922 /* determine whether character is able and player is willing to carry `obj' */
923 STATIC_OVL
lift_object(obj,container,cnt_p,telekinesis)924 int lift_object(obj, container, cnt_p, telekinesis)
925 struct obj *obj, *container; /* object to pick up, bag it's coming out of */
926 long *cnt_p;
927 boolean telekinesis;
928 {
929 int result, old_wt, new_wt, prev_encumbr, next_encumbr;
930
931
932 if (obj->otyp == BOULDER && In_sokoban(&u.uz)) {
933 You("cannot get your %s around this %s.",
934 body_part(HAND), xname(obj));
935 return -1;
936 }
937 if (obj->otyp == LOADSTONE ||
938 (obj->otyp == BOULDER && throws_rocks(youmonst.data)))
939 return 1; /* lift regardless of current situation */
940
941 *cnt_p = carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt);
942 if (*cnt_p < 1L) {
943 result = -1; /* nothing lifted */
944 } else if (obj->oclass != GOLD_CLASS && inv_cnt() >= 52 &&
945 !merge_choice(invent, obj)) {
946 Your("knapsack cannot accommodate any more items.");
947 result = -1; /* nothing lifted */
948 } else {
949 result = 1;
950 prev_encumbr = near_capacity();
951 if (prev_encumbr < flags.pickup_burden)
952 prev_encumbr = flags.pickup_burden;
953 next_encumbr = calc_capacity(new_wt - old_wt);
954 if (next_encumbr > prev_encumbr) {
955 if (telekinesis) {
956 result = 0; /* don't lift */
957 } else {
958 char qbuf[QBUFSZ];
959 long savequan = obj->quan;
960
961 obj->quan = *cnt_p;
962 Sprintf(qbuf, "%s %s. Continue?",
963 (next_encumbr > HVY_ENCUMBER) ? overloadmsg :
964 (next_encumbr > MOD_ENCUMBER) ? nearloadmsg :
965 moderateloadmsg, doname(obj));
966 obj->quan = savequan;
967 switch (ynq(qbuf)) {
968 case 'q': result = -1; break;
969 case 'n': result = 0; break;
970 default: break; /* 'y' => result == 1 */
971 }
972 }
973 }
974 }
975
976 if (obj->otyp == SCR_SCARE_MONSTER && result <= 0 && !container)
977 obj->spe = 0;
978 return result;
979 }
980
981 /*
982 * Pick up <count> of obj from the ground and add it to the hero's inventory.
983 * Returns -1 if caller should break out of its loop, 0 if nothing picked
984 * up, 1 if otherwise.
985 */
986 int
pickup_object(obj,count,telekinesis)987 pickup_object(obj, count, telekinesis)
988 struct obj *obj;
989 long count;
990 boolean telekinesis; /* not picking it up directly by hand */
991 {
992 int res, nearload;
993 const char *where = (obj->ox == u.ux && obj->oy == u.uy) ?
994 "here" : "there";
995
996 if (obj->quan < count) {
997 impossible("pickup_object: count %ld > quan %ld?",
998 count, obj->quan);
999 return 0;
1000 }
1001
1002 /* In case of auto-pickup, where we haven't had a chance
1003 to look at it yet; affects docall(SCR_SCARE_MONSTER). */
1004 if (!Blind)
1005 #ifdef INVISIBLE_OBJECTS
1006 if (!obj->oinvis || See_invisible)
1007 #endif
1008 obj->dknown = 1;
1009
1010 if (obj == uchain) { /* do not pick up attached chain */
1011 return 0;
1012 } else if (obj->oartifact && !touch_artifact(obj,&youmonst)) {
1013 return 0;
1014 } else if (obj->oclass == GOLD_CLASS) {
1015 /* Special consideration for gold pieces... */
1016 long iw = (long)max_capacity() - GOLD_WT(u.ugold);
1017 long gold_capacity = GOLD_CAPACITY(iw, u.ugold);
1018
1019 if (gold_capacity <= 0L) {
1020 pline(
1021 "There %s %ld gold piece%s %s, but you cannot carry any more.",
1022 (obj->quan == 1L) ? "is" : "are",
1023 obj->quan, plur(obj->quan), where);
1024 return 0;
1025 } else if (gold_capacity < count) {
1026 You("can only %s %s of the %ld gold pieces lying %s.",
1027 telekinesis ? "acquire" : "carry",
1028 gold_capacity == 1L ? "one" : "some", obj->quan, where);
1029 pline("%s %ld gold piece%s.",
1030 nearloadmsg, gold_capacity, plur(gold_capacity));
1031 u.ugold += gold_capacity;
1032 obj->quan -= gold_capacity;
1033 costly_gold(obj->ox, obj->oy, gold_capacity);
1034 } else {
1035 u.ugold += count;
1036 if ((nearload = near_capacity()) != 0)
1037 pline("%s %ld gold piece%s.",
1038 nearload < MOD_ENCUMBER ?
1039 moderateloadmsg : nearloadmsg,
1040 count, plur(count));
1041 else
1042 prinv((char *) 0, obj, count);
1043 costly_gold(obj->ox, obj->oy, count);
1044 if (count == obj->quan)
1045 delobj(obj);
1046 else
1047 obj->quan -= count;
1048 }
1049 flags.botl = 1;
1050 if (flags.run) nomul(0);
1051 return 1;
1052 } else if (obj->otyp == CORPSE) {
1053 if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
1054 && !Stone_resistance && !telekinesis) {
1055 if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1056 display_nhwindow(WIN_MESSAGE, FALSE);
1057 else {
1058 char kbuf[BUFSZ];
1059
1060 pline("Touching %s corpse is a fatal mistake.",
1061 an(mons[obj->corpsenm].mname));
1062 Sprintf(kbuf, "%s corpse", an(mons[obj->corpsenm].mname));
1063 instapetrify(kbuf);
1064 return -1;
1065 }
1066 } else if (is_rider(&mons[obj->corpsenm])) {
1067 pline("At your %s, the corpse suddenly moves...",
1068 telekinesis ? "attempted acquisition" : "touch");
1069 (void) revive_corpse(obj);
1070 exercise(A_WIS, FALSE);
1071 return -1;
1072 }
1073 } else if (obj->otyp == SCR_SCARE_MONSTER) {
1074 if (obj->blessed) obj->blessed = 0;
1075 else if (!obj->spe && !obj->cursed) obj->spe = 1;
1076 else {
1077 pline_The("scroll%s turn%s to dust as you %s %s up.",
1078 plur(obj->quan), (obj->quan == 1L) ? "s" : "",
1079 telekinesis ? "raise" : "pick",
1080 (obj->quan == 1L) ? "it" : "them");
1081 if (!(objects[SCR_SCARE_MONSTER].oc_name_known) &&
1082 !(objects[SCR_SCARE_MONSTER].oc_uname))
1083 docall(obj);
1084 useupf(obj, obj->quan);
1085 return 1; /* tried to pick something up and failed, but
1086 don't want to terminate pickup loop yet */
1087 }
1088 }
1089
1090 if ((res = lift_object(obj, (struct obj *)0, &count, telekinesis)) <= 0)
1091 return res;
1092
1093 if (obj->quan != count && obj->otyp != LOADSTONE)
1094 (void) splitobj(obj, count);
1095
1096 obj = pick_obj(obj);
1097
1098 if (uwep && uwep == obj) mrg_to_wielded = TRUE;
1099 nearload = near_capacity();
1100 prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0, obj, count);
1101 mrg_to_wielded = FALSE;
1102 return 1;
1103 }
1104
1105 /*
1106 * Do the actual work of picking otmp from the floor and putting
1107 * it in the hero's inventory. Take care of billing. Return a
1108 * pointer to the object where otmp ends up. This may be different
1109 * from otmp because of merging.
1110 *
1111 * Gold never reaches this routine.
1112 */
1113 struct obj *
pick_obj(otmp)1114 pick_obj(otmp)
1115 register struct obj *otmp;
1116 {
1117 obj_extract_self(otmp);
1118 if (*u.ushops && costly_spot(u.ux, u.uy) &&
1119 otmp != uball) /* don't charge for this - kd, 1/17/90 */
1120 /* sets obj->unpaid if necessary */
1121 addtobill(otmp, TRUE, FALSE, FALSE);
1122 if(Invisible) newsym(u.ux,u.uy);
1123 return(addinv(otmp)); /* might merge it with other objects */
1124 }
1125
1126 /*
1127 * prints a message if encumbrance changed since the last check and
1128 * returns the new encumbrance value (from near_capacity()).
1129 */
1130 int
encumber_msg()1131 encumber_msg()
1132 {
1133 static int oldcap = UNENCUMBERED;
1134 int newcap = near_capacity();
1135
1136 if(oldcap < newcap) {
1137 switch(newcap) {
1138 case 1: Your("movements are slowed slightly because of your load.");
1139 break;
1140 case 2: You("rebalance your load. Movement is difficult.");
1141 break;
1142 case 3: You("stagger under your heavy load. Movement is very hard.");
1143 break;
1144 default: You("%s move a handspan with this load!",
1145 newcap == 4 ? "can barely" : "can't even");
1146 break;
1147 }
1148 flags.botl = 1;
1149 } else if(oldcap > newcap) {
1150 switch(newcap) {
1151 case 0: Your("movements are now unencumbered.");
1152 break;
1153 case 1: Your("movements are only slowed slightly by your load.");
1154 break;
1155 case 2: You("rebalance your load. Movement is still difficult.");
1156 break;
1157 case 3: You("stagger under your load. Movement is still very hard.");
1158 break;
1159 }
1160 flags.botl = 1;
1161 }
1162
1163 oldcap = newcap;
1164 return (newcap);
1165 }
1166
1167 /* Is there a container at x,y. Optional: return count of containers at x,y */
1168 STATIC_OVL int
container_at(x,y,countem)1169 container_at(x, y, countem)
1170 int x,y;
1171 boolean countem;
1172 {
1173 struct obj *cobj, *nobj;
1174 int container_count = 0;
1175
1176 for(cobj = level.objects[x][y]; cobj; cobj = nobj) {
1177 nobj = cobj->nexthere;
1178 if(Is_container(cobj)) {
1179 container_count++;
1180 if (!countem) break;
1181 }
1182 }
1183 return container_count;
1184 }
1185
1186 STATIC_OVL boolean
able_to_loot(x,y)1187 able_to_loot(x, y)
1188 int x, y;
1189 {
1190 if (!can_reach_floor()) {
1191 #ifdef STEED
1192 if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
1193 You("aren't skilled enough to reach from %s.",
1194 mon_nam(u.usteed));
1195 else
1196 #endif
1197 You("cannot reach the %s.", surface(x, y));
1198 return FALSE;
1199 } else if (is_pool(x, y) || is_lava(x, y)) {
1200 /* at present, can't loot in water even when Underwater */
1201 You("cannot loot things that are deep in the %s.",
1202 is_lava(x, y) ? "lava" : "water");
1203 return FALSE;
1204 } else if (nolimbs(youmonst.data)) {
1205 pline("Without limbs, you cannot loot anything.");
1206 return FALSE;
1207 }
1208 return TRUE;
1209 }
1210
1211 STATIC_OVL
mon_beside(x,y)1212 boolean mon_beside(x,y)
1213 int x, y;
1214 {
1215 int i,j,nx,ny;
1216 for(i = -1; i <= 1; i++)
1217 for(j = -1; j <= 1; j++) {
1218 nx = x + i;
1219 ny = y + j;
1220 if(isok(nx, ny) && MON_AT(nx, ny))
1221 return TRUE;
1222 }
1223 return FALSE;
1224 }
1225
1226 int
doloot()1227 doloot() /* loot a container on the floor. */
1228 {
1229 register struct obj *cobj, *nobj;
1230 register int c = -1;
1231 int timepassed = 0;
1232 int x,y;
1233 boolean underfoot = TRUE;
1234 const char *dont_find_anything = "don't find anything";
1235 struct monst *mtmp;
1236 char qbuf[QBUFSZ];
1237 #ifdef STEED
1238 struct obj *otmp;
1239 boolean saddled_there = FALSE;
1240 boolean got_saddle = FALSE;
1241 #endif
1242
1243 if (check_capacity((char *)0)) {
1244 /* "Can't do that while carrying so much stuff." */
1245 return 0;
1246 }
1247 x = u.ux; y = u.uy;
1248
1249 lootcont:
1250
1251 if (container_at(x, y, FALSE)) {
1252 if (!able_to_loot(x, y)) return 0;
1253 for (cobj = level.objects[x][y]; cobj; cobj = nobj) {
1254 nobj = cobj->nexthere;
1255
1256 if (Is_container(cobj)) {
1257 Sprintf(qbuf, "There is %s here, loot it?", doname(cobj));
1258 c = ynq(qbuf);
1259 if (c == 'q') return (timepassed);
1260 if (c == 'n') continue;
1261
1262 if (cobj->olocked) {
1263 pline("Hmmm, it seems to be locked.");
1264 continue;
1265 }
1266 if (cobj->otyp == BAG_OF_TRICKS) {
1267 You("carefully open the bag...");
1268 pline("It develops a huge set of teeth and bites you!");
1269 c = rnd(10);
1270 if (Half_physical_damage) c = (c+1) / 2;
1271 losehp(c, "carnivorous bag", KILLED_BY_AN);
1272 makeknown(BAG_OF_TRICKS);
1273 timepassed = 1;
1274 continue;
1275 }
1276
1277 You("carefully open %s...", the(xname(cobj)));
1278 timepassed |= use_container(cobj, 0);
1279 if (multi < 0) return 1; /* chest trap */
1280 }
1281 }
1282 } else if (Confusion) {
1283 if (u.ugold){
1284 long contribution = rnd((int)min(LARGEST_INT,u.ugold));
1285 struct obj *goldob = mkgoldobj(contribution);
1286 if (IS_THRONE(levl[u.ux][u.uy].typ)){
1287 struct obj *coffers;
1288 int pass;
1289 /* find the original coffers chest, or any chest */
1290 for (pass = 2; pass > -1; pass -= 2)
1291 for (coffers = fobj; coffers; coffers = coffers->nobj)
1292 if (coffers->otyp == CHEST && coffers->spe == pass)
1293 goto gotit; /* two level break */
1294 gotit:
1295 if (coffers){
1296 struct obj *tmp;
1297 verbalize("Thank you for your contribution to reduce the debt.");
1298 for (tmp = coffers->cobj; tmp; tmp = tmp->nobj)
1299 if (tmp->otyp == goldob->otyp) break;
1300
1301 if (tmp) {
1302 tmp->quan += goldob->quan;
1303 delobj(goldob);
1304 } else {
1305 add_to_container(coffers, goldob);
1306 }
1307 } else {
1308 struct monst *mon = makemon(courtmon(),
1309 u.ux, u.uy, NO_MM_FLAGS);
1310 if (mon) {
1311 mon->mgold += goldob->quan;
1312 delobj(goldob);
1313 pline("The exchequer accepts your contribution.");
1314 } else {
1315 dropx(goldob);
1316 }
1317 }
1318 } else {
1319 dropx(goldob);
1320 pline("Ok, now there is loot here.");
1321 }
1322 }
1323 } else if (IS_GRAVE(levl[x][y].typ)) {
1324 You("need to dig up the grave to effectively loot it...");
1325 }
1326 /*
1327 * 3.3.1 introduced directional looting for some things.
1328 */
1329 if (c != 'y' && mon_beside(u.ux, u.uy)) {
1330 if (!getdir("Loot in what direction?")) {
1331 pline(Never_mind);
1332 return(0);
1333 }
1334 x = u.ux + u.dx;
1335 y = u.uy + u.dy;
1336 if (x == u.ux && y == u.uy) {
1337 underfoot = TRUE;
1338 if (container_at(x, y, FALSE))
1339 goto lootcont;
1340 } else
1341 underfoot = FALSE;
1342 if (u.dz < 0) {
1343 You("%s to loot on the %s.", dont_find_anything,
1344 ceiling(x, y));
1345 timepassed = 1;
1346 return timepassed;
1347 }
1348 mtmp = m_at(x, y);
1349 #ifdef STEED
1350 /* 3.3.1 introduced the ability to remove saddle from a steed */
1351 if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
1352 long unwornmask;
1353 saddled_there = TRUE;
1354 Sprintf(qbuf, "Do you want to remove the saddle from %s?",
1355 x_monnam(mtmp, ARTICLE_THE, (char *)0, SUPPRESS_SADDLE, FALSE));
1356 if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
1357 if (nolimbs(youmonst.data)) {
1358 You_cant("do that without limbs."); /* not body_part(HAND) */
1359 return (0);
1360 }
1361 if (otmp->cursed) {
1362 You("can't. The saddle seems to be stuck to %s.",
1363 x_monnam(mtmp, ARTICLE_THE, (char *)0,
1364 SUPPRESS_SADDLE, FALSE));
1365
1366 /* the attempt costs you time */
1367 return (1);
1368 }
1369 obj_extract_self(otmp);
1370 if ((unwornmask = otmp->owornmask) != 0L) {
1371 mtmp->misc_worn_check &= ~unwornmask;
1372 otmp->owornmask = 0L;
1373 update_mon_intrinsics(mtmp, otmp, FALSE);
1374 }
1375 otmp = hold_another_object(otmp, "You drop %s!", doname(otmp),
1376 (const char *)0);
1377 timepassed = rnd(3);
1378 got_saddle = TRUE;
1379 } else if (c == 'q') {
1380 return (0);
1381 }
1382 }
1383 # if 0
1384 /* Loot your steed, even if you can't reach the floor */
1385 if (u.usteed) {
1386 Sprintf(qbuf, "Do you want to loot %s inventory?",
1387 s_suffix(x_monnam(u.usteed, ARTICLE_YOUR,
1388 (char *)0, SUPPRESS_SADDLE, FALSE)));
1389 switch (c = ynq(qbuf)) {
1390 case 'y':
1391 if (!u.usteed->minvent) {
1392 impossible("no saddle?");
1393 break;
1394 }
1395 /* TO DO: get and put things into the inventory */
1396 You("peek at %s inventory...",
1397 s_suffix(x_monnam(u.usteed, ARTICLE_YOUR,
1398 (char *)0, SUPPRESS_SADDLE, FALSE)));
1399 (void) display_minventory(u.usteed, MINV_ALL);
1400 timepassed = 1;
1401 break;
1402 case 'n':
1403 break;
1404 case 'q':
1405 return (0);
1406 }
1407 }
1408 # endif
1409 #endif /* STEED */
1410
1411 /* Preserve pre-3.3.1 behaviour for containers.
1412 * Adjust this if-block to allow container looting
1413 * from one square away to change that in the future.
1414 */
1415 if (!underfoot) {
1416 if (container_at(x, y, FALSE)) {
1417 if (mtmp) {
1418 You("can't loot anything %sthere with %s in the way.",
1419 #ifdef STEED
1420 saddled_there ? "else " :
1421 #endif
1422 "", mon_nam(mtmp));
1423 return timepassed;
1424 } else {
1425 You("have to be at a container to loot it.");
1426 }
1427 } else {
1428 You("%s %sthere to loot.", dont_find_anything,
1429 #ifdef STEED
1430 (saddled_there || got_saddle) ? "else " :
1431 #endif
1432 "");
1433 return timepassed;
1434 }
1435 }
1436 } else if (c != 'y' && c != 'n') {
1437 You("%s %s to loot.", dont_find_anything,
1438 underfoot ? "here" : "there");
1439 }
1440 return (timepassed);
1441 }
1442
1443 /*
1444 * Decide whether an object being placed into a magic bag will cause
1445 * it to explode. If the object is a bag itself, check recursively.
1446 */
1447 STATIC_OVL boolean
mbag_explodes(obj,depthin)1448 mbag_explodes(obj, depthin)
1449 struct obj *obj;
1450 int depthin;
1451 {
1452 /* these won't cause an explosion when they're empty */
1453 if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS) &&
1454 obj->spe <= 0)
1455 return FALSE;
1456
1457 /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
1458 if ((Is_mbag(obj) || obj->otyp == WAN_CANCELLATION) &&
1459 (rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin))
1460 return TRUE;
1461 else if (Has_contents(obj)) {
1462 struct obj *otmp;
1463
1464 for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
1465 if (mbag_explodes(otmp, depthin+1)) return TRUE;
1466 }
1467 return FALSE;
1468 }
1469
1470 /* A variable set in use_container(), to be used by the callback routines */
1471 /* in_container(), and out_container() from askchain() and use_container(). */
1472 static NEARDATA struct obj *current_container;
1473 #define Icebox (current_container->otyp == ICE_BOX)
1474
1475 /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
1476 STATIC_PTR int
in_container(obj)1477 in_container(obj)
1478 register struct obj *obj;
1479 {
1480 register struct obj *gold;
1481 boolean is_gold = (obj->oclass == GOLD_CLASS);
1482 boolean floor_container = !carried(current_container);
1483 char buf[BUFSZ];
1484
1485 if (!current_container) {
1486 impossible("<in> no current_container?");
1487 return 0;
1488 } else if (obj == uball || obj == uchain) {
1489 You("must be kidding.");
1490 return 0;
1491 } else if (obj == current_container) {
1492 pline("That would be an interesting topological exercise.");
1493 return 0;
1494 } else if (obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
1495 Norep("You cannot %s %s you are wearing.",
1496 Icebox ? "refrigerate" : "stash", something);
1497 return 0;
1498 } else if ((obj->otyp == LOADSTONE) && obj->cursed) {
1499 obj->bknown = 1;
1500 pline_The("stone%s won't leave your person.", plur(obj->quan));
1501 return 0;
1502 } else if (obj->otyp == AMULET_OF_YENDOR ||
1503 obj->otyp == CANDELABRUM_OF_INVOCATION ||
1504 obj->otyp == BELL_OF_OPENING ||
1505 obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1506 /* Prohibit Amulets in containers; if you allow it, monsters can't
1507 * steal them. It also becomes a pain to check to see if someone
1508 * has the Amulet. Ditto for the Candelabrum, the Bell and the Book.
1509 */
1510 pline("%s cannot be confined in such trappings.", The(xname(obj)));
1511 return 0;
1512 } else if (obj->otyp == LEASH && obj->leashmon != 0) {
1513 pline("%s is attached to your pet.", The(xname(obj)));
1514 return 0;
1515 } else if (obj == uwep) {
1516 if (welded(obj)) {
1517 weldmsg(obj);
1518 return 0;
1519 }
1520 setuwep((struct obj *) 0);
1521 if (uwep) return 0; /* unwielded, died, rewielded */
1522 } else if (obj == uswapwep) {
1523 setuswapwep((struct obj *) 0);
1524 if (uswapwep) return 0; /* unwielded, died, rewielded */
1525 } else if (obj == uquiver) {
1526 setuqwep((struct obj *) 0);
1527 if (uquiver) return 0; /* unwielded, died, rewielded */
1528 }
1529
1530 /* boxes, boulders, and big statues can't fit into any container */
1531 if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER ||
1532 (obj->otyp == STATUE && bigmonst(&mons[obj->corpsenm]))) {
1533 /*
1534 * xname() uses a static result array. Save obj's name
1535 * before current_container's name is computed. Don't
1536 * use the result of strcpy() within You() --- the order
1537 * of evaluation of the parameters is undefined.
1538 */
1539 Strcpy(buf, the(xname(obj)));
1540 You("cannot fit %s into %s.", buf,
1541 the(xname(current_container)));
1542 return 0;
1543 }
1544
1545 freeinv(obj);
1546
1547 if (is_gold) { /* look for other money to merge within the container */
1548 for (gold = current_container->cobj; gold; gold = gold->nobj)
1549 if (gold->otyp == obj->otyp) break;
1550 } else
1551 gold = 0;
1552
1553 if (gold) {
1554 gold->quan += obj->quan;
1555 } else {
1556 add_to_container(current_container, obj);
1557 }
1558
1559 current_container->owt = weight(current_container);
1560
1561 Strcpy(buf, the(xname(current_container)));
1562 You("put %s into %s.", doname(obj), buf);
1563
1564 if (obj_is_burning(obj)) /* this used to be part of freeinv() */
1565 (void) snuff_lit(obj);
1566
1567 if (floor_container && costly_spot(u.ux, u.uy)) {
1568 sellobj_state(TRUE);
1569 sellobj(obj, u.ux, u.uy);
1570 sellobj_state(FALSE);
1571 }
1572 if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN
1573 && !Is_candle(obj)) {
1574 obj->age = monstermoves - obj->age; /* actual age */
1575 /* stop any corpse timeouts when frozen */
1576 if (obj->otyp == CORPSE && obj->timed) {
1577 (void) stop_timer(ROT_CORPSE, (genericptr_t)obj);
1578 (void) stop_timer(REVIVE_MON, (genericptr_t)obj);
1579 }
1580 }
1581
1582 else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
1583 You("are blasted by a magical explosion!");
1584
1585 /* the !floor_container case is taken care of */
1586 if(*u.ushops && costly_spot(u.ux, u.uy) && floor_container) {
1587 register struct monst *shkp;
1588
1589 if ((shkp = shop_keeper(*u.ushops)) != 0)
1590 (void)stolen_value(current_container, u.ux, u.uy,
1591 (boolean)shkp->mpeaceful, FALSE);
1592 }
1593 delete_contents(current_container);
1594 if (!floor_container)
1595 useup(current_container);
1596 else if (obj_here(current_container, u.ux, u.uy))
1597 useupf(current_container, obj->quan);
1598 else
1599 panic("in_container: bag not found.");
1600
1601 losehp(d(6,6),"magical explosion", KILLED_BY_AN);
1602 current_container = 0; /* baggone = TRUE; */
1603 }
1604
1605 if (is_gold) {
1606 if (gold) dealloc_obj(obj);
1607 bot(); /* update character's gold piece count immediately */
1608 }
1609
1610 return(current_container ? 1 : -1);
1611 }
1612
1613 STATIC_PTR int
ck_bag(obj)1614 ck_bag(obj)
1615 struct obj *obj;
1616 {
1617 return current_container && obj != current_container;
1618 }
1619
1620 /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
1621 STATIC_PTR int
out_container(obj)1622 out_container(obj)
1623 register struct obj *obj;
1624 {
1625 register struct obj *otmp;
1626 boolean is_gold = (obj->oclass == GOLD_CLASS);
1627 int res, loadlev;
1628 long count;
1629
1630 if (!current_container) {
1631 impossible("<out> no current_container?");
1632 return -1;
1633 } else if (is_gold) {
1634 obj->owt = weight(obj);
1635 }
1636
1637 if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0;
1638
1639 count = obj->quan;
1640 if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0)
1641 return res;
1642
1643 if (obj->quan != count && obj->otyp != LOADSTONE)
1644 (void) splitobj(obj, count);
1645
1646 /* Remove the object from the list. */
1647 obj_extract_self(obj);
1648 current_container->owt = weight(current_container);
1649
1650 if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN
1651 && !Is_candle(obj)) {
1652 obj->age = monstermoves - obj->age; /* actual age */
1653 if (obj->otyp == CORPSE)
1654 start_corpse_timeout(obj);
1655 }
1656 /* simulated point of time */
1657
1658 if (is_pick(obj) && !obj->unpaid && *u.ushops && shop_keeper(*u.ushops))
1659 verbalize("You sneaky cad! Get out of here with that pick!");
1660 if(!obj->unpaid && !carried(current_container) &&
1661 costly_spot(current_container->ox, current_container->oy)) {
1662
1663 obj->ox = current_container->ox;
1664 obj->oy = current_container->oy;
1665 addtobill(obj, FALSE, FALSE, FALSE);
1666 }
1667
1668 otmp = addinv(obj);
1669 loadlev = near_capacity();
1670 prinv(loadlev ?
1671 (loadlev < MOD_ENCUMBER ?
1672 "You have a little trouble removing" :
1673 "You have much trouble removing") : (char *)0,
1674 otmp, count);
1675
1676 if (is_gold) {
1677 dealloc_obj(obj);
1678 bot(); /* update character's gold piece count immediately */
1679 }
1680 return 1;
1681 }
1682
1683 #undef Icebox
1684
1685 int
use_container(obj,held)1686 use_container(obj, held)
1687 register struct obj *obj;
1688 register int held;
1689 {
1690 struct obj *curr, *otmp, *u_gold = (struct obj *)0;
1691 struct monst *shkp;
1692 boolean one_by_one, allflag, loot_out = FALSE, loot_in = FALSE;
1693 char select[MAXOCLASSES+1];
1694 char qbuf[QBUFSZ];
1695 long loss = 0L;
1696 int cnt = 0, used = 0, lcnt = 0,
1697 menu_on_request;
1698
1699 if (obj->olocked) {
1700 pline("%s seems to be locked.", The(xname(obj)));
1701 if (held) You("must put it down to unlock.");
1702 return 0;
1703 } else if (obj->otrapped) {
1704 if (held) You("open %s...", the(xname(obj)));
1705 (void) chest_trap(obj, HAND, FALSE);
1706 /* even if the trap fails, you've used up this turn */
1707 if (multi >= 0) { /* in case we didn't become paralyzed */
1708 nomul(-1);
1709 nomovemsg = "";
1710 }
1711 return 1;
1712 }
1713 current_container = obj; /* for use by in/out_container */
1714
1715 if (obj->spe == 1) {
1716 static NEARDATA const char sc[] = "Schroedinger's Cat";
1717 struct obj *ocat;
1718 struct monst *cat;
1719
1720 obj->spe = 0; /* obj->owt will be updated below */
1721 /* this isn't really right, since any form of observation
1722 (telepathic or monster/object/food detection) ought to
1723 force the determination of alive vs dead state; but basing
1724 it just on opening the box is much simpler to cope with */
1725 cat = rn2(2) ? makemon(&mons[PM_HOUSECAT],
1726 obj->ox, obj->oy, NO_MINVENT) : 0;
1727 if (cat) {
1728 cat->mpeaceful = 1;
1729 set_malign(cat);
1730 if (Blind)
1731 You("think %s brushed your %s.", something,
1732 body_part(FOOT));
1733 else
1734 pline("%s inside the box is still alive!", Monnam(cat));
1735 (void) christen_monst(cat, sc);
1736 } else {
1737 ocat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
1738 obj->ox, obj->oy, sc);
1739 if (ocat) {
1740 obj_extract_self(ocat);
1741 add_to_container(obj, ocat); /* weight handled below */
1742 }
1743 pline_The("%s inside the box is dead!",
1744 Hallucination ? rndmonnam() : "housecat");
1745 }
1746 used = 1;
1747 }
1748 /* Count the number of contained objects. Sometimes toss objects if */
1749 /* a cursed magic bag. */
1750 for (curr = obj->cobj; curr; curr = otmp) {
1751 otmp = curr->nobj;
1752 if (Is_mbag(obj) && obj->cursed && !rn2(13)) {
1753 if (curr->dknown)
1754 pline("%s to have vanished!", The(aobjnam(curr,"seem")));
1755 else
1756 You("%s %s disappear.", Blind ? "notice" : "see",
1757 doname(curr));
1758 obj_extract_self(curr);
1759 if (*u.ushops && (shkp = shop_keeper(*u.ushops)) != 0) {
1760 if(held) {
1761 if(curr->unpaid)
1762 loss += stolen_value(curr, u.ux, u.uy,
1763 (boolean)shkp->mpeaceful, TRUE);
1764 lcnt++;
1765 } else if(costly_spot(u.ux, u.uy)) {
1766 loss += stolen_value(curr, u.ux, u.uy,
1767 (boolean)shkp->mpeaceful, TRUE);
1768 lcnt++;
1769 }
1770 }
1771 /* obfree() will free all contained objects */
1772 obfree(curr, (struct obj *) 0);
1773 used = 1;
1774 } else {
1775 cnt++;
1776 }
1777 }
1778
1779 if (cnt && loss)
1780 You("owe %ld zorkmids for lost item%s.",
1781 loss, lcnt > 1 ? "s" : "");
1782
1783 obj->owt = weight(obj);
1784
1785 if (!cnt) {
1786 pline("%s is empty.", Yname2(obj));
1787 } else {
1788 Sprintf(qbuf, "Do you want to take %s out of %s?",
1789 something, yname(obj));
1790 if (flags.menu_style != MENU_TRADITIONAL) {
1791 if (flags.menu_style == MENU_FULL) {
1792 int t = in_or_out_menu("Do what?", current_container);
1793 if (t <= 0) return 0;
1794 loot_out = (t & 0x01) != 0;
1795 loot_in = (t & 0x02) != 0;
1796 } else { /* MENU_COMBINATION or MENU_PARTIAL */
1797 loot_out = (yn_function(qbuf, "ynq", 'n') == 'y');
1798 }
1799 if (loot_out) {
1800 add_valid_menu_class(0); /* reset */
1801 used |= menu_loot(0, current_container, FALSE) > 0;
1802 }
1803 } else {
1804 /* traditional code */
1805 ask_again2:
1806 menu_on_request = 0;
1807 add_valid_menu_class(0); /* reset */
1808 switch (yn_function(qbuf, ":ynq", 'n')) {
1809 case ':':
1810 container_contents(current_container, FALSE, FALSE);
1811 goto ask_again2;
1812 case 'y':
1813 if (query_classes(select, &one_by_one, &allflag,
1814 "take out", current_container->cobj,
1815 FALSE, FALSE, &menu_on_request)) {
1816 if (askchain((struct obj **)¤t_container->cobj,
1817 (one_by_one ? (char *)0 : select),
1818 allflag, out_container,
1819 (int FDECL((*),(OBJ_P)))0,
1820 0, "nodot"))
1821 used = 1;
1822 } else if (menu_on_request < 0) {
1823 used |= menu_loot(menu_on_request,
1824 current_container, FALSE) > 0;
1825 }
1826 /*FALLTHRU*/
1827 case 'n':
1828 break;
1829 case 'q':
1830 default:
1831 return used;
1832 }
1833 }
1834 }
1835
1836 if (!invent && u.ugold == 0) {
1837 /* nothing to put in, but some feedback is necessary */
1838 You("don't have anything to put in.");
1839 return used;
1840 }
1841 if (flags.menu_style != MENU_FULL || !cnt) {
1842 loot_in = (yn_function("Do you wish to put something in?",
1843 ynqchars, 'n') == 'y');
1844 }
1845 /*
1846 * Gone: being nice about only selecting food if we know we are
1847 * putting things in an ice chest.
1848 */
1849 if (loot_in) {
1850 if (u.ugold) {
1851 /*
1852 * Hack: gold is not in the inventory, so make a gold object
1853 * and put it at the head of the inventory list.
1854 */
1855 u_gold = mkgoldobj(u.ugold); /* removes from u.ugold */
1856 u.ugold = u_gold->quan; /* put the gold back */
1857 assigninvlet(u_gold); /* might end up as NOINVSYM */
1858 u_gold->nobj = invent;
1859 invent = u_gold;
1860 }
1861 add_valid_menu_class(0); /* reset */
1862 if (flags.menu_style != MENU_TRADITIONAL) {
1863 used |= menu_loot(0, current_container, TRUE) > 0;
1864 } else {
1865 /* traditional code */
1866 menu_on_request = 0;
1867 if (query_classes(select, &one_by_one, &allflag, "put in",
1868 invent, FALSE, (u.ugold != 0L),
1869 &menu_on_request)) {
1870 (void) askchain((struct obj **)&invent,
1871 (one_by_one ? (char *)0 : select), allflag,
1872 in_container, ck_bag, 0, "nodot");
1873 used = 1;
1874 } else if (menu_on_request < 0) {
1875 used |= menu_loot(menu_on_request,
1876 current_container, TRUE) > 0;
1877 }
1878 }
1879 }
1880
1881 if (u_gold && invent && invent->oclass == GOLD_CLASS) {
1882 /* didn't stash [all of] it */
1883 u_gold = invent;
1884 invent = u_gold->nobj;
1885 dealloc_obj(u_gold);
1886 }
1887
1888 return used;
1889 }
1890
1891 /* Loot a container (take things out, put things in), using a menu. */
1892 STATIC_OVL int
menu_loot(retry,container,put_in)1893 menu_loot(retry, container, put_in)
1894 int retry;
1895 struct obj *container;
1896 boolean put_in;
1897 {
1898 int n, i, n_looted = 0;
1899 boolean all_categories = TRUE, loot_everything = FALSE;
1900 char buf[BUFSZ];
1901 const char *takeout = "Take out", *putin = "Put in";
1902 struct obj *otmp, *otmp2;
1903 menu_item *pick_list;
1904 int mflags, res;
1905 long count;
1906
1907 if (retry) {
1908 all_categories = (retry == -2);
1909 } else if (flags.menu_style == MENU_FULL) {
1910 all_categories = FALSE;
1911 Sprintf(buf,"%s what type of objects?", put_in ? putin : takeout);
1912 mflags = put_in ? ALL_TYPES : ALL_TYPES|CHOOSE_ALL;
1913 n = query_category(buf, put_in ? invent : container->cobj,
1914 mflags, &pick_list, PICK_ANY);
1915 if (!n) return 0;
1916 for (i = 0; i < n; i++) {
1917 if (pick_list[i].item.a_int == 'A')
1918 loot_everything = TRUE;
1919 else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
1920 all_categories = TRUE;
1921 else
1922 add_valid_menu_class(pick_list[i].item.a_int);
1923 }
1924 free((genericptr_t) pick_list);
1925 }
1926
1927 if (loot_everything) {
1928 for (otmp = container->cobj; otmp; otmp = otmp2) {
1929 otmp2 = otmp->nobj;
1930 res = out_container(otmp);
1931 if (res < 0) break;
1932 }
1933 } else {
1934 mflags = INVORDER_SORT;
1935 if (put_in && flags.invlet_constant) mflags |= USE_INVLET;
1936 Sprintf(buf,"%s what?", put_in ? putin : takeout);
1937 n = query_objlist(buf, put_in ? invent : container->cobj,
1938 mflags, &pick_list, PICK_ANY,
1939 all_categories ? allow_all : allow_category);
1940 if (n) {
1941 n_looted = n;
1942 for (i = 0; i < n; i++) {
1943 otmp = pick_list[i].item.a_obj;
1944 count = pick_list[i].count;
1945 if (count > 0 && count < otmp->quan) {
1946 otmp2 = splitobj(otmp, count);
1947 /* special split case also handled by askchain() */
1948 if (otmp == uwep) setuwep(otmp2);
1949 if (otmp == uquiver) setuqwep(otmp2);
1950 if (otmp == uswapwep) setuswapwep(otmp2);
1951 }
1952 res = put_in ? in_container(otmp) : out_container(otmp);
1953 if (res < 0)
1954 break;
1955 }
1956 free((genericptr_t)pick_list);
1957 }
1958 }
1959 return n_looted;
1960 }
1961
1962 STATIC_OVL int
in_or_out_menu(prompt,obj)1963 in_or_out_menu(prompt, obj)
1964 const char *prompt;
1965 struct obj *obj;
1966 {
1967 winid win;
1968 anything any;
1969 menu_item *pick_list;
1970 char buf[BUFSZ];
1971 int n;
1972
1973 any.a_void = 0;
1974 win = create_nhwindow(NHW_MENU);
1975 start_menu(win);
1976 any.a_int = 1;
1977 Sprintf(buf,"Take %s out of %s", something, the(xname(obj)));
1978 add_menu(win, NO_GLYPH, &any, 'a', 0, ATR_NONE, buf, MENU_UNSELECTED);
1979 any.a_int = 2;
1980 Sprintf(buf,"Put %s into %s", something, the(xname(obj)));
1981 add_menu(win, NO_GLYPH, &any, 'b', 0, ATR_NONE, buf, MENU_UNSELECTED);
1982 any.a_int = 3;
1983 add_menu(win, NO_GLYPH, &any, 'c', 0, ATR_NONE,
1984 "Both of the above", MENU_UNSELECTED);
1985 end_menu(win, prompt);
1986 n = select_menu(win, PICK_ONE, &pick_list);
1987 destroy_nhwindow(win);
1988 if (n > 0) {
1989 n = pick_list[0].item.a_int;
1990 free((genericptr_t) pick_list);
1991 }
1992 return n;
1993 }
1994
1995 /*pickup.c*/
1996