Source:NetHack 3.1.0/pickup.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to pickup.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)pickup.c	3.1	93/01/04	*/
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(unsplitobj, (struct obj *,struct obj *,long));
12.   static void FDECL(simple_look, (struct obj *,BOOLEAN_P));
13.   static boolean FDECL(query_classes, (char *,boolean *,boolean *,
14.   			     const char *,struct obj *,BOOLEAN_P,BOOLEAN_P));
15.   static boolean FDECL(pickup_object, (struct obj *,struct obj *));
16.   static boolean FDECL(mbag_explodes, (struct obj *,int));
17.   STATIC_PTR int FDECL(in_container,(struct obj *));
18.   STATIC_PTR int FDECL(ck_bag,(struct obj *));
19.   STATIC_PTR int FDECL(out_container,(struct obj *));
20.   
21.   /*
22.    *  How much the weight of the given container will change when the given
23.    *  object is removed from it.  This calculation must match the one used
24.    *  by weight() in mkobj.c.
25.    */
26.   #define DELTA_CWT(cont,obj)		\
27.       ((cont)->cursed ? (obj)->owt * 2 :	\
28.   		      1 + ((obj)->owt / ((cont)->blessed ? 4 : 2)))
29.   
30.   static const char moderateloadmsg[] = "You have a little trouble lifting";
31.   static const char nearloadmsg[] = "You have much trouble lifting";
32.   
33.   static void
34.   unsplitobj(obj_block, obj_chip, resplit)
35.   register struct obj *obj_block, *obj_chip;
36.   long resplit;	/* non-zero => shift the quantities */
37.   {
38.   	if (obj_block->nobj != obj_chip) {
39.   		impossible("can't unsplit objects");
40.   	} else if (resplit) { /* 1st object should be reduced to 'resplit' */
41.   		obj_chip->quan += (obj_block->quan - resplit);
42.   		obj_block->quan = resplit;
43.   		obj_block->owt = weight(obj_block);
44.   		obj_chip->owt = weight(obj_chip);
45.   	} else {  /* 2nd obj should be merged back into 1st, then destroyed */
46.   		obj_block->nobj = obj_chip->nobj;
47.   		obj_block->nexthere = obj_chip->nexthere;
48.   		obj_block->quan += obj_chip->quan;
49.   		obj_block->owt = weight(obj_block);
50.   		/* no need to worry about 'unsplitbill'; unsplit only occurs
51.   		   when unable to pick something up, hence we're not dealing
52.   		   with billable objects here (I hope!)
53.   		 */
54.   		dealloc_obj(obj_chip);
55.   	}
56.   }
57.   
58.   /* much simpler version of the look-here code; used by query_classes() */
59.   static void
60.   simple_look(otmp, here)
61.   struct obj *otmp;	/* list of objects */
62.   boolean here;		/* flag for type of obj list linkage */
63.   {
64.   	/* Neither of the first two cases is expected to happen, since
65.   	 * we're only called after multiple classes of objects have been
66.   	 * detected, hence multiple objects must be present.
67.   	 */
68.   	if (!otmp) {
69.   	    impossible("simple_look(NULL)");
70.   	} else if (!(here ? otmp->nexthere : otmp->nobj)) {
71.   	    pline("%s", doname(otmp));
72.   	} else {
73.   	    winid tmpwin = create_nhwindow(NHW_MENU);
74.   	    putstr(tmpwin, 0, "");
75.   	    do {
76.   		putstr(tmpwin, 0, doname(otmp));
77.   		otmp = here ? otmp->nexthere : otmp->nobj;
78.   	    } while (otmp);
79.   	    display_nhwindow(tmpwin, TRUE);
80.   	    destroy_nhwindow(tmpwin);
81.   	}
82.   }
83.   
84.   int
85.   collect_obj_classes(ilets, otmp, here, incl_gold)
86.   char ilets[];
87.   register struct obj *otmp;
88.   boolean here, incl_gold;
89.   {
90.   	register int iletct = 0;
91.   	register char c, last_c = '\0';
92.   
93.   	if (incl_gold)
94.   		ilets[iletct++] = def_oc_syms[GOLD_CLASS];
95.   	ilets[iletct] = '\0'; /* terminate ilets so that index() will work */
96.   	while (otmp) {
97.   		c = def_oc_syms[(int)otmp->oclass];
98.   		if (c != last_c && !index(ilets, (last_c = c)))
99.   			ilets[iletct++] = c,  ilets[iletct] = '\0';
100.  		otmp = here ? otmp->nexthere : otmp->nobj;
101.  	}
102.  
103.  	return iletct;
104.  }
105.  
106.  static boolean
107.  query_classes(olets, one_at_a_time, everything, action, objs, here, incl_gold)
108.  char olets[];
109.  boolean *one_at_a_time, *everything;
110.  const char *action;
111.  struct obj *objs;
112.  boolean here, incl_gold;
113.  {
114.  	char ilets[20], inbuf[BUFSZ];
115.  	int iletct, oletct;
116.  	char qbuf[QBUFSZ];
117.  
118.  	olets[oletct = 0] = '\0';
119.  	*one_at_a_time = *everything = FALSE;
120.  	iletct = collect_obj_classes(ilets, objs, here, incl_gold);
121.  	if (iletct == 0) {
122.  		return FALSE;
123.  	} else if (iletct == 1) {
124.  		olets[0] = def_char_to_objclass(ilets[0]);
125.  		olets[1] = '\0';
126.  	} else  {	/* more than one choice available */
127.  		const char *where = 0;
128.  		register char sym, oc_of_sym, *p;
129.  		/* additional choices */
130.  		ilets[iletct++] = ' ';
131.  		ilets[iletct++] = 'a';
132.  		ilets[iletct++] = 'A';
133.  		ilets[iletct++] = (objs == invent ? 'i' : ':');
134.  		ilets[iletct] = '\0';
135.  ask_again:
136.  		olets[oletct = 0] = '\0';
137.  		*one_at_a_time = *everything = FALSE;
138.  		Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
139.  			action, ilets);
140.  		getlin(qbuf,inbuf);
141.  		if (*inbuf == '\033') {
142.  			clear_nhwindow(WIN_MESSAGE);
143.  			return FALSE;
144.  		}
145.  		for (p = inbuf; (sym = *p++); ) {
146.  		    /* new A function (selective all) added by GAN 01/09/87 */
147.  		    if (sym == ' ') continue;
148.  		    else if (sym == 'A') *one_at_a_time = TRUE;
149.  		    else if (sym == 'a') *everything = TRUE;
150.  		    else if (sym == ':') {
151.  			simple_look(objs, here);  /* dumb if objs==invent */
152.  			goto ask_again;
153.  		    } else if (sym == 'i') {
154.  			(void) display_inventory(NULL, FALSE);
155.  			goto ask_again;
156.  		    } else {
157.  			oc_of_sym = def_char_to_objclass(sym);
158.  			if (index(ilets,sym)) {
159.  			    olets[oletct++] = oc_of_sym;
160.  			    olets[oletct] = '\0';
161.  			} else {
162.  			    if (!where)
163.  				where = !strcmp(action,"pick up")  ? "here" :
164.  					!strcmp(action,"take out") ?
165.  							    "inside" : "";
166.  			    if (*where)
167.  				pline("There are no %c's %s.", sym, where);
168.  			    else
169.  				You("have no %c's.", sym);
170.  			}
171.  		    }
172.  		}
173.  		if (!oletct && !*everything) *one_at_a_time = TRUE;
174.  	}
175.  	return TRUE;
176.  }
177.  
178.  void
179.  pickup(all)
180.  int all;	/* all >= 0 => yes/no; < 0 => -count */
181.  {
182.  	register struct obj *obj;
183.  	struct obj *obj2, *objx;
184.  	boolean all_of_a_type = FALSE, selective = FALSE;
185.  	char olets[20];
186.  	long count;
187.  
188.  	count = (all < 0) ? (-1L * all) : 0L;
189.  	if (count) all = 0;
190.  
191.  	if(Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
192.  		if ((multi && !flags.run) || (all && !flags.pickup))
193.  			read_engr_at(u.ux,u.uy);
194.  		return;
195.  	}
196.  
197.  	/* multi && !flags.run means they are in the middle of some other
198.  	 * action, or possibly paralyzed, sleeping, etc.... and they just
199.  	 * teleported onto the object.  They shouldn't pick it up.
200.  	 */
201.  	if ((multi && !flags.run) || (all && !flags.pickup)) {
202.  		int ct = 0;
203.  
204.  		for (obj = level.objects[u.ux][u.uy]; obj;
205.  						 obj = obj->nexthere)
206.  			if(obj != uchain)
207.  				ct++;
208.  
209.  		/* If there are objects here, take a look.
210.  		 */
211.  		if (ct) {
212.  			if (flags.run)
213.  				nomul(0);
214.  			flush_screen(1);
215.  			if (ct < 5)
216.  				(void) dolook();
217.  			else {
218.  				read_engr_at(u.ux,u.uy);
219.  				pline("There are several objects here.");
220.  			}
221.  		} else read_engr_at(u.ux,u.uy);
222.  		return;
223.  	}
224.  
225.  	/* check for more than one object */
226.  	if(!all) {
227.  		register int ct = 0;
228.  
229.  		for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
230.  			ct++;
231.  		if(ct < 2)
232.  			all++;
233.  		else {
234.  			pline("There are several objects here.");
235.  			count = 0;
236.  		}
237.  	}
238.  
239.  #ifdef POLYSELF
240.  	if (nolimbs(uasmon)) {
241.  		You("cannot pick things up without limbs.");
242.  		return;
243.  	}
244.  #endif
245.  
246.  	/* added by GAN 10/24/86 to allow selective picking up */
247.  	if (!all) {
248.  		if (!query_classes(olets, &selective, &all_of_a_type,
249.  			  "pick up", level.objects[u.ux][u.uy], TRUE, FALSE))
250.  			return;
251.  	}
252.  	if(all_of_a_type && !olets[0]) all = TRUE;
253.  
254.  	for(obj = level.objects[u.ux][u.uy]; obj; obj = obj2) {
255.  		obj2 = obj->nexthere;	/* perhaps obj will be picked up */
256.  		objx = 0;
257.  		if(flags.run) nomul(0);
258.  
259.  		if(!all)  {
260.  		    if(!selective && !index(olets,obj->oclass)) continue;
261.  
262.  		    if (!all_of_a_type) {
263.  			char qbuf[QBUFSZ];
264.  			Sprintf(qbuf,"Pick up %s?", doname(obj));
265.  			switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
266.  			case 'q': return;
267.  			case 'n': continue;
268.  			case 'a':
269.  			    all_of_a_type = TRUE;
270.  			    if (selective) {
271.  				selective = FALSE;
272.  				olets[0] = obj->oclass;
273.  				olets[1] = '\0';
274.  			    }
275.  			    break;
276.  			case '#':	/* count was entered */
277.  			    if (!yn_number) continue; /* 0 count => No */
278.  			    else count = yn_number;
279.  			    /* fall thru :-} */
280.  			default:	/* 'y' */
281.  			    break;
282.  			}
283.  		    }
284.  		}
285.  
286.  		if (count) {
287.  		    /* Pickup a specific number of items; split the object
288.  		       unless count corresponds to full quantity.  1 special
289.  		       case:  cursed loadstones will remain as merged unit.
290.  		     */
291.  		    if (count < obj->quan &&
292.  			    (!obj->cursed || obj->otyp != LOADSTONE)) {
293.  			objx = splitobj(obj, count);
294.  			if (!objx || objx->nexthere != obj2)
295.  			    impossible("bad object split in pickup");
296.  		    }
297.  		    count = 0;	/* reset */
298.  		}
299.  		if (pickup_object(obj, objx)) break;
300.  	}
301.  
302.  	/*
303.  	 *  Re-map what is at the hero's location after the pickup so the
304.  	 *  map is correct.
305.  	 */
306.  	newsym(u.ux,u.uy);
307.  }
308.  
309.  /*
310.   * Pick up an object from the ground or out of a container and add it to
311.   * the inventory.  Returns true if pickup() should break out of its loop.
312.   */
313.  static boolean
314.  pickup_object(obj, objx)
315.  struct obj *obj, *objx;
316.  {
317.  	int wt, nearload;
318.  	long pickquan;
319.  
320.  	if (obj == uchain) {    /* do not pick up attached chain */
321.  	    return FALSE;
322.  	} else if (obj->oartifact && !touch_artifact(obj,&youmonst)) {
323.  	    return FALSE;
324.  	} else if (obj->otyp == GOLD_PIECE) {
325.  	    /*
326.  	     *  Special consideration for gold pieces...
327.  	     */
328.  	    long iw = (long)max_capacity() - ((u.ugold + 50L) / 100L);
329.  	    long gold_capacity = ((-iw) * 100L) - 50L + 99L - u.ugold;
330.  
331.  	    if (gold_capacity <= 0L) {
332.  		if (objx) unsplitobj(obj, objx, 0L);
333.         pline("There %s %ld gold piece%s here, but you cannot carry any more.",
334.  			(obj->quan == 1L) ? "is" : "are",
335.  			obj->quan, plur(obj->quan));
336.  		return FALSE;
337.  	    } else if (gold_capacity < obj->quan) {
338.  		if (objx) unsplitobj(obj, objx, 0L);
339.  		You("can only carry %s of the %ld gold pieces lying here.",
340.  		    gold_capacity == 1L ? "one" : "some", obj->quan);
341.  		pline("%s %ld gold piece%s.",
342.  		    nearloadmsg, gold_capacity, plur(gold_capacity));
343.  		u.ugold += gold_capacity;
344.  		obj->quan -= gold_capacity;
345.  		costly_gold(obj->ox, obj->oy, gold_capacity);
346.  	    } else {
347.  		u.ugold += obj->quan;
348.  		if ((nearload = near_capacity()) != 0)
349.  		    pline("%s %ld gold piece%s.",
350.  			  nearload < MOD_ENCUMBER ?
351.  			  moderateloadmsg : nearloadmsg,
352.  			  obj->quan, plur(obj->quan));
353.  		else
354.  		    prinv(NULL, obj, 0L);
355.  		costly_gold(obj->ox, obj->oy, obj->quan);
356.  		delobj(obj);
357.  	    }
358.  	    flags.botl = 1;
359.  	    if (flags.run) nomul(0);
360.  	    return FALSE;
361.  	} else if (obj->otyp == CORPSE) {
362.  
363.  	    if (obj->corpsenm == PM_COCKATRICE && !uarmg
364.  #ifdef POLYSELF
365.  		&& !resists_ston(uasmon)
366.  #endif
367.  	    ) {
368.  #ifdef POLYSELF
369.  		if (poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
370.  		    display_nhwindow(WIN_MESSAGE, FALSE);
371.  		else
372.  #endif
373.  		{
374.  		  pline("Touching the cockatrice corpse is a fatal mistake.");
375.  		    You("turn to stone.");
376.  		    You("die...");
377.  		    killer_format = KILLED_BY_AN;
378.  		    killer = "cockatrice corpse";
379.  		    done(STONING);
380.  		}
381.  	    } else if (is_rider(&mons[obj->corpsenm])) {
382.  		pline("At your touch, the corpse suddenly moves...");
383.  		revive_corpse(obj, 1, FALSE);
384.  		exercise(A_WIS, FALSE);
385.  		return FALSE;
386.  	    }
387.  
388.  	} else  if (obj->otyp == SCR_SCARE_MONSTER) {
389.  	    if (obj->blessed) obj->blessed = 0;
390.  	    else if (!obj->spe && !obj->cursed) obj->spe = 1;
391.  	    else {
392.  		pline("The scroll%s turn%s to dust as you pick %s up.",
393.  			plur(obj->quan), (obj->quan == 1L) ? "s" : "",
394.  			(obj->quan == 1L) ? "it" : "them");
395.  		if (!(objects[SCR_SCARE_MONSTER].oc_name_known) &&
396.  				    !(objects[SCR_SCARE_MONSTER].oc_uname))
397.  		    docall(obj);
398.  		useupf(obj);
399.  		return FALSE;
400.  	    }
401.  	}
402.  
403.  	wt = max_capacity() + (int)obj->owt;
404.  	if (obj->otyp == LOADSTONE)
405.  	    goto lift_some;     /* pick it up even if too heavy */
406.  #ifdef POLYSELF
407.  	if (obj->otyp == BOULDER && throws_rocks(uasmon)) {
408.  	    goto lift_some;
409.  	}
410.  #endif
411.  	if (wt > 0) {
412.  	    if (obj->quan > 1L) {
413.  		/* see how many we can lift */
414.  		long qq, savequan = obj->quan;
415.  		int iw = max_capacity();
416.  		/*  This is correct only because containers */
417.  		/*  don't merge.	-dean		    */
418.  		for (qq = 1; qq < savequan; qq++) {
419.  			obj->quan = qq;
420.  			if (iw + weight(obj) > 0)
421.  				break;
422.  		}
423.  		obj->quan = savequan;
424.  		qq--;
425.  		/* we can carry qq of them */
426.  		if (qq) {
427.  		    if (objx) {		/* temporarily unsplit */
428.  			savequan = obj->quan;
429.  			obj->quan += objx->quan;
430.  		    }
431.  		    You("can only carry %s of the %s lying here.",
432.  			(qq == 1L) ? "one" : "some", doname(obj));
433.  		    if (objx) {		/* re-do the prior split */
434.  			obj->quan = savequan;
435.  			unsplitobj(obj, objx, qq);
436.  		    } else {		/* split into two groups */
437.  			objx = splitobj(obj, qq);
438.  			if (objx->otyp == SCR_SCARE_MONSTER) objx->spe = 0;
439.  		    }
440.  		    goto lift_some;
441.  		}
442.  	    }
443.  	    if (objx) unsplitobj(obj, objx, 0L);
444.  	    pline("There %s %s here, but %s.",
445.  		    (obj->quan == 1L) ? "is" : "are", doname(obj),
446.  		    !invent ? (obj->quan == 1L ?
447.  				"it is too heavy for you to lift" :
448.  				"they are too heavy for you to lift") :
449.  			"you cannot carry any more");
450.  	    if (obj->otyp == SCR_SCARE_MONSTER) obj->spe = 0;
451.  	    return TRUE;
452.  	}
453.  
454.  lift_some:
455.  	if (inv_cnt() >= 52) {
456.  	    if (objx) unsplitobj(obj, objx, 0L);
457.  	    Your("knapsack cannot accommodate any more items.");
458.  	    if (obj->otyp == SCR_SCARE_MONSTER) obj->spe = 0;
459.  	    return TRUE;
460.  	}
461.  
462.  	pickquan = obj->quan;	/* save number picked up */
463.  	obj = pick_obj(obj);
464.  
465.  	if (!Blind) obj->dknown = 1;
466.  	if (uwep && uwep == obj) mrg_to_wielded = TRUE;
467.  	nearload = near_capacity();
468.  	prinv(nearload > SLT_ENCUMBER ? nearloadmsg :
469.  	      nearload > UNENCUMBERED ? moderateloadmsg : NULL,
470.  	      obj, pickquan);
471.  	mrg_to_wielded = FALSE;
472.  	return FALSE;
473.  }
474.  
475.  /* Gold never reaches this routine. */
476.  struct obj *
477.  pick_obj(otmp)
478.  register struct obj *otmp;
479.  {
480.  	freeobj(otmp);
481.  	if (*u.ushops && costly_spot(u.ux, u.uy) &&
482.  	    otmp != uball)     /* don't charge for this - kd, 1/17/90 */
483.  	   /* sets obj->unpaid if necessary */
484.  	    addtobill(otmp, TRUE, FALSE, FALSE);
485.  	if(Invisible) newsym(u.ux,u.uy);
486.  	return(addinv(otmp));    /* might merge it with other objects */
487.  }
488.  
489.  /*
490.   * prints a message if encumbrance changed since the last check and
491.   * returns the new encumbrance value (from near_capacity()).
492.   */
493.  int
494.  encumber_msg()
495.  {
496.      static int oldcap = UNENCUMBERED;
497.      int newcap = near_capacity();
498.  
499.      if(oldcap < newcap) {
500.  	switch(newcap) {
501.  	case 1: Your("movements are slowed slightly because of your load.");
502.  		break;
503.  	case 2: You("rebalance your load.  Movement is difficult.");
504.  		break;
505.  	case 3: You("stagger under your heavy load.  Movement is very hard.");
506.  		break;
507.  	default: You("can barely move a handspan with this load!");
508.  		break;
509.  	}
510.  	flags.botl = 1;
511.      } else if(oldcap > newcap) {
512.  	switch(newcap) {
513.  	case 0: Your("movements are now unencumbered.");
514.  		break;
515.  	case 1: Your("movements are only slowed slightly by your load.");
516.  		break;
517.  	case 2: You("rebalance your load.  Movement is still difficult.");
518.  		break;
519.  	case 3: You("stagger under your load.  Movement is still very hard.");
520.  		break;
521.  	}
522.  	flags.botl = 1;
523.      }
524.  
525.      oldcap = newcap;
526.      return (newcap);
527.  }
528.  
529.  int
530.  doloot()	/* loot a container on the floor. */
531.  {
532.  	register struct obj *cobj, *nobj;
533.  	register int c;
534.  	int timepassed = 0;
535.  
536.  	if (Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
537.  		You("cannot reach the floor.");
538.  		return(0);
539.  	}
540.  	if(is_pool(u.ux, u.uy)) {
541.  		You("cannot loot things that are deep in the water.");
542.  		return(0);
543.  	}
544.  
545.  #ifdef POLYSELF
546.  	if(nolimbs(uasmon)) {
547.  		You("cannot loot things without limbs.");
548.  		return(0);
549.  	}
550.  #endif
551.  
552.  	for(cobj = level.objects[u.ux][u.uy]; cobj; cobj = nobj) {
553.  		nobj = cobj->nexthere;
554.  
555.  		if(Is_container(cobj)) {
556.  		    char qbuf[QBUFSZ];
557.  
558.  		    Sprintf(qbuf, "There is %s here, loot it?", doname(cobj));
559.  		    c = ynq(qbuf);
560.  		    if(c == 'q') return (timepassed);
561.  		    if(c == 'n') continue;
562.  
563.  		    if(cobj->olocked) {
564.  			pline("Hmmm, it seems to be locked.");
565.  			continue;
566.  		    }
567.  		    if(cobj->otyp == BAG_OF_TRICKS) {
568.  			You("carefully open the bag...");
569.  			pline("It develops a huge set of teeth and bites you!");
570.  			c = rnd(10);
571.  			if(Half_physical_damage) c = (c+1) / 2;
572.  			losehp(c, "carnivorous bag", KILLED_BY_AN);
573.  			makeknown(BAG_OF_TRICKS);
574.  			timepassed = 1;
575.  			continue;
576.  		    }
577.  
578.  		    You("carefully open %s...", the(xname(cobj)));
579.  		    if (cobj->otrapped && chest_trap(cobj, FINGER, FALSE)) {
580.  			timepassed = 1;
581.  			continue;	/* explosion destroyed cobj */
582.  		    }
583.  		    if(multi < 0) return (1); /* a paralysis trap */
584.  
585.  		    timepassed |= use_container(cobj, 0);
586.  		}
587.  	}
588.  	return (timepassed);
589.  }
590.  
591.  /*
592.   * Decide whether an object being placed into a magic bag will cause
593.   * it to explode.  If the object is a bag itself, check recursively.
594.   */
595.  static boolean
596.  mbag_explodes(obj, depthin)
597.      struct obj *obj;
598.      int depthin;
599.  {
600.      /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
601.      if ((Is_mbag(obj) || (obj->otyp == WAN_CANCELLATION && obj->spe > 0)) &&
602.  	(rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin))
603.  	return TRUE;
604.      else if (Is_container(obj)) {
605.  	struct obj *otmp;
606.  
607.  	for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
608.  	    if (mbag_explodes(otmp, depthin+1)) return TRUE;
609.      }
610.      return FALSE;
611.  }
612.  
613.  /* A variable set in use_container(), to be used by the callback routines */
614.  /* chk_bg(), in_container(), and out_container() from askchain().	  */
615.  static struct obj NEARDATA *current_container;
616.  #define Icebox (current_container->otyp == ICE_BOX)
617.  
618.  STATIC_PTR int
619.  in_container(obj)
620.  register struct obj *obj;
621.  {
622.  	register struct obj *gold;
623.  	boolean is_gold = (obj->otyp == GOLD_PIECE);
624.  	boolean floor_container = !carried(current_container);
625.  	char buf[BUFSZ];
626.  
627.  	if (!current_container) {
628.  		impossible("<in> no current_container?");
629.  		return 0;
630.  	} else if (obj == uball || obj == uchain) {
631.  		You("must be kidding.");
632.  		return 0;
633.  	} else if (obj == current_container) {
634.  		pline("That would be an interesting topological exercise.");
635.  		return 0;
636.  	} else if (obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
637.  		Norep("You cannot %s something you are wearing.",
638.  			Icebox ? "refrigerate" : "stash");
639.  		return 0;
640.  	} else if ((obj->otyp == LOADSTONE) && obj->cursed) {
641.  		obj->bknown = 1;
642.  	      pline("The stone%s won't leave your person.", plur(obj->quan));
643.  		return 0;
644.  	} else if (obj->otyp == AMULET_OF_YENDOR ||
645.  		   obj->otyp == CANDELABRUM_OF_INVOCATION ||
646.  		   obj->otyp == BELL_OF_OPENING ||
647.  		   obj->otyp == SPE_BOOK_OF_THE_DEAD) {
648.  	/* Prohibit Amulets in containers; if you allow it, monsters can't
649.  	 * steal them.  It also becomes a pain to check to see if someone
650.  	 * has the Amulet.  Ditto for the Candelabrum, the Bell and the Book.
651.  	 */
652.  	    pline("%s cannot be confined in such trappings.", The(xname(obj)));
653.  	    return 0;
654.  	}
655.  #ifdef WALKIES
656.  	else if (obj->otyp == LEASH && obj->leashmon != 0) {
657.  		pline("%s is attached to your pet.", The(xname(obj)));
658.  		return 0;
659.  	}
660.  #endif
661.  	else if (obj == uwep) {
662.  		if (welded(obj)) {
663.  			weldmsg(obj, FALSE);
664.  			return 0;
665.  		}
666.  		setuwep((struct obj *) 0);
667.  		if (uwep) return 0;	/* unwielded, died, rewielded */
668.  	}
669.  
670.  	/* boxes can't fit into any container */
671.  	if (obj->otyp == ICE_BOX || Is_box(obj)) {
672.  		/*
673.  		 *  xname() uses a static result array.  Save obj's name
674.  		 *  before current_container's name is computed.  Don't
675.  		 *  use the result of strcpy() within You() --- the order
676.  		 *  of evaluation of the parameters is undefined.
677.  		 */
678.  		Strcpy(buf, the(xname(obj)));
679.  		You("cannot fit %s into %s.", buf,
680.  		    the(xname(current_container)));
681.  		return 0;
682.  	}
683.  
684.  	freeinv(obj);
685.  
686.  	if (is_gold) {	/* look for other gold within the container */
687.  		for (gold = current_container->cobj; gold; gold = gold->nobj)
688.  			if (gold->otyp == GOLD_PIECE) break;
689.  	} else
690.  		gold = 0;
691.  
692.  	if (gold) {
693.  		gold->quan += obj->quan;
694.  	} else {
695.  		obj->nobj = current_container->cobj;
696.  		current_container->cobj = obj;
697.  	}
698.  
699.  	current_container->owt = weight(current_container);
700.  
701.  	Strcpy(buf, the(xname(current_container)));
702.  	You("put %s into %s.", doname(obj), buf);
703.  
704.  	if (floor_container && costly_spot(u.ux, u.uy)) {
705.  		sellobj_state(TRUE);
706.  		sellobj(obj, u.ux, u.uy);
707.  		sellobj_state(FALSE);
708.  	}
709.  	(void) snuff_candle(obj); /* must follow the "put" msg */
710.  	if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN
711.  			&& !Is_candle(obj))
712.  		obj->age = monstermoves - obj->age; /* actual age */
713.  
714.  	else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
715.  		You("are blasted by a magical explosion!");
716.  
717.  		/* the !floor_container case is taken care of */
718.  		if(*u.ushops && costly_spot(u.ux, u.uy) && floor_container) {
719.  		    register struct monst *shkp;
720.  
721.  		    if ((shkp = shop_keeper(*u.ushops)) != 0)
722.  			(void)stolen_value(current_container, u.ux, u.uy,
723.  					   (boolean)shkp->mpeaceful, FALSE);
724.  		}
725.  		delete_contents(current_container);
726.  		if (!floor_container)
727.  			useup(current_container);
728.  		else if (obj_here(current_container, u.ux, u.uy))
729.  			useupf(current_container);
730.  		else
731.  			panic("in_container:  bag not found.");
732.  
733.  		losehp(d(6,6),"magical explosion", KILLED_BY_AN);
734.  		current_container = 0;	/* baggone = TRUE; */
735.  	}
736.  
737.  	if (is_gold) {
738.  		if (gold) dealloc_obj(obj);
739.  		bot();	/* update character's gold piece count immediately */
740.  	}
741.  
742.  	return(current_container ? 1 : -1);
743.  }
744.  
745.  STATIC_PTR int
746.  ck_bag(obj)
747.  struct obj *obj;
748.  {
749.  	return current_container && obj != current_container;
750.  }
751.  
752.  STATIC_PTR int
753.  out_container(obj)
754.  register struct obj *obj;
755.  {
756.  	register struct obj *otmp, *ootmp;
757.  	boolean is_gold = (obj->otyp == GOLD_PIECE);
758.  	int loadlev;
759.  	long quan;
760.  
761.  	if (!current_container) {
762.  		impossible("<out> no current_container?");
763.  		return -1;
764.  	} else if (is_gold) {
765.  		obj->owt = weight(obj);
766.  	} else if (inv_cnt() >= 52) {
767.  		You("have no room to hold anything else.");
768.  		return -1;	/* skips gold too; oh well */
769.  	}
770.  
771.  	if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0;
772.  
773.  	if(obj->otyp != LOADSTONE && max_capacity() + (int)obj->owt -
774.  	   (carried(current_container) ?
775.  	    (current_container->otyp == BAG_OF_HOLDING ?
776.  	     (int)DELTA_CWT(current_container,obj) : (int)obj->owt) : 0) > 0) {
777.  		char buf[BUFSZ];
778.  
779.  		Strcpy(buf, doname(obj));
780.  		pline("There %s %s in %s, but %s.",
781.  			obj->quan==1 ? "is" : "are",
782.  			buf, the(xname(current_container)),
783.  			invent ? "you cannot carry any more"
784.  			: "it is too heavy for you to carry");
785.  		/* "too heavy for you to lift" is not right if you're carrying
786.  		   the container... */
787.  		return(0);
788.  	}
789.  	/* Remove the object from the list. */
790.  	if (obj == current_container->cobj)
791.  		current_container->cobj = obj->nobj;
792.  	else {
793.  		for(otmp = current_container->cobj; otmp->nobj != obj;
794.  							    otmp = otmp->nobj)
795.  			if(!otmp->nobj) panic("out_container");
796.  		otmp->nobj = obj->nobj;
797.  	}
798.  
799.  	current_container->owt = weight(current_container);
800.  
801.  	if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN
802.  			&& !Is_candle(obj))
803.  		obj->age = monstermoves - obj->age;
804.  	/* simulated point of time */
805.  
806.  	if(!obj->unpaid && !carried(current_container) &&
807.  	     costly_spot(current_container->ox, current_container->oy)) {
808.  
809.  		addtobill(obj, FALSE, FALSE, FALSE);
810.  	}
811.  
812.  	quan = obj->quan;
813.  	ootmp = addinv(obj);
814.  	loadlev = near_capacity();
815.  	prinv(loadlev ?
816.  	      (loadlev < MOD_ENCUMBER ?
817.  	       "You have a little trouble removing" :
818.  	       "You have much trouble removing") : NULL,
819.  	      ootmp, quan);
820.  
821.  	if (is_gold) {
822.  		dealloc_obj(obj);
823.  		bot();	/* update character's gold piece count immediately */
824.  	}
825.  	return 1;
826.  }
827.  
828.  /* for getobj: allow counts, allow all types, expect food */
829.  static const char NEARDATA frozen_food[] =
830.  	{ ALLOW_COUNT, ALL_CLASSES, FOOD_CLASS, 0 };
831.  
832.  int
833.  use_container(obj, held)
834.  register struct obj *obj;
835.  register int held;
836.  {
837.  	register int cnt = 0;
838.  	register struct obj *curr, *prev, *otmp;
839.  	boolean one_by_one, allflag;
840.  	char select[MAXOCLASSES+1];
841.  	char qbuf[QBUFSZ];
842.  	int used = 0, lcnt = 0;
843.  	long loss = 0L;
844.  	register struct monst *shkp;
845.  
846.  	current_container = obj;	/* for use by in/out_container */
847.  	if (current_container->olocked) {
848.  		pline("%s seems to be locked.", The(xname(current_container)));
849.  		if (held) You("must put it down to unlock.");
850.  		return 0;
851.  	}
852.  	/* Count the number of contained objects. Sometimes toss objects if */
853.  	/* a cursed magic bag.						    */
854.  	for(curr = obj->cobj, prev = (struct obj *) 0; curr;
855.  					    prev = curr, curr = otmp) {
856.  	    otmp = curr->nobj;
857.  	    if (Is_mbag(obj) && obj->cursed && !rn2(13)) {
858.  		if (curr->known)
859.  		    pline("%s to have vanished!", The(aobjnam(curr,"seem")));
860.  		else
861.  		    You("%s %s disappear.", Blind ? "notice" : "see",
862.  							doname(curr));
863.  		if (prev)
864.  		    prev->nobj = otmp;
865.  		else
866.  		    obj->cobj = otmp;
867.  
868.  		if(*u.ushops && (shkp = shop_keeper(*u.ushops))) {
869.  		    if(held) {
870.  			if(curr->unpaid)
871.  			    loss += stolen_value(curr, u.ux, u.uy,
872.  					     (boolean)shkp->mpeaceful, TRUE);
873.  			lcnt++;
874.  		    } else if(costly_spot(u.ux, u.uy)) {
875.  			loss += stolen_value(curr, u.ux, u.uy,
876.  					     (boolean)shkp->mpeaceful, TRUE);
877.  			lcnt++;
878.  		    }
879.  		}
880.  		/* obfree() will free all contained objects */
881.  		obfree(curr, (struct obj *) 0);
882.  	    } else
883.  		cnt++;
884.  	}
885.  
886.  	if (cnt && loss)
887.  	    You("owe %ld zorkmids for lost item%s.",
888.  		loss, lcnt > 1 ? "s" : "");
889.  
890.  	current_container->owt = weight(current_container);
891.  
892.  	if(!cnt)
893.  	    pline("%s %s is empty.", (held) ? "Your" : "The", xname(obj));
894.  	else {
895.  	    Sprintf(qbuf, "Do you want to take something out of %s?",
896.  			the(xname(obj)));
897.  ask_again:
898.  	    switch (yn_function(qbuf, ":ynq", 'n')) {
899.  	    case ':':
900.  		container_contents(current_container, FALSE, FALSE);
901.  		goto ask_again;
902.  	    case 'y':
903.  		if (query_classes(select, &one_by_one, &allflag, "take out",
904.  				   current_container->cobj, FALSE, FALSE)) {
905.  		    if (askchain((struct obj **)&current_container->cobj,
906.  				 (one_by_one ? (char *)0 : select), allflag,
907.  				 out_container, (int (*)())0, 0, "nodot"))
908.  			used = 1;
909.  		}
910.  		/*FALLTHRU*/
911.  	    case 'n':
912.  		break;
913.  	    case 'q':
914.  	    default:
915.  		return 0;
916.  	    }
917.  	}
918.  
919.  	if (!invent && (u.ugold == 0 || Icebox)) return used;
920.  	if (yn_function("Do you wish to put something in?", ynqchars, 'n')
921.  	    != 'y') return used;
922.  	if (Icebox && current_container->dknown) {
923.  		otmp = getobj(frozen_food, "put in");
924.  		if(!otmp || !in_container(otmp))
925.  			flags.move = multi = 0;
926.  	} else {
927.  		if (query_classes(select, &one_by_one, &allflag, "put in",
928.  					   invent, FALSE, (u.ugold != 0L))) {
929.  		    struct obj *u_gold = (struct obj *)0;
930.  		    if (u.ugold && (one_by_one || (allflag && !*select)
931.  				    || index(select, GOLD_CLASS))) {
932.  			/* make gold object & insert at head of inventory */
933.  			u_gold = mkgoldobj(u.ugold);	/*(removes gold too)*/
934.  			u.ugold = u_gold->quan;		/* put the gold back */
935.  			u_gold->nobj = invent;
936.  			invent = u_gold;
937.  		    }
938.  		    used = (askchain((struct obj **)&invent,
939.  				(one_by_one ? (char *)0 : select), allflag,
940.  				in_container, ck_bag, 0, "nodot") > 0);
941.  		    if (u_gold && invent && invent->otyp == GOLD_PIECE) {
942.  			/* didn't stash [all of] it */
943.  			u_gold = invent;
944.  			invent = u_gold->nobj;
945.  			dealloc_obj(u_gold);
946.  		    }
947.  		}
948.  	}
949.  
950.  	return used;
951.  }
952.  
953.  /*pickup.c*/