FANDOM


Below is the full text to pickup.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/pickup.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


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

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.