Wikia

Wikihack

Source:Pickup.c

2,032pages on
this wiki
Talk0

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

Top of file Edit

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.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    /*
6.     *	Contains code for picking objects up, and container use.
7.     */
8.    
9.    #include "hack.h"
10.   
11.   STATIC_DCL void FDECL(simple_look, (struct obj *,BOOLEAN_P));
12.   #ifndef GOLDOBJ
13.   STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
14.   		const char *,struct obj *,BOOLEAN_P,BOOLEAN_P,int *));
15.   #else
16.   STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *,
17.   		const char *,struct obj *,BOOLEAN_P,int *));
18.   #endif
19.   STATIC_DCL void FDECL(check_here, (BOOLEAN_P));
20.   STATIC_DCL boolean FDECL(n_or_more, (struct obj *));
21.   STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *));
22.   #if 0 /* not used */
23.   STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *));
24.   #endif
25.   STATIC_DCL int FDECL(autopick, (struct obj*, int, menu_item **));
26.   STATIC_DCL int FDECL(count_categories, (struct obj *,int));
27.   STATIC_DCL long FDECL(carry_count,
28.   		      (struct obj *,struct obj *,long,BOOLEAN_P,int *,int *));
29.   STATIC_DCL int FDECL(lift_object, (struct obj *,struct obj *,long *,BOOLEAN_P));
30.   STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *,int));
31.   STATIC_PTR int FDECL(in_container,(struct obj *));
32.   STATIC_PTR int FDECL(ck_bag,(struct obj *));
33.   STATIC_PTR int FDECL(out_container,(struct obj *));
34.   STATIC_DCL long FDECL(mbag_item_gone, (int,struct obj *));
35.   STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
36.   STATIC_DCL int FDECL(menu_loot, (int, struct obj *, BOOLEAN_P));
37.   STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *, BOOLEAN_P, BOOLEAN_P));
38.   STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
39.   STATIC_DCL boolean FDECL(able_to_loot, (int, int));
40.   STATIC_DCL boolean FDECL(mon_beside, (int, int));
41.   
42.   /* define for query_objlist() and autopickup() */
43.   #define FOLLOW(curr, flags) \
44.       (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
45.   
46.   /*
47.    *  How much the weight of the given container will change when the given
48.    *  object is removed from it.  This calculation must match the one used
49.    *  by weight() in mkobj.c.
50.    */
51.   #define DELTA_CWT(cont,obj)		\
52.       ((cont)->cursed ? (obj)->owt * 2 :	\
53.   		      1 + ((obj)->owt / ((cont)->blessed ? 4 : 2)))
54.   #define GOLD_WT(n)		(((n) + 50L) / 100L)
55.   /* if you can figure this out, give yourself a hearty pat on the back... */
56.   #define GOLD_CAPACITY(w,n)	(((w) * -100L) - ((n) + 50L) - 1L)
57.   
58.   static const char moderateloadmsg[] = "You have a little trouble lifting";
59.   static const char nearloadmsg[] = "You have much trouble lifting";
60.   static const char overloadmsg[] = "You have extreme difficulty lifting";
61.   

simple_look Edit

62.   /* BUG: this lets you look at cockatrice corpses while blind without
63.      touching them */
64.   /* much simpler version of the look-here code; used by query_classes() */
65.   STATIC_OVL void
66.   simple_look(otmp, here)
67.   struct obj *otmp;	/* list of objects */
68.   boolean here;		/* flag for type of obj list linkage */
69.   {
70.   	/* Neither of the first two cases is expected to happen, since
71.   	 * we're only called after multiple classes of objects have been
72.   	 * detected, hence multiple objects must be present.
73.   	 */
74.   	if (!otmp) {
75.   	    impossible("simple_look(null)");
76.   	} else if (!(here ? otmp->nexthere : otmp->nobj)) {
77.   	    pline("%s", doname(otmp));
78.   	} else {
79.   	    winid tmpwin = create_nhwindow(NHW_MENU);
80.   	    putstr(tmpwin, 0, "");
81.   	    do {
82.   		putstr(tmpwin, 0, doname(otmp));
83.   		otmp = here ? otmp->nexthere : otmp->nobj;
84.   	    } while (otmp);
85.   	    display_nhwindow(tmpwin, TRUE);
86.   	    destroy_nhwindow(tmpwin);
87.   	}
88.   }
89.   

collect_obj_classes Edit

90.   #ifndef GOLDOBJ
91.   int
92.   collect_obj_classes(ilets, otmp, here, incl_gold, filter, itemcount)
93.   char ilets[];
94.   register struct obj *otmp;
95.   boolean here, incl_gold;
96.   boolean FDECL((*filter),(OBJ_P));
97.   int *itemcount;
98.   #else
99.   int
100.  collect_obj_classes(ilets, otmp, here, filter, itemcount)
101.  char ilets[];
102.  register struct obj *otmp;
103.  boolean here;
104.  boolean FDECL((*filter),(OBJ_P));
105.  int *itemcount;
106.  #endif
107.  {
108.  	register int iletct = 0;
109.  	register char c;
110.  
111.  	*itemcount = 0;
112.  #ifndef GOLDOBJ
113.  	if (incl_gold)
114.  	    ilets[iletct++] = def_oc_syms[COIN_CLASS];
115.  #endif
116.  	ilets[iletct] = '\0'; /* terminate ilets so that index() will work */
117.  	while (otmp) {
118.  	    c = def_oc_syms[(int)otmp->oclass];
119.  	    if (!index(ilets, c) && (!filter || (*filter)(otmp)))
120.  		ilets[iletct++] = c,  ilets[iletct] = '\0';
121.  	    *itemcount += 1;
122.  	    otmp = here ? otmp->nexthere : otmp->nobj;
123.  	}
124.  
125.  	return iletct;
126.  }
127.  

query_classes Edit

128.  /*
129.   * Suppose some '?' and '!' objects are present, but '/' objects aren't:
130.   *	"a" picks all items without further prompting;
131.   *	"A" steps through all items, asking one by one;
132.   *	"?" steps through '?' items, asking, and ignores '!' ones;
133.   *	"/" becomes 'A', since no '/' present;
134.   *	"?a" or "a?" picks all '?' without further prompting;
135.   *	"/a" or "a/" becomes 'A' since there aren't any '/'
136.   *	    (bug fix:  3.1.0 thru 3.1.3 treated it as "a");
137.   *	"?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
138.   *	    (ie, treated as if it had just been "?a").
139.   */
140.  #ifndef GOLDOBJ
141.  STATIC_OVL boolean
142.  query_classes(oclasses, one_at_a_time, everything, action, objs,
143.  	      here, incl_gold, menu_on_demand)
144.  char oclasses[];
145.  boolean *one_at_a_time, *everything;
146.  const char *action;
147.  struct obj *objs;
148.  boolean here, incl_gold;
149.  int *menu_on_demand;
150.  #else
151.  STATIC_OVL boolean
152.  query_classes(oclasses, one_at_a_time, everything, action, objs,
153.  	      here, menu_on_demand)
154.  char oclasses[];
155.  boolean *one_at_a_time, *everything;
156.  const char *action;
157.  struct obj *objs;
158.  boolean here;
159.  int *menu_on_demand;
160.  #endif
161.  {
162.  	char ilets[20], inbuf[BUFSZ];
163.  	int iletct, oclassct;
164.  	boolean not_everything;
165.  	char qbuf[QBUFSZ];
166.  	boolean m_seen;
167.  	int itemcount;
168.  
169.  	oclasses[oclassct = 0] = '\0';
170.  	*one_at_a_time = *everything = m_seen = FALSE;
171.  	iletct = collect_obj_classes(ilets, objs, here,
172.  #ifndef GOLDOBJ
173.  				     incl_gold,
174.  #endif
175.  				     (boolean FDECL((*),(OBJ_P))) 0, &itemcount);
176.  	if (iletct == 0) {
177.  		return FALSE;
178.  	} else if (iletct == 1) {
179.  		oclasses[0] = def_char_to_objclass(ilets[0]);
180.  		oclasses[1] = '\0';
181.  		if (itemcount && menu_on_demand) {
182.  			ilets[iletct++] = 'm';
183.  			*menu_on_demand = 0;
184.  			ilets[iletct] = '\0';
185.  		}
186.  	} else  {	/* more than one choice available */
187.  		const char *where = 0;
188.  		register char sym, oc_of_sym, *p;
189.  		/* additional choices */
190.  		ilets[iletct++] = ' ';
191.  		ilets[iletct++] = 'a';
192.  		ilets[iletct++] = 'A';
193.  		ilets[iletct++] = (objs == invent ? 'i' : ':');
194.  		if (menu_on_demand) {
195.  			ilets[iletct++] = 'm';
196.  			*menu_on_demand = 0;
197.  		}
198.  		ilets[iletct] = '\0';
199.  ask_again:
200.  		oclasses[oclassct = 0] = '\0';
201.  		*one_at_a_time = *everything = FALSE;
202.  		not_everything = FALSE;
203.  		Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
204.  			action, ilets);
205.  		getlin(qbuf,inbuf);
206.  		if (*inbuf == '\033') return FALSE;
207.  
208.  		for (p = inbuf; (sym = *p++); ) {
209.  		    /* new A function (selective all) added by GAN 01/09/87 */
210.  		    if (sym == ' ') continue;
211.  		    else if (sym == 'A') *one_at_a_time = TRUE;
212.  		    else if (sym == 'a') *everything = TRUE;
213.  		    else if (sym == ':') {
214.  			simple_look(objs, here);  /* dumb if objs==invent */
215.  			goto ask_again;
216.  		    } else if (sym == 'i') {
217.  			(void) display_inventory((char *)0, TRUE);
218.  			goto ask_again;
219.  		    } else if (sym == 'm') {
220.  			m_seen = TRUE;
221.  		    } else {
222.  			oc_of_sym = def_char_to_objclass(sym);
223.  			if (index(ilets,sym)) {
224.  			    add_valid_menu_class(oc_of_sym);
225.  			    oclasses[oclassct++] = oc_of_sym;
226.  			    oclasses[oclassct] = '\0';
227.  			} else {
228.  			    if (!where)
229.  				where = !strcmp(action,"pick up")  ? "here" :
230.  					!strcmp(action,"take out") ?
231.  							    "inside" : "";
232.  			    if (*where)
233.  				There("are no %c's %s.", sym, where);
234.  			    else
235.  				You("have no %c's.", sym);
236.  			    not_everything = TRUE;
237.  			}
238.  		    }
239.  		}
240.  		if (m_seen && menu_on_demand) {
241.  			*menu_on_demand = (*everything || !oclassct) ? -2 : -3;
242.  			return FALSE;
243.  		}
244.  		if (!oclassct && (!*everything || not_everything)) {
245.  		    /* didn't pick anything,
246.  		       or tried to pick something that's not present */
247.  		    *one_at_a_time = TRUE;	/* force 'A' */
248.  		    *everything = FALSE;	/* inhibit 'a' */
249.  		}
250.  	}
251.  	return TRUE;
252.  }
253.  

check_here Edit

254.  /* look at the objects at our location, unless there are too many of them */
255.  STATIC_OVL void
256.  check_here(picked_some)
257.  boolean picked_some;
258.  {
259.  	register struct obj *obj;
260.  	register int ct = 0;
261.  
262.  	/* count the objects here */
263.  	for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) {
264.  	    if (obj != uchain)
265.  		ct++;
266.  	}
267.  
268.  	/* If there are objects here, take a look. */
269.  	if (ct) {
270.  	    if (flags.run) nomul(0);
271.  	    flush_screen(1);
272.  	    (void) look_here(ct, picked_some);
273.  	} else {
274.  	    read_engr_at(u.ux,u.uy);
275.  	}
276.  }
277.  

n_or_more Edit

278.  /* Value set by query_objlist() for n_or_more(). */
279.  static long val_for_n_or_more;
280.  
281.  /* query_objlist callback: return TRUE if obj's count is >= reference value */
282.  STATIC_OVL boolean
283.  n_or_more(obj)
284.  struct obj *obj;
285.  {
286.      if (obj == uchain) return FALSE;
287.      return (obj->quan >= val_for_n_or_more);
288.  }
289.  

add_valid_menu_class Edit

290.  /* List of valid menu classes for query_objlist() and allow_category callback */
291.  static char valid_menu_classes[MAXOCLASSES + 2];
292.  
293.  void
294.  add_valid_menu_class(c)
295.  int c;
296.  {
297.  	static int vmc_count = 0;
298.  
299.  	if (c == 0)  /* reset */
300.  	  vmc_count = 0;
301.  	else
302.  	  valid_menu_classes[vmc_count++] = (char)c;
303.  	valid_menu_classes[vmc_count] = '\0';
304.  }
305.  

