Wikia

Wikihack

Source:NetHack 3.2.0/pickup.c

2,032pages on
this wiki
Talk0

Below is the full text to pickup.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/pickup.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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

Around Wikia's network

Random Wiki