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
11STATIC_DCL void FDECL(simple_look, (struct obj *,BOOLEAN_P));
12#ifndef GOLDOBJ
13STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
14		const char *,struct obj *,BOOLEAN_P,BOOLEAN_P,int *));
15#else
16STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
17		const char *,struct obj *,BOOLEAN_P,int *));
18#endif
19STATIC_DCL void FDECL(check_here, (BOOLEAN_P));
20STATIC_DCL boolean FDECL(n_or_more, (struct obj *));
21STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *));
22#if 0 /* not used */
23STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *));
24#endif
25STATIC_DCL int FDECL(autopick, (struct obj*, int, menu_item **));
26STATIC_DCL int FDECL(count_categories, (struct obj *,int));
27STATIC_DCL long FDECL(carry_count,
28		      (struct obj *,struct obj *,long,BOOLEAN_P,int *,int *));
29STATIC_DCL int FDECL(lift_object, (struct obj *,struct obj *,long *,BOOLEAN_P));
30STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *,int));
31STATIC_PTR int FDECL(in_container,(struct obj *));
32STATIC_PTR int FDECL(ck_bag,(struct obj *));
33STATIC_PTR int FDECL(out_container,(struct obj *));
34STATIC_DCL long FDECL(mbag_item_gone, (int,struct obj *));
35STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
36STATIC_DCL int FDECL(menu_loot, (int, struct obj *, BOOLEAN_P));
37STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *, BOOLEAN_P, BOOLEAN_P));
38STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
39STATIC_DCL boolean FDECL(able_to_loot, (int, int));
40STATIC_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
58static const char moderateloadmsg[] = "You have a little trouble lifting";
59static const char nearloadmsg[] = "You have much trouble lifting";
60static 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() */
65STATIC_OVL void
66simple_look(otmp, here)
67struct obj *otmp;	/* list of objects */
68boolean 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
91int
92collect_obj_classes(ilets, otmp, here, incl_gold, filter, itemcount)
93char ilets[];
94register struct obj *otmp;
95boolean here, incl_gold;
96boolean FDECL((*filter),(OBJ_P));
97int *itemcount;
98#else
99int
100collect_obj_classes(ilets, otmp, here, filter, itemcount)
101char ilets[];
102register struct obj *otmp;
103boolean here;
104boolean FDECL((*filter),(OBJ_P));
105int *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
141STATIC_OVL boolean
142query_classes(oclasses, one_at_a_time, everything, action, objs,
143	      here, incl_gold, menu_on_demand)
144char oclasses[];
145boolean *one_at_a_time, *everything;
146const char *action;
147struct obj *objs;
148boolean here, incl_gold;
149int *menu_on_demand;
150#else
151STATIC_OVL boolean
152query_classes(oclasses, one_at_a_time, everything, action, objs,
153	      here, menu_on_demand)
154char oclasses[];
155boolean *one_at_a_time, *everything;
156const char *action;
157struct obj *objs;
158boolean here;
159int *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';
199ask_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 */
255STATIC_OVL void
256check_here(picked_some)
257boolean 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(). */
279static long val_for_n_or_more;
280
281/* query_objlist callback: return TRUE if obj's count is >= reference value */
282STATIC_OVL boolean
283n_or_more(obj)
284struct 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 */
291static char valid_menu_classes[MAXOCLASSES + 2];
292
293void
294add_valid_menu_class(c)
295int 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 */
307STATIC_OVL boolean
308all_but_uchain(obj)
309struct obj *obj;
310{
311    return (obj != uchain);
312}
313
314/* query_objlist callback: return TRUE */
315/*ARGSUSED*/
316boolean
317allow_all(obj)
318struct obj *obj;
319{
320    return TRUE;
321}
322
323boolean
324allow_category(obj)
325struct 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 */
349STATIC_OVL boolean
350allow_cat_no_uchain(obj)
351struct 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 */
363boolean
364is_worn_by_type(otmp)
365register 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 */
384int
385pickup(what)
386int 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	    }
483menu_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	    }
582end_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
599boolean
600is_autopickup_exception(obj, grab)
601struct obj *obj;
602boolean 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 */
626STATIC_OVL int
627autopick(olist, follow, pick_list)
628struct obj *olist;	/* the object list */
629int follow;		/* how to follow the object list */
630menu_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 */
684int
685query_objlist(qstr, olist, qflags, pick_list, how, allow)
686const char *qstr;		/* query string */
687struct obj *olist;		/* the list to pick from */
688int qflags;			/* options to control the query */
689menu_item **pick_list;		/* return list of items picked */
690int how;			/* type of query */
691boolean 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 */
783int
784query_category(qstr, olist, qflags, pick_list, how)
785const char *qstr;		/* query string */
786struct obj *olist;		/* the list to pick from */
787int qflags;			/* behaviour modification flags */
788menu_item **pick_list;		/* return list of items picked */
789int 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 NETHACK_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
946STATIC_OVL int
947count_categories(olist, qflags)
948struct obj *olist;
949int 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? */
977STATIC_OVL long
978carry_count(obj, container, count, telekinesis, wt_before, wt_after)
979struct obj *obj, *container;	/* object to pick up, bag it's coming out of */
980long count;
981boolean telekinesis;
982int *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' */
1140STATIC_OVL
1141int
1142lift_object(obj, container, cnt_p, telekinesis)
1143struct obj *obj, *container;	/* object to pick up, bag it's coming out of */
1144long *cnt_p;
1145boolean 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 */
1211const char *
1212safe_qbuf(qbuf, padlength, planA, planB, last_resort)
1213const char *qbuf, *planA, *planB, *last_resort;
1214unsigned 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 */
1237int
1238pickup_object(obj, count, telekinesis)
1239struct obj *obj;
1240long count;
1241boolean 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 */
1372struct obj *
1373pick_obj(otmp)
1374struct 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 */
1404int
1405encumber_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 */
1444STATIC_OVL int
1445container_at(x, y, countem)
1446int x,y;
1447boolean 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
1462STATIC_OVL boolean
1463able_to_loot(x, y)
1464int 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
1490STATIC_OVL boolean
1491mon_beside(x,y)
1492int 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
1505int
1506doloot()	/* 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
1529lootcont:
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 */
1595gotit:
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 */
1679int
1680loot_mon(mtmp, passed_info, prev_loot)
1681struct monst *mtmp;
1682int *passed_info;
1683boolean *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 */
1739STATIC_OVL boolean
1740mbag_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(). */
1764static 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. */
1768STATIC_PTR int
1769in_container(obj)
1770register 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
1918STATIC_PTR int
1919ck_bag(obj)
1920struct 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. */
1926STATIC_PTR int
1927out_container(obj)
1928register 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 */
2005STATIC_OVL long
2006mbag_item_gone(held, item)
2007int held;
2008struct 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
2027STATIC_OVL void
2028observe_quantum_cat(box)
2029struct 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
2070int
2071use_container(obj, held)
2072register struct obj *obj;
2073register 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 */
2172ask_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. */
2300STATIC_OVL int
2301menu_loot(retry, container, put_in)
2302int retry;
2303struct obj *container;
2304boolean 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
2373STATIC_OVL int
2374in_or_out_menu(prompt, obj, outokay, inokay)
2375const char *prompt;
2376struct obj *obj;
2377boolean 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