Source:Pickup.c

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. 1.   /*	SCCS Id: @(#)pickup.c	3.4	2003/07/27	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.

5.   /*  6.     *	Contains code for picking objects up, and container use. 7.    */  8.     9.    #include "hack.h"  10. 11.  STATIC_DCL void FDECL(simple_look, (struct obj *,BOOLEAN_P)); 12.  #ifndef GOLDOBJ 13.  STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, 14.  		const char *,struct obj *,BOOLEAN_P,BOOLEAN_P,int *)); 15.  #else 16.  STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, 17.  		const char *,struct obj *,BOOLEAN_P,int *)); 18.  #endif 19.  STATIC_DCL void FDECL(check_here, (BOOLEAN_P)); 20.  STATIC_DCL boolean FDECL(n_or_more, (struct obj *)); 21.  STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *)); 22.  #if 0 /* not used */ 23.  STATIC_DCL boolean FDECL(allow_cat_no_uchain, (struct obj *)); 24.  #endif 25.  STATIC_DCL int FDECL(autopick, (struct obj*, int, menu_item **)); 26.  STATIC_DCL int FDECL(count_categories, (struct obj *,int)); 27.  STATIC_DCL long FDECL(carry_count,  28.   		      (struct obj *,struct obj *,long,BOOLEAN_P,int *,int *)); 29.  STATIC_DCL int FDECL(lift_object, (struct obj *,struct obj *,long *,BOOLEAN_P)); 30.  STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *,int)); 31.  STATIC_PTR int FDECL(in_container,(struct obj *)); 32.  STATIC_PTR int FDECL(ck_bag,(struct obj *)); 33.  STATIC_PTR int FDECL(out_container,(struct obj *)); 34.  STATIC_DCL long FDECL(mbag_item_gone, (int,struct obj *)); 35.  STATIC_DCL 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.   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.    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.   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.   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.   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.   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.   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.   314.  /* query_objlist callback: return TRUE */ 315. /*ARGSUSED*/ 316. boolean 317. allow_all(obj) 318. struct obj *obj; 319. {  320.      return TRUE; 321. }  322.   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.   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.  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.   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.   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.  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.   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.   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.   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.   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.  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.  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.  1232. /*  1233.  * Pick up 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.  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.  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.  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.  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.  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.  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.  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.  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.  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(" 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.  1918. STATIC_PTR int 1919. ck_bag(obj) 1920. struct obj *obj; 1921. { 1922. 	return current_container && obj != current_container; 1923. } 1924.  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(" 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.  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.  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. 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);		/* 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.  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.  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*/