all_but_uchain Edit

306.  /* query_objlist callback: return TRUE if not uchain */
307.  STATIC_OVL boolean
308.  all_but_uchain(obj)
309.  struct obj *obj;
310.  {
311.      return (obj != uchain);
312.  }
313.  

allow_all Edit

314.  /* query_objlist callback: return TRUE */
315.  /*ARGSUSED*/
316.  boolean
317.  allow_all(obj)
318.  struct obj *obj;
319.  {
320.      return TRUE;
321.  }
322.  

allow_category Edit

323.  boolean
324.  allow_category(obj)
325.  struct obj *obj;
326.  {
327.      if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
328.      if (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
329.  	(index(valid_menu_classes, obj->oclass) != (char *)0))
330.  	return TRUE;
331.      else if (((index(valid_menu_classes,'U') != (char *)0) &&
332.  	(obj->oclass != COIN_CLASS && obj->bknown && !obj->blessed && !obj->cursed)))
333.  	return TRUE;
334.      else if (((index(valid_menu_classes,'B') != (char *)0) &&
335.  	(obj->oclass != COIN_CLASS && obj->bknown && obj->blessed)))
336.  	return TRUE;
337.      else if (((index(valid_menu_classes,'C') != (char *)0) &&
338.  	(obj->oclass != COIN_CLASS && obj->bknown && obj->cursed)))
339.  	return TRUE;
340.      else if (((index(valid_menu_classes,'X') != (char *)0) &&
341.  	(obj->oclass != COIN_CLASS && !obj->bknown)))
342.  	return TRUE;
343.      else
344.  	return FALSE;
345.  }
346.  

allow_cat_no_uchain Edit

347.  #if 0 /* not used */
348.  /* query_objlist callback: return TRUE if valid category (class), no uchain */
349.  STATIC_OVL boolean
350.  allow_cat_no_uchain(obj)
351.  struct obj *obj;
352.  {
353.      if ((obj != uchain) &&
354.  	(((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) ||
355.  	(index(valid_menu_classes, obj->oclass) != (char *)0)))
356.  	return TRUE;
357.      else
358.  	return FALSE;
359.  }
360.  #endif
361.  

is_worn_by_type Edit

362.  /* query_objlist callback: return TRUE if valid class and worn */
363.  boolean
364.  is_worn_by_type(otmp)
365.  register struct obj *otmp;
366.  {
367.  	return((boolean)(!!(otmp->owornmask &
368.  			(W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP | W_SWAPWEP | W_QUIVER)))
369.  	        && (index(valid_menu_classes, otmp->oclass) != (char *)0));
370.  }
371.  

pickup Edit

372.  /*
373.   * Have the hero pick things from the ground
374.   * or a monster's inventory if swallowed.
375.   *
376.   * Arg what:
377.   *	>0  autopickup
378.   *	=0  interactive
379.   *	<0  pickup count of something
380.   *
381.   * Returns 1 if tried to pick something up, whether
382.   * or not it succeeded.
383.   */
384.  int
385.  pickup(what)
386.  int what;		/* should be a long */
387.  {
388.  	int i, n, res, count, n_tried = 0, n_picked = 0;
389.  	menu_item *pick_list = (menu_item *) 0;
390.  	boolean autopickup = what > 0;
391.  	struct obj *objchain;
392.  	int traverse_how;
393.  
394.  	if (what < 0)		/* pick N of something */
395.  	    count = -what;
396.  	else			/* pick anything */
397.  	    count = 0;
398.  
399.  	if (!u.uswallow) {
400.  		struct trap *ttmp = t_at(u.ux, u.uy);
401.  		/* no auto-pick if no-pick move, nothing there, or in a pool */
402.  		if (autopickup && (flags.nopick || !OBJ_AT(u.ux, u.uy) ||
403.  			(is_pool(u.ux, u.uy) && !Underwater) || is_lava(u.ux, u.uy))) {
404.  			read_engr_at(u.ux, u.uy);
405.  			return (0);
406.  		}
407.  
408.  		/* no pickup if levitating & not on air or water level */
409.  		if (!can_reach_floor()) {
410.  		    if ((multi && !flags.run) || (autopickup && !flags.pickup))
411.  			read_engr_at(u.ux, u.uy);
412.  		    return (0);
413.  		}
414.  		if (ttmp && ttmp->tseen) {
415.  		    /* Allow pickup from holes and trap doors that you escaped
416.  		     * from because that stuff is teetering on the edge just
417.  		     * like you, but not pits, because there is an elevation
418.  		     * discrepancy with stuff in pits.
419.  		     */
420.  		    if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT) &&
421.  			(!u.utrap || (u.utrap && u.utraptype != TT_PIT))) {
422.  			read_engr_at(u.ux, u.uy);
423.  			return(0);
424.  		    }
425.  		}
426.  		/* multi && !flags.run means they are in the middle of some other
427.  		 * action, or possibly paralyzed, sleeping, etc.... and they just
428.  		 * teleported onto the object.  They shouldn't pick it up.
429.  		 */
430.  		if ((multi && !flags.run) || (autopickup && !flags.pickup)) {
431.  		    check_here(FALSE);
432.  		    return (0);
433.  		}
434.  		if (notake(youmonst.data)) {
435.  		    if (!autopickup)
436.  			You("are physically incapable of picking anything up.");
437.  		    else
438.  			check_here(FALSE);
439.  		    return (0);
440.  		}
441.  
442.  		/* if there's anything here, stop running */
443.  		if (OBJ_AT(u.ux,u.uy) && flags.run && flags.run != 8 && !flags.nopick) nomul(0);
444.  	}
445.  
446.  	add_valid_menu_class(0);	/* reset */
447.  	if (!u.uswallow) {
448.  		objchain = level.objects[u.ux][u.uy];
449.  		traverse_how = BY_NEXTHERE;
450.  	} else {
451.  		objchain = u.ustuck->minvent;
452.  		traverse_how = 0;	/* nobj */
453.  	}
454.  	/*
455.  	 * Start the actual pickup process.  This is split into two main
456.  	 * sections, the newer menu and the older "traditional" methods.
457.  	 * Automatic pickup has been split into its own menu-style routine
458.  	 * to make things less confusing.
459.  	 */
460.  	if (autopickup) {
461.  	    n = autopick(objchain, traverse_how, &pick_list);
462.  	    goto menu_pickup;
463.  	}
464.  
465.  	if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
466.  
467.  	    /* use menus exclusively */
468.  	    if (count) {	/* looking for N of something */
469.  		char buf[QBUFSZ];
470.  		Sprintf(buf, "Pick %d of what?", count);
471.  		val_for_n_or_more = count;	/* set up callback selector */
472.  		n = query_objlist(buf, objchain,
473.  			    traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT,
474.  			    &pick_list, PICK_ONE, n_or_more);
475.  		/* correct counts, if any given */
476.  		for (i = 0; i < n; i++)
477.  		    pick_list[i].count = count;
478.  	    } else {
479.  		n = query_objlist("Pick up what?", objchain,
480.  			traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT|FEEL_COCKATRICE,
481.  			&pick_list, PICK_ANY, all_but_uchain);
482.  	    }
483.  menu_pickup:
484.  	    n_tried = n;
485.  	    for (n_picked = i = 0 ; i < n; i++) {
486.  		res = pickup_object(pick_list[i].item.a_obj,pick_list[i].count,
487.  					FALSE);
488.  		if (res < 0) break;	/* can't continue */
489.  		n_picked += res;
490.  	    }
491.  	    if (pick_list) free((genericptr_t)pick_list);
492.  
493.  	} else {
494.  	    /* old style interface */
495.  	    int ct = 0;
496.  	    long lcount;
497.  	    boolean all_of_a_type, selective;
498.  	    char oclasses[MAXOCLASSES];
499.  	    struct obj *obj, *obj2;
500.  
501.  	    oclasses[0] = '\0';		/* types to consider (empty for all) */
502.  	    all_of_a_type = TRUE;	/* take all of considered types */
503.  	    selective = FALSE;		/* ask for each item */
504.  
505.  	    /* check for more than one object */
506.  	    for (obj = objchain;
507.  		  obj; obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj)
508.  		ct++;
509.  
510.  	    if (ct == 1 && count) {
511.  		/* if only one thing, then pick it */
512.  		obj = objchain;
513.  		lcount = min(obj->quan, (long)count);
514.  		n_tried++;
515.  		if (pickup_object(obj, lcount, FALSE) > 0)
516.  		    n_picked++;	/* picked something */
517.  		goto end_query;
518.  
519.  	    } else if (ct >= 2) {
520.  		int via_menu = 0;
521.  
522.  		There("are %s objects here.",
523.  		      (ct <= 10) ? "several" : "many");
524.  		if (!query_classes(oclasses, &selective, &all_of_a_type,
525.  				   "pick up", objchain,
526.  				   traverse_how == BY_NEXTHERE,
527.  #ifndef GOLDOBJ
528.  				   FALSE,
529.  #endif
530.  				   &via_menu)) {
531.  		    if (!via_menu) return (0);
532.  		    n = query_objlist("Pick up what?",
533.  				  objchain,
534.  				  traverse_how|(selective ? 0 : INVORDER_SORT),
535.  				  &pick_list, PICK_ANY,
536.  				  via_menu == -2 ? allow_all : allow_category);
537.  		    goto menu_pickup;
538.  		}
539.  	    }
540.  
541.  	    for (obj = objchain; obj; obj = obj2) {
542.  		if (traverse_how == BY_NEXTHERE)
543.  			obj2 = obj->nexthere;	/* perhaps obj will be picked up */
544.  		else
545.  			obj2 = obj->nobj;
546.  		lcount = -1L;
547.  
548.  		if (!selective && oclasses[0] && !index(oclasses,obj->oclass))
549.  		    continue;
550.  
551.  		if (!all_of_a_type) {
552.  		    char qbuf[BUFSZ];
553.  		    Sprintf(qbuf, "Pick up %s?",
554.  			safe_qbuf("", sizeof("Pick up ?"), doname(obj),
555.  					an(simple_typename(obj->otyp)), "something"));
556.  		    switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
557.  		    case 'q': goto end_query;	/* out 2 levels */
558.  		    case 'n': continue;
559.  		    case 'a':
560.  			all_of_a_type = TRUE;
561.  			if (selective) {
562.  			    selective = FALSE;
563.  			    oclasses[0] = obj->oclass;
564.  			    oclasses[1] = '\0';
565.  			}
566.  			break;
567.  		    case '#':	/* count was entered */
568.  			if (!yn_number) continue; /* 0 count => No */
569.  			lcount = (long) yn_number;
570.  			if (lcount > obj->quan) lcount = obj->quan;
571.  			/* fall thru */
572.  		    default:	/* 'y' */
573.  			break;
574.  		    }
575.  		}
576.  		if (lcount == -1L) lcount = obj->quan;
577.  
578.  		n_tried++;
579.  		if ((res = pickup_object(obj, lcount, FALSE)) < 0) break;
580.  		n_picked += res;
581.  	    }
582.  end_query:
583.  	    ;	/* semicolon needed by brain-damaged compilers */
584.  	}
585.  
586.  	if (!u.uswallow) {
587.  		if (!OBJ_AT(u.ux,u.uy)) u.uundetected = 0;
588.  
589.  		/* position may need updating (invisible hero) */
590.  		if (n_picked) newsym(u.ux,u.uy);
591.  
592.  		/* see whether there's anything else here, after auto-pickup is done */
593.  		if (autopickup) check_here(n_picked > 0);
594.  	}
595.  	return (n_tried > 0);
596.  }
597.  

is_autopickup_exception Edit

598.  #ifdef AUTOPICKUP_EXCEPTIONS
599.  boolean
600.  is_autopickup_exception(obj, grab)
601.  struct obj *obj;
602.  boolean grab;	 /* forced pickup, rather than forced leave behind? */
603.  {
604.  	/*
605.  	 *  Does the text description of this match an exception?
606.  	 */
607.  	char *objdesc = makesingular(doname(obj));
608.  	struct autopickup_exception *ape = (grab) ?
609.  					iflags.autopickup_exceptions[AP_GRAB] :
610.  					iflags.autopickup_exceptions[AP_LEAVE];
611.  	while (ape) {
612.  		if (pmatch(ape->pattern, objdesc)) return TRUE;
613.  		ape = ape->next;
614.  	}
615.  	return FALSE;
616.  }
617.  #endif /* AUTOPICKUP_EXCEPTIONS */
618.  

