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. */
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 #ifndef GOLDOBJ
13 STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
14 		const char *,struct obj *,BOOLEAN_P,BOOLEAN_P,int *));
15 #else
16 STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
17 		const char *,struct obj *,BOOLEAN_P,int *));
18 #endif
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 *));
22 #if 0 /* not used */
23 STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *));
24 #endif
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));
41 
42 /* define for query_objlist() and autopickup() */
43 #define FOLLOW(curr, flags) \
44     (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
45 
46 /*
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.
50  */
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)
57 
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";
61 
62 /* BUG: this lets you look at cockatrice corpses while blind without
63    touching them */
64 /* much simpler version of the look-here code; used by query_classes() */
65 STATIC_OVL void
simple_look(otmp,here)66 simple_look(otmp, here)
67 struct obj *otmp;	/* list of objects */
68 boolean here;		/* flag for type of obj list linkage */
69 {
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.
73 	 */
74 	if (!otmp) {
75 	    impossible("simple_look(null)");
76 	} else if (!(here ? otmp->nexthere : otmp->nobj)) {
77 	    pline("%s", doname(otmp));
78 	} else {
79 	    winid tmpwin = create_nhwindow(NHW_MENU);
80 	    putstr(tmpwin, 0, "");
81 	    do {
82 		putstr(tmpwin, 0, doname(otmp));
83 		otmp = here ? otmp->nexthere : otmp->nobj;
84 	    } while (otmp);
85 	    display_nhwindow(tmpwin, TRUE);
86 	    destroy_nhwindow(tmpwin);
87 	}
88 }
89 
90 #ifndef GOLDOBJ
91 int
collect_obj_classes(ilets,otmp,here,incl_gold,filter,itemcount)92 collect_obj_classes(ilets, otmp, here, incl_gold, filter, itemcount)
93 char ilets[];
94 register struct obj *otmp;
95 boolean here, incl_gold;
96 boolean FDECL((*filter),(OBJ_P));
97 int *itemcount;
98 #else
99 int
100 collect_obj_classes(ilets, otmp, here, filter, itemcount)
101 char ilets[];
102 register struct obj *otmp;
103 boolean here;
104 boolean FDECL((*filter),(OBJ_P));
105 int *itemcount;
106 #endif
107 {
108 	register int iletct = 0;
109 	register char c;
110 
111 	*itemcount = 0;
112 #ifndef GOLDOBJ
113 	if (incl_gold)
114 	    ilets[iletct++] = def_oc_syms[COIN_CLASS];
115 #endif
116 	ilets[iletct] = '\0'; /* terminate ilets so that index() will work */
117 	while (otmp) {
118 	    c = def_oc_syms[(int)otmp->oclass];
119 	    if (!index(ilets, c) && (!filter || (*filter)(otmp)))
120 		ilets[iletct++] = c,  ilets[iletct] = '\0';
121 	    *itemcount += 1;
122 	    otmp = here ? otmp->nexthere : otmp->nobj;
123 	}
124 
125 	return iletct;
126 }
127 
128 /*
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").
139  */
140 #ifndef GOLDOBJ
141 STATIC_OVL boolean
query_classes(oclasses,one_at_a_time,everything,action,objs,here,incl_gold,menu_on_demand)142 query_classes(oclasses, one_at_a_time, everything, action, objs,
143 	      here, incl_gold, menu_on_demand)
144 char oclasses[];
145 boolean *one_at_a_time, *everything;
146 const char *action;
147 struct obj *objs;
148 boolean here, incl_gold;
149 int *menu_on_demand;
150 #else
151 STATIC_OVL boolean
152 query_classes(oclasses, one_at_a_time, everything, action, objs,
153 	      here, menu_on_demand)
154 char oclasses[];
155 boolean *one_at_a_time, *everything;
156 const char *action;
157 struct obj *objs;
158 boolean here;
159 int *menu_on_demand;
160 #endif
161 {
162 	char ilets[20], inbuf[BUFSZ];
163 	int iletct, oclassct;
164 	boolean not_everything;
165 	char qbuf[QBUFSZ];
166 	boolean m_seen;
167 	int itemcount;
168 
169 	oclasses[oclassct = 0] = '\0';
170 	*one_at_a_time = *everything = m_seen = FALSE;
171 	iletct = collect_obj_classes(ilets, objs, here,
172 #ifndef GOLDOBJ
173 				     incl_gold,
174 #endif
175 				     (boolean FDECL((*),(OBJ_P))) 0, &itemcount);
176 	if (iletct == 0) {
177 		return FALSE;
178 	} else if (iletct == 1) {
179 		oclasses[0] = def_char_to_objclass(ilets[0]);
180 		oclasses[1] = '\0';
181 		if (itemcount && menu_on_demand) {
182 			ilets[iletct++] = 'm';
183 			*menu_on_demand = 0;
184 			ilets[iletct] = '\0';
185 		}
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';
196 			*menu_on_demand = 0;
197 		}
198 		ilets[iletct] = '\0';
199 ask_again:
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]",
204 			action, ilets);
205 		getlin(qbuf,inbuf);
206 		if (*inbuf == '\033') return FALSE;
207 
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 */
215 			goto ask_again;
216 		    } else if (sym == 'i') {
217 			(void) display_inventory((char *)0, TRUE);
218 			goto ask_again;
219 		    } else if (sym == 'm') {
220 			m_seen = TRUE;
221 		    } else {
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';
227 			} else {
228 			    if (!where)
229 				where = !strcmp(action,"pick up")  ? "here" :
230 					!strcmp(action,"take out") ?
231 							    "inside" : "";
232 			    if (*where)
233 				There("are no %c's %s.", sym, where);
234 			    else
235 				You("have no %c's.", sym);
236 			    not_everything = TRUE;
237 			}
238 		    }
239 		}
240 		if (m_seen && menu_on_demand) {
241 			*menu_on_demand = (*everything || !oclassct) ? -2 : -3;
242 			return FALSE;
243 		}
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' */
249 		}
250 	}
251 	return TRUE;
252 }
253 
254 /* look at the objects at our location, unless there are too many of them */
255 STATIC_OVL void
check_here(picked_some)256 check_here(picked_some)
257 boolean picked_some;
258 {
259 	register struct obj *obj;
260 	register int ct = 0;
261 
262 	/* count the objects here */
263 	for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) {
264 	    if (obj != uchain)
265 		ct++;
266 	}
267 
268 	/* If there are objects here, take a look. */
269 	if (ct) {
270 	    if (flags.run) nomul(0);
271 	    flush_screen(1);
272 	    (void) look_here(ct, picked_some);
273 	} else {
274 	    read_engr_at(u.ux,u.uy);
275 	}
276 }
277 
278 /* Value set by query_objlist() for n_or_more(). */
279 static long val_for_n_or_more;
280 
281 /* query_objlist callback: return TRUE if obj's count is >= reference value */
282 STATIC_OVL boolean
n_or_more(obj)283 n_or_more(obj)
284 struct obj *obj;
285 {
286     if (obj == uchain) return FALSE;
287     return (obj->quan >= val_for_n_or_more);
288 }
289 
290 /* List of valid menu classes for query_objlist() and allow_category callback */
291 static char valid_menu_classes[MAXOCLASSES + 2];
292 
293 void
add_valid_menu_class(c)294 add_valid_menu_class(c)
295 int c;
296 {
297 	static int vmc_count = 0;
298 
299 	if (c == 0)  /* reset */
300 	  vmc_count = 0;
301 	else
302 	  valid_menu_classes[vmc_count++] = (char)c;
303 	valid_menu_classes[vmc_count] = '\0';
304 }
305 
306 /* query_objlist callback: return TRUE if not uchain */
307 STATIC_OVL boolean
all_but_uchain(obj)308 all_but_uchain(obj)
309 struct obj *obj;
310 {
311     return (obj != uchain);
312 }
313 
314 /* query_objlist callback: return TRUE */
315 /*ARGSUSED*/
316 boolean
allow_all(obj)317 allow_all(obj)
318 struct obj *obj;
319 {
320     return TRUE;
321 }
322 
323 boolean
allow_category(obj)324 allow_category(obj)
325 struct obj *obj;
326 {
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))
330 	return TRUE;
331     else if (((index(valid_menu_classes,'U') != (char *)0) &&
332 	(obj->oclass != COIN_CLASS && obj->bknown && !obj->blessed && !obj->cursed)))
333 	return TRUE;
334     else if (((index(valid_menu_classes,'B') != (char *)0) &&
335 	(obj->oclass != COIN_CLASS && obj->bknown && obj->blessed)))
336 	return TRUE;
337     else if (((index(valid_menu_classes,'C') != (char *)0) &&
338 	(obj->oclass != COIN_CLASS && obj->bknown && obj->cursed)))
339 	return TRUE;
340     else if (((index(valid_menu_classes,'X') != (char *)0) &&
341 	(obj->oclass != COIN_CLASS && !obj->bknown)))
342 	return TRUE;
343     else
344 	return FALSE;
345 }
346 
347 #if 0 /* not used */
348 /* query_objlist callback: return TRUE if valid category (class), no uchain */
349 STATIC_OVL boolean
350 allow_cat_no_uchain(obj)
351 struct obj *obj;
352 {
353     if ((obj != uchain) &&
354 	(((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
355 	(index(valid_menu_classes, obj->oclass) != (char *)0)))
356 	return TRUE;
357     else
358 	return FALSE;
359 }
360 #endif
361 
362 /* query_objlist callback: return TRUE if valid class and worn */
363 boolean
is_worn_by_type(otmp)364 is_worn_by_type(otmp)
365 register struct obj *otmp;
366 {
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));
370 }
371 
372 /*
373  * Have the hero pick things from the ground
374  * or a monster's inventory if swallowed.
375  *
376  * Arg what:
377  *	>0  autopickup
378  *	=0  interactive
379  *	<0  pickup count of something
380  *
381  * Returns 1 if tried to pick something up, whether
382  * or not it succeeded.
383  */
384 int
pickup(what)385 pickup(what)
386 int what;		/* should be a long */
387 {
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;
392 	int traverse_how;
393 
394 	if (what < 0)		/* pick N of something */
395 	    count = -what;
396 	else			/* pick anything */
397 	    count = 0;
398 
399 	if (!u.uswallow) {
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);
405 			return (0);
406 		}
407 
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);
412 		    return (0);
413 		}
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.
419 		     */
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);
423 			return(0);
424 		    }
425 		}
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.
429 		 */
430 		if ((multi && !flags.run) || (autopickup && !flags.pickup)) {
431 		    check_here(FALSE);
432 		    return (0);
433 		}
434 		if (notake(youmonst.data)) {
435 		    if (!autopickup)
436 			You("are physically incapable of picking anything up.");
437 		    else
438 			check_here(FALSE);
439 		    return (0);
440 		}
441 
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);
444 	}
445 
446 	add_valid_menu_class(0);	/* reset */
447 	if (!u.uswallow) {
448 		objchain = level.objects[u.ux][u.uy];
449 		traverse_how = BY_NEXTHERE;
450 	} else {
451 		objchain = u.ustuck->minvent;
452 		traverse_how = 0;	/* nobj */
453 	}
454 	/*
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.
459 	 */
460 	if (autopickup) {
461 	    n = autopick(objchain, traverse_how, &pick_list);
462 	    goto menu_pickup;
463 	}
464 
465 	if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
466 
467 	    /* use menus exclusively */
468 	    if (count) {	/* looking for N of something */
469 		char buf[QBUFSZ];
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;
478 	    } else {
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);
482 	    }
483 menu_pickup:
484 	    n_tried = n;
485 	    for (n_picked = i = 0 ; i < n; i++) {
486 		res = pickup_object(pick_list[i].item.a_obj,pick_list[i].count,
487 					FALSE);
488 		if (res < 0) break;	/* can't continue */
489 		n_picked += res;
490 	    }
491 	    if (pick_list) free((genericptr_t)pick_list);
492 
493 	} else {
494 	    /* old style interface */
495 	    int ct = 0;
496 	    long lcount;
497 	    boolean all_of_a_type, selective;
498 	    char oclasses[MAXOCLASSES];
499 	    struct obj *obj, *obj2;
500 
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 */
504 
505 	    /* check for more than one object */
506 	    for (obj = objchain;
507 		  obj; obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj)
508 		ct++;
509 
510 	    if (ct == 1 && count) {
511 		/* if only one thing, then pick it */
512 		obj = objchain;
513 		lcount = min(obj->quan, (long)count);
514 		n_tried++;
515 		if (pickup_object(obj, lcount, FALSE) > 0)
516 		    n_picked++;	/* picked something */
517 		goto end_query;
518 
519 	    } else if (ct >= 2) {
520 		int via_menu = 0;
521 
522 		There("are %s objects here.",
523 		      (ct <= 10) ? "several" : "many");
524 		if (!query_classes(oclasses, &selective, &all_of_a_type,
525 				   "pick up", objchain,
526 				   traverse_how == BY_NEXTHERE,
527 #ifndef GOLDOBJ
528 				   FALSE,
529 #endif
530 				   &via_menu)) {
531 		    if (!via_menu) return (0);
532 		    n = query_objlist("Pick up what?",
533 				  objchain,
534 				  traverse_how|(selective ? 0 : INVORDER_SORT),
535 				  &pick_list, PICK_ANY,
536 				  via_menu == -2 ? allow_all : allow_category);
537 		    goto menu_pickup;
538 		}
539 	    }
540 
541 	    for (obj = objchain; obj; obj = obj2) {
542 		if (traverse_how == BY_NEXTHERE)
543 			obj2 = obj->nexthere;	/* perhaps obj will be picked up */
544 		else
545 			obj2 = obj->nobj;
546 		lcount = -1L;
547 
548 		if (!selective && oclasses[0] && !index(oclasses,obj->oclass))
549 		    continue;
550 
551 		if (!all_of_a_type) {
552 		    char qbuf[BUFSZ];
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 */
558 		    case 'n': continue;
559 		    case 'a':
560 			all_of_a_type = TRUE;
561 			if (selective) {
562 			    selective = FALSE;
563 			    oclasses[0] = obj->oclass;
564 			    oclasses[1] = '\0';
565 			}
566 			break;
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;
571 			/* fall thru */
572 		    default:	/* 'y' */
573 			break;
574 		    }
575 		}
576 		if (lcount == -1L) lcount = obj->quan;
577 
578 		n_tried++;
579 		if ((res = pickup_object(obj, lcount, FALSE)) < 0) break;
580 		n_picked += res;
581 	    }
582 end_query:
583 	    ;	/* semicolon needed by brain-damaged compilers */
584 	}
585 
586 	if (!u.uswallow) {
587 		if (!OBJ_AT(u.ux,u.uy)) u.uundetected = 0;
588 
589 		/* position may need updating (invisible hero) */
590 		if (n_picked) newsym(u.ux,u.uy);
591 
592 		/* see whether there's anything else here, after auto-pickup is done */
593 		if (autopickup) check_here(n_picked > 0);
594 	}
595 	return (n_tried > 0);
596 }
597 
598 #ifdef AUTOPICKUP_EXCEPTIONS
599 boolean
is_autopickup_exception(obj,grab)600 is_autopickup_exception(obj, grab)
601 struct obj *obj;
602 boolean grab;	 /* forced pickup, rather than forced leave behind? */
603 {
604 	/*
605 	 *  Does the text description of this match an exception?
606 	 */
607 	char *objdesc = makesingular(doname(obj));
608 	struct autopickup_exception *ape = (grab) ?
609 					iflags.autopickup_exceptions[AP_GRAB] :
610 					iflags.autopickup_exceptions[AP_LEAVE];
611 	while (ape) {
612 		if (pmatch(ape->pattern, objdesc)) return TRUE;
613 		ape = ape->next;
614 	}
615 	return FALSE;
616 }
617 #endif /* AUTOPICKUP_EXCEPTIONS */
618 
619 /*
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.
625  */
626 STATIC_OVL int
autopick(olist,follow,pick_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 */
631 {
632 	menu_item *pi;	/* pick item */
633 	struct obj *curr;
634 	int n;
635 	const char *otypes = flags.pickup_types;
636 
637 	/* first count the number of eligible items */
638 	for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
639 
640 
641 #ifndef AUTOPICKUP_EXCEPTIONS
642 	    if (!*otypes || index(otypes, curr->oclass))
643 #else
644 	    if ((!*otypes || index(otypes, curr->oclass) ||
645 		 is_autopickup_exception(curr, TRUE)) &&
646 	    	 !is_autopickup_exception(curr, FALSE))
647 #endif
648 		n++;
649 
650 	if (n) {
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)) {
655 #else
656 	    if ((!*otypes || index(otypes, curr->oclass) ||
657 		 is_autopickup_exception(curr, TRUE)) &&
658 	    	 !is_autopickup_exception(curr, FALSE)) {
659 #endif
660 		    pi[n].item.a_obj = curr;
661 		    pi[n].count = curr->quan;
662 		    n++;
663 		}
664 	}
665 	return n;
666 }
667 
668 
669 /*
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.
675  *
676  * Query flags:
677  *	BY_NEXTHERE	  - Follow object list via nexthere instead of nobj.
678  *	AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
679  *			    use it.
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".
683  */
684 int
query_objlist(qstr,olist,qflags,pick_list,how,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 */
692 {
693 	int n;
694 	winid win;
695 	struct obj *curr, *last;
696 	char *pack;
697 	anything any;
698 	boolean printed_type_name;
699 
700 	*pick_list = (menu_item *) 0;
701 	if (!olist) return 0;
702 
703 	/* count the number of items allowed */
704 	for (n = 0, last = 0, curr = olist; curr; curr = FOLLOW(curr, qflags))
705 	    if ((*allow)(curr)) {
706 		last = curr;
707 		n++;
708 	    }
709 
710 	if (n == 0)	/* nothing to pick here */
711 	    return (qflags & SIGNAL_NOMENU) ? -1 : 0;
712 
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;
717 	    return 1;
718 	}
719 
720 	win = create_nhwindow(NHW_MENU);
721 	start_menu(win);
722 	any.a_obj = (struct obj *) 0;
723 
724 	/*
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.
729 	 */
730 	pack = flags.inv_order;
731 	do {
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);
738 			return 0;
739 		}
740 		if ((!(qflags & INVORDER_SORT) || curr->oclass == *pack)
741 							&& (*allow)(curr)) {
742 
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;
749 		    }
750 
751 		    any.a_obj = curr;
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);
756 		}
757 	    }
758 	    pack++;
759 	} while (qflags & INVORDER_SORT && *pack);
760 
761 	end_menu(win, qstr);
762 	n = select_menu(win, how, pick_list);
763 	destroy_nhwindow(win);
764 
765 	if (n > 0) {
766 	    menu_item *mi;
767 	    int i;
768 
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;
773 	} else if (n < 0) {
774 	    n = 0;	/* caller's don't expect -1 */
775 	}
776 	return n;
777 }
778 
779 /*
780  * allow menu-based category (class) selection (for Drop,take off etc.)
781  *
782  */
783 int
query_category(qstr,olist,qflags,pick_list,how)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 */
790 {
791 	int n;
792 	winid win;
793 	struct obj *curr;
794 	char *pack;
795 	anything any;
796 	boolean collected_type_name;
797 	char invlet;
798 	int ccount;
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;
803 
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)) {
808 	    do_blessed = TRUE;
809 	    num_buc_types++;
810 	}
811 	if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) {
812 	    do_cursed = TRUE;
813 	    num_buc_types++;
814 	}
815 	if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) {
816 	    do_uncursed = TRUE;
817 	    num_buc_types++;
818 	}
819 	if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) {
820 	    do_buc_unknown = TRUE;
821 	    num_buc_types++;
822 	}
823 
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)))
830 		    continue;
831 		break;
832 	    }
833 	    if (curr) {
834 		*pick_list = (menu_item *) alloc(sizeof(menu_item));
835 		(*pick_list)->item.a_int = curr->oclass;
836 		return 1;
837 	    } else {
838 #ifdef DEBUG
839 		impossible("query_category: no single object match");
840 #endif
841 	    }
842 	    return 0;
843 	}
844 
845 	win = create_nhwindow(NHW_MENU);
846 	start_menu(win);
847 	pack = flags.inv_order;
848 	if ((qflags & ALL_TYPES) && (ccount > 1)) {
849 		invlet = 'a';
850 		any.a_void = 0;
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",
854 			MENU_UNSELECTED);
855 		invlet = 'b';
856 	} else
857 		invlet = 'a';
858 	do {
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)))
865 			 continue;
866 		   if (!collected_type_name) {
867 			any.a_void = 0;
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),
872 				MENU_UNSELECTED);
873 			collected_type_name = TRUE;
874 		   }
875 		}
876 	    }
877 	    pack++;
878 	    if (invlet >= 'u') {
879 		impossible("query_category: too many categories");
880 		return 0;
881 	    }
882 	} while (*pack);
883 	/* unpaid items if there are any */
884 	if (do_unpaid) {
885 		invlet = 'u';
886 		any.a_void = 0;
887 		any.a_int = 'u';
888 		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
889 			"Unpaid items", MENU_UNSELECTED);
890 	}
891 	/* billed items: checked by caller, so always include if BILLED_TYPES */
892 	if (qflags & BILLED_TYPES) {
893 		invlet = 'x';
894 		any.a_void = 0;
895 		any.a_int = 'x';
896 		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
897 			 "Unpaid items already used up", MENU_UNSELECTED);
898 	}
899 	if (qflags & CHOOSE_ALL) {
900 		invlet = 'A';
901 		any.a_void = 0;
902 		any.a_int = 'A';
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);
907 	}
908 	/* items with b/u/c/unknown if there are any */
909 	if (do_blessed) {
910 		invlet = 'B';
911 		any.a_void = 0;
912 		any.a_int = 'B';
913 		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
914 			"Items known to be Blessed", MENU_UNSELECTED);
915 	}
916 	if (do_cursed) {
917 		invlet = 'C';
918 		any.a_void = 0;
919 		any.a_int = 'C';
920 		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
921 			"Items known to be Cursed", MENU_UNSELECTED);
922 	}
923 	if (do_uncursed) {
924 		invlet = 'U';
925 		any.a_void = 0;
926 		any.a_int = 'U';
927 		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
928 			"Items known to be Uncursed", MENU_UNSELECTED);
929 	}
930 	if (do_buc_unknown) {
931 		invlet = 'X';
932 		any.a_void = 0;
933 		any.a_int = 'X';
934 		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
935 			"Items of unknown B/C/U status",
936 			MENU_UNSELECTED);
937 	}
938 	end_menu(win, qstr);
939 	n = select_menu(win, how, pick_list);
940 	destroy_nhwindow(win);
941 	if (n < 0)
942 	    n = 0;	/* caller's don't expect -1 */
943 	return n;
944 }
945 
946 STATIC_OVL int
count_categories(olist,qflags)947 count_categories(olist, qflags)
948 struct obj *olist;
949 int qflags;
950 {
951 	char *pack;
952 	boolean counted_category;
953 	int ccount = 0;
954 	struct obj *curr;
955 
956 	pack = flags.inv_order;
957 	do {
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)))
964 			 continue;
965 		   if (!counted_category) {
966 			ccount++;
967 			counted_category = TRUE;
968 		   }
969 		}
970 	    }
971 	    pack++;
972 	} while (*pack);
973 	return ccount;
974 }
975 
976 /* could we carry `obj'? if not, could we carry some of it/them? */
977 STATIC_OVL long
carry_count(obj,container,count,telekinesis,wt_before,wt_after)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 */
980 long count;
981 boolean telekinesis;
982 int *wt_before, *wt_after;
983 {
984     boolean adjust_wt = container && carried(container),
985 	    is_gold = obj->oclass == COIN_CLASS;
986     int wt, iw, ow, oow;
987     long qq, savequan;
988 #ifdef GOLDOBJ
989     long umoney = money_cnt(invent);
990 #endif
991     unsigned saveowt;
992     const char *verb, *prefx1, *prefx2, *suffx;
993     char obj_nambuf[BUFSZ], where[BUFSZ];
994 
995     savequan = obj->quan;
996     saveowt = obj->owt;
997 
998     iw = max_capacity();
999 
1000     if (count != savequan) {
1001 	obj->quan = count;
1002 	obj->owt = (unsigned)weight(obj);
1003     }
1004     wt = iw + (int)obj->owt;
1005     if (adjust_wt)
1006 	wt -= (container->otyp == BAG_OF_HOLDING) ?
1007 		(int)DELTA_CWT(container, obj) : (int)obj->owt;
1008 #ifndef GOLDOBJ
1009     if (is_gold)	/* merged gold might affect cumulative weight */
1010 	wt -= (GOLD_WT(u.ugold) + GOLD_WT(count) - GOLD_WT(u.ugold + count));
1011 #else
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));
1015 #endif
1016     if (count != savequan) {
1017 	obj->quan = savequan;
1018 	obj->owt = saveowt;
1019     }
1020     *wt_before = iw;
1021     *wt_after  = wt;
1022 
1023     if (wt < 0)
1024 	return count;
1025 
1026     /* see how many we can lift */
1027     if (is_gold) {
1028 #ifndef GOLDOBJ
1029 	iw -= (int)GOLD_WT(u.ugold);
1030 	if (!adjust_wt) {
1031 	    qq = GOLD_CAPACITY((long)iw, u.ugold);
1032 	} else {
1033 	    oow = 0;
1034 	    qq = 50L - (u.ugold % 100L) - 1L;
1035 #else
1036 	iw -= (int)GOLD_WT(umoney);
1037 	if (!adjust_wt) {
1038 	    qq = GOLD_CAPACITY((long)iw, umoney);
1039 	} else {
1040 	    oow = 0;
1041 	    qq = 50L - (umoney % 100L) - 1L;
1042 #endif
1043 	    if (qq < 0L) qq += 100L;
1044 	    for ( ; qq <= count; qq += 100L) {
1045 		obj->quan = qq;
1046 		obj->owt = (unsigned)GOLD_WT(qq);
1047 #ifndef GOLDOBJ
1048 		ow = (int)GOLD_WT(u.ugold + qq);
1049 #else
1050 		ow = (int)GOLD_WT(umoney + qq);
1051 #endif
1052 		ow -= (container->otyp == BAG_OF_HOLDING) ?
1053 			(int)DELTA_CWT(container, obj) : (int)obj->owt;
1054 		if (iw + ow >= 0) break;
1055 		oow = ow;
1056 	    }
1057 	    iw -= oow;
1058 	    qq -= 100L;
1059 	}
1060 	if (qq < 0L) qq = 0L;
1061 	else if (qq > count) qq = count;
1062 #ifndef GOLDOBJ
1063 	wt = iw + (int)GOLD_WT(u.ugold + qq);
1064 #else
1065 	wt = iw + (int)GOLD_WT(umoney + qq);
1066 #endif
1067     } else if (count > 1 || count < obj->quan) {
1068 	/*
1069 	 * Ugh. Calc num to lift by changing the quan of of the
1070 	 * object and calling weight.
1071 	 *
1072 	 * This works for containers only because containers
1073 	 * don't merge.		-dean
1074 	 */
1075 	for (qq = 1L; qq <= count; qq++) {
1076 	    obj->quan = qq;
1077 	    obj->owt = (unsigned)(ow = weight(obj));
1078 	    if (adjust_wt)
1079 		ow -= (container->otyp == BAG_OF_HOLDING) ?
1080 			(int)DELTA_CWT(container, obj) : (int)obj->owt;
1081 	    if (iw + ow >= 0)
1082 		break;
1083 	    wt = iw + ow;
1084 	}
1085 	--qq;
1086     } else {
1087 	/* there's only one, and we can't lift it */
1088 	qq = 0L;
1089     }
1090     obj->quan = savequan;
1091     obj->owt = saveowt;
1092 
1093     if (qq < count) {
1094 	/* some message will be given */
1095 	Strcpy(obj_nambuf, doname(obj));
1096 	if (container) {
1097 	    Sprintf(where, "in %s", the(xname(container)));
1098 	    verb = "carry";
1099 	} else {
1100 	    Strcpy(where, "lying here");
1101 	    verb = telekinesis ? "acquire" : "lift";
1102 	}
1103     } else {
1104 	/* lint supppression */
1105 	*obj_nambuf = *where = '\0';
1106 	verb = "";
1107     }
1108     /* we can carry qq of them */
1109     if (qq > 0) {
1110 	if (qq < count)
1111 	    You("can only %s %s of the %s %s.",
1112 		verb, (qq == 1L) ? "one" : "some", obj_nambuf, where);
1113 	*wt_after = wt;
1114 	return qq;
1115     }
1116 
1117     if (!container) Strcpy(where, "here");  /* slightly shorter form */
1118 #ifndef GOLDOBJ
1119     if (invent || u.ugold) {
1120 #else
1121     if (invent || umoney) {
1122 #endif
1123 	prefx1 = "you cannot ";
1124 	prefx2 = "";
1125 	suffx  = " any more";
1126     } else {
1127 	prefx1 = (obj->quan == 1L) ? "it " : "even one ";
1128 	prefx2 = "is too heavy for you to ";
1129 	suffx  = "";
1130     }
1131     There("%s %s %s, but %s%s%s%s.",
1132 	  otense(obj, "are"), obj_nambuf, where,
1133 	  prefx1, prefx2, verb, suffx);
1134 
1135  /* *wt_after = iw; */
1136     return 0L;
1137 }
1138 
1139 /* determine whether character is able and player is willing to carry `obj' */
1140 STATIC_OVL
1141 int
lift_object(obj,container,cnt_p,telekinesis)1142 lift_object(obj, container, cnt_p, telekinesis)
1143 struct obj *obj, *container;	/* object to pick up, bag it's coming out of */
1144 long *cnt_p;
1145 boolean telekinesis;
1146 {
1147     int result, old_wt, new_wt, prev_encumbr, next_encumbr;
1148 
1149     if (obj->otyp == BOULDER && In_sokoban(&u.uz)) {
1150 	You("cannot get your %s around this %s.",
1151 			body_part(HAND), xname(obj));
1152 	return -1;
1153     }
1154     if (obj->otyp == LOADSTONE ||
1155 	    (obj->otyp == BOULDER && throws_rocks(youmonst.data)))
1156 	return 1;		/* lift regardless of current situation */
1157 
1158     *cnt_p = carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt);
1159     if (*cnt_p < 1L) {
1160 	result = -1;	/* nothing lifted */
1161 #ifndef GOLDOBJ
1162     } else if (obj->oclass != COIN_CLASS && inv_cnt() >= 52 &&
1163 		!merge_choice(invent, obj)) {
1164 #else
1165     } else if (inv_cnt() >= 52 && !merge_choice(invent, obj)) {
1166 #endif
1167 	Your("knapsack cannot accommodate any more items.");
1168 	result = -1;	/* nothing lifted */
1169     } else {
1170 	result = 1;
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) {
1176 	    if (telekinesis) {
1177 		result = 0;	/* don't lift */
1178 	    } else {
1179 		char qbuf[BUFSZ];
1180 		long savequan = obj->quan;
1181 
1182 		obj->quan = *cnt_p;
1183 		Strcpy(qbuf,
1184 			(next_encumbr > HVY_ENCUMBER) ? overloadmsg :
1185 			(next_encumbr > MOD_ENCUMBER) ? nearloadmsg :
1186 			moderateloadmsg);
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 */
1195 		}
1196 		clear_nhwindow(WIN_MESSAGE);
1197 	    }
1198 	}
1199     }
1200 
1201     if (obj->otyp == SCR_SCARE_MONSTER && result <= 0 && !container)
1202 	obj->spe = 0;
1203     return result;
1204 }
1205 
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.
1210  */
1211 const char *
safe_qbuf(qbuf,padlength,planA,planB,last_resort)1212 safe_qbuf(qbuf, padlength, planA, planB, last_resort)
1213 const char *qbuf, *planA, *planB, *last_resort;
1214 unsigned padlength;
1215 {
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);
1222 
1223 	if (len_lastR >= textleft) {
1224 	    impossible("safe_qbuf: last_resort too large at %u characters.",
1225 		       len_lastR);
1226 	    return "";
1227 	}
1228 	return (len_planA < textleft) ? planA :
1229 		    (len_planB < textleft) ? planB : last_resort;
1230 }
1231 
1232 /*
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.
1236  */
1237 int
pickup_object(obj,count,telekinesis)1238 pickup_object(obj, count, telekinesis)
1239 struct obj *obj;
1240 long count;
1241 boolean telekinesis;	/* not picking it up directly by hand */
1242 {
1243 	int res, nearload;
1244 #ifndef GOLDOBJ
1245 	const char *where = (obj->ox == u.ux && obj->oy == u.uy) ?
1246 			    "here" : "there";
1247 #endif
1248 
1249 	if (obj->quan < count) {
1250 	    impossible("pickup_object: count %ld > quan %ld?",
1251 		count, obj->quan);
1252 	    return 0;
1253 	}
1254 
1255 	/* In case of auto-pickup, where we haven't had a chance
1256 	   to look at it yet; affects docall(SCR_SCARE_MONSTER). */
1257 	if (!Blind)
1258 #ifdef INVISIBLE_OBJECTS
1259 		if (!obj->oinvis || See_invisible)
1260 #endif
1261 		obj->dknown = 1;
1262 
1263 	if (obj == uchain) {    /* do not pick up attached chain */
1264 	    return 0;
1265 	} else if (obj->oartifact && !touch_artifact(obj,&youmonst)) {
1266 	    return 0;
1267 #ifndef GOLDOBJ
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);
1272 
1273 	    if (gold_capacity <= 0L) {
1274 		pline(
1275 	       "There %s %ld gold piece%s %s, but you cannot carry any more.",
1276 		      otense(obj, "are"),
1277 		      obj->quan, plur(obj->quan), where);
1278 		return 0;
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);
1288 	    } else {
1289 		u.ugold += count;
1290 		if ((nearload = near_capacity()) != 0)
1291 		    pline("%s %ld gold piece%s.",
1292 			  nearload < MOD_ENCUMBER ?
1293 			  moderateloadmsg : nearloadmsg,
1294 			  count, plur(count));
1295 		else
1296 		    prinv((char *) 0, obj, count);
1297 		costly_gold(obj->ox, obj->oy, count);
1298 		if (count == obj->quan)
1299 		    delobj(obj);
1300 		else
1301 		    obj->quan -= count;
1302 	    }
1303 	    flags.botl = 1;
1304 	    if (flags.run) nomul(0);
1305 	    return 1;
1306 #endif
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);
1312 		else {
1313 			char kbuf[BUFSZ];
1314 
1315 			Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1316 			pline("Touching %s is a fatal mistake.", kbuf);
1317 			instapetrify(kbuf);
1318 		    return -1;
1319 		}
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);
1325 		return -1;
1326 	    }
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;
1330 	    else {
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))
1337 		    docall(obj);
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   */
1341 	    }
1342 	}
1343 
1344 	if ((res = lift_object(obj, (struct obj *)0, &count, telekinesis)) <= 0)
1345 	    return res;
1346 
1347 #ifdef GOLDOBJ
1348         /* Whats left of the special case for gold :-) */
1349 	if (obj->oclass == COIN_CLASS) flags.botl = 1;
1350 #endif
1351 	if (obj->quan != count && obj->otyp != LOADSTONE)
1352 	    obj = splitobj(obj, count);
1353 
1354 	obj = pick_obj(obj);
1355 
1356 	if (uwep && uwep == obj) mrg_to_wielded = TRUE;
1357 	nearload = near_capacity();
1358 	prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0,
1359 	      obj, count);
1360 	mrg_to_wielded = FALSE;
1361 	return 1;
1362 }
1363 
1364 /*
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.
1369  *
1370  * Gold never reaches this routine unless GOLDOBJ is defined.
1371  */
1372 struct obj *
pick_obj(otmp)1373 pick_obj(otmp)
1374 struct obj *otmp;
1375 {
1376 	obj_extract_self(otmp);
1377 	if (!u.uswallow && otmp != uball && costly_spot(otmp->ox, otmp->oy)) {
1378 	    char saveushops[5], fakeshop[2];
1379 
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);
1385 	    fakeshop[1] = '\0';
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);
1393 	}
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 */
1398 }
1399 
1400 /*
1401  * prints a message if encumbrance changed since the last check and
1402  * returns the new encumbrance value (from near_capacity()).
1403  */
1404 int
encumber_msg()1405 encumber_msg()
1406 {
1407     static int oldcap = UNENCUMBERED;
1408     int newcap = near_capacity();
1409 
1410     if(oldcap < newcap) {
1411 	switch(newcap) {
1412 	case 1: Your("movements are slowed slightly because of your load.");
1413 		break;
1414 	case 2: You("rebalance your load.  Movement is difficult.");
1415 		break;
1416 	case 3: You("%s under your heavy load.  Movement is very hard.",
1417 		    stagger(youmonst.data, "stagger"));
1418 		break;
1419 	default: You("%s move a handspan with this load!",
1420 		     newcap == 4 ? "can barely" : "can't even");
1421 		break;
1422 	}
1423 	flags.botl = 1;
1424     } else if(oldcap > newcap) {
1425 	switch(newcap) {
1426 	case 0: Your("movements are now unencumbered.");
1427 		break;
1428 	case 1: Your("movements are only slowed slightly by your load.");
1429 		break;
1430 	case 2: You("rebalance your load.  Movement is still difficult.");
1431 		break;
1432 	case 3: You("%s under your load.  Movement is still very hard.",
1433 		    stagger(youmonst.data, "stagger"));
1434 		break;
1435 	}
1436 	flags.botl = 1;
1437     }
1438 
1439     oldcap = newcap;
1440     return (newcap);
1441 }
1442 
1443 /* Is there a container at x,y. Optional: return count of containers at x,y */
1444 STATIC_OVL int
container_at(x,y,countem)1445 container_at(x, y, countem)
1446 int x,y;
1447 boolean countem;
1448 {
1449 	struct obj *cobj, *nobj;
1450 	int container_count = 0;
1451 
1452 	for(cobj = level.objects[x][y]; cobj; cobj = nobj) {
1453 		nobj = cobj->nexthere;
1454 		if(Is_container(cobj)) {
1455 			container_count++;
1456 			if (!countem) break;
1457 		}
1458 	}
1459 	return container_count;
1460 }
1461 
1462 STATIC_OVL boolean
able_to_loot(x,y)1463 able_to_loot(x, y)
1464 int x, y;
1465 {
1466 	if (!can_reach_floor()) {
1467 #ifdef STEED
1468 		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
1469 			rider_cant_reach(); /* not skilled enough to reach */
1470 		else
1471 #endif
1472 			You("cannot reach the %s.", surface(x, y));
1473 		return FALSE;
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");
1478 		return FALSE;
1479 	} else if (nolimbs(youmonst.data)) {
1480 		pline("Without limbs, you cannot loot anything.");
1481 		return FALSE;
1482 	} else if (!freehand()) {
1483 		pline("Without a free %s, you cannot loot anything.",
1484 			body_part(HAND));
1485 		return FALSE;
1486 	}
1487 	return TRUE;
1488 }
1489 
1490 STATIC_OVL boolean
mon_beside(x,y)1491 mon_beside(x,y)
1492 int x, y;
1493 {
1494 	int i,j,nx,ny;
1495 	for(i = -1; i <= 1; i++)
1496 	    for(j = -1; j <= 1; j++) {
1497 	    	nx = x + i;
1498 	    	ny = y + j;
1499 		if(isok(nx, ny) && MON_AT(nx, ny))
1500 			return TRUE;
1501 	    }
1502 	return FALSE;
1503 }
1504 
1505 int
doloot()1506 doloot()	/* loot a container on the floor or loot saddle from mon. */
1507 {
1508     register struct obj *cobj, *nobj;
1509     register int c = -1;
1510     int timepassed = 0;
1511     coord cc;
1512     boolean underfoot = TRUE;
1513     const char *dont_find_anything = "don't find anything";
1514     struct monst *mtmp;
1515     char qbuf[BUFSZ];
1516     int prev_inquiry = 0;
1517     boolean prev_loot = FALSE;
1518 
1519     if (check_capacity((char *)0)) {
1520 	/* "Can't do that while carrying so much stuff." */
1521 	return 0;
1522     }
1523     if (nohands(youmonst.data)) {
1524 	You("have no hands!");	/* not `body_part(HAND)' */
1525 	return 0;
1526     }
1527     cc.x = u.ux; cc.y = u.uy;
1528 
1529 lootcont:
1530 
1531     if (container_at(cc.x, cc.y, FALSE)) {
1532 	boolean any = FALSE;
1533 
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;
1537 
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)),
1542 			     "a container"));
1543 		c = ynq(qbuf);
1544 		if (c == 'q') return (timepassed);
1545 		if (c == 'n') continue;
1546 		any = TRUE;
1547 
1548 		if (cobj->olocked) {
1549 		    pline("Hmmm, it seems to be locked.");
1550 		    continue;
1551 		}
1552 		if (cobj->otyp == BAG_OF_TRICKS) {
1553 		    int tmp;
1554 		    You("carefully open the bag...");
1555 		    pline("It develops a huge set of teeth and bites you!");
1556 		    tmp = rnd(10);
1557 		    if (Half_physical_damage) tmp = (tmp+1) / 2;
1558 		    losehp(tmp, "carnivorous bag", KILLED_BY_AN);
1559 		    makeknown(BAG_OF_TRICKS);
1560 		    timepassed = 1;
1561 		    continue;
1562 		}
1563 
1564 		You("carefully open %s...", the(xname(cobj)));
1565 		timepassed |= use_container(cobj, 0);
1566 		if (multi < 0) return 1;		/* chest trap */
1567 	    }
1568 	}
1569 	if (any) c = 'y';
1570     } else if (Confusion) {
1571 #ifndef GOLDOBJ
1572 	if (u.ugold){
1573 	    long contribution = rnd((int)min(LARGEST_INT,u.ugold));
1574 	    struct obj *goldob = mkgoldobj(contribution);
1575 #else
1576 	struct obj *goldob;
1577 	/* Find a money object to mess with */
1578 	for (goldob = invent; goldob; goldob = goldob->nobj) {
1579 	    if (goldob->oclass == COIN_CLASS) break;
1580 	}
1581 	if (goldob){
1582 	    long contribution = rnd((int)min(LARGEST_INT, goldob->quan));
1583 	    if (contribution < goldob->quan)
1584 		goldob = splitobj(goldob, contribution);
1585 	    freeinv(goldob);
1586 #endif
1587 	    if (IS_THRONE(levl[u.ux][u.uy].typ)){
1588 		struct obj *coffers;
1589 		int pass;
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 */
1595 gotit:
1596 		if (coffers) {
1597 	    verbalize("Thank you for your contribution to reduce the debt.");
1598 		    (void) add_to_container(coffers, goldob);
1599 		    coffers->owt = weight(coffers);
1600 		} else {
1601 		    struct monst *mon = makemon(courtmon(),
1602 					    u.ux, u.uy, NO_MM_FLAGS);
1603 		    if (mon) {
1604 #ifndef GOLDOBJ
1605 			mon->mgold += goldob->quan;
1606 			delobj(goldob);
1607 			pline("The exchequer accepts your contribution.");
1608 		    } else {
1609 			dropx(goldob);
1610 		    }
1611 		}
1612 	    } else {
1613 		dropx(goldob);
1614 #else
1615 			add_to_minv(mon, goldob);
1616 			pline("The exchequer accepts your contribution.");
1617 		    } else {
1618 			dropy(goldob);
1619 		    }
1620 		}
1621 	    } else {
1622 		dropy(goldob);
1623 #endif
1624 		pline("Ok, now there is loot here.");
1625 	    }
1626 	}
1627     } else if (IS_GRAVE(levl[cc.x][cc.y].typ)) {
1628 	You("need to dig up the grave to effectively loot it...");
1629     }
1630     /*
1631      * 3.3.1 introduced directional looting for some things.
1632      */
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) {
1637 	    underfoot = TRUE;
1638 	    if (container_at(cc.x, cc.y, FALSE))
1639 		goto lootcont;
1640 	} else
1641 	    underfoot = FALSE;
1642 	if (u.dz < 0) {
1643 	    You("%s to loot on the %s.", dont_find_anything,
1644 		ceiling(cc.x, cc.y));
1645 	    timepassed = 1;
1646 	    return timepassed;
1647 	}
1648 	mtmp = m_at(cc.x, cc.y);
1649 	if (mtmp) timepassed = loot_mon(mtmp, &prev_inquiry, &prev_loot);
1650 
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.
1654 	 */
1655 	if (!underfoot) {
1656 	    if (container_at(cc.x, cc.y, FALSE)) {
1657 		if (mtmp) {
1658 		    You_cant("loot anything %sthere with %s in the way.",
1659 			    prev_inquiry ? "else " : "", mon_nam(mtmp));
1660 		    return timepassed;
1661 		} else {
1662 		    You("have to be at a container to loot it.");
1663 		}
1664 	    } else {
1665 		You("%s %sthere to loot.", dont_find_anything,
1666 			(prev_inquiry || prev_loot) ? "else " : "");
1667 		return timepassed;
1668 	    }
1669 	}
1670     } else if (c != 'y' && c != 'n') {
1671 	You("%s %s to loot.", dont_find_anything,
1672 		    underfoot ? "here" : "there");
1673     }
1674     return (timepassed);
1675 }
1676 
1677 /* loot_mon() returns amount of time passed.
1678  */
1679 int
loot_mon(mtmp,passed_info,prev_loot)1680 loot_mon(mtmp, passed_info, prev_loot)
1681 struct monst *mtmp;
1682 int *passed_info;
1683 boolean *prev_loot;
1684 {
1685     int c = -1;
1686     int timepassed = 0;
1687 #ifdef STEED
1688     struct obj *otmp;
1689     char qbuf[QBUFSZ];
1690 
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))) {
1695 	long unwornmask;
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) */
1702 		    return (0);
1703 		}
1704 		if (otmp->cursed) {
1705 		    You("can't. The saddle seems to be stuck to %s.",
1706 			x_monnam(mtmp, ARTICLE_THE, (char *)0,
1707 				SUPPRESS_SADDLE, FALSE));
1708 
1709 		    /* the attempt costs you time */
1710 			return (1);
1711 		}
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);
1717 		}
1718 		otmp = hold_another_object(otmp, "You drop %s!", doname(otmp),
1719 					(const char *)0);
1720 		timepassed = rnd(3);
1721 		if (prev_loot) *prev_loot = TRUE;
1722 	} else if (c == 'q') {
1723 		return (0);
1724 	}
1725     }
1726 #endif	/* STEED */
1727     /* 3.4.0 introduced the ability to pick things up from within swallower's stomach */
1728     if (u.uswallow) {
1729 	int count = passed_info ? *passed_info : 0;
1730 	timepassed = pickup(count);
1731     }
1732     return timepassed;
1733 }
1734 
1735 /*
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.
1738  */
1739 STATIC_OVL boolean
mbag_explodes(obj,depthin)1740 mbag_explodes(obj, depthin)
1741     struct obj *obj;
1742     int depthin;
1743 {
1744     /* these won't cause an explosion when they're empty */
1745     if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS) &&
1746 	    obj->spe <= 0)
1747 	return FALSE;
1748 
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))
1752 	return TRUE;
1753     else if (Has_contents(obj)) {
1754 	struct obj *otmp;
1755 
1756 	for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
1757 	    if (mbag_explodes(otmp, depthin+1)) return TRUE;
1758     }
1759     return FALSE;
1760 }
1761 
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)
1766 
1767 /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
1768 STATIC_PTR int
in_container(obj)1769 in_container(obj)
1770 register struct obj *obj;
1771 {
1772 	boolean floor_container = !carried(current_container);
1773 	boolean was_unpaid = FALSE;
1774 	char buf[BUFSZ];
1775 
1776 	if (!current_container) {
1777 		impossible("<in> no current_container?");
1778 		return 0;
1779 	} else if (obj == uball || obj == uchain) {
1780 		You("must be kidding.");
1781 		return 0;
1782 	} else if (obj == current_container) {
1783 		pline("That would be an interesting topological exercise.");
1784 		return 0;
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);
1788 		return 0;
1789 	} else if ((obj->otyp == LOADSTONE) && obj->cursed) {
1790 		obj->bknown = 1;
1791 	      pline_The("stone%s won't leave your person.", plur(obj->quan));
1792 		return 0;
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.
1800 	 */
1801 	    pline("%s cannot be confined in such trappings.", The(xname(obj)));
1802 	    return 0;
1803 	} else if (obj->otyp == LEASH && obj->leashmon != 0) {
1804 		pline("%s attached to your pet.", Tobjnam(obj, "are"));
1805 		return 0;
1806 	} else if (obj == uwep) {
1807 		if (welded(obj)) {
1808 			weldmsg(obj);
1809 			return 0;
1810 		}
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 */
1819 	}
1820 
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);
1826 		else {
1827 		    char kbuf[BUFSZ];
1828 
1829 		    Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1830 		    pline("Touching %s is a fatal mistake.", kbuf);
1831 		    instapetrify(kbuf);
1832 		    return -1;
1833 		}
1834 	    }
1835 	}
1836 
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]))) {
1840 		/*
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.
1845 		 */
1846 		Strcpy(buf, the(xname(obj)));
1847 		You("cannot fit %s into %s.", buf,
1848 		    the(xname(current_container)));
1849 		return 0;
1850 	}
1851 
1852 	freeinv(obj);
1853 
1854 	if (obj_is_burning(obj))	/* this used to be part of freeinv() */
1855 		(void) snuff_lit(obj);
1856 
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 */
1860 		obj->no_charge = 1;
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);
1868 	    }
1869 	}
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;
1878 		}
1879 	} else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
1880 		/* explicitly mention what item is triggering the explosion */
1881 		pline(
1882 	      "As you put %s inside, you are blasted by a magical explosion!",
1883 		      doname(obj));
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);
1892 		else
1893 			panic("in_container:  bag not found.");
1894 
1895 		losehp(d(6,6),"magical explosion", KILLED_BY_AN);
1896 		current_container = 0;	/* baggone = TRUE; */
1897 	}
1898 
1899 	if (current_container) {
1900 	    Strcpy(buf, the(xname(current_container)));
1901 	    You("put %s into %s.", doname(obj), buf);
1902 
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);
1908 	}
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.
1912 	 */
1913 	bot();
1914 
1915 	return(current_container ? 1 : -1);
1916 }
1917 
1918 STATIC_PTR int
ck_bag(obj)1919 ck_bag(obj)
1920 struct obj *obj;
1921 {
1922 	return current_container && obj != current_container;
1923 }
1924 
1925 /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
1926 STATIC_PTR int
out_container(obj)1927 out_container(obj)
1928 register struct obj *obj;
1929 {
1930 	register struct obj *otmp;
1931 	boolean is_gold = (obj->oclass == COIN_CLASS);
1932 	int res, loadlev;
1933 	long count;
1934 
1935 	if (!current_container) {
1936 		impossible("<out> no current_container?");
1937 		return -1;
1938 	} else if (is_gold) {
1939 		obj->owt = weight(obj);
1940 	}
1941 
1942 	if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0;
1943 
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);
1949 		else {
1950 		    char kbuf[BUFSZ];
1951 
1952 		    Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1953 		    pline("Touching %s is a fatal mistake.", kbuf);
1954 		    instapetrify(kbuf);
1955 		    return -1;
1956 		}
1957 	    }
1958 	}
1959 
1960 	count = obj->quan;
1961 	if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0)
1962 	    return res;
1963 
1964 	if (obj->quan != count && obj->otyp != LOADSTONE)
1965 	    obj = splitobj(obj, count);
1966 
1967 	/* Remove the object from the list. */
1968 	obj_extract_self(obj);
1969 	current_container->owt = weight(current_container);
1970 
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);
1975 	}
1976 	/* simulated point of time */
1977 
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);
1983 	}
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!");
1986 
1987 	otmp = addinv(obj);
1988 	loadlev = near_capacity();
1989 	prinv(loadlev ?
1990 	      (loadlev < MOD_ENCUMBER ?
1991 	       "You have a little trouble removing" :
1992 	       "You have much trouble removing") : (char *)0,
1993 	      otmp, count);
1994 
1995 	if (is_gold) {
1996 #ifndef GOLDOBJ
1997 		dealloc_obj(obj);
1998 #endif
1999 		bot();	/* update character's gold piece count immediately */
2000 	}
2001 	return 1;
2002 }
2003 
2004 /* an object inside a cursed bag of holding is being destroyed */
2005 STATIC_OVL long
mbag_item_gone(held,item)2006 mbag_item_gone(held, item)
2007 int held;
2008 struct obj *item;
2009 {
2010     struct monst *shkp;
2011     long loss = 0L;
2012 
2013     if (item->dknown)
2014 	pline("%s %s vanished!", Doname2(item), otense(item, "have"));
2015     else
2016 	You("%s %s disappear!", Blind ? "notice" : "see", doname(item));
2017 
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);
2022     }
2023     obfree(item, (struct obj *) 0);
2024     return loss;
2025 }
2026 
2027 STATIC_OVL void
observe_quantum_cat(box)2028 observe_quantum_cat(box)
2029 struct obj *box;
2030 {
2031     static NEARDATA const char sc[] = "Schroedinger's Cat";
2032     struct obj *deadcat;
2033     struct monst *livecat;
2034     xchar ox, oy;
2035 
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 */
2039 
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;
2046     if (livecat) {
2047 	livecat->mpeaceful = 1;
2048 	set_malign(livecat);
2049 	if (!canspotmon(livecat))
2050 	    You("think %s brushed your %s.", something, body_part(FOOT));
2051 	else
2052 	    pline("%s inside the box is still alive!", Monnam(livecat));
2053 	(void) christen_monst(livecat, sc);
2054     } else {
2055 	deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
2056 				  box->ox, box->oy, sc);
2057 	if (deadcat) {
2058 	    obj_extract_self(deadcat);
2059 	    (void) add_to_container(box, deadcat);
2060 	}
2061 	pline_The("%s inside the box is dead!",
2062 	    Hallucination ? rndmonnam() : "housecat");
2063     }
2064     box->owt = weight(box);
2065     return;
2066 }
2067 
2068 #undef Icebox
2069 
2070 int
use_container(obj,held)2071 use_container(obj, held)
2072 register struct obj *obj;
2073 register int held;
2074 {
2075 	struct obj *curr, *otmp;
2076 #ifndef GOLDOBJ
2077 	struct obj *u_gold = (struct obj *)0;
2078 #endif
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];
2083 	long loss = 0L;
2084 	int cnt = 0, used = 0,
2085 	    menu_on_request;
2086 
2087 	emptymsg[0] = '\0';
2088 	if (nohands(youmonst.data)) {
2089 		You("have no hands!");	/* not `body_part(HAND)' */
2090 		return 0;
2091 	} else if (!freehand()) {
2092 		You("have no free %s.", body_part(HAND));
2093 		return 0;
2094 	}
2095 	if (obj->olocked) {
2096 	    pline("%s to be locked.", Tobjnam(obj, "seem"));
2097 	    if (held) You("must put it down to unlock.");
2098 	    return 0;
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 */
2104 		nomul(-1);
2105 		nomovemsg = "";
2106 	    }
2107 	    return 1;
2108 	}
2109 	current_container = obj;	/* for use by in/out_container */
2110 
2111 	if (obj->spe == 1) {
2112 	    observe_quantum_cat(obj);
2113 	    used = 1;
2114 	    quantum_cat = TRUE;	/* for adjusting "it's empty" message */
2115 	}
2116 	/* Count the number of contained objects. Sometimes toss objects if */
2117 	/* a cursed magic bag.						    */
2118 	for (curr = obj->cobj; curr; curr = otmp) {
2119 	    otmp = curr->nobj;
2120 	    if (Is_mbag(obj) && obj->cursed && !rn2(13)) {
2121 		obj_extract_self(curr);
2122 		loss += mbag_item_gone(held, curr);
2123 		used = 1;
2124 	    } else {
2125 		cnt++;
2126 	    }
2127 	}
2128 
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 */
2132 
2133 	if (!cnt)
2134 	    Sprintf(emptymsg, "%s is %sempty.", Yname2(obj),
2135 		    quantum_cat ? "now " : "");
2136 
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) {
2143 		    int t;
2144 		    char menuprompt[BUFSZ];
2145 		    boolean outokay = (cnt != 0);
2146 #ifndef GOLDOBJ
2147 		    boolean inokay = (invent != 0) || (u.ugold != 0);
2148 #else
2149 		    boolean inokay = (invent != 0);
2150 #endif
2151 		    if (!outokay && !inokay) {
2152 			pline("%s", emptymsg);
2153 			You("don't have anything to put in.");
2154 			return used;
2155 		    }
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');
2165 		}
2166 		if (loot_out) {
2167 		    add_valid_menu_class(0);	/* reset */
2168 		    used |= menu_loot(0, current_container, FALSE) > 0;
2169 		}
2170 	    } else {
2171 		/* traditional code */
2172 ask_again2:
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')) {
2178 		case ':':
2179 		    container_contents(current_container, FALSE, FALSE);
2180 		    goto ask_again2;
2181 		case 'y':
2182 		    if (query_classes(select, &one_by_one, &allflag,
2183 				      "take out", current_container->cobj,
2184 				      FALSE,
2185 #ifndef GOLDOBJ
2186 				      FALSE,
2187 #endif
2188 				      &menu_on_request)) {
2189 			if (askchain((struct obj **)&current_container->cobj,
2190 				     (one_by_one ? (char *)0 : select),
2191 				     allflag, out_container,
2192 				     (int FDECL((*),(OBJ_P)))0,
2193 				     0, "nodot"))
2194 			    used = 1;
2195 		    } else if (menu_on_request < 0) {
2196 			used |= menu_loot(menu_on_request,
2197 					  current_container, FALSE) > 0;
2198 		    }
2199 		    /*FALLTHRU*/
2200 		case 'n':
2201 		    break;
2202 		case 'm':
2203 		    menu_on_request = -2; /* triggers ALL_CLASSES */
2204 		    used |= menu_loot(menu_on_request, current_container, FALSE) > 0;
2205 		    break;
2206 		case 'q':
2207 		default:
2208 		    return used;
2209 		}
2210 	    }
2211 	} else {
2212 	    pline("%s", emptymsg);		/* <whatever> is empty. */
2213 	}
2214 
2215 #ifndef GOLDOBJ
2216 	if (!invent && u.ugold == 0) {
2217 #else
2218 	if (!invent) {
2219 #endif
2220 	    /* nothing to put in, but some feedback is necessary */
2221 	    You("don't have anything to put in.");
2222 	    return used;
2223 	}
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)
2228 		Strcat(pbuf, "m");
2229 	    switch (yn_function(qbuf, pbuf, 'n')) {
2230 		case 'y':
2231 		    loot_in = TRUE;
2232 		    break;
2233 		case 'n':
2234 		    break;
2235 		case 'm':
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;
2239 		    break;
2240 		case 'q':
2241 		default:
2242 		    return used;
2243 	    }
2244 	}
2245 	/*
2246 	 * Gone: being nice about only selecting food if we know we are
2247 	 * putting things in an ice chest.
2248 	 */
2249 	if (loot_in) {
2250 #ifndef GOLDOBJ
2251 	    if (u.ugold) {
2252 		/*
2253 		 * Hack: gold is not in the inventory, so make a gold object
2254 		 * and put it at the head of the inventory list.
2255 		 */
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;
2261 		invent = u_gold;
2262 	    }
2263 #endif
2264 	    add_valid_menu_class(0);	  /* reset */
2265 	    if (flags.menu_style != MENU_TRADITIONAL) {
2266 		used |= menu_loot(0, current_container, TRUE) > 0;
2267 	    } else {
2268 		/* traditional code */
2269 		menu_on_request = 0;
2270 		if (query_classes(select, &one_by_one, &allflag, "put in",
2271 				   invent, FALSE,
2272 #ifndef GOLDOBJ
2273 				   (u.ugold != 0L),
2274 #endif
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");
2279 		    used = 1;
2280 		} else if (menu_on_request < 0) {
2281 		    used |= menu_loot(menu_on_request,
2282 				      current_container, TRUE) > 0;
2283 		}
2284 	    }
2285 	}
2286 
2287 #ifndef GOLDOBJ
2288 	if (u_gold && invent && invent->oclass == COIN_CLASS) {
2289 	    /* didn't stash [all of] it */
2290 	    u_gold = invent;
2291 	    invent = u_gold->nobj;
2292 	    u_gold->in_use = FALSE;
2293 	    dealloc_obj(u_gold);
2294 	}
2295 #endif
2296 	return used;
2297 }
2298 
2299 /* Loot a container (take things out, put things in), using a menu. */
2300 STATIC_OVL int
menu_loot(retry,container,put_in)2301 menu_loot(retry, container, put_in)
2302 int retry;
2303 struct obj *container;
2304 boolean put_in;
2305 {
2306     int n, i, n_looted = 0;
2307     boolean all_categories = TRUE, loot_everything = FALSE;
2308     char buf[BUFSZ];
2309     const char *takeout = "Take out", *putin = "Put in";
2310     struct obj *otmp, *otmp2;
2311     menu_item *pick_list;
2312     int mflags, res;
2313     long count;
2314 
2315     if (retry) {
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);
2324 	if (!n) return 0;
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;
2330 	    else
2331 		add_valid_menu_class(pick_list[i].item.a_int);
2332 	}
2333 	free((genericptr_t) pick_list);
2334     }
2335 
2336     if (loot_everything) {
2337 	for (otmp = container->cobj; otmp; otmp = otmp2) {
2338 	    otmp2 = otmp->nobj;
2339 	    res = out_container(otmp);
2340 	    if (res < 0) break;
2341 	}
2342     } else {
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);
2349 	if (n) {
2350 		n_looted = n;
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() */
2357 		    }
2358 		    res = put_in ? in_container(otmp) : out_container(otmp);
2359 		    if (res < 0) {
2360 			if (otmp != pick_list[i].item.a_obj) {
2361 			    /* split occurred, merge again */
2362 			    (void) merged(&pick_list[i].item.a_obj, &otmp);
2363 			}
2364 			break;
2365 		    }
2366 		}
2367 		free((genericptr_t)pick_list);
2368 	}
2369     }
2370     return n_looted;
2371 }
2372 
2373 STATIC_OVL int
in_or_out_menu(prompt,obj,outokay,inokay)2374 in_or_out_menu(prompt, obj, outokay, inokay)
2375 const char *prompt;
2376 struct obj *obj;
2377 boolean outokay, inokay;
2378 {
2379     winid win;
2380     anything any;
2381     menu_item *pick_list;
2382     char buf[BUFSZ];
2383     int n;
2384     const char *menuselector = iflags.lootabc ? "abc" : "oib";
2385 
2386     any.a_void = 0;
2387     win = create_nhwindow(NHW_MENU);
2388     start_menu(win);
2389     if (outokay) {
2390 	any.a_int = 1;
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);
2394     }
2395     menuselector++;
2396     if (inokay) {
2397 	any.a_int = 2;
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);
2400     }
2401     menuselector++;
2402     if (outokay && inokay) {
2403 	any.a_int = 3;
2404 	add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE,
2405 			"Both of the above", MENU_UNSELECTED);
2406     }
2407     end_menu(win, prompt);
2408     n = select_menu(win, PICK_ONE, &pick_list);
2409     destroy_nhwindow(win);
2410     if (n > 0) {
2411 	n = pick_list[0].item.a_int;
2412 	free((genericptr_t) pick_list);
2413     }
2414     return n;
2415 }
2416 
2417 /*pickup.c*/
2418