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 int FDECL(menu_loot, (int, struct obj *, BOOLEAN_P));
36 STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *, BOOLEAN_P, BOOLEAN_P));
37 STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
38 STATIC_DCL boolean FDECL(able_to_loot, (int, int, BOOLEAN_P));
39 STATIC_DCL boolean FDECL(mon_beside, (int, int));
40 STATIC_DCL int FDECL(dump_container, (struct obj*, BOOLEAN_P));
41 STATIC_DCL void NDECL(del_sokoprize);
42 
43 /* define for query_objlist() and autopickup() */
44 #define FOLLOW(curr, flags) \
45     (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
46 
47 /*
48  *  How much the weight of the given container will change when the given
49  *  object is removed from it.  This calculation must match the one used
50  *  by weight() in mkobj.c.
51  */
52 #define DELTA_CWT(cont,obj)		\
53     ((cont)->cursed ? (obj)->owt * 2 :	\
54 		      1 + ((obj)->owt / ((cont)->blessed ? 4 : 2)))
55 #define GOLD_WT(n)		(((n) + 50L) / 100L)
56 /* if you can figure this out, give yourself a hearty pat on the back... */
57 #define GOLD_CAPACITY(w,n)	(((w) * -100L) - ((n) + 50L) - 1L)
58 
59 static const char moderateloadmsg[] = "You have a little trouble lifting";
60 static const char nearloadmsg[] = "You have much trouble lifting";
61 static const char overloadmsg[] = "You have extreme difficulty lifting";
62 
63 /* BUG: this lets you look at cockatrice corpses while blind without
64    touching them */
65 /* much simpler version of the look-here code; used by query_classes() */
66 STATIC_OVL void
simple_look(otmp,here)67 simple_look(otmp, here)
68 struct obj *otmp;	/* list of objects */
69 boolean here;		/* flag for type of obj list linkage */
70 {
71 	/* Neither of the first two cases is expected to happen, since
72 	 * we're only called after multiple classes of objects have been
73 	 * detected, hence multiple objects must be present.
74 	 */
75 	if (!otmp) {
76 	    impossible("simple_look(null)");
77 	} else if (!(here ? otmp->nexthere : otmp->nobj)) {
78 	    pline("%s", doname(otmp));
79 	} else {
80 	    winid tmpwin = create_nhwindow(NHW_MENU);
81 	    putstr(tmpwin, 0, "");
82 	    do {
83 		putstr(tmpwin, 0, doname(otmp));
84 		otmp = here ? otmp->nexthere : otmp->nobj;
85 	    } while (otmp);
86 	    display_nhwindow(tmpwin, TRUE);
87 	    destroy_nhwindow(tmpwin);
88 	}
89 }
90 
91 #ifndef GOLDOBJ
92 int
collect_obj_classes(ilets,otmp,here,incl_gold,filter,itemcount)93 collect_obj_classes(ilets, otmp, here, incl_gold, filter, itemcount)
94 char ilets[];
95 register struct obj *otmp;
96 boolean here, incl_gold;
97 boolean FDECL((*filter),(OBJ_P));
98 int *itemcount;
99 #else
100 int
101 collect_obj_classes(ilets, otmp, here, filter, itemcount)
102 char ilets[];
103 register struct obj *otmp;
104 boolean here;
105 boolean FDECL((*filter),(OBJ_P));
106 int *itemcount;
107 #endif
108 {
109 	register int iletct = 0;
110 	register char c;
111 
112 	*itemcount = 0;
113 #ifndef GOLDOBJ
114 	if (incl_gold)
115 	    ilets[iletct++] = def_oc_syms[COIN_CLASS];
116 #endif
117 	ilets[iletct] = '\0'; /* terminate ilets so that index() will work */
118 	while (otmp) {
119 	    c = def_oc_syms[(int)otmp->oclass];
120 	    if (!index(ilets, c) && (!filter || (*filter)(otmp)))
121 		ilets[iletct++] = c,  ilets[iletct] = '\0';
122 	    *itemcount += 1;
123 	    otmp = here ? otmp->nexthere : otmp->nobj;
124 	}
125 
126 	return iletct;
127 }
128 
129 /*
130  * Suppose some '?' and '!' objects are present, but '/' objects aren't:
131  *	"a" picks all items without further prompting;
132  *	"A" steps through all items, asking one by one;
133  *	"?" steps through '?' items, asking, and ignores '!' ones;
134  *	"/" becomes 'A', since no '/' present;
135  *	"?a" or "a?" picks all '?' without further prompting;
136  *	"/a" or "a/" becomes 'A' since there aren't any '/'
137  *	    (bug fix:  3.1.0 thru 3.1.3 treated it as "a");
138  *	"?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
139  *	    (ie, treated as if it had just been "?a").
140  */
141 #ifndef GOLDOBJ
142 STATIC_OVL boolean
query_classes(oclasses,one_at_a_time,everything,action,objs,here,incl_gold,menu_on_demand)143 query_classes(oclasses, one_at_a_time, everything, action, objs,
144 	      here, incl_gold, menu_on_demand)
145 char oclasses[];
146 boolean *one_at_a_time, *everything;
147 const char *action;
148 struct obj *objs;
149 boolean here, incl_gold;
150 int *menu_on_demand;
151 #else
152 STATIC_OVL boolean
153 query_classes(oclasses, one_at_a_time, everything, action, objs,
154 	      here, menu_on_demand)
155 char oclasses[];
156 boolean *one_at_a_time, *everything;
157 const char *action;
158 struct obj *objs;
159 boolean here;
160 int *menu_on_demand;
161 #endif
162 {
163 	char ilets[20], inbuf[BUFSZ];
164 	int iletct, oclassct;
165 	boolean not_everything;
166 	char qbuf[QBUFSZ];
167 	boolean m_seen;
168 	int itemcount;
169 
170 	oclasses[oclassct = 0] = '\0';
171 	*one_at_a_time = *everything = m_seen = FALSE;
172 	iletct = collect_obj_classes(ilets, objs, here,
173 #ifndef GOLDOBJ
174 				     incl_gold,
175 #endif
176 				     (boolean FDECL((*),(OBJ_P))) 0, &itemcount);
177 	if (iletct == 0) {
178 		return FALSE;
179 	} else if (iletct == 1) {
180 		oclasses[0] = def_char_to_objclass(ilets[0]);
181 		oclasses[1] = '\0';
182 		if (itemcount && menu_on_demand) {
183 			ilets[iletct++] = 'm';
184 			*menu_on_demand = 0;
185 			ilets[iletct] = '\0';
186 		}
187 	} else  {	/* more than one choice available */
188 		const char *where = 0;
189 		register char sym, oc_of_sym, *p;
190 		/* additional choices */
191 		ilets[iletct++] = ' ';
192 		ilets[iletct++] = 'a';
193 		ilets[iletct++] = 'A';
194 		ilets[iletct++] = (objs == invent ? 'i' : ':');
195 		if (menu_on_demand) {
196 			ilets[iletct++] = 'm';
197 			*menu_on_demand = 0;
198 		}
199 		ilets[iletct] = '\0';
200 ask_again:
201 		oclasses[oclassct = 0] = '\0';
202 		*one_at_a_time = *everything = FALSE;
203 		not_everything = FALSE;
204 		Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
205 			action, ilets);
206 		getlin(qbuf,inbuf);
207 		if (*inbuf == '\033') return FALSE;
208 
209 		for (p = inbuf; (sym = *p++); ) {
210 		    /* new A function (selective all) added by GAN 01/09/87 */
211 		    if (sym == ' ') continue;
212 		    else if (sym == 'A') *one_at_a_time = TRUE;
213 		    else if (sym == 'a') *everything = TRUE;
214 		    else if (sym == ':') {
215 			simple_look(objs, here);  /* dumb if objs==invent */
216 			goto ask_again;
217 		    } else if (sym == 'i') {
218 			(void) display_inventory((char *)0, TRUE);
219 			goto ask_again;
220 		    } else if (sym == 'm') {
221 			m_seen = TRUE;
222 		    } else {
223 			oc_of_sym = def_char_to_objclass(sym);
224 			if (index(ilets,sym)) {
225 			    add_valid_menu_class(oc_of_sym);
226 			    oclasses[oclassct++] = oc_of_sym;
227 			    oclasses[oclassct] = '\0';
228 			} else {
229 			    if (!where)
230 				where = !strcmp(action,"pick up")  ? "here" :
231 					!strcmp(action,"take out") ?
232 							    "inside" : "";
233 			    if (*where)
234 				There("are no %c's %s.", sym, where);
235 			    else
236 				You("have no %c's.", sym);
237 			    not_everything = TRUE;
238 			}
239 		    }
240 		}
241 		if (m_seen && menu_on_demand) {
242 			*menu_on_demand = (*everything || !oclassct) ? -2 : -3;
243 			return FALSE;
244 		}
245 		if (!oclassct && (!*everything || not_everything)) {
246 		    /* didn't pick anything,
247 		       or tried to pick something that's not present */
248 		    *one_at_a_time = TRUE;	/* force 'A' */
249 		    *everything = FALSE;	/* inhibit 'a' */
250 		}
251 	}
252 	return TRUE;
253 }
254 
255 /* look at the objects at our location, unless there are too many of them */
256 STATIC_OVL void
check_here(picked_some)257 check_here(picked_some)
258 boolean picked_some;
259 {
260 	register struct obj *obj;
261 	register int ct = 0;
262 
263 	/* count the objects here */
264 	for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) {
265 	    if (obj != uchain)
266 		ct++;
267 	}
268 
269 	/* If there are objects here, take a look. */
270 	if (ct) {
271 	    if (flags.run) nomul(0, 0);
272 	    flush_screen(1);
273 	    (void) look_here(ct, picked_some);
274 	} else {
275 	    read_engr_at(u.ux,u.uy);
276 	}
277 }
278 
279 /* Value set by query_objlist() for n_or_more(). */
280 static long val_for_n_or_more;
281 
282 /* query_objlist callback: return TRUE if obj's count is >= reference value */
283 STATIC_OVL boolean
n_or_more(obj)284 n_or_more(obj)
285 struct obj *obj;
286 {
287     if (obj == uchain) return FALSE;
288     return (obj->quan >= val_for_n_or_more);
289 }
290 
291 /* List of valid menu classes for query_objlist() and allow_category callback */
292 static char valid_menu_classes[MAXOCLASSES + 2];
293 
294 void
add_valid_menu_class(c)295 add_valid_menu_class(c)
296 int c;
297 {
298 	static int vmc_count = 0;
299 
300 	if (c == 0)  /* reset */
301 	  vmc_count = 0;
302 	else
303 	  valid_menu_classes[vmc_count++] = (char)c;
304 	valid_menu_classes[vmc_count] = '\0';
305 }
306 
307 /* query_objlist callback: return TRUE if not uchain */
308 STATIC_OVL boolean
all_but_uchain(obj)309 all_but_uchain(obj)
310 struct obj *obj;
311 {
312     return (obj != uchain);
313 }
314 
315 /* query_objlist callback: return TRUE */
316 /*ARGSUSED*/
317 boolean
allow_all(obj)318 allow_all(obj)
319 struct obj *obj;
320 {
321     return TRUE;
322 }
323 
324 boolean
allow_category(obj)325 allow_category(obj)
326 struct obj *obj;
327 {
328     if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
329     if (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
330 	(index(valid_menu_classes, obj->oclass) != (char *)0))
331 	return TRUE;
332     else if (((index(valid_menu_classes,'I') != (char *)0) &&
333 	(obj->oclass != COIN_CLASS && not_fully_identified(obj))))
334 	return TRUE;
335     else if (((index(valid_menu_classes,'U') != (char *)0) &&
336 	(obj->oclass != COIN_CLASS && obj->bknown && !obj->blessed && !obj->cursed)))
337 	return TRUE;
338     else if (((index(valid_menu_classes,'B') != (char *)0) &&
339 	(obj->oclass != COIN_CLASS && obj->bknown && obj->blessed)))
340 	return TRUE;
341     else if (((index(valid_menu_classes,'C') != (char *)0) &&
342 	(obj->oclass != COIN_CLASS && obj->bknown && obj->cursed)))
343 	return TRUE;
344     else if (((index(valid_menu_classes,'X') != (char *)0) &&
345 	(obj->oclass != COIN_CLASS && !obj->bknown)))
346 	return TRUE;
347     else
348 	return FALSE;
349 }
350 
351 #if 0 /* not used */
352 /* query_objlist callback: return TRUE if valid category (class), no uchain */
353 STATIC_OVL boolean
354 allow_cat_no_uchain(obj)
355 struct obj *obj;
356 {
357     if ((obj != uchain) &&
358 	(((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
359 	(index(valid_menu_classes, obj->oclass) != (char *)0)))
360 	return TRUE;
361     else
362 	return FALSE;
363 }
364 #endif
365 
366 /* query_objlist callback: return TRUE if valid class and worn */
367 boolean
is_worn_by_type(otmp)368 is_worn_by_type(otmp)
369 register struct obj *otmp;
370 {
371 	return((boolean)(!!(otmp->owornmask &
372 			(W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP | W_SWAPWEP | W_QUIVER)))
373 	        && (index(valid_menu_classes, otmp->oclass) != (char *)0));
374 }
375 
376 /*
377  * Have the hero pick things from the ground
378  * or a monster's inventory if swallowed.
379  *
380  * Arg what:
381  *	>0  autopickup
382  *	=0  interactive
383  *	<0  pickup count of something
384  *
385  * Returns 1 if tried to pick something up, whether
386  * or not it succeeded.
387  */
388 int
pickup(what)389 pickup(what)
390 int what;		/* should be a long */
391 {
392 	int i, n, res, count, n_tried = 0, n_picked = 0;
393 	menu_item *pick_list = (menu_item *) 0;
394 	boolean autopickup = what > 0;
395 	struct obj *objchain;
396 	int traverse_how;
397 
398 	if (what < 0)		/* pick N of something */
399 	    count = -what;
400 	else			/* pick anything */
401 	    count = 0;
402 
403 	if (!u.uswallow) {
404 		struct trap *ttmp = t_at(u.ux, u.uy);
405 		/* no auto-pick if no-pick move, nothing there, or in a pool */
406 		if (autopickup && (flags.nopick || !OBJ_AT(u.ux, u.uy) ||
407 			(is_pool(u.ux, u.uy) && !Underwater) || is_lava(u.ux, u.uy))) {
408 			read_engr_at(u.ux, u.uy);
409 			return (0);
410 		}
411 
412 		/* no pickup if levitating & not on air or water level */
413 		if (!can_reach_floor()) {
414 		    if ((multi && !flags.run) || (autopickup && !flags.pickup))
415 			read_engr_at(u.ux, u.uy);
416 		    return (0);
417 		}
418 		if (ttmp && ttmp->tseen) {
419 		    /* Allow pickup from holes and trap doors that you escaped
420 		     * from because that stuff is teetering on the edge just
421 		     * like you, but not pits, because there is an elevation
422 		     * discrepancy with stuff in pits.
423 		     */
424 		    if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT) &&
425 			(!u.utrap || (u.utrap && u.utraptype != TT_PIT))) {
426 			read_engr_at(u.ux, u.uy);
427 			return(0);
428 		    }
429 		}
430 		/* multi && !flags.run means they are in the middle of some other
431 		 * action, or possibly paralyzed, sleeping, etc.... and they just
432 		 * teleported onto the object.  They shouldn't pick it up.
433 		 */
434 		if ((multi && !flags.run) || (autopickup && !flags.pickup)) {
435 		    check_here(FALSE);
436 		    return (0);
437 		}
438 		if (notake(youmonst.data)) {
439 		    if (!autopickup)
440 			You("are physically incapable of picking anything up.");
441 		    else
442 			check_here(FALSE);
443 		    return (0);
444 		}
445 
446 		/* if there's anything here, stop running */
447 		if (OBJ_AT(u.ux,u.uy) && flags.run && flags.run != 8 && !flags.nopick) nomul(0, 0);
448 	}
449 
450 	add_valid_menu_class(0);	/* reset */
451 	if (!u.uswallow) {
452 		objchain = level.objects[u.ux][u.uy];
453 		traverse_how = BY_NEXTHERE;
454 	} else {
455 		objchain = u.ustuck->minvent;
456 		traverse_how = 0;	/* nobj */
457 	}
458 	/*
459 	 * Start the actual pickup process.  This is split into two main
460 	 * sections, the newer menu and the older "traditional" methods.
461 	 * Automatic pickup has been split into its own menu-style routine
462 	 * to make things less confusing.
463 	 */
464 	if (autopickup) {
465 	    n = autopick(objchain, traverse_how, &pick_list);
466 	    goto menu_pickup;
467 	}
468 
469 	if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
470 
471 	    /* use menus exclusively */
472 	    if (count) {	/* looking for N of something */
473 		char buf[QBUFSZ];
474 		Sprintf(buf, "Pick %d of what?", count);
475 		val_for_n_or_more = count;	/* set up callback selector */
476 		n = query_objlist(buf, objchain,
477 			    traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT,
478 			    &pick_list, PICK_ONE, n_or_more);
479 		/* correct counts, if any given */
480 		for (i = 0; i < n; i++)
481 		    pick_list[i].count = count;
482 	    } else {
483 		n = query_objlist("Pick up what?", objchain,
484 			traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT|FEEL_COCKATRICE,
485 			&pick_list, PICK_ANY, all_but_uchain);
486 	    }
487 menu_pickup:
488 	    n_tried = n;
489 	    for (n_picked = i = 0 ; i < n; i++) {
490 		res = pickup_object(pick_list[i].item.a_obj,pick_list[i].count,
491 					FALSE);
492 		if (res < 0) break;	/* can't continue */
493 		n_picked += res;
494 	    }
495 	    if (pick_list) free((genericptr_t)pick_list);
496 
497 	} else {
498 	    /* old style interface */
499 	    int ct = 0;
500 	    long lcount;
501 	    boolean all_of_a_type, selective;
502 	    char oclasses[MAXOCLASSES];
503 	    struct obj *obj, *obj2;
504 
505 	    oclasses[0] = '\0';		/* types to consider (empty for all) */
506 	    all_of_a_type = TRUE;	/* take all of considered types */
507 	    selective = FALSE;		/* ask for each item */
508 
509 	    /* check for more than one object */
510 	    for (obj = objchain;
511 		  obj; obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj)
512 		ct++;
513 
514 	    if (ct == 1 && count) {
515 		/* if only one thing, then pick it */
516 		obj = objchain;
517 		lcount = min(obj->quan, (long)count);
518 		n_tried++;
519 		if (pickup_object(obj, lcount, FALSE) > 0)
520 		    n_picked++;	/* picked something */
521 		goto end_query;
522 
523 	    } else if (ct >= 2) {
524 		int via_menu = 0;
525 
526 		There("are %s objects here.",
527 		      (ct <= 10) ? "several" : "many");
528 		if (!query_classes(oclasses, &selective, &all_of_a_type,
529 				   "pick up", objchain,
530 				   traverse_how == BY_NEXTHERE,
531 #ifndef GOLDOBJ
532 				   FALSE,
533 #endif
534 				   &via_menu)) {
535 		    if (!via_menu) return (0);
536 		    n = query_objlist("Pick up what?",
537 				  objchain,
538 				  traverse_how|(selective ? 0 : INVORDER_SORT),
539 				  &pick_list, PICK_ANY,
540 				  via_menu == -2 ? allow_all : allow_category);
541 		    goto menu_pickup;
542 		}
543 	    }
544 
545 	    for (obj = objchain; obj; obj = obj2) {
546 		if (traverse_how == BY_NEXTHERE)
547 			obj2 = obj->nexthere;	/* perhaps obj will be picked up */
548 		else
549 			obj2 = obj->nobj;
550 		lcount = -1L;
551 
552 		if (!selective && oclasses[0] && !index(oclasses,obj->oclass))
553 		    continue;
554 
555 		if (!all_of_a_type) {
556 		    char qbuf[BUFSZ];
557 		    Sprintf(qbuf, "Pick up %s?",
558 			safe_qbuf("", sizeof("Pick up ?"), doname(obj),
559 					an(simple_typename(obj->otyp)), "something"));
560 		    switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
561 		    case 'q': goto end_query;	/* out 2 levels */
562 		    case 'n': continue;
563 		    case 'a':
564 			all_of_a_type = TRUE;
565 			if (selective) {
566 			    selective = FALSE;
567 			    oclasses[0] = obj->oclass;
568 			    oclasses[1] = '\0';
569 			}
570 			break;
571 		    case '#':	/* count was entered */
572 			if (!yn_number) continue; /* 0 count => No */
573 			lcount = (long) yn_number;
574 			if (lcount > obj->quan) lcount = obj->quan;
575 			/* fall thru */
576 		    default:	/* 'y' */
577 			break;
578 		    }
579 		}
580 		if (lcount == -1L) lcount = obj->quan;
581 
582 		n_tried++;
583 		if ((res = pickup_object(obj, lcount, FALSE)) < 0) break;
584 		n_picked += res;
585 	    }
586 end_query:
587 	    ;	/* semicolon needed by brain-damaged compilers */
588 	}
589 
590 	if (!u.uswallow) {
591 		if (!OBJ_AT(u.ux,u.uy)) u.uundetected = 0;
592 
593 		/* position may need updating (invisible hero) */
594 		if (n_picked) newsym(u.ux,u.uy);
595 
596 		/* see whether there's anything else here, after auto-pickup is done */
597 		if (autopickup) check_here(n_picked > 0);
598 	}
599 	return (n_tried > 0);
600 }
601 
602 #ifdef AUTOPICKUP_EXCEPTIONS
603 boolean
is_autopickup_exception(obj,grab)604 is_autopickup_exception(obj, grab)
605 struct obj *obj;
606 boolean grab;	 /* forced pickup, rather than forced leave behind? */
607 {
608 	/*
609 	 *  Does the text description of this match an exception?
610 	 */
611 	char *objdesc = makesingular(doname(obj));
612 	struct autopickup_exception *ape = (grab) ?
613 					iflags.autopickup_exceptions[AP_GRAB] :
614 					iflags.autopickup_exceptions[AP_LEAVE];
615 	while (ape) {
616 		if (pmatch(ape->pattern, objdesc)) return TRUE;
617 		ape = ape->next;
618 	}
619 	return FALSE;
620 }
621 #endif /* AUTOPICKUP_EXCEPTIONS */
622 
623 /*
624  * Pick from the given list using flags.pickup_types.  Return the number
625  * of items picked (not counts).  Create an array that returns pointers
626  * and counts of the items to be picked up.  If the number of items
627  * picked is zero, the pickup list is left alone.  The caller of this
628  * function must free the pickup list.
629  */
630 STATIC_OVL int
autopick(olist,follow,pick_list)631 autopick(olist, follow, pick_list)
632 struct obj *olist;	/* the object list */
633 int follow;		/* how to follow the object list */
634 menu_item **pick_list;	/* list of objects and counts to pick up */
635 {
636 	menu_item *pi;	/* pick item */
637 	struct obj *curr;
638 	int n;
639 	const char *otypes = flags.pickup_types;
640 
641 	/* first count the number of eligible items */
642 	for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) {
643 #ifndef AUTOPICKUP_EXCEPTIONS
644 	    if ((!*otypes || index(otypes, curr->oclass) ||
645 	         (flags.pickup_thrown && curr->was_thrown)) &&
646 	        (flags.pickup_dropped || !curr->was_dropped) &&
647 	        !Is_sokoprize(curr))
648 #else
649 	    if ((!*otypes || index(otypes, curr->oclass) ||
650 	         (flags.pickup_thrown && curr->was_thrown) ||
651 		 is_autopickup_exception(curr, TRUE)) &&
652 	        ((flags.pickup_dropped || !curr->was_dropped) &&
653 	         !is_autopickup_exception(curr, FALSE) &&
654 	         !Is_sokoprize(curr)))
655 #endif
656 		n++;
657 	}
658 
659 	if (n) {
660 	    *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n);
661 	    for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
662 #ifndef AUTOPICKUP_EXCEPTIONS
663 		if ((!*otypes || index(otypes, curr->oclass) ||
664 	             (flags.pickup_thrown && curr->was_thrown)) &&
665 	            (flags.pickup_dropped || !curr->was_dropped) &&
666 	            !Is_sokoprize(curr)) {
667 #else
668 	    if ((!*otypes || index(otypes, curr->oclass) ||
669 		 (flags.pickup_thrown && curr->was_thrown) ||
670 		 is_autopickup_exception(curr, TRUE)) &&
671 	        ((flags.pickup_dropped || !curr->was_dropped) &&
672 	         !is_autopickup_exception(curr, FALSE) &&
673 	         !Is_sokoprize(curr))) {
674 #endif
675 		    pi[n].item.a_obj = curr;
676 		    pi[n].count = curr->quan;
677 		    n++;
678 		}
679 	}
680 	return n;
681 }
682 
683 
684 /*
685  * Put up a menu using the given object list.  Only those objects on the
686  * list that meet the approval of the allow function are displayed.  Return
687  * a count of the number of items selected, as well as an allocated array of
688  * menu_items, containing pointers to the objects selected and counts.  The
689  * returned counts are guaranteed to be in bounds and non-zero.
690  *
691  * Query flags:
692  *	BY_NEXTHERE	  - Follow object list via nexthere instead of nobj.
693  *	AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
694  *			    use it.
695  *	USE_INVLET	  - Use object's invlet.
696  *	INVORDER_SORT	  - Use hero's pack order.
697  *	SIGNAL_NOMENU	  - Return -1 rather than 0 if nothing passes "allow".
698  */
699 int
query_objlist(qstr,olist,qflags,pick_list,how,allow)700 query_objlist(qstr, olist, qflags, pick_list, how, allow)
701 const char *qstr;		/* query string */
702 struct obj *olist;		/* the list to pick from */
703 int qflags;			/* options to control the query */
704 menu_item **pick_list;		/* return list of items picked */
705 int how;			/* type of query */
706 boolean FDECL((*allow), (OBJ_P));/* allow function */
707 {
708 #ifdef SORTLOOT
709 	int i, j;
710 #endif
711 	int n;
712 	winid win;
713 	struct obj *curr, *last;
714 #ifdef SORTLOOT
715 	struct obj **oarray;
716 #endif
717 	char *pack;
718 	anything any;
719 	boolean printed_type_name;
720 
721 	*pick_list = (menu_item *) 0;
722 	if (!olist) return 0;
723 
724 	/* count the number of items allowed */
725 	for (n = 0, last = 0, curr = olist; curr; curr = FOLLOW(curr, qflags))
726 	    if ((*allow)(curr)) {
727 		last = curr;
728 		n++;
729 	    }
730 
731 	if (n == 0)	/* nothing to pick here */
732 	    return (qflags & SIGNAL_NOMENU) ? -1 : 0;
733 
734 	if (n == 1 && (qflags & AUTOSELECT_SINGLE)) {
735 	    *pick_list = (menu_item *) alloc(sizeof(menu_item));
736 	    (*pick_list)->item.a_obj = last;
737 	    (*pick_list)->count = last->quan;
738 	    return 1;
739 	}
740 
741 #ifdef SORTLOOT
742 	/* Make a temporary array to store the objects sorted */
743 	oarray = (struct obj **)alloc(n*sizeof(struct obj*));
744 
745 	/* Add objects to the array */
746 	i = 0;
747 	for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
748 	  if ((*allow)(curr)) {
749 	    if (iflags.sortloot == 'f' ||
750 		(iflags.sortloot == 'l' && !(qflags & USE_INVLET)))
751 	      {
752 		/* Insert object at correct index */
753 		for (j = i; j; j--)
754 		  {
755 		    if (sortloot_cmp(curr, oarray[j-1])>0) break;
756 		    oarray[j] = oarray[j-1];
757 		  }
758 		oarray[j] = curr;
759 		i++;
760 	      } else {
761 		/* Just add it to the array */
762 		oarray[i++] = curr;
763 	      }
764 	  }
765 	}
766 #endif /* SORTLOOT */
767 
768 	win = create_nhwindow(NHW_MENU);
769 	start_menu(win);
770 	any.a_obj = (struct obj *) 0;
771 
772 	/*
773 	 * Run through the list and add the objects to the menu.  If
774 	 * INVORDER_SORT is set, we'll run through the list once for
775 	 * each type so we can group them.  The allow function will only
776 	 * be called once per object in the list.
777 	 */
778 	pack = flags.inv_order;
779 	do {
780 	    printed_type_name = FALSE;
781 #ifdef SORTLOOT
782 	    for (i = 0; i < n; i++) {
783 		curr = oarray[i];
784 #else /* SORTLOOT */
785 	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
786 #endif /* SORTLOOT */
787 		if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE &&
788 		     will_feel_cockatrice(curr, FALSE)) {
789 			destroy_nhwindow(win);	/* stop the menu and revert */
790 			(void) look_here(0, FALSE);
791 			return 0;
792 		}
793 		if ((!(qflags & INVORDER_SORT) || curr->oclass == *pack)
794 							&& (*allow)(curr)) {
795 
796 		    /* if sorting, print type name (once only) */
797 		    if (qflags & INVORDER_SORT && !printed_type_name) {
798 			any.a_obj = (struct obj *) 0;
799 			add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, 0, 0, iflags.menu_headings,
800 					let_to_name(*pack, FALSE), MENU_UNSELECTED);
801 			printed_type_name = TRUE;
802 		    }
803 
804 		    any.a_obj = curr;
805 		    add_menu(win, obj_to_glyph(curr), curr->quan, &any,
806 			    qflags & USE_INVLET ? curr->invlet : 0,
807 			    def_oc_syms[(int)objects[curr->otyp].oc_class],
808 			    ATR_NONE, doname_with_price(curr), MENU_UNSELECTED);
809 		}
810 	    }
811 	    pack++;
812 	} while (qflags & INVORDER_SORT && *pack);
813 
814 #ifdef SORTLOOT
815 	free(oarray);
816 #endif
817 	end_menu(win, qstr);
818 	n = select_menu(win, how, pick_list);
819 	destroy_nhwindow(win);
820 
821 	if (n > 0) {
822 	    menu_item *mi;
823 	    int i;
824 
825 	    /* fix up counts:  -1 means no count used => pick all */
826 	    for (i = 0, mi = *pick_list; i < n; i++, mi++)
827 		if (mi->count == -1L || mi->count > mi->item.a_obj->quan)
828 		    mi->count = mi->item.a_obj->quan;
829 	} else if (n < 0) {
830 	    n = 0;	/* caller's don't expect -1 */
831 	}
832 	return n;
833 }
834 
835 /*
836  * allow menu-based category (class) selection (for Drop,take off etc.)
837  *
838  */
839 int
query_category(qstr,olist,qflags,pick_list,how)840 query_category(qstr, olist, qflags, pick_list, how)
841 const char *qstr;		/* query string */
842 struct obj *olist;		/* the list to pick from */
843 int qflags;			/* behaviour modification flags */
844 menu_item **pick_list;		/* return list of items picked */
845 int how;			/* type of query */
846 {
847 	int n;
848 	winid win;
849 	struct obj *curr;
850 	char *pack;
851 	anything any;
852 	boolean collected_type_name;
853 	char invlet;
854 	int ccount;
855 	boolean do_unpaid = FALSE;
856 	boolean do_unidentified = FALSE;
857 	boolean do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE,
858 	    do_buc_unknown = FALSE;
859 	int num_buc_types = 0;
860 
861 	*pick_list = (menu_item *) 0;
862 	if (!olist) return 0;
863 	if ((qflags & UNPAID_TYPES) && count_unpaid(olist)) do_unpaid = TRUE;
864 	if ((qflags & UNIDENTIFIED_TYPES) && count_unidentified(olist)) do_unidentified = TRUE;
865 	if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED)) {
866 	    do_blessed = TRUE;
867 	    num_buc_types++;
868 	}
869 	if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) {
870 	    do_cursed = TRUE;
871 	    num_buc_types++;
872 	}
873 	if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) {
874 	    do_uncursed = TRUE;
875 	    num_buc_types++;
876 	}
877 	if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) {
878 	    do_buc_unknown = TRUE;
879 	    num_buc_types++;
880 	}
881 
882 	ccount = count_categories(olist, qflags);
883 	/* no point in actually showing a menu for a single category */
884 	if (ccount == 1 && !do_unpaid && num_buc_types <= 1 && !(qflags & BILLED_TYPES)) {
885 	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
886 		if ((qflags & WORN_TYPES) &&
887 		    !(curr->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL|W_WEP|W_SWAPWEP|W_QUIVER)))
888 		    continue;
889 		break;
890 	    }
891 	    if (curr) {
892 		*pick_list = (menu_item *) alloc(sizeof(menu_item));
893 		(*pick_list)->item.a_int = curr->oclass;
894 		return 1;
895 	    } else {
896 #ifdef DEBUG
897 		impossible("query_category: no single object match");
898 #endif
899 	    }
900 	    return 0;
901 	}
902 
903 	win = create_nhwindow(NHW_MENU);
904 	start_menu(win);
905 	pack = flags.inv_order;
906 	if ((qflags & ALL_TYPES) && (ccount > 1)) {
907 		invlet = 'a';
908 		any.a_void = 0;
909 		any.a_int = ALL_TYPES_SELECTED;
910 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
911 		       (qflags & WORN_TYPES) ? "All worn types" : "All types",
912 			MENU_UNSELECTED);
913 		invlet = 'b';
914 	} else
915 		invlet = 'a';
916 	do {
917 	    collected_type_name = FALSE;
918 	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
919 		if (curr->oclass == *pack) {
920 		   if ((qflags & WORN_TYPES) &&
921 		   		!(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
922 		    	W_WEP | W_SWAPWEP | W_QUIVER)))
923 			 continue;
924 		   if (!collected_type_name) {
925 			any.a_void = 0;
926 			any.a_int = curr->oclass;
927 			add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet++,
928 				def_oc_syms[(int)objects[curr->otyp].oc_class],
929 				ATR_NONE, let_to_name(*pack, FALSE),
930 				MENU_UNSELECTED);
931 			collected_type_name = TRUE;
932 		   }
933 		}
934 	    }
935 	    pack++;
936 	    if (invlet >= 'u') {
937 		impossible("query_category: too many categories");
938 		return 0;
939 	    }
940 	} while (*pack);
941 	/* unpaid items if there are any */
942 	if (do_unpaid) {
943 		invlet = 'u';
944 		any.a_void = 0;
945 		any.a_int = 'u';
946 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
947 			"Unpaid items", MENU_UNSELECTED);
948 	}
949 	/* billed items: checked by caller, so always include if BILLED_TYPES */
950 	if (qflags & BILLED_TYPES) {
951 		invlet = 'x';
952 		any.a_void = 0;
953 		any.a_int = 'x';
954 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
955 			 "Unpaid items already used up", MENU_UNSELECTED);
956 	}
957 	if (qflags & CHOOSE_ALL) {
958 		invlet = 'A';
959 		any.a_void = 0;
960 		any.a_int = 'A';
961 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
962 			(qflags & WORN_TYPES) ?
963 			"Auto-select every item being worn" :
964 			"Auto-select every item", MENU_UNSELECTED);
965 	}
966 	/* unidentifed items if there are any */
967 	if (do_unidentified) {
968 		invlet = 'I';
969 		any.a_void = 0;
970 		any.a_int = 'I';
971 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
972 			"Unidentified items", MENU_UNSELECTED);
973 	}
974 	/* items with b/u/c/unknown if there are any */
975 	if (do_blessed) {
976 		invlet = 'B';
977 		any.a_void = 0;
978 		any.a_int = 'B';
979 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
980 			"Items known to be Blessed", MENU_UNSELECTED);
981 	}
982 	if (do_cursed) {
983 		invlet = 'C';
984 		any.a_void = 0;
985 		any.a_int = 'C';
986 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
987 			"Items known to be Cursed", MENU_UNSELECTED);
988 	}
989 	if (do_uncursed) {
990 		invlet = 'U';
991 		any.a_void = 0;
992 		any.a_int = 'U';
993 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
994 			"Items known to be Uncursed", MENU_UNSELECTED);
995 	}
996 	if (do_buc_unknown) {
997 		invlet = 'X';
998 		any.a_void = 0;
999 		any.a_int = 'X';
1000 		add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, invlet, 0, ATR_NONE,
1001 			"Items of unknown B/C/U status",
1002 			MENU_UNSELECTED);
1003 	}
1004 	end_menu(win, qstr);
1005 	n = select_menu(win, how, pick_list);
1006 	destroy_nhwindow(win);
1007 	if (n < 0)
1008 	    n = 0;	/* caller's don't expect -1 */
1009 	return n;
1010 }
1011 
1012 STATIC_OVL int
count_categories(olist,qflags)1013 count_categories(olist, qflags)
1014 struct obj *olist;
1015 int qflags;
1016 {
1017 	char *pack;
1018 	boolean counted_category;
1019 	int ccount = 0;
1020 	struct obj *curr;
1021 
1022 	pack = flags.inv_order;
1023 	do {
1024 	    counted_category = FALSE;
1025 	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
1026 		if (curr->oclass == *pack) {
1027 		   if ((qflags & WORN_TYPES) &&
1028 		    	!(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
1029 		    	W_WEP | W_SWAPWEP | W_QUIVER)))
1030 			 continue;
1031 		   if (!counted_category) {
1032 			ccount++;
1033 			counted_category = TRUE;
1034 		   }
1035 		}
1036 	    }
1037 	    pack++;
1038 	} while (*pack);
1039 	return ccount;
1040 }
1041 
1042 /* could we carry `obj'? if not, could we carry some of it/them? */
1043 STATIC_OVL long
carry_count(obj,container,count,telekinesis,wt_before,wt_after)1044 carry_count(obj, container, count, telekinesis, wt_before, wt_after)
1045 struct obj *obj, *container;	/* object to pick up, bag it's coming out of */
1046 long count;
1047 boolean telekinesis;
1048 int *wt_before, *wt_after;
1049 {
1050     boolean adjust_wt = container && carried(container),
1051 	    is_gold = obj->oclass == COIN_CLASS;
1052     int wt, iw, ow, oow;
1053     long qq, savequan;
1054 #ifdef GOLDOBJ
1055     long umoney = money_cnt(invent);
1056 #endif
1057     unsigned saveowt;
1058     const char *verb, *prefx1, *prefx2, *suffx;
1059     char obj_nambuf[BUFSZ], where[BUFSZ];
1060 
1061     savequan = obj->quan;
1062     saveowt = obj->owt;
1063 
1064     iw = max_capacity();
1065 
1066     if (count != savequan) {
1067 	obj->quan = count;
1068 	obj->owt = (unsigned)weight(obj);
1069     }
1070     wt = iw + (int)obj->owt;
1071     if (adjust_wt)
1072 	wt -= (container->otyp == BAG_OF_HOLDING) ?
1073 		(int)DELTA_CWT(container, obj) : (int)obj->owt;
1074 #ifndef GOLDOBJ
1075     if (is_gold)	/* merged gold might affect cumulative weight */
1076 	wt -= (GOLD_WT(u.ugold) + GOLD_WT(count) - GOLD_WT(u.ugold + count));
1077 #else
1078     /* This will go with silver+copper & new gold weight */
1079     if (is_gold)	/* merged gold might affect cumulative weight */
1080 	wt -= (GOLD_WT(umoney) + GOLD_WT(count) - GOLD_WT(umoney + count));
1081 #endif
1082     if (count != savequan) {
1083 	obj->quan = savequan;
1084 	obj->owt = saveowt;
1085     }
1086     *wt_before = iw;
1087     *wt_after  = wt;
1088 
1089     if (wt < 0)
1090 	return count;
1091 
1092     /* see how many we can lift */
1093     if (is_gold) {
1094 #ifndef GOLDOBJ
1095 	iw -= (int)GOLD_WT(u.ugold);
1096 	if (!adjust_wt) {
1097 	    qq = GOLD_CAPACITY((long)iw, u.ugold);
1098 	} else {
1099 	    oow = 0;
1100 	    qq = 50L - (u.ugold % 100L) - 1L;
1101 #else
1102 	iw -= (int)GOLD_WT(umoney);
1103 	if (!adjust_wt) {
1104 	    qq = GOLD_CAPACITY((long)iw, umoney);
1105 	} else {
1106 	    oow = 0;
1107 	    qq = 50L - (umoney % 100L) - 1L;
1108 #endif
1109 	    if (qq < 0L) qq += 100L;
1110 	    for ( ; qq <= count; qq += 100L) {
1111 		obj->quan = qq;
1112 		obj->owt = (unsigned)GOLD_WT(qq);
1113 #ifndef GOLDOBJ
1114 		ow = (int)GOLD_WT(u.ugold + qq);
1115 #else
1116 		ow = (int)GOLD_WT(umoney + qq);
1117 #endif
1118 		ow -= (container->otyp == BAG_OF_HOLDING) ?
1119 			(int)DELTA_CWT(container, obj) : (int)obj->owt;
1120 		if (iw + ow >= 0) break;
1121 		oow = ow;
1122 	    }
1123 	    iw -= oow;
1124 	    qq -= 100L;
1125 	}
1126 	if (qq < 0L) qq = 0L;
1127 	else if (qq > count) qq = count;
1128 #ifndef GOLDOBJ
1129 	wt = iw + (int)GOLD_WT(u.ugold + qq);
1130 #else
1131 	wt = iw + (int)GOLD_WT(umoney + qq);
1132 #endif
1133     } else if (count > 1 || count < obj->quan) {
1134 	/*
1135 	 * Ugh. Calc num to lift by changing the quan of of the
1136 	 * object and calling weight.
1137 	 *
1138 	 * This works for containers only because containers
1139 	 * don't merge.		-dean
1140 	 */
1141 	for (qq = 1L; qq <= count; qq++) {
1142 	    obj->quan = qq;
1143 	    obj->owt = (unsigned)(ow = weight(obj));
1144 	    if (adjust_wt)
1145 		ow -= (container->otyp == BAG_OF_HOLDING) ?
1146 			(int)DELTA_CWT(container, obj) : (int)obj->owt;
1147 	    if (iw + ow >= 0)
1148 		break;
1149 	    wt = iw + ow;
1150 	}
1151 	--qq;
1152     } else {
1153 	/* there's only one, and we can't lift it */
1154 	qq = 0L;
1155     }
1156     obj->quan = savequan;
1157     obj->owt = saveowt;
1158 
1159     if (qq < count) {
1160 	/* some message will be given */
1161 	Strcpy(obj_nambuf, doname(obj));
1162 	if (container) {
1163 	    Sprintf(where, "in %s", the(xname(container)));
1164 	    verb = "carry";
1165 	} else {
1166 	    Strcpy(where, "lying here");
1167 	    verb = telekinesis ? "acquire" : "lift";
1168 	}
1169     } else {
1170 	/* lint supppression */
1171 	*obj_nambuf = *where = '\0';
1172 	verb = "";
1173     }
1174     /* we can carry qq of them */
1175     if (qq > 0) {
1176 	if (qq < count)
1177 	    You("can only %s %s of the %s %s.",
1178 		verb, (qq == 1L) ? "one" : "some", obj_nambuf, where);
1179 	*wt_after = wt;
1180 	return qq;
1181     }
1182 
1183     if (!container) Strcpy(where, "here");  /* slightly shorter form */
1184 #ifndef GOLDOBJ
1185     if (invent || u.ugold) {
1186 #else
1187     if (invent || umoney) {
1188 #endif
1189 	prefx1 = "you cannot ";
1190 	prefx2 = "";
1191 	suffx  = " any more";
1192     } else {
1193 	prefx1 = (obj->quan == 1L) ? "it " : "even one ";
1194 	prefx2 = "is too heavy for you to ";
1195 	suffx  = "";
1196     }
1197     There("%s %s %s, but %s%s%s%s.",
1198 	  otense(obj, "are"), obj_nambuf, where,
1199 	  prefx1, prefx2, verb, suffx);
1200 
1201  /* *wt_after = iw; */
1202     return 0L;
1203 }
1204 
1205 /* determine whether character is able and player is willing to carry `obj' */
1206 STATIC_OVL
1207 int
lift_object(obj,container,cnt_p,telekinesis)1208 lift_object(obj, container, cnt_p, telekinesis)
1209 struct obj *obj, *container;	/* object to pick up, bag it's coming out of */
1210 long *cnt_p;
1211 boolean telekinesis;
1212 {
1213     int result, old_wt, new_wt, prev_encumbr, next_encumbr;
1214 
1215     if (obj->otyp == BOULDER && In_sokoban(&u.uz)) {
1216 	You("cannot get your %s around this %s.",
1217 			body_part(HAND), xname(obj));
1218 	return -1;
1219     }
1220     if (obj->otyp == LOADSTONE ||
1221 	    (obj->otyp == BOULDER && throws_rocks(youmonst.data)))
1222 	return 1;		/* lift regardless of current situation */
1223 
1224     *cnt_p = carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt);
1225     if (*cnt_p < 1L) {
1226 	result = -1;	/* nothing lifted */
1227 #ifndef GOLDOBJ
1228     } else if (obj->oclass != COIN_CLASS && inv_cnt() >= 52 &&
1229 		!merge_choice(invent, obj)) {
1230 #else
1231     } else if (inv_cnt() >= 52 && !merge_choice(invent, obj)) {
1232 #endif
1233 	Your("knapsack cannot accommodate any more items.");
1234 	result = -1;	/* nothing lifted */
1235     } else {
1236 	result = 1;
1237 	prev_encumbr = near_capacity();
1238 	if (prev_encumbr < flags.pickup_burden)
1239 		prev_encumbr = flags.pickup_burden;
1240 	next_encumbr = calc_capacity(new_wt - old_wt);
1241 	if (next_encumbr > prev_encumbr) {
1242 	    if (telekinesis) {
1243 		result = 0;	/* don't lift */
1244 	    } else {
1245 		char qbuf[BUFSZ];
1246 		long savequan = obj->quan;
1247 
1248 		obj->quan = *cnt_p;
1249 		Strcpy(qbuf,
1250 			(next_encumbr > HVY_ENCUMBER) ? overloadmsg :
1251 			(next_encumbr > MOD_ENCUMBER) ? nearloadmsg :
1252 			moderateloadmsg);
1253 		Sprintf(eos(qbuf), " %s. Continue?",
1254 			safe_qbuf(qbuf, sizeof(" . Continue?"),
1255 				doname(obj), an(simple_typename(obj->otyp)), "something"));
1256 		obj->quan = savequan;
1257 		switch (ynq(qbuf)) {
1258 		case 'q':  result = -1; break;
1259 		case 'n':  result =  0; break;
1260 		default:   break;	/* 'y' => result == 1 */
1261 		}
1262 		clear_nhwindow(WIN_MESSAGE);
1263 	    }
1264 	}
1265     }
1266 
1267     if (obj->otyp == SCR_SCARE_MONSTER && result <= 0 && !container)
1268 	obj->spe = 0;
1269     return result;
1270 }
1271 
1272 /* To prevent qbuf overflow in prompts use planA only
1273  * if it fits, or planB if PlanA doesn't fit,
1274  * finally using the fallback as a last resort.
1275  * last_restort is expected to be very short.
1276  */
1277 const char *
safe_qbuf(qbuf,padlength,planA,planB,last_resort)1278 safe_qbuf(qbuf, padlength, planA, planB, last_resort)
1279 const char *qbuf, *planA, *planB, *last_resort;
1280 unsigned padlength;
1281 {
1282 	/* convert size_t (or int for ancient systems) to ordinary unsigned */
1283 	unsigned len_qbuf = (unsigned)strlen(qbuf),
1284 	         len_planA = (unsigned)strlen(planA),
1285 	         len_planB = (unsigned)strlen(planB),
1286 	         len_lastR = (unsigned)strlen(last_resort);
1287 	unsigned textleft = QBUFSZ - (len_qbuf + padlength);
1288 
1289 	if (len_lastR >= textleft) {
1290 	    impossible("safe_qbuf: last_resort too large at %u characters.",
1291 		       len_lastR);
1292 	    return "";
1293 	}
1294 	return (len_planA < textleft) ? planA :
1295 		    (len_planB < textleft) ? planB : last_resort;
1296 }
1297 
1298 /*
1299  * Pick up <count> of obj from the ground and add it to the hero's inventory.
1300  * Returns -1 if caller should break out of its loop, 0 if nothing picked
1301  * up, 1 if otherwise.
1302  */
1303 int
pickup_object(obj,count,telekinesis)1304 pickup_object(obj, count, telekinesis)
1305 struct obj *obj;
1306 long count;
1307 boolean telekinesis;	/* not picking it up directly by hand */
1308 {
1309 	int res, nearload;
1310 #ifndef GOLDOBJ
1311 	const char *where = (obj->ox == u.ux && obj->oy == u.uy) ?
1312 			    "here" : "there";
1313 #endif
1314 
1315 	if (obj->quan < count) {
1316 	    impossible("pickup_object: count %ld > quan %ld?",
1317 		count, obj->quan);
1318 	    return 0;
1319 	}
1320 
1321 	/* In case of auto-pickup, where we haven't had a chance
1322 	   to look at it yet; affects docall(SCR_SCARE_MONSTER). */
1323 	if (!Blind)
1324 #ifdef INVISIBLE_OBJECTS
1325 		if (!obj->oinvis || See_invisible)
1326 #endif
1327 		obj->dknown = 1;
1328 
1329 	if (obj == uchain) {    /* do not pick up attached chain */
1330 	    return 0;
1331 	} else if (obj->oartifact && !touch_artifact(obj,&youmonst)) {
1332 	    return 0;
1333 #ifndef GOLDOBJ
1334 	} else if (obj->oclass == COIN_CLASS) {
1335 	    /* Special consideration for gold pieces... */
1336 	    long iw = (long)max_capacity() - GOLD_WT(u.ugold);
1337 	    long gold_capacity = GOLD_CAPACITY(iw, u.ugold);
1338 
1339 	    if ((res = lift_object(obj, (struct obj *)0, &count, telekinesis)) <= 0) {
1340 		return res;
1341 	    }
1342 
1343 	    if (gold_capacity <= 0L) {
1344 		pline(
1345 	       "There %s %ld gold piece%s %s, but you cannot carry any more.",
1346 		      otense(obj, "are"),
1347 		      obj->quan, plur(obj->quan), where);
1348 		return 0;
1349 	    } else if (gold_capacity < count) {
1350 		You("can only %s %s of the %ld gold pieces lying %s.",
1351 		    telekinesis ? "acquire" : "carry",
1352 		    gold_capacity == 1L ? "one" : "some", obj->quan, where);
1353 		pline("%s %ld gold piece%s.",
1354 		    nearloadmsg, gold_capacity, plur(gold_capacity));
1355 		costly_gold(obj->ox, obj->oy, gold_capacity);
1356 		u.ugold += gold_capacity;
1357 		obj->quan -= gold_capacity;
1358 	    } else {
1359 		if ((nearload = calc_capacity(GOLD_WT(count))) != 0)
1360 		    pline("%s %ld gold piece%s.",
1361 			  nearload < MOD_ENCUMBER ?
1362 			  moderateloadmsg : nearloadmsg,
1363 			  count, plur(count));
1364 		else
1365 		    prinv((char *) 0, obj, count);
1366 		costly_gold(obj->ox, obj->oy, count);
1367 		u.ugold += count;
1368 		if (count == obj->quan)
1369 		    delobj(obj);
1370 		else
1371 		    obj->quan -= count;
1372 	    }
1373 	    flags.botl = 1;
1374 	    if (flags.run) nomul(0, 0);
1375 	    return 1;
1376 #endif
1377 	} else if (obj->otyp == CORPSE) {
1378 	    if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
1379 				&& !Stone_resistance && !telekinesis) {
1380 		if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1381 		    display_nhwindow(WIN_MESSAGE, FALSE);
1382 		else {
1383 			char kbuf[BUFSZ];
1384 
1385 			Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1386 			pline("Touching %s is a fatal mistake.", kbuf);
1387 			instapetrify(kbuf);
1388 		    return -1;
1389 		}
1390 	    } else if (is_rider(&mons[obj->corpsenm])) {
1391 		pline("At your %s, the corpse suddenly moves...",
1392 			telekinesis ? "attempted acquisition" : "touch");
1393 		(void) revive_corpse(obj);
1394 		exercise(A_WIS, FALSE);
1395 		return -1;
1396 	    }
1397 	} else  if (obj->otyp == SCR_SCARE_MONSTER) {
1398 	    if (obj->blessed) obj->blessed = 0;
1399 	    else if (!obj->spe && !obj->cursed) obj->spe = 1;
1400 	    else {
1401 		pline_The("scroll%s %s to dust as you %s %s up.",
1402 			plur(obj->quan), otense(obj, "turn"),
1403 			telekinesis ? "raise" : "pick",
1404 			(obj->quan == 1L) ? "it" : "them");
1405 		if (!(objects[SCR_SCARE_MONSTER].oc_name_known) &&
1406 				    !(objects[SCR_SCARE_MONSTER].oc_uname))
1407 		    docall(obj);
1408 		useupf(obj, obj->quan);
1409 		return 1;	/* tried to pick something up and failed, but
1410 				   don't want to terminate pickup loop yet   */
1411 	    }
1412 	}
1413 
1414 	if ((res = lift_object(obj, (struct obj *)0, &count, telekinesis)) <= 0)
1415 	    return res;
1416 
1417 #ifdef GOLDOBJ
1418         /* Whats left of the special case for gold :-) */
1419 	if (obj->oclass == COIN_CLASS) flags.botl = 1;
1420 #endif
1421 	if (obj->quan != count && obj->otyp != LOADSTONE)
1422 	    obj = splitobj(obj, count);
1423 
1424 	obj = pick_obj(obj);
1425 
1426 	if (uwep && uwep == obj) mrg_to_wielded = TRUE;
1427 	nearload = near_capacity();
1428 	prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0,
1429 	      obj, count);
1430 	mrg_to_wielded = FALSE;
1431 
1432 	if (Is_sokoprize(obj)) {
1433 	    makeknown(obj->otyp); /* obj is already known */
1434 	    obj->sokoprize = FALSE; /* reset sokoprize flag */
1435 	    del_sokoprize();	/* delete other sokoprizes */
1436 	    /* stop picking up other objects to prevent picking up
1437 	       one of the just deleted other sokoban prizes */
1438 	    return -1;
1439 	}
1440 	return 1;
1441 }
1442 
1443 /*
1444  * Do the actual work of picking otmp from the floor or monster's interior
1445  * and putting it in the hero's inventory.  Take care of billing.  Return a
1446  * pointer to the object where otmp ends up.  This may be different
1447  * from otmp because of merging.
1448  *
1449  * Gold never reaches this routine unless GOLDOBJ is defined.
1450  */
1451 struct obj *
pick_obj(otmp)1452 pick_obj(otmp)
1453 struct obj *otmp;
1454 {
1455 	obj_extract_self(otmp);
1456 	if (!u.uswallow && otmp != uball && costly_spot(otmp->ox, otmp->oy)) {
1457 	    char saveushops[5], fakeshop[2];
1458 
1459 	    /* addtobill cares about your location rather than the object's;
1460 	       usually they'll be the same, but not when using telekinesis
1461 	       (if ever implemented) or a grappling hook */
1462 	    Strcpy(saveushops, u.ushops);
1463 	    fakeshop[0] = *in_rooms(otmp->ox, otmp->oy, SHOPBASE);
1464 	    fakeshop[1] = '\0';
1465 	    Strcpy(u.ushops, fakeshop);
1466 	    /* sets obj->unpaid if necessary */
1467 	    addtobill(otmp, TRUE, FALSE, FALSE);
1468 	    Strcpy(u.ushops, saveushops);
1469 	    /* if you're outside the shop, make shk notice */
1470 	    if (!index(u.ushops, *fakeshop))
1471 		remote_burglary(otmp->ox, otmp->oy);
1472 	}
1473 	if (otmp->no_charge)	/* only applies to objects outside invent */
1474 	    otmp->no_charge = 0;
1475 	newsym(otmp->ox, otmp->oy);
1476 	return addinv(otmp);	/* might merge it with other objects */
1477 }
1478 
1479 /*
1480  * prints a message if encumbrance changed since the last check and
1481  * returns the new encumbrance value (from near_capacity()).
1482  */
1483 int
encumber_msg()1484 encumber_msg()
1485 {
1486     static int oldcap = UNENCUMBERED;
1487     int newcap = near_capacity();
1488 
1489     if(oldcap < newcap) {
1490 	switch(newcap) {
1491 	case 1: Your("movements are slowed slightly because of your load.");
1492 		break;
1493 	case 2: You("rebalance your load.  Movement is difficult.");
1494 		break;
1495 	case 3: You("%s under your heavy load.  Movement is very hard.",
1496 		    stagger(youmonst.data, "stagger"));
1497 		break;
1498 	default: You("%s move a handspan with this load!",
1499 		     newcap == 4 ? "can barely" : "can't even");
1500 		break;
1501 	}
1502 	flags.botl = 1;
1503     } else if(oldcap > newcap) {
1504 	switch(newcap) {
1505 	case 0: Your("movements are now unencumbered.");
1506 		break;
1507 	case 1: Your("movements are only slowed slightly by your load.");
1508 		break;
1509 	case 2: You("rebalance your load.  Movement is still difficult.");
1510 		break;
1511 	case 3: You("%s under your load.  Movement is still very hard.",
1512 		    stagger(youmonst.data, "stagger"));
1513 		break;
1514 	}
1515 	flags.botl = 1;
1516     }
1517 
1518     oldcap = newcap;
1519     return (newcap);
1520 }
1521 
1522 /* Is there a container at x,y. Optional: return count of containers at x,y */
1523 STATIC_OVL int
container_at(x,y,countem)1524 container_at(x, y, countem)
1525 int x,y;
1526 boolean countem;
1527 {
1528 	struct obj *cobj, *nobj;
1529 	int container_count = 0;
1530 
1531 	for(cobj = level.objects[x][y]; cobj; cobj = nobj) {
1532 		nobj = cobj->nexthere;
1533 		if(Is_container(cobj)) {
1534 			container_count++;
1535 			if (!countem) break;
1536 		}
1537 	}
1538 	return container_count;
1539 }
1540 
1541 /* If called to check for the ability to tip a container,
1542  * allow despite the lack of limbs or free hands, and do
1543  * not bother mentioning anything if not possible. This
1544  * difference in responses is because #loot can only be
1545  * used on items on the ground or adjacent, while #tip can
1546  * also be used on containers in the player's inventory.
1547  * We don't want to add annoying messages between checking
1548  * for tippability and bringing up the inventory prompt.
1549  */
1550 STATIC_OVL boolean
able_to_loot(x,y,tip)1551 able_to_loot(x, y, tip)
1552 int x, y;
1553 boolean tip;
1554 {
1555 	if (!can_reach_floor()) {
1556 	    if (!tip) {
1557 #ifdef STEED
1558 		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
1559 		    rider_cant_reach(); /* not skilled enough to reach */
1560 		else
1561 #endif
1562 		    You("cannot reach the %s.", surface(x, y));
1563 	    }
1564 		return FALSE;
1565 	} else if (is_pool(x, y) || is_lava(x, y)) {
1566 		/* at present, can't loot in water even when Underwater */
1567 		if (!tip) You("cannot loot things that are deep in the %s.",
1568 				is_lava(x, y) ? "lava" : "water");
1569 		return FALSE;
1570 	} else if (!tip) {
1571 	    if (nolimbs(youmonst.data)) {
1572 		pline("Without limbs, you cannot loot anything.");
1573 		return FALSE;
1574 	    } else if (!freehand()) {
1575 		pline("Without a free %s, you cannot loot anything.",
1576 			body_part(HAND));
1577 		return FALSE;
1578 	    }
1579 	}
1580 	return TRUE;
1581 }
1582 
1583 STATIC_OVL boolean
mon_beside(x,y)1584 mon_beside(x,y)
1585 int x, y;
1586 {
1587 	int i,j,nx,ny;
1588 	for(i = -1; i <= 1; i++)
1589 	    for(j = -1; j <= 1; j++) {
1590 	    	nx = x + i;
1591 	    	ny = y + j;
1592 		if(isok(nx, ny) && MON_AT(nx, ny))
1593 			return TRUE;
1594 	    }
1595 	return FALSE;
1596 }
1597 
1598 int
doloot()1599 doloot()	/* loot a container on the floor or loot saddle from mon. */
1600 {
1601     register struct obj *cobj, *nobj, *otmp;
1602     register int c = -1;
1603     int timepassed = 0;
1604     coord cc;
1605     boolean underfoot = TRUE;
1606     const char *dont_find_anything = "don't find anything";
1607     struct monst *mtmp;
1608     char qbuf[BUFSZ];
1609     int prev_inquiry = 0;
1610     boolean prev_loot = FALSE;
1611     int container_count = 0;
1612 
1613     if (check_capacity((char *)0)) {
1614 	/* "Can't do that while carrying so much stuff." */
1615 	return 0;
1616     }
1617     if (nohands(youmonst.data)) {
1618 	You("have no hands!");	/* not `body_part(HAND)' */
1619 	return 0;
1620     }
1621     cc.x = u.ux; cc.y = u.uy;
1622 
1623 lootcont:
1624 
1625     if ((container_count = container_at(cc.x, cc.y, TRUE))) {
1626 	boolean any = FALSE;
1627 
1628 	if (!able_to_loot(cc.x, cc.y, FALSE)) return 0;
1629 	for (cobj = level.objects[cc.x][cc.y]; cobj; cobj = nobj) {
1630 	    nobj = cobj->nexthere;
1631 
1632 	    if (Is_container(cobj)) {
1633 		/* don't ask if there is only one lootable object */
1634 		if (container_count != 1 || iflags.vanilla_ui_behavior) {
1635 			Sprintf(qbuf, "There is %s here, loot it?",
1636 				safe_qbuf("", sizeof("There is  here, loot it?"),
1637 				     doname(cobj), an(simple_typename(cobj->otyp)),
1638 				     "a container"));
1639 			c = ynq(qbuf);
1640 			if (c == 'q') return (timepassed);
1641 			if (c == 'n') continue;
1642 		}
1643 		any = TRUE;
1644 
1645 		if (cobj->olocked) {
1646 		    pline("Hmmm, it seems to be locked.");
1647 		    /* autounlock only works properly with one container */
1648 		    if (flags.autounlock && container_count == 1) {
1649 			if(cobj->otyp == IRON_SAFE) {
1650 			    if((otmp = carrying(STETHOSCOPE))) {
1651 				pick_lock(otmp, cc.x, cc.y, TRUE);
1652 			    }
1653 			} else {
1654 			    if(((otmp = carrying(SKELETON_KEY)) ||
1655 				(otmp = carrying(CREDIT_CARD)) ||
1656 				(otmp = carrying(LOCK_PICK)))) {
1657 				    pick_lock(otmp, cc.x, cc.y, TRUE);
1658 			    }
1659 			}
1660 		    }
1661 		    continue;
1662 		}
1663 		if (cobj->otyp == BAG_OF_TRICKS && cobj->spe>0) {
1664 		    int tmp;
1665 		    You("carefully open the bag...");
1666 		    pline("It develops a huge set of %s you!",
1667 				Hallucination ? "lips and kisses":"teeth and bites");
1668 		    tmp = rnd(10);
1669 		    if (Half_physical_damage) tmp = (tmp+1) / 2;
1670 		    losehp(tmp, Hallucination ? "amorous bag":"carnivorous bag", KILLED_BY_AN);
1671 		    makeknown(BAG_OF_TRICKS);
1672 		    timepassed = 1;
1673 		    continue;
1674 		}
1675 
1676 		You("carefully open %s...", the(xname(cobj)));
1677 		timepassed |= use_container(cobj, 0);
1678 		if (multi < 0) return 1;		/* chest trap */
1679 	    }
1680 	}
1681 	if (any) c = 'y';
1682     } else if (Confusion) {
1683 #ifndef GOLDOBJ
1684 	if (u.ugold){
1685 	    long contribution = rnd((int)min(LARGEST_INT,u.ugold));
1686 	    struct obj *goldob = mkgoldobj(contribution);
1687 #else
1688 	struct obj *goldob;
1689 	/* Find a money object to mess with */
1690 	for (goldob = invent; goldob; goldob = goldob->nobj) {
1691 	    if (goldob->oclass == COIN_CLASS) break;
1692 	}
1693 	if (goldob){
1694 	    long contribution = rnd((int)min(LARGEST_INT, goldob->quan));
1695 	    if (contribution < goldob->quan)
1696 		goldob = splitobj(goldob, contribution);
1697 	    freeinv(goldob);
1698 #endif
1699 	    if (IS_THRONE(levl[u.ux][u.uy].typ)){
1700 		struct obj *coffers;
1701 		int pass;
1702 		/* find the original coffers chest, or any chest */
1703 		for (pass = 2; pass > -1; pass -= 2)
1704 		    for (coffers = fobj; coffers; coffers = coffers->nobj)
1705 			if ((coffers->otyp == CHEST || coffers->otyp == IRON_SAFE) && coffers->spe == pass)
1706 			    goto gotit;	/* two level break */
1707 gotit:
1708 		if (coffers) {
1709 	    verbalize("Thank you for your contribution to reduce the debt.");
1710 		    (void) add_to_container(coffers, goldob);
1711 		    coffers->owt = weight(coffers);
1712 		} else {
1713 		    struct monst *mon = makemon(courtmon(),
1714 					    u.ux, u.uy, NO_MM_FLAGS);
1715 		    if (mon) {
1716 #ifndef GOLDOBJ
1717 			mon->mgold += goldob->quan;
1718 			delobj(goldob);
1719 			pline("The exchequer accepts your contribution.");
1720 		    } else {
1721 			dropx(goldob);
1722 		    }
1723 		}
1724 	    } else {
1725 		dropx(goldob);
1726 #else
1727 			add_to_minv(mon, goldob);
1728 			pline("The exchequer accepts your contribution.");
1729 		    } else {
1730 			dropy(goldob);
1731 		    }
1732 		}
1733 	    } else {
1734 		dropy(goldob);
1735 #endif
1736 		pline("Ok, now there is loot here.");
1737 	    }
1738 	}
1739     } else if (IS_GRAVE(levl[cc.x][cc.y].typ)) {
1740 	You("need to dig up the grave to effectively loot it...");
1741     }
1742     /*
1743      * 3.3.1 introduced directional looting for some things.
1744      */
1745     if (c != 'y' && mon_beside(u.ux, u.uy)) {
1746 	if (!get_adjacent_loc("Loot in what direction?", "Invalid loot location",
1747 			u.ux, u.uy, &cc)) return 0;
1748 	if (cc.x == u.ux && cc.y == u.uy) {
1749 	    underfoot = TRUE;
1750 	    if (container_at(cc.x, cc.y, FALSE))
1751 		goto lootcont;
1752 	} else
1753 	    underfoot = FALSE;
1754 	if (u.dz < 0) {
1755 	    You("%s to loot on the %s.", dont_find_anything,
1756 		ceiling(cc.x, cc.y));
1757 	    timepassed = 1;
1758 	    return timepassed;
1759 	}
1760 	mtmp = m_at(cc.x, cc.y);
1761 	if (mtmp) timepassed = loot_mon(mtmp, &prev_inquiry, &prev_loot);
1762 
1763 	/* Preserve pre-3.3.1 behaviour for containers.
1764 	 * Adjust this if-block to allow container looting
1765 	 * from one square away to change that in the future.
1766 	 */
1767 	if (!underfoot) {
1768 	    if (container_at(cc.x, cc.y, FALSE)) {
1769 		if (mtmp) {
1770 		    You_cant("loot anything %sthere with %s in the way.",
1771 			    prev_inquiry ? "else " : "", mon_nam(mtmp));
1772 		    return timepassed;
1773 		} else {
1774 		    You("have to be at a container to loot it.");
1775 		}
1776 	    } else {
1777 		You("%s %sthere to loot.", dont_find_anything,
1778 			(prev_inquiry || prev_loot) ? "else " : "");
1779 		return timepassed;
1780 	    }
1781 	}
1782     } else if (c != 'y' && c != 'n') {
1783 	You("%s %s to loot.", dont_find_anything,
1784 		    underfoot ? "here" : "there");
1785     }
1786     return (timepassed);
1787 }
1788 
1789 boolean
shopclutter()1790 shopclutter()
1791 {
1792     /* try to be a civilized adventurer, will you? */
1793     if (*u.ushops && shop_keeper(*u.ushops)
1794 		&& inhishop(shop_keeper(*u.ushops))) {
1795 	char buf[BUFSZ];
1796 	if (!(shop_keeper(*u.ushops))->mpeaceful) {
1797 	    verbalize("Don't even think about cluttering my shop!");
1798 	} else {
1799 	    Strcpy(buf, "\"Please, ");
1800 	    append_honorific(buf);
1801 	    pline("%s; try not to create a mess.\"", buf);
1802 	}
1803 	return TRUE;
1804     } else {
1805 	return FALSE;
1806     }
1807 }
1808 
1809 /* Actually tip over and empty a container. Bags of tricks
1810  * with charges behave as though applied. Traps are still
1811  * set off this way, and quantum mechanic boxes and
1812  * vampires in coffins still work appropriately. (Note
1813  * that dump_container() is called twice in the case of
1814  * Schroedinger's Cat: once to empty the box, and again
1815  * to dump the corpse should the cat's wavefunction be
1816  * collapsed in an unfortunate manner.) The "seems to
1817  * be locked" message comes after the potential item
1818  * breakage which takes place in dump_container().
1819  */
1820 int
tip_container(cobj)1821 tip_container(cobj)
1822 struct obj *cobj;
1823 {
1824     /* tipping in shops is buggy, thus temporarily disallowed */
1825     if (*u.ushops && shop_keeper(*u.ushops) &&
1826 	 inhishop(shop_keeper(*u.ushops))) return shopclutter();
1827 
1828     You("tip %s over.", the(xname(cobj)));
1829 
1830     if (cobj->otyp == BAG_OF_TRICKS && cobj->spe > 0) {
1831 	bagotricks(cobj);
1832     } else {
1833 	sellobj_state(SELL_DELIBERATE);
1834 	dump_container(cobj, FALSE);
1835 	sellobj_state(SELL_NORMAL);
1836 	if (cobj->olocked) {
1837 	    pline("%s to be locked.", Tobjnam(cobj, "seem"));
1838 	    return 0;
1839 	} else if (cobj->otrapped) {
1840 	    (void) chest_trap(cobj, HAND, FALSE);
1841 	} else if (cobj->spe > 0) {
1842 	    if (cobj->spe == 1) {
1843 		observe_quantum_cat(cobj, FALSE);
1844 		sellobj_state(SELL_DELIBERATE);
1845 		dump_container(cobj, FALSE);
1846 		sellobj_state(SELL_NORMAL);
1847 	    } else if (cobj->spe == 4) {
1848 		open_coffin(cobj, TRUE);
1849 	    }
1850 	}
1851     }
1852     return 1;
1853 }
1854 
1855 /* Called to tip over a container. Ask for boxes at the
1856  * hero's current location unless the hero is unable to
1857  * reach any that could be there, or if there are none.
1858  * Since tipping in shops is disallowed, act differently
1859  * when confused or hallucinating in such a circumstance.
1860  */
1861 int
dotip()1862 dotip()
1863 {
1864     register struct obj *cobj, *nobj;
1865     register struct monst *shkp;
1866     register int c = -1;
1867     coord cc;
1868     char qbuf[BUFSZ];
1869     const char tools[] = {TOOL_CLASS, 0};
1870     cc.x = u.ux; cc.y = u.uy;
1871 
1872     if (check_capacity((char *)0)) return 0;
1873 
1874     if (Underwater) {
1875 	pline("Water turbulence prevents you from tipping anything.");
1876 	return 0;
1877     }
1878 
1879     if (*u.ushops && (shkp = shop_keeper(*u.ushops)) &&
1880 	inhishop(shkp) && (Confusion || Hallucination)) {
1881 	if (uarmh && !cursed(uarmh) && rn2(3)) {
1882 	    You("tip your %s to %s.", xname(uarmh),
1883 		Hallucination ? the(rndmonnam()) : shkname(shkp));
1884 	} else {
1885 #ifndef GOLDOBJ
1886 	    if (u.ugold >= 10) {
1887 #else
1888 	    if (money_cnt(invent) >= 10) {
1889 #endif
1890 		int gratuity = rnd(10);
1891 		You("tip %s for providing a pleasant shopping experience.",
1892 		    Hallucination ? the(rndmonnam()) : shkname(shkp));
1893 #ifndef GOLDOBJ
1894 		u.ugold -= gratuity;
1895 		shkp->mgold += gratuity;
1896 #else
1897 		money2mon(shkp, gratuity);
1898 #endif
1899 	    } else {
1900 		pline("Unfortunately, you do not have enough money to tip %s.",
1901 		    Hallucination ? the(rndmonnam()) : shkname(shkp));
1902 	    }
1903 	}
1904 	return 0;
1905     }
1906 
1907     if (!able_to_loot(cc.x, cc.y, TRUE)) {
1908 	goto tipinventory;
1909     } else if (container_at(cc.x, cc.y, FALSE)) {
1910 	for (cobj = level.objects[cc.x][cc.y]; cobj; cobj = nobj) {
1911 	    nobj = cobj->nexthere;
1912 
1913 	    if (Is_container(cobj)) {
1914 		Sprintf(qbuf, "There is %s here; tip it?",
1915 			safe_qbuf("", sizeof("There is  here, tip it?"),
1916 			     doname(cobj), an(simple_typename(cobj->otyp)),
1917 			     "a container"));
1918 		c = ynq(qbuf);
1919 		if (c == 'q') return 0;
1920 		if (c == 'n') continue;
1921 
1922 		return tip_container(cobj);
1923 	    }
1924 	}
1925     }
1926 
1927  tipinventory:
1928     cobj = getobj(tools, "empty");
1929     if(!cobj) return 0;
1930 
1931     /* TODO: empty out other items, like potions? */
1932     if (!Is_container(cobj)) {
1933 	pline("That isn't a container.");
1934 	return 0;
1935     }
1936 
1937     return tip_container(cobj);
1938 }
1939 
1940 /* loot_mon() returns amount of time passed.
1941  */
1942 int
1943 loot_mon(mtmp, passed_info, prev_loot)
1944 struct monst *mtmp;
1945 int *passed_info;
1946 boolean *prev_loot;
1947 {
1948     int c = -1;
1949     int timepassed = 0;
1950 #ifdef STEED
1951     struct obj *otmp;
1952     char qbuf[QBUFSZ];
1953 
1954     /* 3.3.1 introduced the ability to remove saddle from a steed             */
1955     /* 	*passed_info is set to TRUE if a loot query was given.               */
1956     /*	*prev_loot is set to TRUE if something was actually acquired in here. */
1957     if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
1958 	long unwornmask;
1959 	if (passed_info) *passed_info = 1;
1960 	Sprintf(qbuf, "Do you want to remove the saddle from %s?",
1961 		x_monnam(mtmp, ARTICLE_THE, (char *)0, SUPPRESS_SADDLE, FALSE));
1962 	if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
1963 		if (nolimbs(youmonst.data)) {
1964 		    You_cant("do that without limbs."); /* not body_part(HAND) */
1965 		    return (0);
1966 		}
1967 		if (otmp->cursed) {
1968 		    You("can't. The saddle seems to be stuck to %s.",
1969 			x_monnam(mtmp, ARTICLE_THE, (char *)0,
1970 				SUPPRESS_SADDLE, FALSE));
1971 
1972 		    /* the attempt costs you time */
1973 			return (1);
1974 		}
1975 		obj_extract_self(otmp);
1976 		if ((unwornmask = otmp->owornmask) != 0L) {
1977 		    mtmp->misc_worn_check &= ~unwornmask;
1978 		    otmp->owornmask = 0L;
1979 		    update_mon_intrinsics(mtmp, otmp, FALSE, FALSE);
1980 		}
1981 		otmp = hold_another_object(otmp, "You drop %s!", doname(otmp),
1982 					(const char *)0);
1983 		timepassed = rnd(3);
1984 		if (prev_loot) *prev_loot = TRUE;
1985 	} else if (c == 'q') {
1986 		return (0);
1987 	}
1988     }
1989 #endif	/* STEED */
1990     /* 3.4.0 introduced the ability to pick things up from within swallower's stomach */
1991     if (u.uswallow) {
1992 	int count = passed_info ? *passed_info : 0;
1993 	timepassed = pickup(count);
1994     }
1995     return timepassed;
1996 }
1997 
1998 /*
1999  * Decide whether an object being placed into a magic bag will cause
2000  * it to explode.  If the object is a bag itself, check recursively.
2001  */
2002 STATIC_OVL boolean
2003 mbag_explodes(obj, depthin)
2004     struct obj *obj;
2005     int depthin;
2006 {
2007     /* these won't cause an explosion when they're empty */
2008     if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS) &&
2009 	    obj->spe <= 0)
2010 	return FALSE;
2011 
2012     /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
2013     if ((Is_mbag(obj) || obj->otyp == WAN_CANCELLATION) &&
2014 	(rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin))
2015 	return TRUE;
2016     else if (Has_contents(obj)) {
2017 	struct obj *otmp;
2018 
2019 	for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
2020 	    if (mbag_explodes(otmp, depthin+1)) return TRUE;
2021     }
2022     return FALSE;
2023 }
2024 
2025 /* A variable set in use_container(), to be used by the callback routines   */
2026 /* in_container(), and out_container() from askchain() and use_container(). */
2027 static NEARDATA struct obj *current_container;
2028 #define Icebox (current_container->otyp == ICE_BOX)
2029 
2030 /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
2031 STATIC_PTR int
2032 in_container(obj)
2033 register struct obj *obj;
2034 {
2035 	boolean floor_container = !carried(current_container);
2036 	boolean was_unpaid = FALSE;
2037 	char buf[BUFSZ];
2038 
2039 	if (!current_container) {
2040 		impossible("<in> no current_container?");
2041 		return 0;
2042 	} else if (obj == uball || obj == uchain) {
2043 		You("must be kidding.");
2044 		return 0;
2045 	} else if (obj == current_container &&
2046 	           objects[obj->otyp].oc_name_known &&
2047 	           obj->otyp == BAG_OF_HOLDING) {
2048 		pline("Creating an artificial black hole could ruin your whole day!");
2049 		return 0;
2050 	} else if (obj == current_container) {
2051 		pline("That would be an interesting topological exercise.");
2052 		return 0;
2053 	} else if (obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
2054 		Norep("You cannot %s %s you are wearing.",
2055 			Icebox ? "refrigerate" : "stash", something);
2056 		return 0;
2057 	} else if ((obj->otyp == LOADSTONE) && obj->cursed) {
2058 		obj->bknown = 1;	/* unambiguously cursed */
2059 		makeknown(obj->otyp);	/* unambiguously a loadstone */
2060 		pline_The("stone%s won't leave your person.", plur(obj->quan));
2061 		return 0;
2062 	} else if (obj->otyp == AMULET_OF_YENDOR ||
2063 		   obj->otyp == CANDELABRUM_OF_INVOCATION ||
2064 		   obj->otyp == BELL_OF_OPENING ||
2065 		   obj->otyp == SPE_BOOK_OF_THE_DEAD) {
2066 	/* Prohibit Amulets in containers; if you allow it, monsters can't
2067 	 * steal them.  It also becomes a pain to check to see if someone
2068 	 * has the Amulet.  Ditto for the Candelabrum, the Bell and the Book.
2069 	 */
2070 	    pline("%s cannot be confined in such trappings.", The(xname(obj)));
2071 	    return 0;
2072 	} else if (obj->otyp == LEASH && obj->leashmon != 0) {
2073 		pline("%s attached to your pet.", Tobjnam(obj, "are"));
2074 		return 0;
2075 	} else if (obj == uwep) {
2076 		if (welded(obj)) {
2077 			weldmsg(obj);
2078 			return 0;
2079 		}
2080 		setuwep((struct obj *) 0);
2081 		if (uwep) return 0;	/* unwielded, died, rewielded */
2082 	} else if (obj == uswapwep) {
2083 		setuswapwep((struct obj *) 0);
2084 		if (uswapwep) return 0;     /* unwielded, died, rewielded */
2085 	} else if (obj == uquiver) {
2086 		setuqwep((struct obj *) 0);
2087 		if (uquiver) return 0;     /* unwielded, died, rewielded */
2088 	}
2089 
2090 	if (obj->otyp == CORPSE) {
2091 	    if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
2092 		 && !Stone_resistance) {
2093 		if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
2094 		    display_nhwindow(WIN_MESSAGE, FALSE);
2095 		else {
2096 		    char kbuf[BUFSZ];
2097 
2098 		    Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
2099 		    pline("Touching %s is a fatal mistake.", kbuf);
2100 		    instapetrify(kbuf);
2101 		    return -1;
2102 		}
2103 	    }
2104 	}
2105 
2106 	/* boxes, boulders, and big statues can't fit into any container */
2107 	if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER ||
2108 		(obj->otyp == STATUE && bigmonst(&mons[obj->corpsenm]))) {
2109 		/*
2110 		 *  xname() uses a static result array.  Save obj's name
2111 		 *  before current_container's name is computed.  Don't
2112 		 *  use the result of strcpy() within You() --- the order
2113 		 *  of evaluation of the parameters is undefined.
2114 		 */
2115 		Strcpy(buf, the(xname(obj)));
2116 		You("cannot fit %s into %s.", buf,
2117 		    the(xname(current_container)));
2118 		return 0;
2119 	}
2120 
2121 	freeinv(obj);
2122 
2123 	if (obj_is_burning(obj))	/* this used to be part of freeinv() */
2124 		(void) snuff_lit(obj);
2125 
2126 	if (floor_container && costly_spot(u.ux, u.uy)) {
2127 	    if (obj->oclass != COIN_CLASS) {
2128 		/* sellobj() will take an unpaid item off the shop bill
2129 		 * note: coins are handled later */
2130 		was_unpaid = obj->unpaid ? TRUE : FALSE;
2131 		/* don't sell when putting the item into your own container,
2132 		   but handle billing correctly */
2133 		sellobj_state(current_container->no_charge ?
2134 		SELL_DONTSELL : SELL_DELIBERATE);
2135 		sellobj(obj, u.ux, u.uy);
2136 		sellobj_state(SELL_NORMAL);
2137 	    }
2138 	}
2139 	if (Icebox && !age_is_relative(obj)) {
2140 		obj->age = monstermoves - obj->age; /* actual age */
2141 		/* stop any corpse timeouts when frozen */
2142 		if (obj->otyp == CORPSE && obj->timed) {
2143 			long rot_alarm = stop_timer(ROT_CORPSE, (genericptr_t)obj);
2144 			(void) stop_timer(REVIVE_MON, (genericptr_t)obj);
2145 			/* mark a non-reviving corpse as such */
2146 			if (rot_alarm) obj->norevive = 1;
2147 		}
2148 	} else if ((current_container->otyp == BAG_OF_HOLDING) && mbag_explodes(obj, 0)) {
2149 #ifdef LIVELOGFILE
2150 		livelog_generic("boh_explosion", dump_typename(obj->otyp));
2151 #endif
2152 		/* explicitly mention what item is triggering the explosion */
2153 		pline( "As you put %s inside, you are blasted by a magical explosion!", doname(obj));
2154 		/* did not actually insert obj yet */
2155 		if (was_unpaid) addtobill(obj, FALSE, FALSE, TRUE);
2156 		/* At least ID the wand and give some experience for losing a bag of
2157 		 * holding this way. */
2158 		if (obj->otyp == WAN_CANCELLATION) {
2159 			makeknown(obj->otyp);
2160 		}
2161 		obfree(obj, (struct obj *)0);
2162 
2163 		/* dump it out onto the floor so the scatterage can take effect */
2164 		if (dump_container(current_container, TRUE)) {
2165 			pline("The contents fly everywhere!");
2166 		}
2167 		scatter(u.ux,u.uy,10,VIS_EFFECTS|MAY_HIT|MAY_DESTROY|MAY_FRACTURE,0);
2168 
2169 		losehp(d(6,6),"magical explosion", KILLED_BY_AN);
2170 		current_container = 0;	/* baggone = TRUE; */
2171 	}
2172 
2173 	if (current_container) {
2174 	    Strcpy(buf, the(xname(current_container)));
2175 	    You("put %s into %s.", doname(obj), buf);
2176 
2177 	    /* gold in container always needs to be added to credit */
2178 	    if (floor_container && obj->oclass == COIN_CLASS)
2179 		sellobj(obj, current_container->ox, current_container->oy);
2180 	    (void) add_to_container(current_container, obj);
2181 	    current_container->owt = weight(current_container);
2182 	}
2183 	/* gold needs this, and freeinv() many lines above may cause
2184 	 * the encumbrance to disappear from the status, so just always
2185 	 * update status immediately.
2186 	 */
2187 	bot();
2188 
2189 	return(current_container ? 1 : -1);
2190 }
2191 
2192 STATIC_PTR int
2193 ck_bag(obj)
2194 struct obj *obj;
2195 {
2196 	return current_container && obj != current_container;
2197 }
2198 
2199 /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
2200 STATIC_PTR int
2201 out_container(obj)
2202 register struct obj *obj;
2203 {
2204 	register struct obj *otmp;
2205 	boolean is_gold = (obj->oclass == COIN_CLASS);
2206 	int res, loadlev;
2207 	long count;
2208 
2209 	if (!current_container) {
2210 		impossible("<out> no current_container?");
2211 		return -1;
2212 	} else if (is_gold) {
2213 		obj->owt = weight(obj);
2214 	}
2215 
2216 	if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0;
2217 
2218 	if (obj->otyp == CORPSE) {
2219 	    if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
2220 		 && !Stone_resistance) {
2221 		if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
2222 		    display_nhwindow(WIN_MESSAGE, FALSE);
2223 		else {
2224 		    char kbuf[BUFSZ];
2225 
2226 		    Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
2227 		    pline("Touching %s is a fatal mistake.", kbuf);
2228 		    instapetrify(kbuf);
2229 		    return -1;
2230 		}
2231 	    }
2232 	}
2233 
2234 	count = obj->quan;
2235 	if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0)
2236 	    return res;
2237 
2238 	if (obj->quan != count && obj->otyp != LOADSTONE)
2239 	    obj = splitobj(obj, count);
2240 
2241 	/* Remove the object from the list. */
2242 	obj_extract_self(obj);
2243 	current_container->owt = weight(current_container);
2244 
2245 	if (Icebox && !age_is_relative(obj)) {
2246 		obj->age = monstermoves - obj->age; /* actual age */
2247 		if (obj->otyp == CORPSE)
2248 			start_corpse_timeout(obj);
2249 	}
2250 	/* simulated point of time */
2251 
2252 	if(!obj->unpaid && !carried(current_container) &&
2253 	     costly_spot(current_container->ox, current_container->oy)) {
2254 		obj->ox = current_container->ox;
2255 		obj->oy = current_container->oy;
2256 		addtobill(obj, FALSE, FALSE, FALSE);
2257 	}
2258 	if (is_pick(obj) && !obj->unpaid && *u.ushops && shop_keeper(*u.ushops))
2259 		verbalize("You sneaky cad! Get out of here with that pick!");
2260 
2261 	otmp = addinv(obj);
2262 	loadlev = near_capacity();
2263 	prinv(loadlev ?
2264 	      (loadlev < MOD_ENCUMBER ?
2265 	       "You have a little trouble removing" :
2266 	       "You have much trouble removing") : (char *)0,
2267 	      otmp, count);
2268 
2269 	if (is_gold) {
2270 #ifndef GOLDOBJ
2271 		dealloc_obj(obj);
2272 #endif
2273 		bot();	/* update character's gold piece count immediately */
2274 	}
2275 	return 1;
2276 }
2277 
2278 /* an object inside a cursed bag of holding is being destroyed */
2279 STATIC_OVL long
2280 mbag_item_gone(held, item)
2281 int held;
2282 struct obj *item;
2283 {
2284     struct monst *shkp;
2285     long loss = 0L;
2286 
2287     if (item->dknown)
2288 	pline("%s %s vanished!", Doname2(item), otense(item, "have"));
2289     else
2290 	You("%s %s disappear!", Blind ? "notice" : "see", doname(item));
2291 
2292     if (*u.ushops && (shkp = shop_keeper(*u.ushops)) != 0) {
2293 	if (held ? (boolean) item->unpaid : costly_spot(u.ux, u.uy))
2294 	    loss = stolen_value(item, u.ux, u.uy,
2295 				(boolean)shkp->mpeaceful, TRUE);
2296     }
2297     obfree(item, (struct obj *) 0);
2298     return loss;
2299 }
2300 
2301 void
2302 observe_quantum_cat(box, past)
2303 struct obj *box;
2304 boolean past;
2305 {
2306     static NEARDATA const char sc[] = "Schroedinger's Cat";
2307     struct obj *deadcat;
2308     struct monst *livecat;
2309     xchar ox, oy;
2310 
2311     box->spe = 0;		/* box->owt will be updated below */
2312     if (get_obj_location(box, &ox, &oy, 0))
2313 	box->ox = ox, box->oy = oy;	/* in case it's being carried */
2314 
2315     /* this isn't really right, since any form of observation
2316        (telepathic or monster/object/food detection) ought to
2317        force the determination of alive vs dead state; but basing
2318        it just on opening the box is much simpler to cope with */
2319     livecat = (rn2(2) && !past) ? makemon(&mons[PM_HOUSECAT],
2320 			       box->ox, box->oy, NO_MINVENT) : 0;
2321     if (livecat) {
2322 	livecat->mpeaceful = 1;
2323 	set_malign(livecat);
2324 	if (!canspotmon(livecat))
2325 	    You("think %s brushed your %s.", something, body_part(FOOT));
2326 	else
2327 	    pline("%s inside the box is still alive!", Monnam(livecat));
2328 	(void) christen_monst(livecat, sc);
2329     } else {
2330 	deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
2331 				  box->ox, box->oy, sc);
2332 	if (deadcat) {
2333 	    obj_extract_self(deadcat);
2334 	    (void) add_to_container(box, deadcat);
2335 	}
2336 	pline_The("%s%s inside the box is dead!",
2337 		Hallucination ? rndmonnam() : "housecat",
2338 		past ? " that was" : "");
2339     }
2340     box->owt = weight(box);
2341     return;
2342 }
2343 
2344 /* based largely on borrowed code from dNetHack by Chris_ANG */
2345 void
2346 open_coffin(box, past)
2347 struct obj *box;
2348 boolean past;
2349 {
2350     /* static NEARDATA const char sc[] = "Schroedinger's Cat"; */
2351     /* Would be nice to name the vampire and put the name on the coffin. But not today. */
2352     struct monst *vampire;
2353     xchar ox, oy;
2354 
2355     pline("That %s %s, it%s a coffin!", past ? "wasn't" : "isn't",
2356 		an(simple_typename(box->otyp)), past ? " was" : "'s");
2357     box->spe = 3;    /* box->owt will be updated below */
2358     if (get_obj_location(box, &ox, &oy, 0))
2359     box->ox = ox, box->oy = oy;  /* in case it's being carried */
2360 
2361     vampire = makemon(mkclass(S_VAMPIRE,0), box->ox, box->oy, NO_MM_FLAGS);
2362     set_malign(vampire);
2363     if (!canspotmon(vampire)) {
2364 	You("think %s brushed against your %s.", something, body_part(HAND));
2365     } else {
2366 	pline("There %s %s in the coffin.", past ? "was" : "is",
2367 		Hallucination ? "a dark knight" : a_monnam(vampire));
2368 	pline_The("%s rises!", Hallucination ? "dark knight" : m_monnam(vampire));
2369     }
2370     /* (void) christen_monst(vampire, sc); */
2371     box->owt = weight(box);
2372     return;
2373 }
2374 
2375 #undef Icebox
2376 
2377 int
2378 use_container(obj, held)
2379 register struct obj *obj;
2380 register int held;
2381 {
2382 	struct obj *curr, *otmp;
2383 #ifndef GOLDOBJ
2384 	struct obj *u_gold = (struct obj *)0;
2385 #endif
2386 	boolean one_by_one, allflag, quantum_cat = FALSE,
2387 		loot_out = FALSE, loot_in = FALSE;
2388 	char select[MAXOCLASSES+1];
2389 	char qbuf[BUFSZ], emptymsg[BUFSZ], pbuf[QBUFSZ];
2390 	long loss = 0L;
2391 	int cnt = 0, used = 0,
2392 	    menu_on_request;
2393 
2394 	emptymsg[0] = '\0';
2395 	if (nohands(youmonst.data)) {
2396 		You("have no hands!");	/* not `body_part(HAND)' */
2397 		return 0;
2398 	} else if (!freehand()) {
2399 		You("have no free %s.", body_part(HAND));
2400 		return 0;
2401 	}
2402 	if (obj->olocked) {
2403 	    pline("%s to be locked.", Tobjnam(obj, "seem"));
2404 	    if (held) You("must put it down to unlock.");
2405 	    return 0;
2406 	} else if (obj->otrapped) {
2407 	    if (held) You("open %s...", the(xname(obj)));
2408 	    (void) chest_trap(obj, HAND, FALSE);
2409 	    /* even if the trap fails, you've used up this turn */
2410 	    if (multi >= 0) {	/* in case we didn't become paralyzed */
2411 		nomul(-1, "opening a container");
2412 		nomovemsg = "";
2413 	    }
2414 	    return 1;
2415 	}
2416 	current_container = obj;	/* for use by in/out_container */
2417 
2418 	if (obj->spe == 1) {
2419 	    observe_quantum_cat(obj, FALSE); /* box was not destroyed, use present tense */
2420 	    used = 1;
2421 	    quantum_cat = TRUE; 	/* for adjusting "it's empty" message */
2422 	} else if (obj->spe == 4) {
2423 	    open_coffin(obj, FALSE); 	/* box was not destroyed, use present tense */
2424 	    used = 1;
2425 	    return used;
2426 	}
2427 	/* Count the number of contained objects. Sometimes toss objects if */
2428 	/* a cursed magic bag.						    */
2429 	for (curr = obj->cobj; curr; curr = otmp) {
2430 	    otmp = curr->nobj;
2431 	    if (Is_mbag(obj) && obj->cursed && !rn2(13)) {
2432 		obj_extract_self(curr);
2433 		loss += mbag_item_gone(held, curr);
2434 		used = 1;
2435 	    } else {
2436 		cnt++;
2437 	    }
2438 	}
2439 
2440 	if (loss)	/* magic bag lost some shop goods */
2441 	    You("owe %ld %s for lost merchandise.", loss, currency(loss));
2442 	obj->owt = weight(obj);	/* in case any items were lost */
2443 
2444 	if (!cnt)
2445 	    Sprintf(emptymsg, "%s is %sempty.", Yname2(obj),
2446 		    quantum_cat ? "now " : "");
2447 
2448 	if (cnt || flags.menu_style == MENU_FULL) {
2449 	    Strcpy(qbuf, "Do you want to take something out of ");
2450 	    Sprintf(eos(qbuf), "%s?",
2451 		    safe_qbuf(qbuf, 1, yname(obj), ysimple_name(obj), "it"));
2452 	    if (flags.menu_style != MENU_TRADITIONAL) {
2453 		if (flags.menu_style == MENU_FULL) {
2454 		    int t;
2455 		    char menuprompt[BUFSZ];
2456 		    boolean outokay = (cnt != 0);
2457 #ifndef GOLDOBJ
2458 		    boolean inokay = (invent != 0) || (u.ugold != 0);
2459 #else
2460 		    boolean inokay = (invent != 0);
2461 #endif
2462 		    if (!outokay && !inokay) {
2463 			pline("%s", emptymsg);
2464 			You("don't have anything to put in.");
2465 			return used;
2466 		    }
2467 		    menuprompt[0] = '\0';
2468 		    if (!cnt) Sprintf(menuprompt, "%s ", emptymsg);
2469 		    Strcat(menuprompt, "Do what?");
2470 		    t = in_or_out_menu(menuprompt, current_container, outokay, inokay);
2471 		    if (t <= 0) return 0;
2472 		    loot_out = (t & 0x01) != 0;
2473 		    loot_in  = (t & 0x02) != 0;
2474 		} else {	/* MENU_COMBINATION or MENU_PARTIAL */
2475 		    loot_out = (yn_function(qbuf, "ynq", 'n') == 'y');
2476 		}
2477 		if (loot_out) {
2478 		    add_valid_menu_class(0);	/* reset */
2479 		    used |= menu_loot(0, current_container, FALSE) > 0;
2480 		}
2481 	    } else {
2482 		/* traditional code */
2483 ask_again2:
2484 		menu_on_request = 0;
2485 		add_valid_menu_class(0);	/* reset */
2486 		Strcpy(pbuf, ":ynq");
2487 		if (cnt) Strcat(pbuf, "m");
2488 		switch (yn_function(qbuf, pbuf, 'n')) {
2489 		case ':':
2490 		    container_contents(current_container, FALSE, FALSE, TRUE);
2491 		    goto ask_again2;
2492 		case 'y':
2493 		    if (query_classes(select, &one_by_one, &allflag,
2494 				      "take out", current_container->cobj,
2495 				      FALSE,
2496 #ifndef GOLDOBJ
2497 				      FALSE,
2498 #endif
2499 				      &menu_on_request)) {
2500 			if (askchain((struct obj **)&current_container->cobj,
2501 				     (one_by_one ? (char *)0 : select),
2502 				     allflag, out_container,
2503 				     (int FDECL((*),(OBJ_P)))0,
2504 				     0, "nodot"))
2505 			    used = 1;
2506 		    } else if (menu_on_request < 0) {
2507 			used |= menu_loot(menu_on_request,
2508 					  current_container, FALSE) > 0;
2509 		    }
2510 		    /*FALLTHRU*/
2511 		case 'n':
2512 		    break;
2513 		case 'm':
2514 		    menu_on_request = -2; /* triggers ALL_CLASSES */
2515 		    used |= menu_loot(menu_on_request, current_container, FALSE) > 0;
2516 		    break;
2517 		case 'q':
2518 		default:
2519 		    return used;
2520 		}
2521 	    }
2522 	} else {
2523 	    pline("%s", emptymsg);		/* <whatever> is empty. */
2524 	}
2525 
2526 #ifndef GOLDOBJ
2527 	if (!invent && u.ugold == 0) {
2528 #else
2529 	if (!invent) {
2530 #endif
2531 	    /* nothing to put in, but some feedback is necessary */
2532 	    You("don't have anything to put in.");
2533 	    return used;
2534 	}
2535 	if (flags.menu_style != MENU_FULL) {
2536 	    Sprintf(qbuf, "Do you wish to put %s in?", something);
2537 	    Strcpy(pbuf, ynqchars);
2538 	    if (flags.menu_style == MENU_TRADITIONAL && invent && inv_cnt() > 0)
2539 		Strcat(pbuf, "m");
2540 	    switch (yn_function(qbuf, pbuf, 'n')) {
2541 		case 'y':
2542 		    loot_in = TRUE;
2543 		    break;
2544 		case 'n':
2545 		    break;
2546 		case 'm':
2547 		    add_valid_menu_class(0);	  /* reset */
2548 		    menu_on_request = -2; /* triggers ALL_CLASSES */
2549 		    used |= menu_loot(menu_on_request, current_container, TRUE) > 0;
2550 		    break;
2551 		case 'q':
2552 		default:
2553 		    return used;
2554 	    }
2555 	}
2556 	/*
2557 	 * Gone: being nice about only selecting food if we know we are
2558 	 * putting things in an ice chest.
2559 	 */
2560 	if (loot_in) {
2561 #ifndef GOLDOBJ
2562 	    if (u.ugold) {
2563 		/*
2564 		 * Hack: gold is not in the inventory, so make a gold object
2565 		 * and put it at the head of the inventory list.
2566 		 */
2567 		u_gold = mkgoldobj(u.ugold);	/* removes from u.ugold */
2568 		u_gold->in_use = TRUE;
2569 		u.ugold = u_gold->quan;		/* put the gold back */
2570 		assigninvlet(u_gold);		/* might end up as NOINVSYM */
2571 		u_gold->nobj = invent;
2572 		invent = u_gold;
2573 	    }
2574 #endif
2575 	    add_valid_menu_class(0);	  /* reset */
2576 	    if (flags.menu_style != MENU_TRADITIONAL) {
2577 		used |= menu_loot(0, current_container, TRUE) > 0;
2578 	    } else {
2579 		/* traditional code */
2580 		menu_on_request = 0;
2581 		if (query_classes(select, &one_by_one, &allflag, "put in",
2582 				   invent, FALSE,
2583 #ifndef GOLDOBJ
2584 				   (u.ugold != 0L),
2585 #endif
2586 				   &menu_on_request)) {
2587 		    (void) askchain((struct obj **)&invent,
2588 				    (one_by_one ? (char *)0 : select), allflag,
2589 				    in_container, ck_bag, 0, "nodot");
2590 		    used = 1;
2591 		} else if (menu_on_request < 0) {
2592 		    used |= menu_loot(menu_on_request,
2593 				      current_container, TRUE) > 0;
2594 		}
2595 	    }
2596 	}
2597 
2598 #ifndef GOLDOBJ
2599 	if (u_gold && invent && invent->oclass == COIN_CLASS) {
2600 	    /* didn't stash [all of] it */
2601 	    u_gold = invent;
2602 	    invent = u_gold->nobj;
2603 	    u_gold->in_use = FALSE;
2604 	    dealloc_obj(u_gold);
2605 	}
2606 #endif
2607 	return used;
2608 }
2609 
2610 /* Loot a container (take things out, put things in), using a menu. */
2611 STATIC_OVL int
2612 menu_loot(retry, container, put_in)
2613 int retry;
2614 struct obj *container;
2615 boolean put_in;
2616 {
2617     int n, i, n_looted = 0;
2618     boolean all_categories = TRUE, loot_everything = FALSE;
2619     char buf[BUFSZ];
2620     const char *takeout = "Take out", *putin = "Put in";
2621     struct obj *otmp, *otmp2;
2622     menu_item *pick_list;
2623     int mflags, res;
2624     long count;
2625 
2626     if (retry) {
2627 	all_categories = (retry == -2);
2628     } else if (flags.menu_style == MENU_FULL) {
2629 	all_categories = FALSE;
2630 	Sprintf(buf,"%s what type of objects?", put_in ? putin : takeout);
2631 	mflags = put_in ? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN | UNPAID_TYPES | UNIDENTIFIED_TYPES :
2632 		          ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN | UNPAID_TYPES | UNIDENTIFIED_TYPES;
2633 	n = query_category(buf, put_in ? invent : container->cobj,
2634 			   mflags, &pick_list, PICK_ANY);
2635 	if (!n) return 0;
2636 	for (i = 0; i < n; i++) {
2637 	    if (pick_list[i].item.a_int == 'A')
2638 		loot_everything = TRUE;
2639 	    else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
2640 		all_categories = TRUE;
2641 	    else
2642 		add_valid_menu_class(pick_list[i].item.a_int);
2643 	}
2644 	free((genericptr_t) pick_list);
2645     }
2646 
2647     if (loot_everything) {
2648 	for (otmp = container->cobj; otmp; otmp = otmp2) {
2649 	    otmp2 = otmp->nobj;
2650 	    res = out_container(otmp);
2651 	    if (res < 0) break;
2652 	}
2653     } else {
2654 	mflags = INVORDER_SORT;
2655 	if (put_in && flags.invlet_constant) mflags |= USE_INVLET;
2656 	Sprintf(buf,"%s what?", put_in ? putin : takeout);
2657 	n = query_objlist(buf, put_in ? invent : container->cobj,
2658 			  mflags, &pick_list, PICK_ANY,
2659 			  all_categories ? allow_all : allow_category);
2660 	if (n) {
2661 		n_looted = n;
2662 		for (i = 0; i < n; i++) {
2663 		    otmp = pick_list[i].item.a_obj;
2664 		    count = pick_list[i].count;
2665 		    if (count > 0 && count < otmp->quan) {
2666 			otmp = splitobj(otmp, count);
2667 			/* special split case also handled by askchain() */
2668 		    }
2669 		    res = put_in ? in_container(otmp) : out_container(otmp);
2670 		    if (res < 0) {
2671 			if (otmp != pick_list[i].item.a_obj) {
2672 			    /* split occurred, merge again */
2673 			    (void) merged(&pick_list[i].item.a_obj, &otmp);
2674 			}
2675 			break;
2676 		    }
2677 		}
2678 		free((genericptr_t)pick_list);
2679 	}
2680     }
2681     return n_looted;
2682 }
2683 
2684 STATIC_OVL int
2685 in_or_out_menu(prompt, obj, outokay, inokay)
2686 const char *prompt;
2687 struct obj *obj;
2688 boolean outokay, inokay;
2689 {
2690     winid win;
2691     anything any;
2692     menu_item *pick_list;
2693     char buf[BUFSZ];
2694     int n;
2695     const char *menuselector = iflags.lootabc ? "abc" : "oib";
2696 
2697     any.a_void = 0;
2698     win = create_nhwindow(NHW_MENU);
2699     start_menu(win);
2700     if (outokay) {
2701 	any.a_int = 1;
2702 	Sprintf(buf,"Take %s out of %s", something, the(xname(obj)));
2703 	add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, *menuselector, 0, ATR_NONE,
2704 			buf, MENU_UNSELECTED);
2705     }
2706     menuselector++;
2707     if (inokay) {
2708 	any.a_int = 2;
2709 	Sprintf(buf,"Put %s into %s", something, the(xname(obj)));
2710 	add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, *menuselector, 0, ATR_NONE, buf, MENU_UNSELECTED);
2711     }
2712     menuselector++;
2713     if (outokay && inokay) {
2714 	any.a_int = 3;
2715 	add_menu(win, NO_GLYPH, MENU_DEFCNT, &any, *menuselector, 0, ATR_NONE,
2716 			"Both of the above", MENU_UNSELECTED);
2717     }
2718     end_menu(win, prompt);
2719     n = select_menu(win, PICK_ONE, &pick_list);
2720     destroy_nhwindow(win);
2721     if (n > 0) {
2722 	n = pick_list[0].item.a_int;
2723 	free((genericptr_t) pick_list);
2724     }
2725     return n;
2726 }
2727 
2728 
2729 /* Dumps out a container, possibly as the prelude/result of an explosion.
2730  * destroy_after trashes the container afterwards; try not to use it :P
2731  *
2732  * Assumption 1: Player is assumed to not be handling the contents directly.
2733  * Assumption 2: !destroy_after == #tip command
2734  * Assumption 3: #tip always occurs at the hero's location
2735  *
2736  * Returns 1 if at least one object was present, 0 if empty.
2737  */
2738 int
2739 dump_container(container, destroy_after)
2740 struct obj* container;
2741 BOOLEAN_P destroy_after;
2742 {
2743 	struct obj* otmp,*otmp2;
2744 	int ret = 0;
2745 	schar ltyp;
2746 	ltyp = levl[u.ux][u.uy].typ;
2747 
2748 	/* sanity checks */
2749 	if (!container || !Is_container(container))
2750 	    return 0;
2751 
2752 	/* cursed bags of holding are supposed to be generally
2753 	   difficult, so when trying to tip them while cursed,
2754 	   make them literally become bags of "holding" only */
2755 	if (!destroy_after && Is_mbag(container) && container->cursed) {
2756 	    pline("%s reluctant to give up its contents.", Tobjnam(container, "seem"));
2757 	    return 0;
2758 	}
2759 
2760 	/* trying to empty a locked container may damage its contents */
2761 	if (!destroy_after && container->olocked) {
2762 	    ret = !!container->cobj;
2763 	    container_impact_dmg(container);
2764 	    return ret;
2765 	}
2766 
2767 #if 0 /* DEFERRED */
2768         /* make sure floor container contents are billed properly when tipping */
2769         if (!destroy_after) {
2770             struct monst *shkp;
2771 
2772             /* logic courtesy of pick_obj() */
2773             if (container->where == OBJ_FLOOR &&
2774                 !u.uswallow &&
2775                 costly_spot(container->ox, container->oy) &&
2776                 /* logic courtesy of addtobill() */
2777                 *u.ushops &&
2778                 (shkp = shop_keeper(*u.ushops)) &&
2779                 inhishop(shkp)) {
2780 
2781                 /* logic courtesy of addtobill() */
2782                 long gltmp = contained_gold(container);
2783                 if (gltmp) costly_gold(container->ox, container->oy, gltmp);
2784                 bill_box_content(container, FALSE);
2785                 picked_container(container);
2786             }
2787         }
2788 #endif
2789 
2790 	for (otmp = container->cobj; otmp; otmp = otmp2)
2791 	{
2792 	    ret = 1;
2793 	    otmp2 = otmp->nobj;
2794 	    obj_extract_self(otmp);
2795 	    container->owt = weight(container);
2796 
2797 	    /* we do need to start the timer on these */
2798 	    if (container->otyp == ICE_BOX && !age_is_relative(otmp)) {
2799 		otmp->age = monstermoves - otmp->age;
2800 		if (otmp->otyp == CORPSE) {
2801 		    start_corpse_timeout(otmp);
2802 		}
2803 	    }
2804 
2805 	    if (destroy_after) {
2806 		/* bag of holding explosions */
2807 		place_object(otmp, u.ux, u.uy);
2808 	    } else {
2809 		if (!u.uswallow) {
2810 		    if (!can_reach_floor()) {
2811 			hitfloor(otmp);
2812 		    } else {
2813 			if (!IS_ALTAR(ltyp)) pline("%s spill%s %sto the %s.",
2814 			    Doname2(otmp), (otmp->otyp == LENSES || is_gloves(otmp)
2815 			    || is_boots(otmp) || otmp->quan != 1L) ? "" : "s",
2816 			    (IS_SINK(ltyp) || IS_LAVA(ltyp) || IS_SOFT(ltyp)) ?
2817 			    "in" : "on", IS_SINK(ltyp) ? "sink" : surface(u.ux,u.uy));
2818 			dropx(otmp);
2819 		    }
2820 		    /* tipping is too uncoordinated to get rings to hit the drain */
2821 		    if ((otmp->oclass == RING_CLASS) && IS_SINK(ltyp))
2822 			You("hear a%s clatter.", is_metallic(otmp) ? " metallic" : "");
2823 		} else {
2824 		    dropx(otmp);
2825 		}
2826 		/* consider spilled objects deliberately dropped */
2827 		otmp->was_dropped = TRUE;
2828 	    }
2829 
2830 	    if (otmp->otyp == GOLD_PIECE) {
2831 		bot();	/* update character's gold piece count immediately */
2832 	    }
2833 	}
2834 
2835 	if (destroy_after) {
2836 		if (container->where == OBJ_INVENT) {
2837 			useup(container);
2838 		} else if (obj_here(container, u.ux, u.uy)) {
2839 			useupf(container, container->quan);
2840 		}
2841 	}
2842 
2843 	return ret;
2844 }
2845 
2846 
2847 STATIC_OVL void
2848 del_sokoprize()
2849 {
2850 	int x, y, cnt = 0;
2851 	struct obj *otmp, *onext;
2852 	/* check objs on floor */
2853 	for (otmp = fobj; otmp; otmp = onext) {
2854 		onext = otmp->nobj; /* otmp may be destroyed */
2855 		if (Is_sokoprize(otmp)) {
2856 			x = otmp->ox;
2857 			y = otmp->oy;
2858 			obj_extract_self(otmp);
2859 			if (cansee(x, y)) {
2860 				You("see %s vanishing.", an(xname(otmp)));
2861 				newsym(x, y);
2862 			} else cnt++;
2863 			obfree(otmp, (struct obj *)0);
2864 		}
2865 	}
2866 	if (cnt && flags.soundok) You_hear("something popping.");
2867 	/* check buried objs... do we need this? */
2868 	for (otmp = level.buriedobjlist; otmp; otmp = onext) {
2869 		onext = otmp->nobj; /* otmp may be destroyed */
2870 		if (Is_sokoprize(otmp)) {
2871 			obj_extract_self(otmp);
2872 			obfree(otmp, (struct obj *)0);
2873 		}
2874 	}
2875 }
2876 
2877 /*pickup.c*/
2878