autopick Edit

619.  /*
620.   * Pick from the given list using flags.pickup_types.  Return the number
621.   * of items picked (not counts).  Create an array that returns pointers
622.   * and counts of the items to be picked up.  If the number of items
623.   * picked is zero, the pickup list is left alone.  The caller of this
624.   * function must free the pickup list.
625.   */
626.  STATIC_OVL int
627.  autopick(olist, follow, pick_list)
628.  struct obj *olist;	/* the object list */
629.  int follow;		/* how to follow the object list */
630.  menu_item **pick_list;	/* list of objects and counts to pick up */
631.  {
632.  	menu_item *pi;	/* pick item */
633.  	struct obj *curr;
634.  	int n;
635.  	const char *otypes = flags.pickup_types;
636.  
637.  	/* first count the number of eligible items */
638.  	for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
639.  
640.  
641.  #ifndef AUTOPICKUP_EXCEPTIONS
642.  	    if (!*otypes || index(otypes, curr->oclass))
643.  #else
644.  	    if ((!*otypes || index(otypes, curr->oclass) ||
645.  		 is_autopickup_exception(curr, TRUE)) &&
646.  	    	 !is_autopickup_exception(curr, FALSE))
647.  #endif
648.  		n++;
649.  
650.  	if (n) {
651.  	    *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n);
652.  	    for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
653.  #ifndef AUTOPICKUP_EXCEPTIONS
654.  		if (!*otypes || index(otypes, curr->oclass)) {
655.  #else
656.  	    if ((!*otypes || index(otypes, curr->oclass) ||
657.  		 is_autopickup_exception(curr, TRUE)) &&
658.  	    	 !is_autopickup_exception(curr, FALSE)) {
659.  #endif
660.  		    pi[n].item.a_obj = curr;
661.  		    pi[n].count = curr->quan;
662.  		    n++;
663.  		}
664.  	}
665.  	return n;
666.  }
667.  
668.  

query_objlist Edit

669.  /*
670.   * Put up a menu using the given object list.  Only those objects on the
671.   * list that meet the approval of the allow function are displayed.  Return
672.   * a count of the number of items selected, as well as an allocated array of
673.   * menu_items, containing pointers to the objects selected and counts.  The
674.   * returned counts are guaranteed to be in bounds and non-zero.
675.   *
676.   * Query flags:
677.   *	BY_NEXTHERE	  - Follow object list via nexthere instead of nobj.
678.   *	AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
679.   *			    use it.
680.   *	USE_INVLET	  - Use object's invlet.
681.   *	INVORDER_SORT	  - Use hero's pack order.
682.   *	SIGNAL_NOMENU	  - Return -1 rather than 0 if nothing passes "allow".
683.   */
684.  int
685.  query_objlist(qstr, olist, qflags, pick_list, how, allow)
686.  const char *qstr;		/* query string */
687.  struct obj *olist;		/* the list to pick from */
688.  int qflags;			/* options to control the query */
689.  menu_item **pick_list;		/* return list of items picked */
690.  int how;			/* type of query */
691.  boolean FDECL((*allow), (OBJ_P));/* allow function */
692.  {
693.  	int n;
694.  	winid win;
695.  	struct obj *curr, *last;
696.  	char *pack;
697.  	anything any;
698.  	boolean printed_type_name;
699.  
700.  	*pick_list = (menu_item *) 0;
701.  	if (!olist) return 0;
702.  
703.  	/* count the number of items allowed */
704.  	for (n = 0, last = 0, curr = olist; curr; curr = FOLLOW(curr, qflags))
705.  	    if ((*allow)(curr)) {
706.  		last = curr;
707.  		n++;
708.  	    }
709.  
710.  	if (n == 0)	/* nothing to pick here */
711.  	    return (qflags & SIGNAL_NOMENU) ? -1 : 0;
712.  
713.  	if (n == 1 && (qflags & AUTOSELECT_SINGLE)) {
714.  	    *pick_list = (menu_item *) alloc(sizeof(menu_item));
715.  	    (*pick_list)->item.a_obj = last;
716.  	    (*pick_list)->count = last->quan;
717.  	    return 1;
718.  	}
719.  
720.  	win = create_nhwindow(NHW_MENU);
721.  	start_menu(win);
722.  	any.a_obj = (struct obj *) 0;
723.  
724.  	/*
725.  	 * Run through the list and add the objects to the menu.  If
726.  	 * INVORDER_SORT is set, we'll run through the list once for
727.  	 * each type so we can group them.  The allow function will only
728.  	 * be called once per object in the list.
729.  	 */
730.  	pack = flags.inv_order;
731.  	do {
732.  	    printed_type_name = FALSE;
733.  	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
734.  		if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE &&
735.  		     will_feel_cockatrice(curr, FALSE)) {
736.  			destroy_nhwindow(win);	/* stop the menu and revert */
737.  			(void) look_here(0, FALSE);
738.  			return 0;
739.  		}
740.  		if ((!(qflags & INVORDER_SORT) || curr->oclass == *pack)
741.  							&& (*allow)(curr)) {
742.  
743.  		    /* if sorting, print type name (once only) */
744.  		    if (qflags & INVORDER_SORT && !printed_type_name) {
745.  			any.a_obj = (struct obj *) 0;
746.  			add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
747.  					let_to_name(*pack, FALSE), MENU_UNSELECTED);
748.  			printed_type_name = TRUE;
749.  		    }
750.  
751.  		    any.a_obj = curr;
752.  		    add_menu(win, obj_to_glyph(curr), &any,
753.  			    qflags & USE_INVLET ? curr->invlet : 0,
754.  			    def_oc_syms[(int)objects[curr->otyp].oc_class],
755.  			    ATR_NONE, doname(curr), MENU_UNSELECTED);
756.  		}
757.  	    }
758.  	    pack++;
759.  	} while (qflags & INVORDER_SORT && *pack);
760.  
761.  	end_menu(win, qstr);
762.  	n = select_menu(win, how, pick_list);
763.  	destroy_nhwindow(win);
764.  
765.  	if (n > 0) {
766.  	    menu_item *mi;
767.  	    int i;
768.  
769.  	    /* fix up counts:  -1 means no count used => pick all */
770.  	    for (i = 0, mi = *pick_list; i < n; i++, mi++)
771.  		if (mi->count == -1L || mi->count > mi->item.a_obj->quan)
772.  		    mi->count = mi->item.a_obj->quan;
773.  	} else if (n < 0) {
774.  	    n = 0;	/* caller's don't expect -1 */
775.  	}
776.  	return n;
777.  }
778.  

query_category Edit

779.  /*
780.   * allow menu-based category (class) selection (for Drop,take off etc.)
781.   *
782.   */
783.  int
784.  query_category(qstr, olist, qflags, pick_list, how)
785.  const char *qstr;		/* query string */
786.  struct obj *olist;		/* the list to pick from */
787.  int qflags;			/* behaviour modification flags */
788.  menu_item **pick_list;		/* return list of items picked */
789.  int how;			/* type of query */
790.  {
791.  	int n;
792.  	winid win;
793.  	struct obj *curr;
794.  	char *pack;
795.  	anything any;
796.  	boolean collected_type_name;
797.  	char invlet;
798.  	int ccount;
799.  	boolean do_unpaid = FALSE;
800.  	boolean do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE,
801.  	    do_buc_unknown = FALSE;
802.  	int num_buc_types = 0;
803.  
804.  	*pick_list = (menu_item *) 0;
805.  	if (!olist) return 0;
806.  	if ((qflags & UNPAID_TYPES) && count_unpaid(olist)) do_unpaid = TRUE;
807.  	if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED)) {
808.  	    do_blessed = TRUE;
809.  	    num_buc_types++;
810.  	}
811.  	if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) {
812.  	    do_cursed = TRUE;
813.  	    num_buc_types++;
814.  	}
815.  	if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) {
816.  	    do_uncursed = TRUE;
817.  	    num_buc_types++;
818.  	}
819.  	if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) {
820.  	    do_buc_unknown = TRUE;
821.  	    num_buc_types++;
822.  	}
823.  
824.  	ccount = count_categories(olist, qflags);
825.  	/* no point in actually showing a menu for a single category */
826.  	if (ccount == 1 && !do_unpaid && num_buc_types <= 1 && !(qflags & BILLED_TYPES)) {
827.  	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
828.  		if ((qflags & WORN_TYPES) &&
829.  		    !(curr->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL|W_WEP|W_SWAPWEP|W_QUIVER)))
830.  		    continue;
831.  		break;
832.  	    }
833.  	    if (curr) {
834.  		*pick_list = (menu_item *) alloc(sizeof(menu_item));
835.  		(*pick_list)->item.a_int = curr->oclass;
836.  		return 1;
837.  	    } else {
838.  #ifdef DEBUG
839.  		impossible("query_category: no single object match");
840.  #endif
841.  	    }
842.  	    return 0;
843.  	}
844.  
845.  	win = create_nhwindow(NHW_MENU);
846.  	start_menu(win);
847.  	pack = flags.inv_order;
848.  	if ((qflags & ALL_TYPES) && (ccount > 1)) {
849.  		invlet = 'a';
850.  		any.a_void = 0;
851.  		any.a_int = ALL_TYPES_SELECTED;
852.  		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
853.  		       (qflags & WORN_TYPES) ? "All worn types" : "All types",
854.  			MENU_UNSELECTED);
855.  		invlet = 'b';
856.  	} else
857.  		invlet = 'a';
858.  	do {
859.  	    collected_type_name = FALSE;
860.  	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
861.  		if (curr->oclass == *pack) {
862.  		   if ((qflags & WORN_TYPES) &&
863.  		   		!(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
864.  		    	W_WEP | W_SWAPWEP | W_QUIVER)))
865.  			 continue;
866.  		   if (!collected_type_name) {
867.  			any.a_void = 0;
868.  			any.a_int = curr->oclass;
869.  			add_menu(win, NO_GLYPH, &any, invlet++,
870.  				def_oc_syms[(int)objects[curr->otyp].oc_class],
871.  				ATR_NONE, let_to_name(*pack, FALSE),
872.  				MENU_UNSELECTED);
873.  			collected_type_name = TRUE;
874.  		   }
875.  		}
876.  	    }
877.  	    pack++;
878.  	    if (invlet >= 'u') {
879.  		impossible("query_category: too many categories");
880.  		return 0;
881.  	    }
882.  	} while (*pack);
883.  	/* unpaid items if there are any */
884.  	if (do_unpaid) {
885.  		invlet = 'u';
886.  		any.a_void = 0;
887.  		any.a_int = 'u';
888.  		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
889.  			"Unpaid items", MENU_UNSELECTED);
890.  	}
891.  	/* billed items: checked by caller, so always include if BILLED_TYPES */
892.  	if (qflags & BILLED_TYPES) {
893.  		invlet = 'x';
894.  		any.a_void = 0;
895.  		any.a_int = 'x';
896.  		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
897.  			 "Unpaid items already used up", MENU_UNSELECTED);
898.  	}
899.  	if (qflags & CHOOSE_ALL) {
900.  		invlet = 'A';
901.  		any.a_void = 0;
902.  		any.a_int = 'A';
903.  		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
904.  			(qflags & WORN_TYPES) ?
905.  			"Auto-select every item being worn" :
906.  			"Auto-select every item", MENU_UNSELECTED);
907.  	}
908.  	/* items with b/u/c/unknown if there are any */
909.  	if (do_blessed) {
910.  		invlet = 'B';
911.  		any.a_void = 0;
912.  		any.a_int = 'B';
913.  		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
914.  			"Items known to be Blessed", MENU_UNSELECTED);
915.  	}
916.  	if (do_cursed) {
917.  		invlet = 'C';
918.  		any.a_void = 0;
919.  		any.a_int = 'C';
920.  		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
921.  			"Items known to be Cursed", MENU_UNSELECTED);
922.  	}
923.  	if (do_uncursed) {
924.  		invlet = 'U';
925.  		any.a_void = 0;
926.  		any.a_int = 'U';
927.  		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
928.  			"Items known to be Uncursed", MENU_UNSELECTED);
929.  	}
930.  	if (do_buc_unknown) {
931.  		invlet = 'X';
932.  		any.a_void = 0;
933.  		any.a_int = 'X';
934.  		add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE,
935.  			"Items of unknown B/C/U status",
936.  			MENU_UNSELECTED);
937.  	}
938.  	end_menu(win, qstr);
939.  	n = select_menu(win, how, pick_list);
940.  	destroy_nhwindow(win);
941.  	if (n < 0)
942.  	    n = 0;	/* caller's don't expect -1 */
943.  	return n;
944.  }
945.  

count_categories Edit

946.  STATIC_OVL int
947.  count_categories(olist, qflags)
948.  struct obj *olist;
949.  int qflags;
950.  {
951.  	char *pack;
952.  	boolean counted_category;
953.  	int ccount = 0;
954.  	struct obj *curr;
955.  
956.  	pack = flags.inv_order;
957.  	do {
958.  	    counted_category = FALSE;
959.  	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
960.  		if (curr->oclass == *pack) {
961.  		   if ((qflags & WORN_TYPES) &&
962.  		    	!(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
963.  		    	W_WEP | W_SWAPWEP | W_QUIVER)))
964.  			 continue;
965.  		   if (!counted_category) {
966.  			ccount++;
967.  			counted_category = TRUE;
968.  		   }
969.  		}
970.  	    }
971.  	    pack++;
972.  	} while (*pack);
973.  	return ccount;
974.  }
975.  

carry_count Edit

976.  /* could we carry `obj'? if not, could we carry some of it/them? */
977.  STATIC_OVL long
978.  carry_count(obj, container, count, telekinesis, wt_before, wt_after)
979.  struct obj *obj, *container;	/* object to pick up, bag it's coming out of */
980.  long count;
981.  boolean telekinesis;
982.  int *wt_before, *wt_after;
983.  {
984.      boolean adjust_wt = container && carried(container),
985.  	    is_gold = obj->oclass == COIN_CLASS;
986.      int wt, iw, ow, oow;
987.      long qq, savequan;
988.  #ifdef GOLDOBJ
989.      long umoney = money_cnt(invent);
990.  #endif
991.      unsigned saveowt;
992.      const char *verb, *prefx1, *prefx2, *suffx;
993.      char obj_nambuf[BUFSZ], where[BUFSZ];
994.  
995.      savequan = obj->quan;
996.      saveowt = obj->owt;
997.  
998.      iw = max_capacity();
999.  
1000.     if (count != savequan) {
1001. 	obj->quan = count;
1002. 	obj->owt = (unsigned)weight(obj);
1003.     }
1004.     wt = iw + (int)obj->owt;
1005.     if (adjust_wt)
1006. 	wt -= (container->otyp == BAG_OF_HOLDING) ?
1007. 		(int)DELTA_CWT(container, obj) : (int)obj->owt;
1008. #ifndef GOLDOBJ
1009.     if (is_gold)	/* merged gold might affect cumulative weight */
1010. 	wt -= (GOLD_WT(u.ugold) + GOLD_WT(count) - GOLD_WT(u.ugold + count));
1011. #else
1012.     /* This will go with silver+copper & new gold weight */
1013.     if (is_gold)	/* merged gold might affect cumulative weight */
1014. 	wt -= (GOLD_WT(umoney) + GOLD_WT(count) - GOLD_WT(umoney + count));
1015. #endif
1016.     if (count != savequan) {
1017. 	obj->quan = savequan;
1018. 	obj->owt = saveowt;
1019.     }
1020.     *wt_before = iw;
1021.     *wt_after  = wt;
1022. 
1023.     if (wt < 0)
1024. 	return count;
1025. 
1026.     /* see how many we can lift */
1027.     if (is_gold) {
1028. #ifndef GOLDOBJ
1029. 	iw -= (int)GOLD_WT(u.ugold);
1030. 	if (!adjust_wt) {
1031. 	    qq = GOLD_CAPACITY((long)iw, u.ugold);
1032. 	} else {
1033. 	    oow = 0;
1034. 	    qq = 50L - (u.ugold % 100L) - 1L;
1035. #else
1036. 	iw -= (int)GOLD_WT(umoney);
1037. 	if (!adjust_wt) {
1038. 	    qq = GOLD_CAPACITY((long)iw, umoney);
1039. 	} else {
1040. 	    oow = 0;
1041. 	    qq = 50L - (umoney % 100L) - 1L;
1042. #endif
1043. 	    if (qq < 0L) qq += 100L;
1044. 	    for ( ; qq <= count; qq += 100L) {
1045. 		obj->quan = qq;
1046. 		obj->owt = (unsigned)GOLD_WT(qq);
1047. #ifndef GOLDOBJ
1048. 		ow = (int)GOLD_WT(u.ugold + qq);
1049. #else
1050. 		ow = (int)GOLD_WT(umoney + qq);
1051. #endif
1052. 		ow -= (container->otyp == BAG_OF_HOLDING) ?
1053. 			(int)DELTA_CWT(container, obj) : (int)obj->owt;
1054. 		if (iw + ow >= 0) break;
1055. 		oow = ow;
1056. 	    }
1057. 	    iw -= oow;
1058. 	    qq -= 100L;
1059. 	}
1060. 	if (qq < 0L) qq = 0L;
1061. 	else if (qq > count) qq = count;
1062. #ifndef GOLDOBJ
1063. 	wt = iw + (int)GOLD_WT(u.ugold + qq);
1064. #else
1065. 	wt = iw + (int)GOLD_WT(umoney + qq);
1066. #endif
1067.     } else if (count > 1 || count < obj->quan) {
1068. 	/*
1069. 	 * Ugh. Calc num to lift by changing the quan of of the
1070. 	 * object and calling weight.
1071. 	 *
1072. 	 * This works for containers only because containers
1073. 	 * don't merge.		-dean
1074. 	 */
1075. 	for (qq = 1L; qq <= count; qq++) {
1076. 	    obj->quan = qq;
1077. 	    obj->owt = (unsigned)(ow = weight(obj));
1078. 	    if (adjust_wt)
1079. 		ow -= (container->otyp == BAG_OF_HOLDING) ?
1080. 			(int)DELTA_CWT(container, obj) : (int)obj->owt;
1081. 	    if (iw + ow >= 0)
1082. 		break;
1083. 	    wt = iw + ow;
1084. 	}
1085. 	--qq;
1086.     } else {
1087. 	/* there's only one, and we can't lift it */
1088. 	qq = 0L;
1089.     }
1090.     obj->quan = savequan;
1091.     obj->owt = saveowt;
1092. 
1093.     if (qq < count) {
1094. 	/* some message will be given */
1095. 	Strcpy(obj_nambuf, doname(obj));
1096. 	if (container) {
1097. 	    Sprintf(where, "in %s", the(xname(container)));
1098. 	    verb = "carry";
1099. 	} else {
1100. 	    Strcpy(where, "lying here");
1101. 	    verb = telekinesis ? "acquire" : "lift";
1102. 	}
1103.     } else {
1104. 	/* lint supppression */
1105. 	*obj_nambuf = *where = '\0';
1106. 	verb = "";
1107.     }
1108.     /* we can carry qq of them */
1109.     if (qq > 0) {
1110. 	if (qq < count)
1111. 	    You("can only %s %s of the %s %s.",
1112. 		verb, (qq == 1L) ? "one" : "some", obj_nambuf, where);
1113. 	*wt_after = wt;
1114. 	return qq;
1115.     }
1116. 
1117.     if (!container) Strcpy(where, "here");  /* slightly shorter form */
1118. #ifndef GOLDOBJ
1119.     if (invent || u.ugold) {
1120. #else
1121.     if (invent || umoney) {
1122. #endif
1123. 	prefx1 = "you cannot ";
1124. 	prefx2 = "";
1125. 	suffx  = " any more";
1126.     } else {
1127. 	prefx1 = (obj->quan == 1L) ? "it " : "even one ";
1128. 	prefx2 = "is too heavy for you to ";
1129. 	suffx  = "";
1130.     }
1131.     There("%s %s %s, but %s%s%s%s.",
1132. 	  otense(obj, "are"), obj_nambuf, where,
1133. 	  prefx1, prefx2, verb, suffx);
1134. 
1135.  /* *wt_after = iw; */
1136.     return 0L;
1137. }
1138. 

lift_object Edit

1139. /* determine whether character is able and player is willing to carry `obj' */
1140. STATIC_OVL
1141. int 
1142. lift_object(obj, container, cnt_p, telekinesis)
1143. struct obj *obj, *container;	/* object to pick up, bag it's coming out of */
1144. long *cnt_p;
1145. boolean telekinesis;
1146. {
1147.     int result, old_wt, new_wt, prev_encumbr, next_encumbr;
1148. 
1149.     if (obj->otyp == BOULDER && In_sokoban(&u.uz)) {
1150. 	You("cannot get your %s around this %s.",
1151. 			body_part(HAND), xname(obj));
1152. 	return -1;
1153.     }
1154.     if (obj->otyp == LOADSTONE ||
1155. 	    (obj->otyp == BOULDER && throws_rocks(youmonst.data)))
1156. 	return 1;		/* lift regardless of current situation */
1157. 
1158.     *cnt_p = carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt);
1159.     if (*cnt_p < 1L) {
1160. 	result = -1;	/* nothing lifted */
1161. #ifndef GOLDOBJ
1162.     } else if (obj->oclass != COIN_CLASS && inv_cnt() >= 52 &&
1163. 		!merge_choice(invent, obj)) {
1164. #else
1165.     } else if (inv_cnt() >= 52 && !merge_choice(invent, obj)) {
1166. #endif
1167. 	Your("knapsack cannot accommodate any more items.");
1168. 	result = -1;	/* nothing lifted */
1169.     } else {
1170. 	result = 1;
1171. 	prev_encumbr = near_capacity();
1172. 	if (prev_encumbr < flags.pickup_burden)
1173. 		prev_encumbr = flags.pickup_burden;
1174. 	next_encumbr = calc_capacity(new_wt - old_wt);
1175. 	if (next_encumbr > prev_encumbr) {
1176. 	    if (telekinesis) {
1177. 		result = 0;	/* don't lift */
1178. 	    } else {
1179. 		char qbuf[BUFSZ];
1180. 		long savequan = obj->quan;
1181. 
1182. 		obj->quan = *cnt_p;
1183. 		Strcpy(qbuf,
1184. 			(next_encumbr > HVY_ENCUMBER) ? overloadmsg :
1185. 			(next_encumbr > MOD_ENCUMBER) ? nearloadmsg :
1186. 			moderateloadmsg);
1187. 		Sprintf(eos(qbuf), " %s. Continue?",
1188. 			safe_qbuf(qbuf, sizeof(" . Continue?"),
1189. 				doname(obj), an(simple_typename(obj->otyp)), "something"));
1190. 		obj->quan = savequan;
1191. 		switch (ynq(qbuf)) {
1192. 		case 'q':  result = -1; break;
1193. 		case 'n':  result =  0; break;
1194. 		default:   break;	/* 'y' => result == 1 */
1195. 		}
1196. 		clear_nhwindow(WIN_MESSAGE);
1197. 	    }
1198. 	}
1199.     }
1200. 
1201.     if (obj->otyp == SCR_SCARE_MONSTER && result <= 0 && !container)
1202. 	obj->spe = 0;
1203.     return result;
1204. }
1205. 

safe_qbuf Edit

1206. /* To prevent qbuf overflow in prompts use planA only
1207.  * if it fits, or planB if PlanA doesn't fit,
1208.  * finally using the fallback as a last resort.
1209.  * last_restort is expected to be very short.
1210.  */
1211. const char *
1212. safe_qbuf(qbuf, padlength, planA, planB, last_resort)
1213. const char *qbuf, *planA, *planB, *last_resort;
1214. unsigned padlength;
1215. {
1216. 	/* convert size_t (or int for ancient systems) to ordinary unsigned */
1217. 	unsigned len_qbuf = (unsigned)strlen(qbuf),
1218. 	         len_planA = (unsigned)strlen(planA),
1219. 	         len_planB = (unsigned)strlen(planB),
1220. 	         len_lastR = (unsigned)strlen(last_resort);
1221. 	unsigned textleft = QBUFSZ - (len_qbuf + padlength);
1222. 
1223. 	if (len_lastR >= textleft) {
1224. 	    impossible("safe_qbuf: last_resort too large at %u characters.",
1225. 		       len_lastR);
1226. 	    return "";
1227. 	}
1228. 	return (len_planA < textleft) ? planA :
1229. 		    (len_planB < textleft) ? planB : last_resort;
1230. }
1231. 

pickup_object Edit

1232. /*
1233.  * Pick up <count> of obj from the ground and add it to the hero's inventory.
1234.  * Returns -1 if caller should break out of its loop, 0 if nothing picked
1235.  * up, 1 if otherwise.
1236.  */
1237. int
1238. pickup_object(obj, count, telekinesis)
1239. struct obj *obj;
1240. long count;
1241. boolean telekinesis;	/* not picking it up directly by hand */
1242. {
1243. 	int res, nearload;
1244. #ifndef GOLDOBJ
1245. 	const char *where = (obj->ox == u.ux && obj->oy == u.uy) ?
1246. 			    "here" : "there";
1247. #endif
1248. 
1249. 	if (obj->quan < count) {
1250. 	    impossible("pickup_object: count %ld > quan %ld?",
1251. 		count, obj->quan);
1252. 	    return 0;
1253. 	}
1254. 
1255. 	/* In case of auto-pickup, where we haven't had a chance
1256. 	   to look at it yet; affects docall(SCR_SCARE_MONSTER). */
1257. 	if (!Blind)
1258. #ifdef INVISIBLE_OBJECTS
1259. 		if (!obj->oinvis || See_invisible)
1260. #endif
1261. 		obj->dknown = 1;
1262. 
1263. 	if (obj == uchain) {    /* do not pick up attached chain */
1264. 	    return 0;
1265. 	} else if (obj->oartifact && !touch_artifact(obj,&youmonst)) {
1266. 	    return 0;
1267. #ifndef GOLDOBJ
1268. 	} else if (obj->oclass == COIN_CLASS) {
1269. 	    /* Special consideration for gold pieces... */
1270. 	    long iw = (long)max_capacity() - GOLD_WT(u.ugold);
1271. 	    long gold_capacity = GOLD_CAPACITY(iw, u.ugold);
1272. 
1273. 	    if (gold_capacity <= 0L) {
1274. 		pline(
1275. 	       "There %s %ld gold piece%s %s, but you cannot carry any more.",
1276. 		      otense(obj, "are"),
1277. 		      obj->quan, plur(obj->quan), where);
1278. 		return 0;
1279. 	    } else if (gold_capacity < count) {
1280. 		You("can only %s %s of the %ld gold pieces lying %s.",
1281. 		    telekinesis ? "acquire" : "carry",
1282. 		    gold_capacity == 1L ? "one" : "some", obj->quan, where);
1283. 		pline("%s %ld gold piece%s.",
1284. 		    nearloadmsg, gold_capacity, plur(gold_capacity));
1285. 		u.ugold += gold_capacity;
1286. 		obj->quan -= gold_capacity;
1287. 		costly_gold(obj->ox, obj->oy, gold_capacity);
1288. 	    } else {
1289. 		u.ugold += count;
1290. 		if ((nearload = near_capacity()) != 0)
1291. 		    pline("%s %ld gold piece%s.",
1292. 			  nearload < MOD_ENCUMBER ?
1293. 			  moderateloadmsg : nearloadmsg,
1294. 			  count, plur(count));
1295. 		else
1296. 		    prinv((char *) 0, obj, count);
1297. 		costly_gold(obj->ox, obj->oy, count);
1298. 		if (count == obj->quan)
1299. 		    delobj(obj);
1300. 		else
1301. 		    obj->quan -= count;
1302. 	    }
1303. 	    flags.botl = 1;
1304. 	    if (flags.run) nomul(0);
1305. 	    return 1;
1306. #endif
1307. 	} else if (obj->otyp == CORPSE) {
1308. 	    if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
1309. 				&& !Stone_resistance && !telekinesis) {
1310. 		if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1311. 		    display_nhwindow(WIN_MESSAGE, FALSE);
1312. 		else {
1313. 			char kbuf[BUFSZ];
1314. 
1315. 			Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1316. 			pline("Touching %s is a fatal mistake.", kbuf);
1317. 			instapetrify(kbuf);
1318. 		    return -1;
1319. 		}
1320. 	    } else if (is_rider(&mons[obj->corpsenm])) {
1321. 		pline("At your %s, the corpse suddenly moves...",
1322. 			telekinesis ? "attempted acquisition" : "touch");
1323. 		(void) revive_corpse(obj);
1324. 		exercise(A_WIS, FALSE);
1325. 		return -1;
1326. 	    }
1327. 	} else  if (obj->otyp == SCR_SCARE_MONSTER) {
1328. 	    if (obj->blessed) obj->blessed = 0;
1329. 	    else if (!obj->spe && !obj->cursed) obj->spe = 1;
1330. 	    else {
1331. 		pline_The("scroll%s %s to dust as you %s %s up.",
1332. 			plur(obj->quan), otense(obj, "turn"),
1333. 			telekinesis ? "raise" : "pick",
1334. 			(obj->quan == 1L) ? "it" : "them");
1335. 		if (!(objects[SCR_SCARE_MONSTER].oc_name_known) &&
1336. 				    !(objects[SCR_SCARE_MONSTER].oc_uname))
1337. 		    docall(obj);
1338. 		useupf(obj, obj->quan);
1339. 		return 1;	/* tried to pick something up and failed, but
1340. 				   don't want to terminate pickup loop yet   */
1341. 	    }
1342. 	}
1343. 
1344. 	if ((res = lift_object(obj, (struct obj *)0, &count, telekinesis)) <= 0)
1345. 	    return res;
1346. 
1347. #ifdef GOLDOBJ
1348.         /* Whats left of the special case for gold :-) */
1349. 	if (obj->oclass == COIN_CLASS) flags.botl = 1;
1350. #endif
1351. 	if (obj->quan != count && obj->otyp != LOADSTONE)
1352. 	    obj = splitobj(obj, count);
1353. 
1354. 	obj = pick_obj(obj);
1355. 
1356. 	if (uwep && uwep == obj) mrg_to_wielded = TRUE;
1357. 	nearload = near_capacity();
1358. 	prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0,
1359. 	      obj, count);
1360. 	mrg_to_wielded = FALSE;
1361. 	return 1;
1362. }
1363. 

pick_obj Edit

1364. /*
1365.  * Do the actual work of picking otmp from the floor or monster's interior
1366.  * and putting it in the hero's inventory.  Take care of billing.  Return a
1367.  * pointer to the object where otmp ends up.  This may be different
1368.  * from otmp because of merging.
1369.  *
1370.  * Gold never reaches this routine unless GOLDOBJ is defined.
1371.  */
1372. struct obj *
1373. pick_obj(otmp)
1374. struct obj *otmp;
1375. {
1376. 	obj_extract_self(otmp);
1377. 	if (!u.uswallow && otmp != uball && costly_spot(otmp->ox, otmp->oy)) {
1378. 	    char saveushops[5], fakeshop[2];
1379. 
1380. 	    /* addtobill cares about your location rather than the object's;
1381. 	       usually they'll be the same, but not when using telekinesis
1382. 	       (if ever implemented) or a grappling hook */
1383. 	    Strcpy(saveushops, u.ushops);
1384. 	    fakeshop[0] = *in_rooms(otmp->ox, otmp->oy, SHOPBASE);
1385. 	    fakeshop[1] = '\0';
1386. 	    Strcpy(u.ushops, fakeshop);
1387. 	    /* sets obj->unpaid if necessary */
1388. 	    addtobill(otmp, TRUE, FALSE, FALSE);
1389. 	    Strcpy(u.ushops, saveushops);
1390. 	    /* if you're outside the shop, make shk notice */
1391. 	    if (!index(u.ushops, *fakeshop))
1392. 		remote_burglary(otmp->ox, otmp->oy);
1393. 	}
1394. 	if (otmp->no_charge)	/* only applies to objects outside invent */
1395. 	    otmp->no_charge = 0;
1396. 	newsym(otmp->ox, otmp->oy);
1397. 	return addinv(otmp);	/* might merge it with other objects */
1398. }
1399. 

encumber_msg Edit

1400. /*
1401.  * prints a message if encumbrance changed since the last check and
1402.  * returns the new encumbrance value (from near_capacity()).
1403.  */
1404. int
1405. encumber_msg()
1406. {
1407.     static int oldcap = UNENCUMBERED;
1408.     int newcap = near_capacity();
1409. 
1410.     if(oldcap < newcap) {
1411. 	switch(newcap) {
1412. 	case 1: Your("movements are slowed slightly because of your load.");
1413. 		break;
1414. 	case 2: You("rebalance your load.  Movement is difficult.");
1415. 		break;
1416. 	case 3: You("%s under your heavy load.  Movement is very hard.",
1417. 		    stagger(youmonst.data, "stagger"));
1418. 		break;
1419. 	default: You("%s move a handspan with this load!",
1420. 		     newcap == 4 ? "can barely" : "can't even");
1421. 		break;
1422. 	}
1423. 	flags.botl = 1;
1424.     } else if(oldcap > newcap) {
1425. 	switch(newcap) {
1426. 	case 0: Your("movements are now unencumbered.");
1427. 		break;
1428. 	case 1: Your("movements are only slowed slightly by your load.");
1429. 		break;
1430. 	case 2: You("rebalance your load.  Movement is still difficult.");
1431. 		break;
1432. 	case 3: You("%s under your load.  Movement is still very hard.",
1433. 		    stagger(youmonst.data, "stagger"));
1434. 		break;
1435. 	}
1436. 	flags.botl = 1;
1437.     }
1438. 
1439.     oldcap = newcap;
1440.     return (newcap);
1441. }
1442. 

container_at Edit

1443. /* Is there a container at x,y. Optional: return count of containers at x,y */
1444. STATIC_OVL int
1445. container_at(x, y, countem)
1446. int x,y;
1447. boolean countem;
1448. {
1449. 	struct obj *cobj, *nobj;
1450. 	int container_count = 0;
1451. 	
1452. 	for(cobj = level.objects[x][y]; cobj; cobj = nobj) {
1453. 		nobj = cobj->nexthere;
1454. 		if(Is_container(cobj)) {
1455. 			container_count++;
1456. 			if (!countem) break;
1457. 		}
1458. 	}
1459. 	return container_count;
1460. }
1461. 

able_to_loot Edit

1462. STATIC_OVL boolean
1463. able_to_loot(x, y)
1464. int x, y;
1465. {
1466. 	if (!can_reach_floor()) {
1467. #ifdef STEED
1468. 		if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
1469. 			rider_cant_reach(); /* not skilled enough to reach */
1470. 		else
1471. #endif
1472. 			You("cannot reach the %s.", surface(x, y));
1473. 		return FALSE;
1474. 	} else if (is_pool(x, y) || is_lava(x, y)) {
1475. 		/* at present, can't loot in water even when Underwater */
1476. 		You("cannot loot things that are deep in the %s.",
1477. 		    is_lava(x, y) ? "lava" : "water");
1478. 		return FALSE;
1479. 	} else if (nolimbs(youmonst.data)) {
1480. 		pline("Without limbs, you cannot loot anything.");
1481. 		return FALSE;
1482. 	} else if (!freehand()) {
1483. 		pline("Without a free %s, you cannot loot anything.",
1484. 			body_part(HAND));
1485. 		return FALSE;
1486. 	}
1487. 	return TRUE;
1488. }
1489. 

mon_beside Edit

1490. STATIC_OVL boolean
1491. mon_beside(x,y)
1492. int x, y;
1493. {
1494. 	int i,j,nx,ny;
1495. 	for(i = -1; i <= 1; i++)
1496. 	    for(j = -1; j <= 1; j++) {
1497. 	    	nx = x + i;
1498. 	    	ny = y + j;
1499. 		if(isok(nx, ny) && MON_AT(nx, ny))
1500. 			return TRUE;
1501. 	    }
1502. 	return FALSE;
1503. }
1504. 

doloot Edit

1505. int
1506. doloot()	/* loot a container on the floor or loot saddle from mon. */
1507. {
1508.     register struct obj *cobj, *nobj;
1509.     register int c = -1;
1510.     int timepassed = 0;
1511.     coord cc;
1512.     boolean underfoot = TRUE;
1513.     const char *dont_find_anything = "don't find anything";
1514.     struct monst *mtmp;
1515.     char qbuf[BUFSZ];
1516.     int prev_inquiry = 0;
1517.     boolean prev_loot = FALSE;
1518. 
1519.     if (check_capacity((char *)0)) {
1520. 	/* "Can't do that while carrying so much stuff." */
1521. 	return 0;
1522.     }
1523.     if (nohands(youmonst.data)) {
1524. 	You("have no hands!");	/* not `body_part(HAND)' */
1525. 	return 0;
1526.     }
1527.     cc.x = u.ux; cc.y = u.uy;
1528. 
1529. lootcont:
1530. 
1531.     if (container_at(cc.x, cc.y, FALSE)) {
1532. 	boolean any = FALSE;
1533. 
1534. 	if (!able_to_loot(cc.x, cc.y)) return 0;
1535. 	for (cobj = level.objects[cc.x][cc.y]; cobj; cobj = nobj) {
1536. 	    nobj = cobj->nexthere;
1537. 
1538. 	    if (Is_container(cobj)) {
1539. 		Sprintf(qbuf, "There is %s here, loot it?",
1540. 			safe_qbuf("", sizeof("There is  here, loot it?"),
1541. 			     doname(cobj), an(simple_typename(cobj->otyp)),
1542. 			     "a container"));
1543. 		c = ynq(qbuf);
1544. 		if (c == 'q') return (timepassed);
1545. 		if (c == 'n') continue;
1546. 		any = TRUE;
1547. 
1548. 		if (cobj->olocked) {
1549. 		    pline("Hmmm, it seems to be locked.");
1550. 		    continue;
1551. 		}
1552. 		if (cobj->otyp == BAG_OF_TRICKS) {
1553. 		    int tmp;
1554. 		    You("carefully open the bag...");
1555. 		    pline("It develops a huge set of teeth and bites you!");
1556. 		    tmp = rnd(10);
1557. 		    if (Half_physical_damage) tmp = (tmp+1) / 2;
1558. 		    losehp(tmp, "carnivorous bag", KILLED_BY_AN);
1559. 		    makeknown(BAG_OF_TRICKS);
1560. 		    timepassed = 1;
1561. 		    continue;
1562. 		}
1563. 
1564. 		You("carefully open %s...", the(xname(cobj)));
1565. 		timepassed |= use_container(cobj, 0);
1566. 		if (multi < 0) return 1;		/* chest trap */
1567. 	    }
1568. 	}
1569. 	if (any) c = 'y';
1570.     } else if (Confusion) {
1571. #ifndef GOLDOBJ
1572. 	if (u.ugold){
1573. 	    long contribution = rnd((int)min(LARGEST_INT,u.ugold));
1574. 	    struct obj *goldob = mkgoldobj(contribution);
1575. #else
1576. 	struct obj *goldob;
1577. 	/* Find a money object to mess with */
1578. 	for (goldob = invent; goldob; goldob = goldob->nobj) {
1579. 	    if (goldob->oclass == COIN_CLASS) break;
1580. 	}
1581. 	if (goldob){
1582. 	    long contribution = rnd((int)min(LARGEST_INT, goldob->quan));
1583. 	    if (contribution < goldob->quan)
1584. 		goldob = splitobj(goldob, contribution);
1585. 	    freeinv(goldob);
1586. #endif
1587. 	    if (IS_THRONE(levl[u.ux][u.uy].typ)){
1588. 		struct obj *coffers;
1589. 		int pass;
1590. 		/* find the original coffers chest, or any chest */
1591. 		for (pass = 2; pass > -1; pass -= 2)
1592. 		    for (coffers = fobj; coffers; coffers = coffers->nobj)
1593. 			if (coffers->otyp == CHEST && coffers->spe == pass)
1594. 			    goto gotit;	/* two level break */
1595. gotit:
1596. 		if (coffers) {
1597. 	    verbalize("Thank you for your contribution to reduce the debt.");
1598. 		    (void) add_to_container(coffers, goldob);
1599. 		    coffers->owt = weight(coffers);
1600. 		} else {
1601. 		    struct monst *mon = makemon(courtmon(),
1602. 					    u.ux, u.uy, NO_MM_FLAGS);
1603. 		    if (mon) {
1604. #ifndef GOLDOBJ
1605. 			mon->mgold += goldob->quan;
1606. 			delobj(goldob);
1607. 			pline("The exchequer accepts your contribution.");
1608. 		    } else {
1609. 			dropx(goldob);
1610. 		    }
1611. 		}
1612. 	    } else {
1613. 		dropx(goldob);
1614. #else
1615. 			add_to_minv(mon, goldob);
1616. 			pline("The exchequer accepts your contribution.");
1617. 		    } else {
1618. 			dropy(goldob);
1619. 		    }
1620. 		}
1621. 	    } else {
1622. 		dropy(goldob);
1623. #endif
1624. 		pline("Ok, now there is loot here.");
1625. 	    }
1626. 	}
1627.     } else if (IS_GRAVE(levl[cc.x][cc.y].typ)) {
1628. 	You("need to dig up the grave to effectively loot it...");
1629.     }
1630.     /*
1631.      * 3.3.1 introduced directional looting for some things.
1632.      */
1633.     if (c != 'y' && mon_beside(u.ux, u.uy)) {
1634. 	if (!get_adjacent_loc("Loot in what direction?", "Invalid loot location",
1635. 			u.ux, u.uy, &cc)) return 0;
1636. 	if (cc.x == u.ux && cc.y == u.uy) {
1637. 	    underfoot = TRUE;
1638. 	    if (container_at(cc.x, cc.y, FALSE))
1639. 		goto lootcont;
1640. 	} else
1641. 	    underfoot = FALSE;
1642. 	if (u.dz < 0) {
1643. 	    You("%s to loot on the %s.", dont_find_anything,
1644. 		ceiling(cc.x, cc.y));
1645. 	    timepassed = 1;
1646. 	    return timepassed;
1647. 	}
1648. 	mtmp = m_at(cc.x, cc.y);
1649. 	if (mtmp) timepassed = loot_mon(mtmp, &prev_inquiry, &prev_loot);
1650. 
1651. 	/* Preserve pre-3.3.1 behaviour for containers.
1652. 	 * Adjust this if-block to allow container looting
1653. 	 * from one square away to change that in the future.
1654. 	 */
1655. 	if (!underfoot) {
1656. 	    if (container_at(cc.x, cc.y, FALSE)) {
1657. 		if (mtmp) {
1658. 		    You_cant("loot anything %sthere with %s in the way.",
1659. 			    prev_inquiry ? "else " : "", mon_nam(mtmp));
1660. 		    return timepassed;
1661. 		} else {
1662. 		    You("have to be at a container to loot it.");
1663. 		}
1664. 	    } else {
1665. 		You("%s %sthere to loot.", dont_find_anything,
1666. 			(prev_inquiry || prev_loot) ? "else " : "");
1667. 		return timepassed;
1668. 	    }
1669. 	}
1670.     } else if (c != 'y' && c != 'n') {
1671. 	You("%s %s to loot.", dont_find_anything,
1672. 		    underfoot ? "here" : "there");
1673.     }
1674.     return (timepassed);
1675. }
1676. 

loot_mon Edit

1677. /* loot_mon() returns amount of time passed.
1678.  */
1679. int
1680. loot_mon(mtmp, passed_info, prev_loot)
1681. struct monst *mtmp;
1682. int *passed_info;
1683. boolean *prev_loot;
1684. {
1685.     int c = -1;
1686.     int timepassed = 0;
1687. #ifdef STEED
1688.     struct obj *otmp;
1689.     char qbuf[QBUFSZ];
1690. 
1691.     /* 3.3.1 introduced the ability to remove saddle from a steed             */
1692.     /* 	*passed_info is set to TRUE if a loot query was given.               */
1693.     /*	*prev_loot is set to TRUE if something was actually acquired in here. */
1694.     if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
1695. 	long unwornmask;
1696. 	if (passed_info) *passed_info = 1;
1697. 	Sprintf(qbuf, "Do you want to remove the saddle from %s?",
1698. 		x_monnam(mtmp, ARTICLE_THE, (char *)0, SUPPRESS_SADDLE, FALSE));
1699. 	if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
1700. 		if (nolimbs(youmonst.data)) {
1701. 		    You_cant("do that without limbs."); /* not body_part(HAND) */
1702. 		    return (0);
1703. 		}
1704. 		if (otmp->cursed) {
1705. 		    You("can't. The saddle seems to be stuck to %s.",
1706. 			x_monnam(mtmp, ARTICLE_THE, (char *)0,
1707. 				SUPPRESS_SADDLE, FALSE));
1708. 			    
1709. 		    /* the attempt costs you time */
1710. 			return (1);
1711. 		}
1712. 		obj_extract_self(otmp);
1713. 		if ((unwornmask = otmp->owornmask) != 0L) {
1714. 		    mtmp->misc_worn_check &= ~unwornmask;
1715. 		    otmp->owornmask = 0L;
1716. 		    update_mon_intrinsics(mtmp, otmp, FALSE, FALSE);
1717. 		}
1718. 		otmp = hold_another_object(otmp, "You drop %s!", doname(otmp),
1719. 					(const char *)0);
1720. 		timepassed = rnd(3);
1721. 		if (prev_loot) *prev_loot = TRUE;
1722. 	} else if (c == 'q') {
1723. 		return (0);
1724. 	}
1725.     }
1726. #endif	/* STEED */
1727.     /* 3.4.0 introduced the ability to pick things up from within swallower's stomach */
1728.     if (u.uswallow) {
1729. 	int count = passed_info ? *passed_info : 0;
1730. 	timepassed = pickup(count);
1731.     }
1732.     return timepassed;
1733. }
1734. 

mbag_explodes Edit

1735. /*
1736.  * Decide whether an object being placed into a magic bag will cause
1737.  * it to explode.  If the object is a bag itself, check recursively.
1738.  */
1739. STATIC_OVL boolean
1740. mbag_explodes(obj, depthin)
1741.     struct obj *obj;
1742.     int depthin;
1743. {
1744.     /* these won't cause an explosion when they're empty */
1745.     if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS) &&
1746. 	    obj->spe <= 0)
1747. 	return FALSE;
1748. 
1749.     /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
1750.     if ((Is_mbag(obj) || obj->otyp == WAN_CANCELLATION) &&
1751. 	(rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin))
1752. 	return TRUE;
1753.     else if (Has_contents(obj)) {
1754. 	struct obj *otmp;
1755. 
1756. 	for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
1757. 	    if (mbag_explodes(otmp, depthin+1)) return TRUE;
1758.     }
1759.     return FALSE;
1760. }
1761. 

in_container Edit

1762. /* A variable set in use_container(), to be used by the callback routines   */
1763. /* in_container(), and out_container() from askchain() and use_container(). */
1764. static NEARDATA struct obj *current_container;
1765. #define Icebox (current_container->otyp == ICE_BOX)
1766. 
1767. /* Returns: -1 to stop, 1 item was inserted, 0 item was not inserted. */
1768. STATIC_PTR int
1769. in_container(obj)
1770. register struct obj *obj;
1771. {
1772. 	boolean floor_container = !carried(current_container);
1773. 	boolean was_unpaid = FALSE;
1774. 	char buf[BUFSZ];
1775. 
1776. 	if (!current_container) {
1777. 		impossible("<in> no current_container?");
1778. 		return 0;
1779. 	} else if (obj == uball || obj == uchain) {
1780. 		You("must be kidding.");
1781. 		return 0;
1782. 	} else if (obj == current_container) {
1783. 		pline("That would be an interesting topological exercise.");
1784. 		return 0;
1785. 	} else if (obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
1786. 		Norep("You cannot %s %s you are wearing.",
1787. 			Icebox ? "refrigerate" : "stash", something);
1788. 		return 0;
1789. 	} else if ((obj->otyp == LOADSTONE) && obj->cursed) {
1790. 		obj->bknown = 1;
1791. 	      pline_The("stone%s won't leave your person.", plur(obj->quan));
1792. 		return 0;
1793. 	} else if (obj->otyp == AMULET_OF_YENDOR ||
1794. 		   obj->otyp == CANDELABRUM_OF_INVOCATION ||
1795. 		   obj->otyp == BELL_OF_OPENING ||
1796. 		   obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1797. 	/* Prohibit Amulets in containers; if you allow it, monsters can't
1798. 	 * steal them.  It also becomes a pain to check to see if someone
1799. 	 * has the Amulet.  Ditto for the Candelabrum, the Bell and the Book.
1800. 	 */
1801. 	    pline("%s cannot be confined in such trappings.", The(xname(obj)));
1802. 	    return 0;
1803. 	} else if (obj->otyp == LEASH && obj->leashmon != 0) {
1804. 		pline("%s attached to your pet.", Tobjnam(obj, "are"));
1805. 		return 0;
1806. 	} else if (obj == uwep) {
1807. 		if (welded(obj)) {
1808. 			weldmsg(obj);
1809. 			return 0;
1810. 		}
1811. 		setuwep((struct obj *) 0);
1812. 		if (uwep) return 0;	/* unwielded, died, rewielded */
1813. 	} else if (obj == uswapwep) {
1814. 		setuswapwep((struct obj *) 0);
1815. 		if (uswapwep) return 0;     /* unwielded, died, rewielded */
1816. 	} else if (obj == uquiver) {
1817. 		setuqwep((struct obj *) 0);
1818. 		if (uquiver) return 0;     /* unwielded, died, rewielded */
1819. 	}
1820. 
1821. 	if (obj->otyp == CORPSE) {
1822. 	    if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
1823. 		 && !Stone_resistance) {
1824. 		if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1825. 		    display_nhwindow(WIN_MESSAGE, FALSE);
1826. 		else {
1827. 		    char kbuf[BUFSZ];
1828. 
1829. 		    Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1830. 		    pline("Touching %s is a fatal mistake.", kbuf);
1831. 		    instapetrify(kbuf);
1832. 		    return -1;
1833. 		}
1834. 	    }
1835. 	}
1836. 
1837. 	/* boxes, boulders, and big statues can't fit into any container */
1838. 	if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER ||
1839. 		(obj->otyp == STATUE && bigmonst(&mons[obj->corpsenm]))) {
1840. 		/*
1841. 		 *  xname() uses a static result array.  Save obj's name
1842. 		 *  before current_container's name is computed.  Don't
1843. 		 *  use the result of strcpy() within You() --- the order
1844. 		 *  of evaluation of the parameters is undefined.
1845. 		 */
1846. 		Strcpy(buf, the(xname(obj)));
1847. 		You("cannot fit %s into %s.", buf,
1848. 		    the(xname(current_container)));
1849. 		return 0;
1850. 	}
1851. 
1852. 	freeinv(obj);
1853. 
1854. 	if (obj_is_burning(obj))	/* this used to be part of freeinv() */
1855. 		(void) snuff_lit(obj);
1856. 
1857. 	if (floor_container && costly_spot(u.ux, u.uy)) {
1858. 	    if (current_container->no_charge && !obj->unpaid) {
1859. 		/* don't sell when putting the item into your own container */
1860. 		obj->no_charge = 1;
1861. 	    } else if (obj->oclass != COIN_CLASS) {
1862. 		/* sellobj() will take an unpaid item off the shop bill
1863. 		 * note: coins are handled later */
1864. 		was_unpaid = obj->unpaid ? TRUE : FALSE;
1865. 		sellobj_state(SELL_DELIBERATE);
1866. 		sellobj(obj, u.ux, u.uy);
1867. 		sellobj_state(SELL_NORMAL);
1868. 	    }
1869. 	}
1870. 	if (Icebox && !age_is_relative(obj)) {
1871. 		obj->age = monstermoves - obj->age; /* actual age */
1872. 		/* stop any corpse timeouts when frozen */
1873. 		if (obj->otyp == CORPSE && obj->timed) {
1874. 			long rot_alarm = stop_timer(ROT_CORPSE, (genericptr_t)obj);
1875. 			(void) stop_timer(REVIVE_MON, (genericptr_t)obj);
1876. 			/* mark a non-reviving corpse as such */
1877. 			if (rot_alarm) obj->norevive = 1;
1878. 		}
1879. 	} else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
1880. 		/* explicitly mention what item is triggering the explosion */
1881. 		pline(
1882. 	      "As you put %s inside, you are blasted by a magical explosion!",
1883. 		      doname(obj));
1884. 		/* did not actually insert obj yet */
1885. 		if (was_unpaid) addtobill(obj, FALSE, FALSE, TRUE);
1886. 		obfree(obj, (struct obj *)0);
1887. 		delete_contents(current_container);
1888. 		if (!floor_container)
1889. 			useup(current_container);
1890. 		else if (obj_here(current_container, u.ux, u.uy))
1891. 			useupf(current_container, obj->quan);
1892. 		else
1893. 			panic("in_container:  bag not found.");
1894. 
1895. 		losehp(d(6,6),"magical explosion", KILLED_BY_AN);
1896. 		current_container = 0;	/* baggone = TRUE; */
1897. 	}
1898. 
1899. 	if (current_container) {
1900. 	    Strcpy(buf, the(xname(current_container)));
1901. 	    You("put %s into %s.", doname(obj), buf);
1902. 
1903. 	    /* gold in container always needs to be added to credit */
1904. 	    if (floor_container && obj->oclass == COIN_CLASS)
1905. 		sellobj(obj, current_container->ox, current_container->oy);
1906. 	    (void) add_to_container(current_container, obj);
1907. 	    current_container->owt = weight(current_container);
1908. 	}
1909. 	/* gold needs this, and freeinv() many lines above may cause
1910. 	 * the encumbrance to disappear from the status, so just always
1911. 	 * update status immediately.
1912. 	 */
1913. 	bot();
1914. 
1915. 	return(current_container ? 1 : -1);
1916. }
1917. 

ck_bag Edit

1918. STATIC_PTR int
1919. ck_bag(obj)
1920. struct obj *obj;
1921. {
1922. 	return current_container && obj != current_container;
1923. }
1924. 

out_container Edit

1925. /* Returns: -1 to stop, 1 item was removed, 0 item was not removed. */
1926. STATIC_PTR int
1927. out_container(obj)
1928. register struct obj *obj;
1929. {
1930. 	register struct obj *otmp;
1931. 	boolean is_gold = (obj->oclass == COIN_CLASS);
1932. 	int res, loadlev;
1933. 	long count;
1934. 
1935. 	if (!current_container) {
1936. 		impossible("<out> no current_container?");
1937. 		return -1;
1938. 	} else if (is_gold) {
1939. 		obj->owt = weight(obj);
1940. 	}
1941. 
1942. 	if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0;
1943. 
1944. 	if (obj->otyp == CORPSE) {
1945. 	    if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg
1946. 		 && !Stone_resistance) {
1947. 		if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))
1948. 		    display_nhwindow(WIN_MESSAGE, FALSE);
1949. 		else {
1950. 		    char kbuf[BUFSZ];
1951. 
1952. 		    Strcpy(kbuf, an(corpse_xname(obj, TRUE)));
1953. 		    pline("Touching %s is a fatal mistake.", kbuf);
1954. 		    instapetrify(kbuf);
1955. 		    return -1;
1956. 		}
1957. 	    }
1958. 	}
1959. 
1960. 	count = obj->quan;
1961. 	if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0)
1962. 	    return res;
1963. 
1964. 	if (obj->quan != count && obj->otyp != LOADSTONE)
1965. 	    obj = splitobj(obj, count);
1966. 
1967. 	/* Remove the object from the list. */
1968. 	obj_extract_self(obj);
1969. 	current_container->owt = weight(current_container);
1970. 
1971. 	if (Icebox && !age_is_relative(obj)) {
1972. 		obj->age = monstermoves - obj->age; /* actual age */
1973. 		if (obj->otyp == CORPSE)
1974. 			start_corpse_timeout(obj);
1975. 	}
1976. 	/* simulated point of time */
1977. 
1978. 	if(!obj->unpaid && !carried(current_container) &&
1979. 	     costly_spot(current_container->ox, current_container->oy)) {
1980. 		obj->ox = current_container->ox;
1981. 		obj->oy = current_container->oy;
1982. 		addtobill(obj, FALSE, FALSE, FALSE);
1983. 	}
1984. 	if (is_pick(obj) && !obj->unpaid && *u.ushops && shop_keeper(*u.ushops))
1985. 		verbalize("You sneaky cad! Get out of here with that pick!");
1986. 
1987. 	otmp = addinv(obj);
1988. 	loadlev = near_capacity();
1989. 	prinv(loadlev ?
1990. 	      (loadlev < MOD_ENCUMBER ?
1991. 	       "You have a little trouble removing" :
1992. 	       "You have much trouble removing") : (char *)0,
1993. 	      otmp, count);
1994. 
1995. 	if (is_gold) {
1996. #ifndef GOLDOBJ
1997. 		dealloc_obj(obj);
1998. #endif
1999. 		bot();	/* update character's gold piece count immediately */
2000. 	}
2001. 	return 1;
2002. }
2003. 

mbag_item_gone Edit

2004. /* an object inside a cursed bag of holding is being destroyed */
2005. STATIC_OVL long
2006. mbag_item_gone(held, item)
2007. int held;
2008. struct obj *item;
2009. {
2010.     struct monst *shkp;
2011.     long loss = 0L;
2012. 
2013.     if (item->dknown)
2014. 	pline("%s %s vanished!", Doname2(item), otense(item, "have"));
2015.     else
2016. 	You("%s %s disappear!", Blind ? "notice" : "see", doname(item));
2017. 
2018.     if (*u.ushops && (shkp = shop_keeper(*u.ushops)) != 0) {
2019. 	if (held ? (boolean) item->unpaid : costly_spot(u.ux, u.uy))
2020. 	    loss = stolen_value(item, u.ux, u.uy,
2021. 				(boolean)shkp->mpeaceful, TRUE);
2022.     }
2023.     obfree(item, (struct obj *) 0);
2024.     return loss;
2025. }
2026. 

observe_quantum_cat Edit

2027. STATIC_OVL void
2028. observe_quantum_cat(box)
2029. struct obj *box;
2030. {
2031.     static NEARDATA const char sc[] = "Schroedinger's Cat";
2032.     struct obj *deadcat;
2033.     struct monst *livecat;
2034.     xchar ox, oy;
2035. 
2036.     box->spe = 0;		/* box->owt will be updated below */
2037.     if (get_obj_location(box, &ox, &oy, 0))
2038. 	box->ox = ox, box->oy = oy;	/* in case it's being carried */
2039. 
2040.     /* this isn't really right, since any form of observation
2041.        (telepathic or monster/object/food detection) ought to
2042.        force the determination of alive vs dead state; but basing
2043.        it just on opening the box is much simpler to cope with */
2044.     livecat = rn2(2) ? makemon(&mons[PM_HOUSECAT],
2045. 			       box->ox, box->oy, NO_MINVENT) : 0;
2046.     if (livecat) {
2047. 	livecat->mpeaceful = 1;
2048. 	set_malign(livecat);
2049. 	if (!canspotmon(livecat))
2050. 	    You("think %s brushed your %s.", something, body_part(FOOT));
2051. 	else
2052. 	    pline("%s inside the box is still alive!", Monnam(livecat));
2053. 	(void) christen_monst(livecat, sc);
2054.     } else {
2055. 	deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
2056. 				  box->ox, box->oy, sc);
2057. 	if (deadcat) {
2058. 	    obj_extract_self(deadcat);
2059. 	    (void) add_to_container(box, deadcat);
2060. 	}
2061. 	pline_The("%s inside the box is dead!",
2062. 	    Hallucination ? rndmonnam() : "housecat");
2063.     }
2064.     box->owt = weight(box);
2065.     return;
2066. }
2067. 
2068. #undef Icebox
2069. 

use_container Edit

2070. int
2071. use_container(obj, held)
2072. register struct obj *obj;
2073. register int held;
2074. {
2075. 	struct obj *curr, *otmp;
2076. #ifndef GOLDOBJ
2077. 	struct obj *u_gold = (struct obj *)0;
2078. #endif
2079. 	boolean one_by_one, allflag, quantum_cat = FALSE,
2080. 		loot_out = FALSE, loot_in = FALSE;
2081. 	char select[MAXOCLASSES+1];
2082. 	char qbuf[BUFSZ], emptymsg[BUFSZ], pbuf[QBUFSZ];
2083. 	long loss = 0L;
2084. 	int cnt = 0, used = 0,
2085. 	    menu_on_request;
2086. 
2087. 	emptymsg[0] = '\0';
2088. 	if (nohands(youmonst.data)) {
2089. 		You("have no hands!");	/* not `body_part(HAND)' */
2090. 		return 0;
2091. 	} else if (!freehand()) {
2092. 		You("have no free %s.", body_part(HAND));
2093. 		return 0;
2094. 	}
2095. 	if (obj->olocked) {
2096. 	    pline("%s to be locked.", Tobjnam(obj, "seem"));
2097. 	    if (held) You("must put it down to unlock.");
2098. 	    return 0;
2099. 	} else if (obj->otrapped) {
2100. 	    if (held) You("open %s...", the(xname(obj)));
2101. 	    (void) chest_trap(obj, HAND, FALSE);
2102. 	    /* even if the trap fails, you've used up this turn */
2103. 	    if (multi >= 0) {	/* in case we didn't become paralyzed */
2104. 		nomul(-1);
2105. 		nomovemsg = "";
2106. 	    }
2107. 	    return 1;
2108. 	}
2109. 	current_container = obj;	/* for use by in/out_container */
2110. 
2111. 	if (obj->spe == 1) {
2112. 	    observe_quantum_cat(obj);
2113. 	    used = 1;
2114. 	    quantum_cat = TRUE;	/* for adjusting "it's empty" message */
2115. 	}
2116. 	/* Count the number of contained objects. Sometimes toss objects if */
2117. 	/* a cursed magic bag.						    */
2118. 	for (curr = obj->cobj; curr; curr = otmp) {
2119. 	    otmp = curr->nobj;
2120. 	    if (Is_mbag(obj) && obj->cursed && !rn2(13)) {
2121. 		obj_extract_self(curr);
2122. 		loss += mbag_item_gone(held, curr);
2123. 		used = 1;
2124. 	    } else {
2125. 		cnt++;
2126. 	    }
2127. 	}
2128. 
2129. 	if (loss)	/* magic bag lost some shop goods */
2130. 	    You("owe %ld %s for lost merchandise.", loss, currency(loss));
2131. 	obj->owt = weight(obj);	/* in case any items were lost */
2132. 
2133. 	if (!cnt)
2134. 	    Sprintf(emptymsg, "%s is %sempty.", Yname2(obj),
2135. 		    quantum_cat ? "now " : "");
2136. 
2137. 	if (cnt || flags.menu_style == MENU_FULL) {
2138. 	    Strcpy(qbuf, "Do you want to take something out of ");
2139. 	    Sprintf(eos(qbuf), "%s?",
2140. 		    safe_qbuf(qbuf, 1, yname(obj), ysimple_name(obj), "it"));
2141. 	    if (flags.menu_style != MENU_TRADITIONAL) {
2142. 		if (flags.menu_style == MENU_FULL) {
2143. 		    int t;
2144. 		    char menuprompt[BUFSZ];
2145. 		    boolean outokay = (cnt != 0);
2146. #ifndef GOLDOBJ
2147. 		    boolean inokay = (invent != 0) || (u.ugold != 0);
2148. #else
2149. 		    boolean inokay = (invent != 0);
2150. #endif
2151. 		    if (!outokay && !inokay) {
2152. 			pline("%s", emptymsg);
2153. 			You("don't have anything to put in.");
2154. 			return used;
2155. 		    }
2156. 		    menuprompt[0] = '\0';
2157. 		    if (!cnt) Sprintf(menuprompt, "%s ", emptymsg);
2158. 		    Strcat(menuprompt, "Do what?");
2159. 		    t = in_or_out_menu(menuprompt, current_container, outokay, inokay);
2160. 		    if (t <= 0) return 0;
2161. 		    loot_out = (t & 0x01) != 0;
2162. 		    loot_in  = (t & 0x02) != 0;
2163. 		} else {	/* MENU_COMBINATION or MENU_PARTIAL */
2164. 		    loot_out = (yn_function(qbuf, "ynq", 'n') == 'y');
2165. 		}
2166. 		if (loot_out) {
2167. 		    add_valid_menu_class(0);	/* reset */
2168. 		    used |= menu_loot(0, current_container, FALSE) > 0;
2169. 		}
2170. 	    } else {
2171. 		/* traditional code */
2172. ask_again2:
2173. 		menu_on_request = 0;
2174. 		add_valid_menu_class(0);	/* reset */
2175. 		Strcpy(pbuf, ":ynq");
2176. 		if (cnt) Strcat(pbuf, "m");
2177. 		switch (yn_function(qbuf, pbuf, 'n')) {
2178. 		case ':':
2179. 		    container_contents(current_container, FALSE, FALSE);
2180. 		    goto ask_again2;
2181. 		case 'y':
2182. 		    if (query_classes(select, &one_by_one, &allflag,
2183. 				      "take out", current_container->cobj,
2184. 				      FALSE,
2185. #ifndef GOLDOBJ
2186. 				      FALSE,
2187. #endif
2188. 				      &menu_on_request)) {
2189. 			if (askchain((struct obj **)&current_container->cobj,
2190. 				     (one_by_one ? (char *)0 : select),
2191. 				     allflag, out_container,
2192. 				     (int FDECL((*),(OBJ_P)))0,
2193. 				     0, "nodot"))
2194. 			    used = 1;
2195. 		    } else if (menu_on_request < 0) {
2196. 			used |= menu_loot(menu_on_request,
2197. 					  current_container, FALSE) > 0;
2198. 		    }
2199. 		    /*FALLTHRU*/
2200. 		case 'n':
2201. 		    break;
2202. 		case 'm':
2203. 		    menu_on_request = -2; /* triggers ALL_CLASSES */
2204. 		    used |= menu_loot(menu_on_request, current_container, FALSE) > 0;
2205. 		    break;
2206. 		case 'q':
2207. 		default:
2208. 		    return used;
2209. 		}
2210. 	    }
2211. 	} else {
2212. 	    pline("%s", emptymsg);		/* <whatever> is empty. */
2213. 	}
2214. 
2215. #ifndef GOLDOBJ
2216. 	if (!invent && u.ugold == 0) {
2217. #else
2218. 	if (!invent) {
2219. #endif
2220. 	    /* nothing to put in, but some feedback is necessary */
2221. 	    You("don't have anything to put in.");
2222. 	    return used;
2223. 	}
2224. 	if (flags.menu_style != MENU_FULL) {
2225. 	    Sprintf(qbuf, "Do you wish to put %s in?", something);
2226. 	    Strcpy(pbuf, ynqchars);
2227. 	    if (flags.menu_style == MENU_TRADITIONAL && invent && inv_cnt() > 0)
2228. 		Strcat(pbuf, "m");
2229. 	    switch (yn_function(qbuf, pbuf, 'n')) {
2230. 		case 'y':
2231. 		    loot_in = TRUE;
2232. 		    break;
2233. 		case 'n':
2234. 		    break;
2235. 		case 'm':
2236. 		    add_valid_menu_class(0);	  /* reset */
2237. 		    menu_on_request = -2; /* triggers ALL_CLASSES */
2238. 		    used |= menu_loot(menu_on_request, current_container, TRUE) > 0;
2239. 		    break;
2240. 		case 'q':
2241. 		default:
2242. 		    return used;
2243. 	    }
2244. 	}
2245. 	/*
2246. 	 * Gone: being nice about only selecting food if we know we are
2247. 	 * putting things in an ice chest.
2248. 	 */
2249. 	if (loot_in) {
2250. #ifndef GOLDOBJ
2251. 	    if (u.ugold) {
2252. 		/*
2253. 		 * Hack: gold is not in the inventory, so make a gold object
2254. 		 * and put it at the head of the inventory list.
2255. 		 */
2256. 		u_gold = mkgoldobj(u.ugold);	/* removes from u.ugold */
2257. 		u_gold->in_use = TRUE;
2258. 		u.ugold = u_gold->quan;		/* put the gold back */
2259. 		assigninvlet(u_gold);		/* might end up as NOINVSYM */
2260. 		u_gold->nobj = invent;
2261. 		invent = u_gold;
2262. 	    }
2263. #endif
2264. 	    add_valid_menu_class(0);	  /* reset */
2265. 	    if (flags.menu_style != MENU_TRADITIONAL) {
2266. 		used |= menu_loot(0, current_container, TRUE) > 0;
2267. 	    } else {
2268. 		/* traditional code */
2269. 		menu_on_request = 0;
2270. 		if (query_classes(select, &one_by_one, &allflag, "put in",
2271. 				   invent, FALSE,
2272. #ifndef GOLDOBJ
2273. 				   (u.ugold != 0L),
2274. #endif
2275. 				   &menu_on_request)) {
2276. 		    (void) askchain((struct obj **)&invent,
2277. 				    (one_by_one ? (char *)0 : select), allflag,
2278. 				    in_container, ck_bag, 0, "nodot");
2279. 		    used = 1;
2280. 		} else if (menu_on_request < 0) {
2281. 		    used |= menu_loot(menu_on_request,
2282. 				      current_container, TRUE) > 0;
2283. 		}
2284. 	    }
2285. 	}
2286. 
2287. #ifndef GOLDOBJ
2288. 	if (u_gold && invent && invent->oclass == COIN_CLASS) {
2289. 	    /* didn't stash [all of] it */
2290. 	    u_gold = invent;
2291. 	    invent = u_gold->nobj;
2292. 	    u_gold->in_use = FALSE;
2293. 	    dealloc_obj(u_gold);
2294. 	}
2295. #endif
2296. 	return used;
2297. }
2298. 

menu_loot Edit

2299. /* Loot a container (take things out, put things in), using a menu. */
2300. STATIC_OVL int
2301. menu_loot(retry, container, put_in)
2302. int retry;
2303. struct obj *container;
2304. boolean put_in;
2305. {
2306.     int n, i, n_looted = 0;
2307.     boolean all_categories = TRUE, loot_everything = FALSE;
2308.     char buf[BUFSZ];
2309.     const char *takeout = "Take out", *putin = "Put in";
2310.     struct obj *otmp, *otmp2;
2311.     menu_item *pick_list;
2312.     int mflags, res;
2313.     long count;
2314. 
2315.     if (retry) {
2316. 	all_categories = (retry == -2);
2317.     } else if (flags.menu_style == MENU_FULL) {
2318. 	all_categories = FALSE;
2319. 	Sprintf(buf,"%s what type of objects?", put_in ? putin : takeout);
2320. 	mflags = put_in ? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN :
2321. 		          ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN;
2322. 	n = query_category(buf, put_in ? invent : container->cobj,
2323. 			   mflags, &pick_list, PICK_ANY);
2324. 	if (!n) return 0;
2325. 	for (i = 0; i < n; i++) {
2326. 	    if (pick_list[i].item.a_int == 'A')
2327. 		loot_everything = TRUE;
2328. 	    else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
2329. 		all_categories = TRUE;
2330. 	    else
2331. 		add_valid_menu_class(pick_list[i].item.a_int);
2332. 	}
2333. 	free((genericptr_t) pick_list);
2334.     }
2335. 
2336.     if (loot_everything) {
2337. 	for (otmp = container->cobj; otmp; otmp = otmp2) {
2338. 	    otmp2 = otmp->nobj;
2339. 	    res = out_container(otmp);
2340. 	    if (res < 0) break;
2341. 	}
2342.     } else {
2343. 	mflags = INVORDER_SORT;
2344. 	if (put_in && flags.invlet_constant) mflags |= USE_INVLET;
2345. 	Sprintf(buf,"%s what?", put_in ? putin : takeout);
2346. 	n = query_objlist(buf, put_in ? invent : container->cobj,
2347. 			  mflags, &pick_list, PICK_ANY,
2348. 			  all_categories ? allow_all : allow_category);
2349. 	if (n) {
2350. 		n_looted = n;
2351. 		for (i = 0; i < n; i++) {
2352. 		    otmp = pick_list[i].item.a_obj;
2353. 		    count = pick_list[i].count;
2354. 		    if (count > 0 && count < otmp->quan) {
2355. 			otmp = splitobj(otmp, count);
2356. 			/* special split case also handled by askchain() */
2357. 		    }
2358. 		    res = put_in ? in_container(otmp) : out_container(otmp);
2359. 		    if (res < 0) {
2360. 			if (otmp != pick_list[i].item.a_obj) {
2361. 			    /* split occurred, merge again */
2362. 			    (void) merged(&pick_list[i].item.a_obj, &otmp);
2363. 			}
2364. 			break;
2365. 		    }
2366. 		}
2367. 		free((genericptr_t)pick_list);
2368. 	}
2369.     }
2370.     return n_looted;
2371. }
2372. 

in_or_out_menu Edit

2373. STATIC_OVL int
2374. in_or_out_menu(prompt, obj, outokay, inokay)
2375. const char *prompt;
2376. struct obj *obj;
2377. boolean outokay, inokay;
2378. {
2379.     winid win;
2380.     anything any;
2381.     menu_item *pick_list;
2382.     char buf[BUFSZ];
2383.     int n;
2384.     const char *menuselector = iflags.lootabc ? "abc" : "oib";
2385. 
2386.     any.a_void = 0;
2387.     win = create_nhwindow(NHW_MENU);
2388.     start_menu(win);
2389.     if (outokay) {
2390. 	any.a_int = 1;
2391. 	Sprintf(buf,"Take %s out of %s", something, the(xname(obj)));
2392. 	add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE,
2393. 			buf, MENU_UNSELECTED);
2394.     }
2395.     menuselector++;
2396.     if (inokay) {
2397. 	any.a_int = 2;
2398. 	Sprintf(buf,"Put %s into %s", something, the(xname(obj)));
2399. 	add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE, buf, MENU_UNSELECTED);
2400.     }
2401.     menuselector++;
2402.     if (outokay && inokay) {
2403. 	any.a_int = 3;
2404. 	add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE,
2405. 			"Both of the above", MENU_UNSELECTED);
2406.     }
2407.     end_menu(win, prompt);
2408.     n = select_menu(win, PICK_ONE, &pick_list);
2409.     destroy_nhwindow(win);
2410.     if (n > 0) {
2411. 	n = pick_list[0].item.a_int;
2412. 	free((genericptr_t) pick_list);
2413.     }
2414.     return n;
2415. }
2416. 
2417. /*pickup.c*/

Around Wikia's network

Random Wiki