Source:SLASH'EM 0.0.7E7F2/invent.c

From NetHackWiki
Jump to: navigation, search

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

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


The NetHack General Public License applies to screenshots, source code and other content from NetHack.

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: @(#)invent.c	3.4	2003/12/02	*/
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #define NOINVSYM	'#'
  8. #define CONTAINED_SYM	'>'	/* designator for inside a container */
  9.  
  10. #ifdef OVL1
  11. STATIC_DCL void NDECL(reorder_invent);
  12. STATIC_DCL boolean FDECL(mergable,(struct obj *,struct obj *));
  13. STATIC_DCL void FDECL(invdisp_nothing, (const char *,const char *));
  14. STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *));
  15. STATIC_DCL boolean FDECL(only_here, (struct obj *));
  16. #endif /* OVL1 */
  17. STATIC_DCL void FDECL(compactify,(char *));
  18. STATIC_DCL boolean FDECL(taking_off, (const char *));
  19. STATIC_DCL boolean FDECL(putting_on, (const char *));
  20. STATIC_PTR int FDECL(ckunpaid,(struct obj *));
  21. STATIC_PTR int FDECL(ckvalidcat,(struct obj *));
  22. static char FDECL(display_pickinv, (const char *,BOOLEAN_P, long *));
  23. #ifdef OVLB
  24. STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
  25. STATIC_DCL void NDECL(dounpaid);
  26. STATIC_DCL struct obj *FDECL(find_unpaid,(struct obj *,struct obj **));
  27. STATIC_DCL void FDECL(menu_identify, (int));
  28. STATIC_DCL boolean FDECL(tool_in_use, (struct obj *));
  29. #endif /* OVLB */
  30. STATIC_DCL char FDECL(obj_to_let,(struct obj *));
  31.  
  32. /* define for getobj() */
  33. #define FOLLOW(curr, flags) \
  34. (((flags) & BY_NEXTHERE) ? (curr)->nexthere : (curr)->nobj)
  35.  
  36. #ifdef OVLB
  37.  
  38. static int lastinvnr = 51;	/* 0 ... 51 (never saved&restored) */
  39.  
  40. #ifdef WIZARD
  41. /* wizards can wish for venom, which will become an invisible inventory
  42. * item without this.  putting it in inv_order would mean venom would
  43. * suddenly become a choice for all the inventory-class commands, which
  44. * would probably cause mass confusion.  the test for inventory venom
  45. * is only WIZARD and not wizard because the wizard can leave venom lying
  46. * around on a bones level for normal players to find.
  47. */
  48. static char venom_inv[] = { VENOM_CLASS, 0 };	/* (constant) */
  49. #endif
  50.  
  51. void
  52. assigninvlet(otmp)
  53. register struct obj *otmp;
  54. {
  55. 	boolean inuse[52];
  56. 	register int i;
  57. 	register struct obj *obj;
  58.  
  59. #ifdef GOLDOBJ
  60. /* There is only one of these in inventory... */        
  61. if (otmp->oclass == COIN_CLASS) {
  62. 	    otmp->invlet = GOLD_SYM;
  63. 	    return;
  64. 	}
  65. #endif
  66.  
  67. 	for(i = 0; i < 52; i++) inuse[i] = FALSE;
  68. 	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
  69. 		i = obj->invlet;
  70. 		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
  71. 		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
  72. 		if(i == otmp->invlet) otmp->invlet = 0;
  73. 	}
  74. 	if((i = otmp->invlet) &&
  75. 	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
  76. 		return;
  77. 	for(i = lastinvnr+1; i != lastinvnr; i++) {
  78. 		if(i == 52) { i = -1; continue; }
  79. 		if(!inuse[i]) break;
  80. 	}
  81. 	otmp->invlet = (inuse[i] ? NOINVSYM :
  82. 			(i < 26) ? ('a'+i) : ('A'+i-26));
  83. 	lastinvnr = i;
  84. }
  85.  
  86. #endif /* OVLB */
  87. #ifdef OVL1
  88.  
  89. /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
  90. #define inv_rank(o) ((o)->invlet ^ 040)
  91.  
  92. /* sort the inventory; used by addinv() and doorganize() */
  93. STATIC_OVL void
  94. reorder_invent()
  95. {
  96. 	struct obj *otmp, *prev, *next;
  97. 	boolean need_more_sorting;
  98.  
  99. 	do {
  100. 	    /*
  101. 	     * We expect at most one item to be out of order, so this
  102. 	     * isn't nearly as inefficient as it may first appear.
  103. 	     */
  104. 	    need_more_sorting = FALSE;
  105. 	    for (otmp = invent, prev = 0; otmp; ) {
  106. 		next = otmp->nobj;
  107. 		if (next && inv_rank(next) < inv_rank(otmp)) {
  108. 		    need_more_sorting = TRUE;
  109. 		    if (prev) prev->nobj = next;
  110. 		    else      invent = next;
  111. 		    otmp->nobj = next->nobj;
  112. 		    next->nobj = otmp;
  113. 		    prev = next;
  114. 		} else {
  115. 		    prev = otmp;
  116. 		    otmp = next;
  117. 		}
  118. 	    }
  119. 	} while (need_more_sorting);
  120. }
  121.  
  122. #undef inv_rank
  123.  
  124. /* KMH, balance patch -- Idea by Wolfgang von Hansen <wvh@geodesy.inka.de>.
  125. * Harmless to character, yet deliciously evil.
  126. * Somewhat expensive, so don't use it often.
  127. *
  128. * Some players who depend upon fixinv complained.  They take damage
  129. * instead.
  130. */
  131. int jumble_pack ()
  132. {
  133. 	register struct obj *obj, *nobj, *otmp;
  134. 	register char let;
  135. 	register int dmg = 0;
  136.  
  137.  
  138. 	for (obj = invent; obj; obj = nobj)
  139. 	{
  140. 		nobj = obj->nobj;
  141. 		if (rn2(10))
  142. 			/* Skip it */;
  143. 		else if (flags.invlet_constant)
  144. 			dmg += 2;
  145. 		else {
  146. 			/* Remove it from the inventory list (but don't touch the obj) */
  147. 			extract_nobj(obj, &invent);
  148.  
  149. 			/* Determine the new letter */
  150. 			let = rnd(52) + 'A';
  151. 			if (let > 'Z')
  152. 				let = let - 'Z' + 'a' - 1;
  153.  
  154. 			/* Does another object share this letter? */
  155. 			for (otmp = invent; otmp; otmp = otmp->nobj)
  156. 				if (otmp->invlet == let)
  157. 					otmp->invlet = obj->invlet;
  158.  
  159. 			/* Add the item back into the inventory */
  160. 			obj->invlet = let;
  161. 			obj->nobj = invent; /* insert at beginning */
  162. 			obj->where = OBJ_INVENT;
  163. 			invent = obj;
  164. 		}
  165. 	}
  166.  
  167. 	/* Clean up */
  168. 	reorder_invent();
  169. 	return (dmg);
  170. }
  171.  
  172.  
  173. /* scan a list of objects to see whether another object will merge with
  174. one of them; used in pickup.c when all 52 inventory slots are in use,
  175. to figure out whether another object could still be picked up */
  176. struct obj *
  177. merge_choice(objlist, obj)
  178. struct obj *objlist, *obj;
  179. {
  180. 	struct monst *shkp;
  181. 	int save_nocharge;
  182.  
  183. 	if (obj->otyp == SCR_SCARE_MONSTER)	/* punt on these */
  184. 	    return (struct obj *)0;
  185. 	/* if this is an item on the shop floor, the attributes it will
  186. 	   have when carried are different from what they are now; prevent
  187. 	   that from eliciting an incorrect result from mergable() */
  188. 	save_nocharge = obj->no_charge;
  189. 	if (objlist == invent && obj->where == OBJ_FLOOR &&
  190. 		(shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
  191. 	    if (obj->no_charge) obj->no_charge = 0;
  192. 	    /* A billable object won't have its `unpaid' bit set, so would
  193. 	       erroneously seem to be a candidate to merge with a similar
  194. 	       ordinary object.  That's no good, because once it's really
  195. 	       picked up, it won't merge after all.  It might merge with
  196. 	       another unpaid object, but we can't check that here (depends
  197. 	       too much upon shk's bill) and if it doesn't merge it would
  198. 	       end up in the '#' overflow inventory slot, so reject it now. */
  199. 	    else if (inhishop(shkp)) return (struct obj *)0;
  200. 	}
  201. 	while (objlist) {
  202. 	    if (mergable(objlist, obj)) break;
  203. 	    objlist = objlist->nobj;
  204. 	}
  205. 	obj->no_charge = save_nocharge;
  206. 	return objlist;
  207. }
  208.  
  209. /* merge obj with otmp and delete obj if types agree */
  210. int
  211. merged(potmp, pobj)
  212. struct obj **potmp, **pobj;
  213. {
  214. 	register struct obj *otmp = *potmp, *obj = *pobj;
  215.  
  216. 	if(mergable(otmp, obj)) {
  217. 		/* Approximate age: we do it this way because if we were to
  218. 		 * do it "accurately" (merge only when ages are identical)
  219. 		 * we'd wind up never merging any corpses.
  220. 		 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
  221. 		 *
  222. 		 * Don't do the age manipulation if lit.  We would need
  223. 		 * to stop the burn on both items, then merge the age,
  224. 		 * then restart the burn.
  225. 		 */
  226. 		if (!obj->lamplit)
  227. 		    otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan))
  228. 			    / (otmp->quan + obj->quan);
  229.  
  230. 		otmp->quan += obj->quan;
  231. #ifdef GOLDOBJ
  232. /* temporary special case for gold objects!!!! */
  233. #endif
  234. 		if (otmp->oclass == COIN_CLASS) otmp->owt = weight(otmp);
  235. 		else otmp->owt += obj->owt;
  236. 		if(!otmp->onamelth && obj->onamelth)
  237. 			otmp = *potmp = oname(otmp, ONAME(obj));
  238. 		obj_extract_self(obj);
  239.  
  240. 		/* really should merge the timeouts */
  241. 		if (obj->lamplit) obj_merge_light_sources(obj, otmp);
  242. 		if (obj->timed) obj_stop_timers(obj);	/* follows lights */
  243.  
  244. 		/* fixup for `#adjust' merging wielded darts, daggers, &c */
  245. 		if (obj->owornmask && carried(otmp)) {
  246. 		    long wmask = otmp->owornmask | obj->owornmask;
  247.  
  248. 		    /* Both the items might be worn in competing slots;
  249. 		       merger preference (regardless of which is which):
  250. 			 primary weapon + alternate weapon -> primary weapon;
  251. 			 primary weapon + quiver -> primary weapon;
  252. 			 alternate weapon + quiver -> alternate weapon.
  253. 		       (Prior to 3.3.0, it was not possible for the two
  254. 		       stacks to be worn in different slots and `obj'
  255. 		       didn't need to be unworn when merging.) */
  256. 		    if (wmask & W_WEP) wmask = W_WEP;
  257. 		    else if (wmask & W_SWAPWEP) wmask = W_SWAPWEP;
  258. 		    else if (wmask & W_QUIVER) wmask = W_QUIVER;
  259. 		    else {
  260. 			impossible("merging strangely worn items (%lx)", wmask);
  261. 			wmask = otmp->owornmask;
  262. 		    }
  263. 		    if ((otmp->owornmask & ~wmask) != 0L) setnotworn(otmp);
  264. 		    setworn(otmp, wmask);
  265. 		    setnotworn(obj);
  266. 		}
  267. #if 0
  268. 		/* (this should not be necessary, since items
  269. 		    already in a monster's inventory don't ever get
  270. 		    merged into other objects [only vice versa]) */
  271. 		else if (obj->owornmask && mcarried(otmp)) {
  272. 		    if (obj == MON_WEP(otmp->ocarry)) {
  273. 			MON_WEP(otmp->ocarry) = otmp;
  274. 			otmp->owornmask = W_WEP;
  275. 		    }
  276. 		}
  277. #endif /*0*/
  278.  
  279. 		obfree(obj,otmp);	/* free(obj), bill->otmp */
  280. 		return(1);
  281. 	}
  282. 	return 0;
  283. }
  284.  
  285. /*
  286. Adjust hero intrinsics as if this object was being added to the hero's
  287. inventory.  Called _before_ the object has been added to the hero's
  288. inventory.
  289.  
  290. This is called when adding objects to the hero's inventory normally (via
  291. addinv) or when an object in the hero's inventory has been polymorphed
  292. in-place.
  293.  
  294. It may be valid to merge this code with with addinv_core2().
  295. */
  296. void
  297. addinv_core1(obj)
  298. struct obj *obj;
  299. {
  300. 	if (obj->oclass == COIN_CLASS) {
  301. #ifndef GOLDOBJ
  302. 		u.ugold += obj->quan;
  303. #else
  304. 		flags.botl = 1;
  305. #endif
  306. 	} else if (obj->otyp == AMULET_OF_YENDOR) {
  307. 		if (u.uhave.amulet) impossible("already have amulet?");
  308. 		u.uhave.amulet = 1;
  309. 	} else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
  310. 		if (u.uhave.menorah) impossible("already have candelabrum?");
  311. 		u.uhave.menorah = 1;
  312. 	} else if (obj->otyp == BELL_OF_OPENING) {
  313. 		if (u.uhave.bell) impossible("already have silver bell?");
  314. 		u.uhave.bell = 1;
  315. 	} else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
  316. 		if (u.uhave.book) impossible("already have the book?");
  317. 		u.uhave.book = 1;
  318. 	} else if (obj->oartifact) {
  319. 		if (is_quest_artifact(obj)) {
  320. 		    if (u.uhave.questart)
  321. 			impossible("already have quest artifact?");
  322. 		    u.uhave.questart = 1;
  323. 		    artitouch();
  324. 		}
  325. 		set_artifact_intrinsic(obj, 1, W_ART);
  326.  
  327. 	}
  328. }
  329.  
  330. /*
  331. Adjust hero intrinsics as if this object was being added to the hero's
  332. inventory.  Called _after_ the object has been added to the hero's
  333. inventory.
  334.  
  335. This is called when adding objects to the hero's inventory normally (via
  336. addinv) or when an object in the hero's inventory has been polymorphed
  337. in-place.
  338. */
  339. void
  340. addinv_core2(obj)
  341. struct obj *obj;
  342. {
  343. 	if (confers_luck(obj)) {
  344. 		/* new luckstone must be in inventory by this point
  345. 		 * for correct calculation */
  346. 		set_moreluck();
  347. 	}
  348.  
  349. 	/* KMH, balance patch -- recalculate health if you've gained healthstones */
  350. 	if (obj->otyp == HEALTHSTONE)
  351. 		recalc_health();
  352.  
  353. }
  354.  
  355. /*
  356. Add obj to the hero's inventory.  Make sure the object is "free".
  357. Adjust hero attributes as necessary.
  358. */
  359. struct obj *
  360. addinv(obj)
  361. struct obj *obj;
  362. {
  363. 	struct obj *otmp, *prev;
  364.  
  365. 	if (obj->where != OBJ_FREE)
  366. 	    panic("addinv: obj not free");
  367. 	obj->no_charge = 0;	/* not meaningful for invent */
  368.  
  369. 	addinv_core1(obj);
  370. #ifndef GOLDOBJ
  371. 	/* if handed gold, we're done */
  372. 	if (obj->oclass == COIN_CLASS)
  373. 	    return obj;
  374. #endif
  375.  
  376. 	/* merge if possible; find end of chain in the process */
  377. 	for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
  378. 	    if (merged(&otmp, &obj)) {
  379. 		obj = otmp;
  380. 		goto added;
  381. 	    }
  382. 	/* didn't merge, so insert into chain */
  383. 	if (flags.invlet_constant || !prev) {
  384. 	    if (flags.invlet_constant) assigninvlet(obj);
  385. 	    obj->nobj = invent;		/* insert at beginning */
  386. 	    invent = obj;
  387. 	    if (flags.invlet_constant) reorder_invent();
  388. 	} else {
  389. 	    prev->nobj = obj;		/* insert at end */
  390. 	    obj->nobj = 0;
  391. 	}
  392. 	obj->where = OBJ_INVENT;
  393.  
  394. added:
  395. 	addinv_core2(obj);
  396. 	carry_obj_effects(&youmonst, obj); /* carrying affects the obj */
  397. 	update_inventory();
  398. 	return(obj);
  399. }
  400. /*
  401. * Some objects are affected by being carried.
  402. * Make those adjustments here. Called _after_ the object
  403. * has been added to the hero's or monster's inventory,
  404. * and after hero's intrinsics have been updated.
  405. */
  406. void
  407. carry_obj_effects(mon, obj)
  408. struct monst *mon;
  409. struct obj *obj;
  410. {
  411. 	/* Cursed figurines can spontaneously transform
  412. 	   when carried. */
  413. 	if (obj->otyp == FIGURINE) {
  414. 		if (obj->cursed
  415. 	    	    && obj->corpsenm != NON_PM
  416. 	    	    && !dead_species(obj->corpsenm,TRUE)) {
  417. 			attach_fig_transform_timeout(obj);
  418. 		    }
  419. 	}
  420. 	else if (obj->otyp == TORCH && obj->lamplit) {
  421. 	  /* MRKR: extinguish torches before putting them */
  422. 	  /*       away. Should monsters do the same?  */
  423.  
  424. 	  if (mon == &youmonst) {
  425. 	    You("extinguish %s before putting it away.", 
  426. 		yname(obj));
  427. 	    end_burn(obj, TRUE);
  428. 	  }
  429. 	}	
  430. }
  431.  
  432. #endif /* OVL1 */
  433. #ifdef OVLB
  434.  
  435. /* Add an item to the inventory unless we're fumbling or it refuses to be
  436. * held (via touch_artifact), and give a message.
  437. * If there aren't any free inventory slots, we'll drop it instead.
  438. * If both success and failure messages are NULL, then we're just doing the
  439. * fumbling/slot-limit checking for a silent grab.  In any case,
  440. * touch_artifact will print its own messages if they are warranted.
  441. */
  442. struct obj *
  443. hold_another_object(obj, drop_fmt, drop_arg, hold_msg)
  444. struct obj *obj;
  445. const char *drop_fmt, *drop_arg, *hold_msg;
  446. {
  447. 	char buf[BUFSZ];
  448.  
  449. #ifndef INVISIBLE_OBJECTS
  450. 	if (!Blind) obj->dknown = 1;	/* maximize mergibility */
  451. #else
  452. 	if (!Blind && (!obj->oinvis || See_invisible)) obj->dknown = 1;
  453. #endif
  454. 	if (obj->oartifact) {
  455. 	    /* place_object may change these */
  456. 	    boolean crysknife = (obj->otyp == CRYSKNIFE);
  457. 	    int oerode = obj->oerodeproof;
  458. 	    boolean wasUpolyd = Upolyd;
  459.  
  460. 	    /* in case touching this object turns out to be fatal */
  461. 	    place_object(obj, u.ux, u.uy);
  462.  
  463. 	    if (!touch_artifact(obj, &youmonst)) {
  464. 		obj_extract_self(obj);	/* remove it from the floor */
  465. 		dropy(obj);		/* now put it back again :-) */
  466. 		return obj;
  467. 	    } else if (wasUpolyd && !Upolyd) {
  468. 		/* loose your grip if you revert your form */
  469. 		if (drop_fmt) pline(drop_fmt, drop_arg);
  470. 		obj_extract_self(obj);
  471. 		dropy(obj);
  472. 		return obj;
  473. 	    }
  474. 	    obj_extract_self(obj);
  475. 	    if (crysknife) {
  476. 		obj->otyp = CRYSKNIFE;
  477. 		obj->oerodeproof = oerode;
  478. 	    }
  479. 	}
  480. 	if (Fumbling) {
  481. 	    if (drop_fmt) pline(drop_fmt, drop_arg);
  482. 	    dropy(obj);
  483. 	} else {
  484. 	    long oquan = obj->quan;
  485. 	    int prev_encumbr = near_capacity();	/* before addinv() */
  486.  
  487. 	    /* encumbrance only matters if it would now become worse
  488. 	       than max( current_value, stressed ) */
  489. 	    if (prev_encumbr < MOD_ENCUMBER) prev_encumbr = MOD_ENCUMBER;
  490. 	    /* addinv() may redraw the entire inventory, overwriting
  491. 	       drop_arg when it comes from something like doname() */
  492. 	    if (drop_arg) drop_arg = strcpy(buf, drop_arg);
  493.  
  494. 	    obj = addinv(obj);
  495. 	    if (inv_cnt() > 52
  496. 		    || ((obj->otyp != LOADSTONE || !obj->cursed)
  497. 			&& near_capacity() > prev_encumbr)) {
  498. 		if (drop_fmt) pline(drop_fmt, drop_arg);
  499. 		/* undo any merge which took place */
  500. 		if (obj->quan > oquan) obj = splitobj(obj, oquan);
  501. 		dropx(obj);
  502. 	    } else {
  503. 		if (flags.autoquiver && !uquiver && !obj->owornmask &&
  504. 			(is_missile(obj) ||
  505. 			    ammo_and_launcher(obj, uwep) ||
  506. 			    ammo_and_launcher(obj, uswapwep)))
  507. 		    setuqwep(obj);
  508. 		if (hold_msg || drop_fmt) prinv(hold_msg, obj, oquan);
  509. 	    }
  510. 	}
  511. 	return obj;
  512. }
  513.  
  514. /* useup() all of an item regardless of its quantity */
  515. void
  516. useupall(obj)
  517. struct obj *obj;
  518. {
  519. 	if (Has_contents(obj)) delete_contents(obj);
  520. 	setnotworn(obj);
  521. 	freeinv(obj);
  522. 	obfree(obj, (struct obj *)0);
  523. }
  524.  
  525. void
  526. useup(obj)
  527. register struct obj *obj;
  528. {
  529. 	/*  Note:  This works correctly for containers because they */
  530. 	/*	   (containers) don't merge.			    */
  531. 	if(obj->quan > 1L){
  532. 		obj->in_use = FALSE;	/* no longer in use */
  533. 		obj->quan--;
  534. 		obj->owt = weight(obj);
  535. 		update_inventory();
  536. 	} else {
  537. 		useupall(obj);
  538. 	}
  539. }
  540.  
  541. /* use one charge from an item and possibly incur shop debt for it */
  542. void
  543. consume_obj_charge(obj, maybe_unpaid)
  544. struct obj *obj;
  545. boolean maybe_unpaid;	/* false if caller handles shop billing */
  546. {
  547. 	if (maybe_unpaid) check_unpaid(obj);
  548. 	obj->spe -= 1;
  549. 	if (obj->known) update_inventory();
  550. }
  551.  
  552. #endif /* OVLB */
  553. #ifdef OVL3
  554.  
  555. /*
  556. Adjust hero's attributes as if this object was being removed from the
  557. hero's inventory.  This should only be called from freeinv() and
  558. where we are polymorphing an object already in the hero's inventory.
  559.  
  560. Should think of a better name...
  561. */
  562. void
  563. freeinv_core(obj)
  564. struct obj *obj;
  565. {
  566. 	if (obj->oclass == COIN_CLASS) {
  567. #ifndef GOLDOBJ
  568. 		u.ugold -= obj->quan;
  569. 		obj->in_use = FALSE;
  570. #endif
  571. 		flags.botl = 1;
  572. 		return;
  573. 	} else if (obj->otyp == AMULET_OF_YENDOR) {
  574. 		if (!u.uhave.amulet) impossible("don't have amulet?");
  575. 		u.uhave.amulet = 0;
  576. 	} else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
  577. 		if (!u.uhave.menorah) impossible("don't have candelabrum?");
  578. 		u.uhave.menorah = 0;
  579. 	} else if (obj->otyp == BELL_OF_OPENING) {
  580. 		if (!u.uhave.bell) impossible("don't have silver bell?");
  581. 		u.uhave.bell = 0;
  582. 	} else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
  583. 		if (!u.uhave.book) impossible("don't have the book?");
  584. 		u.uhave.book = 0;
  585. 	} else if (obj->oartifact) {
  586. 		if (is_quest_artifact(obj)) {
  587. 		    if (!u.uhave.questart)
  588. 			impossible("don't have quest artifact?");
  589. 		    u.uhave.questart = 0;
  590. 		}
  591. 		set_artifact_intrinsic(obj, 0, W_ART);
  592. 	}
  593.  
  594. 	if (obj->otyp == LOADSTONE) {
  595. 		curse(obj);
  596. 	} else if (confers_luck(obj)) {
  597. 		set_moreluck();
  598. 		flags.botl = 1;
  599. 	} else if (obj->otyp == HEALTHSTONE) {
  600. 	/* KMH, balance patch -- recalculate health if you've lost healthstones */
  601. 		recalc_health();
  602. 	} else if (obj->otyp == FIGURINE && obj->timed) {
  603. 		(void) stop_timer(FIG_TRANSFORM, (genericptr_t) obj);
  604. 	}
  605. }
  606.  
  607. /* remove an object from the hero's inventory */
  608. void
  609. freeinv(obj)
  610. register struct obj *obj;
  611. {
  612. 	extract_nobj(obj, &invent);
  613. 	freeinv_core(obj);
  614. 	update_inventory();
  615. }
  616.  
  617. void
  618. delallobj(x, y)
  619. int x, y;
  620. {
  621. 	struct obj *otmp, *otmp2;
  622.  
  623. 	for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
  624. 		if (otmp == uball)
  625. 			unpunish();
  626. 		/* after unpunish(), or might get deallocated chain */
  627. 		otmp2 = otmp->nexthere;
  628. 		if (otmp == uchain)
  629. 			continue;
  630. 		delobj(otmp);
  631. 	}
  632. }
  633.  
  634. #endif /* OVL3 */
  635. #ifdef OVL2
  636.  
  637. /* destroy object in fobj chain (if unpaid, it remains on the bill) */
  638. void
  639. delobj(obj)
  640. register struct obj *obj;
  641. {
  642. 	boolean update_map;
  643.  
  644. 	if (evades_destruction(obj)) {
  645. 		/* player might be doing something stupid, but we
  646. 		 * can't guarantee that.  assume special artifacts
  647. 		 * are indestructible via drawbridges, and exploding
  648. 		 * chests, and golem creation, and ...
  649. 		 */
  650. 		return;
  651. 	}
  652. 	update_map = (obj->where == OBJ_FLOOR || Has_contents(obj) &&
  653. 		(obj->where == OBJ_INVENT || obj->where == OBJ_MINVENT));
  654. 	if (Has_contents(obj)) delete_contents(obj);
  655. 	obj_extract_self(obj);
  656. 	if (update_map) newsym(obj->ox, obj->oy);
  657. 	obfree(obj, (struct obj *) 0);
  658. }
  659.  
  660. #endif /* OVL2 */
  661. #ifdef OVL0
  662.  
  663. struct obj *
  664. sobj_at(n,x,y)
  665. register int n, x, y;
  666. {
  667. 	register struct obj *otmp;
  668.  
  669. 	for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  670. 		if(otmp->otyp == n)
  671. 		    return(otmp);
  672. 	return((struct obj *)0);
  673. }
  674.  
  675. #endif /* OVL0 */
  676. #ifdef OVLB
  677.  
  678. struct obj *
  679. carrying(type)
  680. register int type;
  681. {
  682. 	register struct obj *otmp;
  683.  
  684. 	for(otmp = invent; otmp; otmp = otmp->nobj)
  685. 		if(otmp->otyp == type)
  686. 			return(otmp);
  687. 	return((struct obj *) 0);
  688. }
  689.  
  690. const char *
  691. currency(amount)
  692. long amount;
  693. {
  694. 	if (amount == 1L) return "zorkmid";
  695. 	else return "zorkmids";
  696. }
  697.  
  698. boolean
  699. have_lizard()
  700. {
  701. 	register struct obj *otmp;
  702.  
  703. 	for(otmp = invent; otmp; otmp = otmp->nobj)
  704. 		if(otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
  705. 			return(TRUE);
  706. 	return(FALSE);
  707. }
  708.  
  709. struct obj *
  710. o_on(id, objchn)
  711. unsigned int id;
  712. register struct obj *objchn;
  713. {
  714. 	struct obj *temp;
  715.  
  716. 	while(objchn) {
  717. 		if(objchn->o_id == id) return(objchn);
  718. 		if (Has_contents(objchn) && (temp = o_on(id,objchn->cobj)))
  719. 			return temp;
  720. 		objchn = objchn->nobj;
  721. 	}
  722. 	return((struct obj *) 0);
  723. }
  724.  
  725. boolean
  726. obj_here(obj, x, y)
  727. register struct obj *obj;
  728. int x, y;
  729. {
  730. 	register struct obj *otmp;
  731.  
  732. 	for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  733. 		if(obj == otmp) return(TRUE);
  734. 	return(FALSE);
  735. }
  736.  
  737. #endif /* OVLB */
  738. #ifdef OVL2
  739.  
  740. struct obj *
  741. g_at(x,y)
  742. register int x, y;
  743. {
  744. 	register struct obj *obj = level.objects[x][y];
  745. 	while(obj) {
  746. 	    if (obj->oclass == COIN_CLASS) return obj;
  747. 	    obj = obj->nexthere;
  748. 	}
  749. 	return((struct obj *)0);
  750. }
  751.  
  752. #endif /* OVL2 */
  753. #ifdef OVLB
  754. #ifndef GOLDOBJ
  755. /* Make a gold object from the hero's gold. */
  756. struct obj *
  757. mkgoldobj(q)
  758. register long q;
  759. {
  760. 	register struct obj *otmp;
  761.  
  762. 	otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
  763. 	u.ugold -= q;
  764. 	otmp->quan = q;
  765. 	otmp->owt = weight(otmp);
  766. 	flags.botl = 1;
  767. 	return(otmp);
  768. }
  769. #endif
  770. #endif /* OVLB */
  771. #ifdef OVL1
  772.  
  773. STATIC_OVL void
  774. compactify(buf)
  775. register char *buf;
  776. /* compact a string of inventory letters by dashing runs of letters */
  777. {
  778. 	register int i1 = 1, i2 = 1;
  779. 	register char ilet, ilet1, ilet2;
  780.  
  781. 	ilet2 = buf[0];
  782. 	ilet1 = buf[1];
  783. 	buf[++i2] = buf[++i1];
  784. 	ilet = buf[i1];
  785. 	while(ilet) {
  786. 		if(ilet == ilet1+1) {
  787. 			if(ilet1 == ilet2+1)
  788. 				buf[i2 - 1] = ilet1 = '-';
  789. 			else if(ilet2 == '-') {
  790. 				buf[i2 - 1] = ++ilet1;
  791. 				buf[i2] = buf[++i1];
  792. 				ilet = buf[i1];
  793. 				continue;
  794. 			}
  795. 		}
  796. 		ilet2 = ilet1;
  797. 		ilet1 = ilet;
  798. 		buf[++i2] = buf[++i1];
  799. 		ilet = buf[i1];
  800. 	}
  801. }
  802.  
  803. /* match the prompt for either 'T' or 'R' command */
  804. STATIC_OVL boolean
  805. taking_off(action)
  806. const char *action;
  807. {
  808. return !strcmp(action, "take off") || !strcmp(action, "remove");
  809. }
  810.  
  811. /* match the prompt for either 'W' or 'P' command */
  812. STATIC_OVL boolean
  813. putting_on(action)
  814. const char *action;
  815. {
  816. return !strcmp(action, "wear") || !strcmp(action, "put on");
  817. }
  818.  
  819. STATIC_OVL int
  820. ugly_checks(let, word, otmp)
  821. const char *let, *word;
  822. struct obj *otmp;
  823. {
  824. 		register int otyp = otmp->otyp;
  825. 		/* ugly check: remove inappropriate things */
  826. 		if((taking_off(word) &&
  827. 		    (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))
  828. 		     || (otmp==uarm && uarmc)
  829. #ifdef TOURIST
  830. 		     || (otmp==uarmu && (uarm || uarmc))
  831. #endif
  832. 		    ))
  833. 		|| (putting_on(word) &&
  834. 		     (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
  835. 							/* already worn */
  836. #if 0	/* 3.4.1 -- include currently wielded weapon among the choices */
  837. 		|| (!strcmp(word, "wield") &&
  838. 		    (otmp->owornmask & W_WEP))
  839. #endif
  840. 		|| (!strcmp(word, "ready") &&
  841. 		    (otmp == uwep || (otmp == uswapwep && u.twoweap)))
  842. 		    ) {
  843. 			return 1;
  844. 		}
  845.  
  846. 		/* Second ugly check; unlike the first it won't trigger an
  847. 		 * "else" in "you don't have anything else to ___".
  848. 		 */
  849. else if ((putting_on(word) &&
  850. 		    ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING) ||
  851. 		    (otmp->oclass == TOOL_CLASS &&
  852. 		     otyp != BLINDFOLD && otyp != TOWEL && otyp != LENSES)))
  853. /*add check for improving*/
  854. || ( (!strcmp(word, "wield") || !strcmp(word, "improve")) &&
  855. 		    (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
  856. 		|| (!strcmp(word, "eat") && !is_edible(otmp))
  857. 		|| (!strcmp(word, "revive") && otyp != CORPSE) /* revive */
  858. 		|| (!strcmp(word, "sacrifice") &&
  859. 		    (otyp != CORPSE &&
  860. 		     otyp != SEVERED_HAND &&                    
  861. 		     otyp != EYEBALL &&	/* KMH -- fixed */
  862. 		     otyp != AMULET_OF_YENDOR && otyp != FAKE_AMULET_OF_YENDOR))
  863. 		|| (!strcmp(word, "write with") &&
  864. 		    (otmp->oclass == TOOL_CLASS &&
  865. #ifdef LIGHTSABERS
  866. 		     (!is_lightsaber(otmp) || !otmp->lamplit) &&
  867. #endif
  868. 		     otyp != MAGIC_MARKER && otyp != TOWEL))
  869. 		|| (!strcmp(word, "tin") &&
  870. 		    (otyp != CORPSE || !tinnable(otmp)))
  871. 		|| (!strcmp(word, "rub") &&
  872. 		    ((otmp->oclass == TOOL_CLASS &&
  873. 		      otyp != OIL_LAMP && otyp != MAGIC_LAMP &&
  874. 		      otyp != BRASS_LANTERN) ||
  875. 		     (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
  876. 		|| (!strncmp(word, "rub on the stone", 16) &&
  877. 		    *let == GEM_CLASS &&	/* using known touchstone */
  878. 		    otmp->dknown && objects[otyp].oc_name_known)
  879. 		|| ((!strcmp(word, "use or apply") ||
  880. 			!strcmp(word, "untrap with")) &&
  881. 		     /* Picks, axes, pole-weapons, bullwhips */
  882. 		    ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) &&
  883. #ifdef FIREARMS
  884. 		      otyp != SUBMACHINE_GUN &&
  885. 		      otyp != AUTO_SHOTGUN &&
  886. 		      otyp != ASSAULT_RIFLE &&
  887. 		      otyp != FRAG_GRENADE &&
  888. 		      otyp != GAS_GRENADE &&
  889. 		      otyp != STICK_OF_DYNAMITE &&
  890. #endif
  891. 		      !is_axe(otmp) && !is_pole(otmp) && otyp != BULLWHIP) ||
  892. 		    (otmp->oclass == POTION_CLASS &&
  893. 		     /* only applicable potion is oil, and it will only
  894. 			be offered as a choice when already discovered */
  895. 		     (otyp != POT_OIL || !otmp->dknown ||
  896. 		      !objects[POT_OIL].oc_name_known) &&
  897. 		      /* water is only for untrapping */
  898. 		     (strcmp(word, "untrap with") || 
  899. 		      otyp != POT_WATER || !otmp->dknown ||
  900. 		      !objects[POT_WATER].oc_name_known)) ||
  901. 		     (otmp->oclass == FOOD_CLASS &&
  902. 		      otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF) ||
  903. 		     (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
  904. 		|| (!strcmp(word, "invoke") &&
  905. 		    (!otmp->oartifact && !objects[otyp].oc_unique &&
  906. 		     (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) &&
  907. 		     otyp != CRYSTAL_BALL &&	/* #invoke synonym for apply */
  908. 		   /* note: presenting the possibility of invoking non-artifact
  909. 		      mirrors and/or lamps is a simply a cruel deception... */
  910. 		     otyp != MIRROR && otyp != MAGIC_LAMP &&
  911. 		     (otyp != OIL_LAMP ||	/* don't list known oil lamp */
  912. 		      (otmp->dknown && objects[OIL_LAMP].oc_name_known))))
  913. 		|| (!strcmp(word, "untrap with") &&
  914. 		    (otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE))
  915. 		|| (!strcmp(word, "charge") && !is_chargeable(otmp))
  916. 		|| (!strcmp(word, "poison") && !is_poisonable(otmp))
  917. 		|| ((!strcmp(word, "draw blood with") ||
  918. 			!strcmp(word, "bandage your wounds with")) &&
  919. 		    (otmp->oclass == TOOL_CLASS && otyp != MEDICAL_KIT))
  920. 		    )
  921. 			return 2;
  922. 		else
  923. 		    return 0;
  924. }
  925.  
  926. /* List of valid classes for allow_ugly callback */
  927. static char valid_ugly_classes[MAXOCLASSES + 1];
  928.  
  929. /* Action word for allow_ugly callback */
  930. static const char *ugly_word;
  931.  
  932. STATIC_OVL boolean
  933. allow_ugly(obj)
  934. struct obj *obj;
  935. {
  936. return index(valid_ugly_classes, obj->oclass) &&
  937. 	   !ugly_checks(valid_ugly_classes, ugly_word, obj);
  938. }
  939.  
  940. /*
  941. * getobj returns:
  942. *	struct obj *xxx:	object to do something with.
  943. *	(struct obj *) 0	error return: no object.
  944. *	&zeroobj		explicitly no object (as in w-).
  945. *	&thisplace		this place (as in r.).
  946. #ifdef GOLDOBJ
  947. !!!! test if gold can be used in unusual ways (eaten etc.)
  948. !!!! may be able to remove "usegold"
  949. #endif
  950. */
  951. struct obj *
  952. getobj(let,word)
  953. register const char *let,*word;
  954. {
  955. 	register struct obj *otmp;
  956. 	register char ilet;
  957. 	char buf[BUFSZ], qbuf[QBUFSZ];
  958. 	char lets[BUFSZ], altlets[BUFSZ], *ap;
  959. 	register int foo = 0;
  960. 	register char *bp = buf;
  961. 	xchar allowcnt = 0;	/* 0, 1 or 2 */
  962. #ifndef GOLDOBJ
  963. 	boolean allowgold = FALSE;	/* can't use gold because they don't have any */
  964. #endif
  965. 	boolean usegold = FALSE;	/* can't use gold because its illegal */
  966. 	boolean allowall = FALSE;
  967. 	boolean allownone = FALSE;
  968. 	boolean allowfloor = FALSE;
  969. 	boolean usefloor = FALSE;
  970. 	boolean allowthisplace = FALSE;
  971. 	boolean useboulder = FALSE;
  972. 	xchar foox = 0;
  973. 	long cnt;
  974. 	boolean prezero = FALSE;
  975. 	long dummymask;
  976. 	int ugly;
  977. 	struct obj *floorchain;
  978. 	int floorfollow;
  979.  
  980. 	if(*let == ALLOW_COUNT) let++, allowcnt = 1;
  981. #ifndef GOLDOBJ
  982. 	if(*let == COIN_CLASS) let++,
  983. 		usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE);
  984. #else
  985. 	if(*let == COIN_CLASS) let++, usegold = TRUE;
  986. #endif
  987.  
  988. 	/* Equivalent of an "ugly check" for gold */
  989. 	if (usegold && !strcmp(word, "eat") &&
  990. 	    (!metallivorous(youmonst.data)
  991. 	     || youmonst.data == &mons[PM_RUST_MONSTER]))
  992. #ifndef GOLDOBJ
  993. 		usegold = allowgold = FALSE;
  994. #else
  995. 		usegold = FALSE;
  996. #endif
  997.  
  998. 	if(*let == ALL_CLASSES) let++, allowall = TRUE;
  999. 	if(*let == ALLOW_NONE) let++, allownone = TRUE;
  1000. 	if(*let == ALLOW_FLOOROBJ) {
  1001. 	    let++;
  1002. 	    if (!u.uswallow) {
  1003. 		floorchain = can_reach_floorobj() ? level.objects[u.ux][u.uy] :
  1004. 			     (struct obj *)0;
  1005. 		floorfollow = BY_NEXTHERE;
  1006. 	    } else {
  1007. 		floorchain = u.ustuck->minvent;
  1008. 		floorfollow = 0;		/* nobj */
  1009. 	    }
  1010. 	    usefloor = TRUE;
  1011. 	    allowfloor = !!floorchain;
  1012. 	}
  1013. 	if(*let == ALLOW_THISPLACE) let++, allowthisplace = TRUE;
  1014. 	/* "ugly check" for reading fortune cookies, part 1 */
  1015. 	/* The normal 'ugly check' keeps the object on the inventory list.
  1016. 	 * We don't want to do that for shirts/cookies, so the check for
  1017. 	 * them is handled a bit differently (and also requires that we set
  1018. 	 * allowall in the caller)
  1019. 	 */
  1020. 	if(allowall && !strcmp(word, "read")) allowall = FALSE;
  1021.  
  1022. 	/* another ugly check: show boulders (not statues) */
  1023. 	if(*let == WEAPON_CLASS &&
  1024. 	   !strcmp(word, "throw") && throws_rocks(youmonst.data))
  1025. 	    useboulder = TRUE;
  1026.  
  1027. 	if(allownone) *bp++ = '-';
  1028. #ifndef GOLDOBJ
  1029. 	if(allowgold) *bp++ = def_oc_syms[COIN_CLASS];
  1030. #endif
  1031. 	if(bp > buf && bp[-1] == '-') *bp++ = ' ';
  1032. 	ap = altlets;
  1033.  
  1034. 	ilet = 'a';
  1035. 	for (otmp = invent; otmp; otmp = otmp->nobj) {
  1036. 	    if (!flags.invlet_constant)
  1037. #ifdef GOLDOBJ
  1038. 		if (otmp->invlet != GOLD_SYM) /* don't reassign this */
  1039. #endif
  1040. 		otmp->invlet = ilet;	/* reassign() */
  1041. 	    if (!*let || index(let, otmp->oclass)
  1042. #ifdef GOLDOBJ
  1043. 		|| (usegold && otmp->invlet == GOLD_SYM)
  1044. #endif
  1045. 		|| (useboulder && otmp->otyp == BOULDER)
  1046. 		) {
  1047. 		bp[foo++] = otmp->invlet;
  1048.  
  1049. 		/* ugly checks */
  1050. 		ugly = ugly_checks(let, word, otmp);
  1051. 		if (ugly == 1) {
  1052. 		    foo--;
  1053. 		    foox++;
  1054. 		} else if (ugly == 2)
  1055. 		    foo--;
  1056. 		/* ugly check for unworn armor that can't be worn */
  1057. 		else if (putting_on(word) && *let == ARMOR_CLASS &&
  1058. 			 !canwearobj(otmp, &dummymask, FALSE)) {
  1059. 			foo--;
  1060. 			allowall = TRUE;
  1061. 			*ap++ = otmp->invlet;
  1062. 		}
  1063. 	    } else {
  1064.  
  1065. 		/* "ugly check" for reading fortune cookies, part 2 */
  1066. 		if ((!strcmp(word, "read") &&
  1067. 		    (otmp->otyp == FORTUNE_COOKIE
  1068. #ifdef TOURIST
  1069. 			|| otmp->otyp == T_SHIRT
  1070. #endif
  1071. 		    )))
  1072. 			allowall = TRUE;
  1073. 	    }
  1074.  
  1075. 	    if(ilet == 'z') ilet = 'A'; else ilet++;
  1076. 	}
  1077. 	bp[foo] = 0;
  1078. 	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
  1079. 	Strcpy(lets, bp);	/* necessary since we destroy buf */
  1080. 	if(foo > 5)			/* compactify string */
  1081. 		compactify(bp);
  1082. 	*ap = '\0';
  1083.  
  1084. 	if (allowfloor && !allowall) {
  1085. 	    if (usegold) {
  1086. 		valid_ugly_classes[0] = COIN_CLASS;
  1087. 		Strcpy(valid_ugly_classes + 1, let);
  1088. 	    } else
  1089. 		Strcpy(valid_ugly_classes, let);
  1090. 	    ugly_word = word;
  1091. 	    for (otmp = floorchain; otmp; otmp = FOLLOW(otmp, floorfollow))
  1092. 		if (allow_ugly(otmp))
  1093. 		    break;
  1094. 	    if (!otmp)
  1095. 		allowfloor = FALSE;
  1096. 	}
  1097.  
  1098. 	if(!foo && !allowall && !allownone &&
  1099. #ifndef GOLDOBJ
  1100. 	   !allowgold &&
  1101. #endif
  1102. 	   !allowfloor && !allowthisplace) {
  1103. 		You("don't have anything %sto %s.",
  1104. 			foox ? "else " : "", word);
  1105. 		return((struct obj *)0);
  1106. 	}
  1107.  
  1108. 	for(;;) {
  1109. 		cnt = 0;
  1110. 		if (allowcnt == 2) allowcnt = 1;  /* abort previous count */
  1111. 		Sprintf(qbuf, "What do you want to %s? [", word);
  1112. 		bp = eos(qbuf);
  1113. 		if (buf[0]) {
  1114. 		    Sprintf(bp, "%s or ?", buf);
  1115. 		    bp = eos(bp);
  1116. 		}
  1117. 		*bp++ = '*';
  1118. 		if (allowfloor)
  1119. 		    *bp++ = ',';
  1120. 		if (allowthisplace)
  1121. 		    *bp++ = '.';
  1122. 		if (!buf[0] && bp[-2] != '[') {
  1123. 		    /* "*," -> "* or ,"; "*." -> "* or ."; "*,." -> "*, or ." */
  1124. 		    --bp;
  1125. 		    Sprintf(bp, " or %c", *bp);
  1126. 		    bp += 5;
  1127. 		}
  1128. 		*bp++ = ']';
  1129. 		*bp = '\0';
  1130. #ifdef REDO
  1131. 		if (in_doagain)
  1132. 		    ilet = readchar();
  1133. 		else
  1134. #endif
  1135. 		    ilet = yn_function(qbuf, (char *)0, '\0');
  1136. 		if(ilet == '0') prezero = TRUE;
  1137. 		while(digit(ilet) && allowcnt) {
  1138. #ifdef REDO
  1139. 			if (ilet != '?' && ilet != '*')	savech(ilet);
  1140. #endif
  1141. 			cnt = 10*cnt + (ilet - '0');
  1142. 			allowcnt = 2;	/* signal presence of cnt */
  1143. 			ilet = readchar();
  1144. 		}
  1145. 		if(digit(ilet)) {
  1146. 			pline("No count allowed with this command.");
  1147. 			continue;
  1148. 		}
  1149. 		if(index(quitchars,ilet)) {
  1150. 		    if(flags.verbose)
  1151. 			pline(Never_mind);
  1152. 		    return((struct obj *)0);
  1153. 		}
  1154. 		if(ilet == '-') {
  1155. 			return(allownone ? &zeroobj : (struct obj *) 0);
  1156. 		}
  1157. 		if(ilet == def_oc_syms[COIN_CLASS]) {
  1158. 			if (!usegold) {
  1159. 			    if (!strncmp(word, "rub on ", 7)) {
  1160. 				/* the dangers of building sentences... */
  1161. 				You("cannot rub gold%s.", word + 3);
  1162. 			    } else {
  1163. 				You("cannot %s gold.", word);
  1164. 			    }
  1165. 			    return(struct obj *)0;
  1166. #ifndef GOLDOBJ
  1167. 			} else if (!allowgold) {
  1168. 				You("are not carrying any gold.");
  1169. 				return(struct obj *)0;
  1170. #endif
  1171. 			} 
  1172. 			if(cnt == 0 && prezero) return((struct obj *)0);
  1173. 			/* Historic note: early Nethack had a bug which was
  1174. 			 * first reported for Larn, where trying to drop 2^32-n
  1175. 			 * gold pieces was allowed, and did interesting things
  1176. 			 * to your money supply.  The LRS is the tax bureau
  1177. 			 * from Larn.
  1178. 			 */
  1179. 			if(cnt < 0) {
  1180. 	pline_The("LRS would be very interested to know you have that much.");
  1181. 				return(struct obj *)0;
  1182. 			}
  1183.  
  1184. #ifndef GOLDOBJ
  1185. 			if(!(allowcnt == 2 && cnt < u.ugold))
  1186. 				cnt = u.ugold;
  1187. 			return(mkgoldobj(cnt));
  1188. #endif
  1189. 		}
  1190. 		if(ilet == '.') {
  1191. 		    if (allowthisplace)
  1192. 			return &thisplace;
  1193. 		    else {
  1194. 			pline(silly_thing_to, word);
  1195. 			return(struct obj *)0;
  1196. 		    }
  1197. 		}
  1198. 		if(ilet == ',') {
  1199. 		    int n;
  1200. 		    menu_item *pick_list;
  1201.  
  1202. 		    if (!usefloor) {
  1203. 			pline(silly_thing_to, word);
  1204. 			return(struct obj *)0;
  1205. 		    } else if (!allowfloor) {
  1206. 			pline("There's nothing here to %s.", word);
  1207. 			return(struct obj *)0;
  1208. 		    }
  1209. 		    Sprintf(qbuf, "%s what?", word);
  1210. 		    n = query_objlist(qbuf, floorchain,
  1211. 			    floorfollow|INVORDER_SORT|SIGNAL_CANCEL, &pick_list,
  1212. 			    PICK_ONE, allowall ? allow_all : allow_ugly);
  1213. 		    if (n<0) {
  1214. 			if (flags.verbose)
  1215. 			    pline(Never_mind);
  1216. 			return (struct obj *)0;
  1217. 		    } else if (!n)
  1218. 			continue;
  1219. 		    otmp = pick_list->item.a_obj;
  1220. 		    if (allowcnt && pick_list->count < otmp->quan)
  1221. 			otmp = splitobj(otmp, pick_list->count);
  1222. 		    free((genericptr_t)pick_list);
  1223. 		    return otmp;
  1224. 		}
  1225. 		if(ilet == '?' || ilet == '*') {
  1226. 		    char *allowed_choices = (ilet == '?') ? lets : (char *)0;
  1227. 		    long ctmp = 0;
  1228.  
  1229. 		    if (ilet == '?' && !*lets && *altlets)
  1230. 			allowed_choices = altlets;
  1231. 		    ilet = display_pickinv(allowed_choices, TRUE,
  1232. 					   allowcnt ? &ctmp : (long *)0);
  1233. 		    if(!ilet) continue;
  1234. 		    if (allowcnt && ctmp >= 0) {
  1235. 			cnt = ctmp;
  1236. 			if (!cnt) prezero = TRUE;
  1237. 			allowcnt = 2;
  1238. 		    }
  1239. 		    if(ilet == '\033') {
  1240. 			if(flags.verbose)
  1241. 			    pline(Never_mind);
  1242. 			return((struct obj *)0);
  1243. 		    }
  1244. 		    /* they typed a letter (not a space) at the prompt */
  1245. 		}
  1246. 		/* WAC - throw now takes a count to allow for single/controlled shooting */
  1247. 		if(allowcnt == 2 && !strcmp(word,"throw")) {
  1248. 		    /* permit counts for throwing gold, but don't accept
  1249. 		     * counts for other things since the throw code will
  1250. 		     * split off a single item anyway */
  1251. #ifdef GOLDOBJ
  1252. 		    if (ilet != def_oc_syms[COIN_CLASS])
  1253. #endif
  1254. 			allowcnt = 1;
  1255. 		    if(cnt == 0 && prezero) return((struct obj *)0);
  1256. 		    if (cnt == 1) {
  1257. 			save_cm = (char *) 1; /* Non zero */
  1258. 			multi = 0;
  1259. 		    }
  1260. 		    if(cnt > 1) {
  1261. 			/* You("can only throw one item at a time.");
  1262. 			continue; */
  1263. 			multi = cnt - 1;
  1264. 			cnt = 1;
  1265. 		    }
  1266. 		}
  1267. #ifdef GOLDOBJ
  1268. 		flags.botl = 1; /* May have changed the amount of money */
  1269. #endif
  1270. #ifdef REDO
  1271. 		savech(ilet);
  1272. #endif
  1273. 		for (otmp = invent; otmp; otmp = otmp->nobj)
  1274. 			if (otmp->invlet == ilet) break;
  1275. 		if(!otmp) {
  1276. 			You("don't have that object.");
  1277. #ifdef REDO
  1278. 			if (in_doagain) return((struct obj *) 0);
  1279. #endif
  1280. 			continue;
  1281. 		} else if (cnt < 0 || otmp->quan < cnt) {
  1282. 			You("don't have that many!  You have only %ld.",
  1283. 			    otmp->quan);
  1284. #ifdef REDO
  1285. 			if (in_doagain) return((struct obj *) 0);
  1286. #endif
  1287. 			continue;
  1288. 		}
  1289. 		break;
  1290. 	}
  1291.  
  1292. 	if(!allowall && let && !index(let,otmp->oclass)
  1293. #ifdef GOLDOBJ
  1294. 	   && !(usegold && otmp->oclass == COIN_CLASS)
  1295. #endif
  1296. 	   ) {
  1297. 		silly_thing(word, otmp);
  1298. 		return((struct obj *)0);
  1299. 	}
  1300. 	if(allowcnt == 2) {	/* cnt given */
  1301. 	    if(cnt == 0) return (struct obj *)0;
  1302. 	    if(cnt != otmp->quan) {
  1303. 		/* don't split a stack of cursed loadstones */
  1304. 		if (otmp->otyp == LOADSTONE && otmp->cursed)
  1305. 		    /* kludge for canletgo()'s can't-drop-this message */
  1306. 		    otmp->corpsenm = (int) cnt;
  1307. 		else
  1308. 		    otmp = splitobj(otmp, cnt);
  1309. 	    }
  1310. 	}
  1311. 	return(otmp);
  1312. }
  1313.  
  1314. void
  1315. silly_thing(word, otmp)
  1316. const char *word;
  1317. struct obj *otmp;
  1318. {
  1319. 	const char *s1, *s2, *s3, *what;
  1320. 	int ocls = otmp->oclass, otyp = otmp->otyp;
  1321.  
  1322. 	s1 = s2 = s3 = 0;
  1323. 	/* check for attempted use of accessory commands ('P','R') on armor
  1324. 	   and for corresponding armor commands ('W','T') on accessories */
  1325. 	if (ocls == ARMOR_CLASS) {
  1326. 	    if (!strcmp(word, "put on"))
  1327. 		s1 = "W", s2 = "wear", s3 = "";
  1328. 	    else if (!strcmp(word, "remove"))
  1329. 		s1 = "T", s2 = "take", s3 = " off";
  1330. 	} else if ((ocls == RING_CLASS || otyp == MEAT_RING) ||
  1331. 		ocls == AMULET_CLASS ||
  1332. 		(otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
  1333. 	    if (!strcmp(word, "wear"))
  1334. 		s1 = "P", s2 = "put", s3 = " on";
  1335. 	    else if (!strcmp(word, "take off"))
  1336. 		s1 = "R", s2 = "remove", s3 = "";
  1337. 	}
  1338. 	if (s1) {
  1339. 	    what = "that";
  1340. 	    /* quantity for armor and accessory objects is always 1,
  1341. 	       but some things should be referred to as plural */
  1342. 	    if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
  1343. 		what = "those";
  1344. 	    pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
  1345. 	} else {
  1346. 	    pline(silly_thing_to, word);
  1347. 	}
  1348. }
  1349.  
  1350. #endif /* OVL1 */
  1351. #ifdef OVLB
  1352.  
  1353. STATIC_PTR int
  1354. ckvalidcat(otmp)
  1355. register struct obj *otmp;
  1356. {
  1357. 	/* use allow_category() from pickup.c */
  1358. 	return((int)allow_category(otmp));
  1359. }
  1360.  
  1361. STATIC_PTR int
  1362. ckunpaid(otmp)
  1363. register struct obj *otmp;
  1364. {
  1365. 	return((int)(otmp->unpaid));
  1366. }
  1367.  
  1368. boolean
  1369. wearing_armor()
  1370. {
  1371. 	return((boolean)(uarm || uarmc || uarmf || uarmg || uarmh || uarms
  1372. #ifdef TOURIST
  1373. 		|| uarmu
  1374. #endif
  1375. 		));
  1376. }
  1377.  
  1378. boolean
  1379. is_worn(otmp)
  1380. register struct obj *otmp;
  1381. {
  1382. return((boolean)(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
  1383. #ifdef STEED
  1384. 			W_SADDLE |
  1385. #endif
  1386. 			W_WEP | W_SWAPWEP | W_QUIVER))));
  1387. }
  1388.  
  1389. static NEARDATA const char removeables[] =
  1390. 	{ ARMOR_CLASS, WEAPON_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, 0 };
  1391.  
  1392. /* interactive version of getobj - used for Drop, Identify and */
  1393. /* Takeoff (A). Return the number of times fn was called successfully */
  1394. /* If combo is TRUE, we just use this to get a category list */
  1395. int
  1396. ggetobj(word, fn, mx, combo, resultflags)
  1397. const char *word;
  1398. int FDECL((*fn),(OBJ_P)), mx;
  1399. boolean combo;		/* combination menu flag */
  1400. unsigned *resultflags;
  1401. {
  1402. 	int FDECL((*ckfn),(OBJ_P)) = (int FDECL((*),(OBJ_P))) 0;
  1403. 	boolean FDECL((*filter),(OBJ_P)) = (boolean FDECL((*),(OBJ_P))) 0;
  1404. 	boolean takeoff, ident, allflag, m_seen;
  1405. 	int itemcount;
  1406. #ifndef GOLDOBJ
  1407. 	int oletct, iletct, allowgold, unpaid, oc_of_sym;
  1408. #else
  1409. 	int oletct, iletct, unpaid, oc_of_sym;
  1410. #endif
  1411. 	char sym, *ip, olets[MAXOCLASSES+5], ilets[MAXOCLASSES+5];
  1412. 	char extra_removeables[3+1];	/* uwep,uswapwep,uquiver */
  1413. 	char buf[BUFSZ], qbuf[QBUFSZ];
  1414.  
  1415. 	if (resultflags) *resultflags = 0;
  1416. #ifndef GOLDOBJ
  1417. 	allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0;
  1418. #endif
  1419. 	takeoff = ident = allflag = m_seen = FALSE;
  1420. #ifndef GOLDOBJ
  1421. 	if(!invent && !allowgold){
  1422. #else
  1423. 	if(!invent){
  1424. #endif
  1425. 		You("have nothing to %s.", word);
  1426. 		return(0);
  1427. 	}
  1428. 	add_valid_menu_class(0);	/* reset */
  1429. 	if (taking_off(word)) {
  1430. 	    takeoff = TRUE;
  1431. 	    filter = is_worn;
  1432. 	} else if (!strcmp(word, "identify")) {
  1433. 	    ident = TRUE;
  1434. 	    filter = not_fully_identified;
  1435. 	}
  1436.  
  1437. 	iletct = collect_obj_classes(ilets, invent,
  1438. 				     	FALSE,
  1439. #ifndef GOLDOBJ
  1440. 					(allowgold != 0),
  1441. #endif
  1442. 					filter, &itemcount);
  1443. 	unpaid = count_unpaid(invent);
  1444.  
  1445. 	if (ident && !iletct) {
  1446. 	    return -1;		/* no further identifications */
  1447. 	} else if (!takeoff && (unpaid || invent)) {
  1448. 	    ilets[iletct++] = ' ';
  1449. 	    if (unpaid) ilets[iletct++] = 'u';
  1450. 	    if (count_buc(invent, BUC_BLESSED))  ilets[iletct++] = 'B';
  1451. 	    if (count_buc(invent, BUC_UNCURSED)) ilets[iletct++] = 'U';
  1452. 	    if (count_buc(invent, BUC_CURSED))   ilets[iletct++] = 'C';
  1453. 	    if (count_buc(invent, BUC_UNKNOWN))  ilets[iletct++] = 'X';
  1454. 	    if (invent) ilets[iletct++] = 'a';
  1455. 	} else if (takeoff && invent) {
  1456. 	    ilets[iletct++] = ' ';
  1457. 	}
  1458. 	ilets[iletct++] = 'i';
  1459. 	if (!combo)
  1460. 	    ilets[iletct++] = 'm';	/* allow menu presentation on request */
  1461. 	ilets[iletct] = '\0';
  1462.  
  1463. 	for (;;) {
  1464. 	    Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
  1465. 		    word, ilets);
  1466. 	    getlin(qbuf, buf);
  1467. 	    if (buf[0] == '\033') return(0);
  1468. 	    if (index(buf, 'i')) {
  1469. 		if (display_inventory((char *)0, TRUE) == '\033') return 0;
  1470. 	    } else
  1471. 		break;
  1472. 	}
  1473.  
  1474. 	extra_removeables[0] = '\0';
  1475. 	if (takeoff) {
  1476. 	    /* arbitrary types of items can be placed in the weapon slots
  1477. 	       [any duplicate entries in extra_removeables[] won't matter] */
  1478. 	    if (uwep) (void)strkitten(extra_removeables, uwep->oclass);
  1479. 	    if (uswapwep) (void)strkitten(extra_removeables, uswapwep->oclass);
  1480. 	    if (uquiver) (void)strkitten(extra_removeables, uquiver->oclass);
  1481. 	}
  1482.  
  1483. 	ip = buf;
  1484. 	olets[oletct = 0] = '\0';
  1485. 	while ((sym = *ip++) != '\0') {
  1486. 	    if (sym == ' ') continue;
  1487. 	    oc_of_sym = def_char_to_objclass(sym);
  1488. 	    if (takeoff && oc_of_sym != MAXOCLASSES) {
  1489. 		if (index(extra_removeables, oc_of_sym)) {
  1490. 		    ;	/* skip rest of takeoff checks */
  1491. 		} else if (!index(removeables, oc_of_sym)) {
  1492. 		    pline("Not applicable.");
  1493. 		    return 0;
  1494. 		} else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
  1495. 		    You("are not wearing any armor.");
  1496. 		    return 0;
  1497. 		} else if (oc_of_sym == WEAPON_CLASS &&
  1498. 			!uwep && !uswapwep && !uquiver) {
  1499. 		    You("are not wielding anything.");
  1500. 		    return 0;
  1501. 		} else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
  1502. 		    You("are not wearing rings.");
  1503. 		    return 0;
  1504. 		} else if (oc_of_sym == AMULET_CLASS && !uamul) {
  1505. 		    You("are not wearing an amulet.");
  1506. 		    return 0;
  1507. 		} else if (oc_of_sym == TOOL_CLASS && !ublindf) {
  1508. 		    You("are not wearing a blindfold.");
  1509. 		    return 0;
  1510. 		}
  1511. 	    }
  1512.  
  1513. 	    if (oc_of_sym == COIN_CLASS && !combo) {
  1514. #ifndef GOLDOBJ
  1515. 		if (allowgold == 1)
  1516. 		    (*fn)(mkgoldobj(u.ugold));
  1517. 		else if (!u.ugold)
  1518. 		    You("have no gold.");
  1519. 		allowgold = 2;
  1520. #else
  1521. 		flags.botl = 1;
  1522. #endif
  1523. 	    } else if (sym == 'a') {
  1524. 		allflag = TRUE;
  1525. 	    } else if (sym == 'A') {
  1526. 		/* same as the default */ ;
  1527. 	    } else if (sym == 'u') {
  1528. 		add_valid_menu_class('u');
  1529. 		ckfn = ckunpaid;
  1530. 	    } else if (sym == 'B') {
  1531. 	    	add_valid_menu_class('B');
  1532. 	    	ckfn = ckvalidcat;
  1533. 	    } else if (sym == 'U') {
  1534. 	    	add_valid_menu_class('U');
  1535. 	    	ckfn = ckvalidcat;
  1536. 	    } else if (sym == 'C') {
  1537. 	    	add_valid_menu_class('C');
  1538. 		ckfn = ckvalidcat;
  1539. 	    } else if (sym == 'X') {
  1540. 	    	add_valid_menu_class('X');
  1541. 		ckfn = ckvalidcat;
  1542. 	    } else if (sym == 'm') {
  1543. 		m_seen = TRUE;
  1544. 	    } else if (oc_of_sym == MAXOCLASSES) {
  1545. 		You("don't have any %c's.", sym);
  1546. 	    } else if (oc_of_sym != VENOM_CLASS) {	/* suppress venom */
  1547. 		if (!index(olets, oc_of_sym)) {
  1548. 		    add_valid_menu_class(oc_of_sym);
  1549. 		    olets[oletct++] = oc_of_sym;
  1550. 		    olets[oletct] = 0;
  1551. 		}
  1552. 	    }
  1553. 	}
  1554.  
  1555. 	if (m_seen)
  1556. 	    return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
  1557. 	else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag)
  1558. 	    return 0;
  1559. #ifndef GOLDOBJ
  1560. 	else if (allowgold == 2 && !oletct)
  1561. 	    return 1;	/* you dropped gold (or at least tried to) */
  1562. 	else {
  1563. #else
  1564. 	else /*!!!! if (allowgold == 2 && !oletct)
  1565. 	    !!!! return 1;	 you dropped gold (or at least tried to) 
  1566. !!!! test gold dropping
  1567. 	else*/ {
  1568. #endif
  1569. 	    int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word); 
  1570. 	    /*
  1571. 	     * askchain() has already finished the job in this case
  1572. 	     * so set a special flag to convey that back to the caller
  1573. 	     * so that it won't continue processing.
  1574. 	     * Fix for bug C331-1 reported by Irina Rempt-Drijfhout. 
  1575. 	     */
  1576. 	    if (combo && allflag && resultflags)
  1577. 		*resultflags |= ALL_FINISHED; 
  1578. 	    return cnt;
  1579. 	}
  1580. }
  1581.  
  1582. /*
  1583. * Walk through the chain starting at objchn and ask for all objects
  1584. * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
  1585. * whether the action in question (i.e., fn) has to be performed.
  1586. * If allflag then no questions are asked. Max gives the max nr of
  1587. * objects to be treated. Return the number of objects treated.
  1588. */
  1589. int
  1590. askchain(objchn, olets, allflag, fn, ckfn, mx, word)
  1591. struct obj **objchn;
  1592. register int allflag, mx;
  1593. register const char *olets, *word;	/* olets is an Obj Class char array */
  1594. register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P));
  1595. {
  1596. 	struct obj *otmp, *otmp2, *otmpo;
  1597. 	register char sym, ilet;
  1598. 	register int cnt = 0, dud = 0, tmp;
  1599. 	boolean takeoff, nodot, ident, ininv;
  1600. 	char qbuf[QBUFSZ];
  1601.  
  1602. 	takeoff = taking_off(word);
  1603. 	ident = !strcmp(word, "identify");
  1604. 	nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
  1605. 		 ident || takeoff);
  1606. 	ininv = (*objchn == invent);
  1607. 	/* Changed so the askchain is interrogated in the order specified.
  1608. 	 * For example, if a person specifies =/ then first all rings will be
  1609. 	 * asked about followed by all wands -dgk
  1610. 	 */
  1611. nextclass:
  1612. 	ilet = 'a'-1;
  1613. 	if (*objchn && (*objchn)->oclass == COIN_CLASS)
  1614. 		ilet--;		/* extra iteration */
  1615. 	for (otmp = *objchn; otmp; otmp = otmp2) {
  1616. 		if(ilet == 'z') ilet = 'A'; else ilet++;
  1617. 		otmp2 = otmp->nobj;
  1618. 		if (olets && *olets && otmp->oclass != *olets) continue;
  1619. 		if (takeoff && !is_worn(otmp)) continue;
  1620. 		if (ident && !not_fully_identified(otmp)) continue;
  1621. 		if (ckfn && !(*ckfn)(otmp)) continue;
  1622. 		if (!allflag) {
  1623. 			Strcpy(qbuf, !ininv ? doname(otmp) :
  1624. 				xprname(otmp, (char *)0, ilet, !nodot, 0L, 0L));
  1625. 			Strcat(qbuf, "?");
  1626. 			sym = (takeoff || ident || otmp->quan < 2L) ?
  1627. 				nyaq(qbuf) : nyNaq(qbuf);
  1628. 		}
  1629. 		else	sym = 'y';
  1630.  
  1631. 		otmpo = otmp;
  1632. 		if (sym == '#') {
  1633. 		 /* Number was entered; split the object unless it corresponds
  1634. 		    to 'none' or 'all'.  2 special cases: cursed loadstones and
  1635. 		    welded weapons (eg, multiple daggers) will remain as merged
  1636. 		    unit; done to avoid splitting an object that won't be
  1637. 		    droppable (even if we're picking up rather than dropping).
  1638. 		  */
  1639. 		    if (!yn_number)
  1640. 			sym = 'n';
  1641. 		    else {
  1642. 			sym = 'y';
  1643. 			if (yn_number < otmp->quan && !welded(otmp) &&
  1644. 			    (!otmp->cursed || otmp->otyp != LOADSTONE)) {
  1645. 			    otmp = splitobj(otmp, yn_number);
  1646. 			}
  1647. 		    }
  1648. 		}
  1649. 		switch(sym){
  1650. 		case 'a':
  1651. 			allflag = 1;
  1652. 		case 'y':
  1653. 			tmp = (*fn)(otmp);
  1654. 			if(tmp < 0) {
  1655. 			    if (container_gone(fn)) {
  1656. 				/* otmp caused magic bag to explode;
  1657. 				   both are now gone */
  1658. 				otmp = 0;		/* and return */
  1659. 			    } else if (otmp && otmp != otmpo) {
  1660. 				/* split occurred, merge again */
  1661. 				(void) merged(&otmpo, &otmp);
  1662. 			    }
  1663. 			    goto ret;
  1664. 			}
  1665. 			cnt += tmp;
  1666. 			if(--mx == 0) goto ret;
  1667. 		case 'n':
  1668. 			if(nodot) dud++;
  1669. 		default:
  1670. 			break;
  1671. 		case 'q':
  1672. 			/* special case for seffects() */
  1673. 			if (ident) cnt = -1;
  1674. 			goto ret;
  1675. 		}
  1676. 	}
  1677. 	if (olets && *olets && *++olets)
  1678. 		goto nextclass;
  1679. 	if(!takeoff && (dud || cnt)) pline("That was all.");
  1680. 	else if(!dud && !cnt) pline("No applicable objects.");
  1681. ret:
  1682. 	return(cnt);
  1683. }
  1684.  
  1685.  
  1686. /*
  1687. *	Object identification routines:
  1688. */
  1689.  
  1690. /* make an object actually be identified; no display updating */
  1691. void
  1692. fully_identify_obj(otmp)
  1693. struct obj *otmp;
  1694. {
  1695. makeknown(otmp->otyp);
  1696. if (otmp->oartifact) discover_artifact((xchar)otmp->oartifact);
  1697. otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
  1698. if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
  1699. 	learn_egg_type(otmp->corpsenm);
  1700. }
  1701.  
  1702. /* ggetobj callback routine; identify an object and give immediate feedback */
  1703. int
  1704. identify(otmp)
  1705. struct obj *otmp;
  1706. {
  1707. fully_identify_obj(otmp);
  1708. prinv((char *)0, otmp, 0L);
  1709. return 1;
  1710. }
  1711.  
  1712. /* menu of unidentified objects; select and identify up to id_limit of them */
  1713. STATIC_OVL void
  1714. menu_identify(id_limit)
  1715. int id_limit;
  1716. {
  1717. menu_item *pick_list;
  1718. int n, i, first = 1;
  1719. char buf[BUFSZ];
  1720. /* assumptions:  id_limit > 0 and at least one unID'd item is present */
  1721.  
  1722. while (id_limit) {
  1723. 	Sprintf(buf, "What would you like to identify %s?",
  1724. 		first ? "first" : "next");
  1725. 	n = query_objlist(buf, invent, SIGNAL_NOMENU|USE_INVLET|INVORDER_SORT,
  1726. 		&pick_list, PICK_ANY, not_fully_identified);
  1727.  
  1728. 	if (n > 0) {
  1729. 	    if (n > id_limit) n = id_limit;
  1730. 	    for (i = 0; i < n; i++, id_limit--)
  1731. 		(void) identify(pick_list[i].item.a_obj);
  1732. 	    free((genericptr_t) pick_list);
  1733. 	    mark_synch(); /* Before we loop to pop open another menu */
  1734. 	} else {
  1735. 	    if (n < 0) pline("That was all.");
  1736. 	    id_limit = 0; /* Stop now */
  1737. 	}
  1738. 	first = 0;
  1739. }
  1740. }
  1741.  
  1742. /* dialog with user to identify a given number of items; 0 means all */
  1743. void
  1744. identify_pack(id_limit)
  1745. int id_limit;
  1746. {
  1747. struct obj *obj, *the_obj;
  1748. int n, unid_cnt;
  1749.  
  1750. unid_cnt = 0;
  1751. the_obj = 0;		/* if unid_cnt ends up 1, this will be it */
  1752. for (obj = invent; obj; obj = obj->nobj)
  1753. 	if (not_fully_identified(obj)) ++unid_cnt, the_obj = obj;
  1754.  
  1755. if (!unid_cnt) {
  1756. 	You("have already identified all of your possessions.");
  1757. } else if (!id_limit) {
  1758. 	/* identify everything */
  1759. 	if (unid_cnt == 1) {
  1760. 	    (void) identify(the_obj);
  1761. 	} else {
  1762.  
  1763. 	    /* TODO:  use fully_identify_obj and cornline/menu/whatever here */
  1764. 	    for (obj = invent; obj; obj = obj->nobj)
  1765. 		if (not_fully_identified(obj)) (void) identify(obj);
  1766.  
  1767. 	}
  1768. } else {
  1769. 	/* identify up to `id_limit' items */
  1770. 	n = 0;
  1771. 	if (flags.menu_style == MENU_TRADITIONAL)
  1772. 	    do {
  1773. 		n = ggetobj("identify", identify, id_limit, FALSE, (unsigned *)0);
  1774. 		if (n < 0) break; /* quit or no eligible items */
  1775. 	    } while ((id_limit -= n) > 0);
  1776. 	if (n == 0 || n < -1)
  1777. 	    menu_identify(id_limit);
  1778. }
  1779. update_inventory();
  1780. }
  1781.  
  1782. #endif /* OVLB */
  1783. #ifdef OVL2
  1784.  
  1785. STATIC_OVL char
  1786. obj_to_let(obj)	/* should of course only be called for things in invent */
  1787. register struct obj *obj;
  1788. {
  1789. #ifndef GOLDOBJ
  1790. 	if (obj->oclass == COIN_CLASS)
  1791. 		return GOLD_SYM;
  1792. #endif
  1793. 	if (!flags.invlet_constant) {
  1794. 		obj->invlet = NOINVSYM;
  1795. 		reassign();
  1796. 	}
  1797. 	return obj->invlet;
  1798. }
  1799.  
  1800. /*
  1801. * Print the indicated quantity of the given object.  If quan == 0L then use
  1802. * the current quantity.
  1803. */
  1804. void
  1805. prinv(prefix, obj, quan)
  1806. const char *prefix;
  1807. register struct obj *obj;
  1808. long quan;
  1809. {
  1810. 	if (!prefix) prefix = "";
  1811. 	pline("%s%s%s",
  1812. 	      prefix, *prefix ? " " : "",
  1813. 	      xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L, quan));
  1814. }
  1815.  
  1816. #endif /* OVL2 */
  1817. #ifdef OVL1
  1818.  
  1819. char *
  1820. xprname(obj, txt, let, dot, cost, quan)
  1821. struct obj *obj;
  1822. const char *txt;	/* text to print instead of obj */
  1823. char let;		/* inventory letter */
  1824. boolean dot;		/* append period; (dot && cost => Iu) */
  1825. long cost;		/* cost (for inventory of unpaid or expended items) */
  1826. long quan;		/* if non-0, print this quantity, not obj->quan */
  1827. {
  1828. #ifdef LINT	/* handle static char li[BUFSZ]; */
  1829. char li[BUFSZ];
  1830. #else
  1831. static char li[BUFSZ];
  1832. #endif
  1833. boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
  1834. long savequan = 0;
  1835.  
  1836. if (quan && obj) {
  1837. 	savequan = obj->quan;
  1838. 	obj->quan = quan;
  1839. }
  1840.  
  1841. /*
  1842. * If let is:
  1843. *	*  Then obj == null and we are printing a total amount.
  1844. *	>  Then the object is contained and doesn't have an inventory letter.
  1845. */
  1846. if (cost != 0 || let == '*') {
  1847. 	/* if dot is true, we're doing Iu, otherwise Ix */
  1848. 	Sprintf(li, "%c - %-45s %6ld %s",
  1849. 		(dot && use_invlet ? obj->invlet : let),
  1850. 		(txt ? txt : doname(obj)), cost, currency(cost));
  1851. #ifndef GOLDOBJ
  1852. } else if (obj && obj->oclass == COIN_CLASS) {
  1853. 	Sprintf(li, "%ld gold piece%s%s", obj->quan, plur(obj->quan),
  1854. 		(dot ? "." : ""));
  1855. #endif
  1856. } else {
  1857. 	/* ordinary inventory display or pickup message */
  1858. 	Sprintf(li, "%c - %s%s",
  1859. 		(use_invlet ? obj->invlet : let),
  1860. 		(txt ? txt : doname(obj)), (dot ? "." : ""));
  1861. }
  1862. if (savequan) obj->quan = savequan;
  1863.  
  1864. return li;
  1865. }
  1866.  
  1867. #endif /* OVL1 */
  1868. #ifdef OVLB
  1869.  
  1870. /* the 'i' command */
  1871. int
  1872. ddoinv()
  1873. {
  1874. 	(void) display_inventory((char *)0, FALSE);
  1875. 	return 0;
  1876. }
  1877.  
  1878. /*
  1879. * find_unpaid()
  1880. *
  1881. * Scan the given list of objects.  If last_found is NULL, return the first
  1882. * unpaid object found.  If last_found is not NULL, then skip over unpaid
  1883. * objects until last_found is reached, then set last_found to NULL so the
  1884. * next unpaid object is returned.  This routine recursively follows
  1885. * containers.
  1886. */
  1887. STATIC_OVL struct obj *
  1888. find_unpaid(list, last_found)
  1889. struct obj *list, **last_found;
  1890. {
  1891. struct obj *obj;
  1892.  
  1893. while (list) {
  1894. 	if (list->unpaid) {
  1895. 	    if (*last_found) {
  1896. 		/* still looking for previous unpaid object */
  1897. 		if (list == *last_found)
  1898. 		    *last_found = (struct obj *) 0;
  1899. 	    } else
  1900. 		return (*last_found = list);
  1901. 	}
  1902. 	if (Has_contents(list)) {
  1903. 	    if ((obj = find_unpaid(list->cobj, last_found)) != 0)
  1904. 		return obj;
  1905. 	}
  1906. 	list = list->nobj;
  1907. }
  1908. return (struct obj *) 0;
  1909. }
  1910.  
  1911. /*
  1912. * Internal function used by display_inventory and getobj that can display
  1913. * inventory and return a count as well as a letter. If out_cnt is not null,
  1914. * any count returned from the menu selection is placed here.
  1915. */
  1916. static char
  1917. display_pickinv(lets, want_reply, out_cnt)
  1918. register const char *lets;
  1919. boolean want_reply;
  1920. long* out_cnt;
  1921. {
  1922. 	struct obj *otmp;
  1923. 	char ilet, ret;
  1924. 	char *invlet = flags.inv_order;
  1925. 	int n, classcount;
  1926. 	winid win;				/* windows being used */
  1927. 	static winid local_win = WIN_ERR;	/* window for partial menus */
  1928. 	anything any;
  1929. 	menu_item *selected;
  1930. #ifdef PROXY_GRAPHICS
  1931. 	static int busy = 0;
  1932. 	if (busy)
  1933. 	    return 0;
  1934. 	busy++;
  1935. #endif
  1936.  
  1937. 	/* overriden by global flag */
  1938. 	if (flags.perm_invent) {
  1939. 	    win = (lets && *lets) ? local_win : WIN_INVEN;
  1940. 	    /* create the first time used */
  1941. 	    if (win == WIN_ERR)
  1942. 		win = local_win = create_nhwindow(NHW_MENU);
  1943. 	} else
  1944. 	    win = WIN_INVEN;
  1945.  
  1946. 	/*
  1947. 	Exit early if no inventory -- but keep going if we are doing
  1948. 	a permanent inventory update.  We need to keep going so the
  1949. 	permanent inventory window updates itself to remove the last
  1950. 	item(s) dropped.  One down side:  the addition of the exception
  1951. 	for permanent inventory window updates _can_ pop the window
  1952. 	up when it's not displayed -- even if it's empty -- because we
  1953. 	don't know at this level if its up or not.  This may not be
  1954. 	an issue if empty checks are done before hand and the call
  1955. 	to here is short circuited away.
  1956. 	*/
  1957. 	if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
  1958. #ifndef GOLDOBJ
  1959. 	    pline("Not carrying anything%s.", u.ugold ? " except gold" : "");
  1960. #else
  1961. 	    pline("Not carrying anything.");
  1962. #endif
  1963. #ifdef PROXY_GRAPHICS
  1964. 	    busy--;
  1965. #endif
  1966. 	    return 0;
  1967. 	}
  1968.  
  1969. 	/* oxymoron? temporarily assign permanent inventory letters */
  1970. 	if (!flags.invlet_constant) reassign();
  1971.  
  1972. 	if (lets && strlen(lets) == 1) {
  1973. 	    /* when only one item of interest, use pline instead of menus;
  1974. 	       we actually use a fake message-line menu in order to allow
  1975. 	       the user to perform selection at the --More-- prompt for tty */
  1976. 	    ret = '\0';
  1977. 	    for (otmp = invent; otmp; otmp = otmp->nobj) {
  1978. 		if (otmp->invlet == lets[0]) {
  1979. 		    ret = message_menu(lets[0],
  1980. 			  want_reply ? PICK_ONE : PICK_NONE,
  1981. 			  xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
  1982. 		    if (out_cnt) *out_cnt = -1L;	/* select all */
  1983. 		    break;
  1984. 		}
  1985. 	    }
  1986. #ifdef PROXY_GRAPHICS
  1987. 	    busy--;
  1988. #endif
  1989. 	    return ret;
  1990. 	}
  1991.  
  1992. 	start_menu(win);
  1993. nextclass:
  1994. 	classcount = 0;
  1995. 	any.a_void = 0;		/* set all bits to zero */
  1996. 	for(otmp = invent; otmp; otmp = otmp->nobj) {
  1997. 		ilet = otmp->invlet;
  1998. 		if(!lets || !*lets || index(lets, ilet)) {
  1999. 			if (!flags.sortpack || otmp->oclass == *invlet) {
  2000. 			    if (flags.sortpack && !classcount) {
  2001. 				any.a_void = 0;		/* zero */
  2002. 				add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
  2003. 				    let_to_name(*invlet, FALSE), MENU_UNSELECTED);
  2004. 				classcount++;
  2005. 			    }
  2006. 			    any.a_char = ilet;
  2007. 			    add_menu(win, obj_to_glyph(otmp),
  2008. 					&any, ilet, 0, ATR_NONE, doname(otmp),
  2009. 					MENU_UNSELECTED);
  2010. 			}
  2011. 		}
  2012. 	}
  2013. 	if (flags.sortpack) {
  2014. 		if (*++invlet) goto nextclass;
  2015. #ifdef WIZARD
  2016. 		if (--invlet != venom_inv) {
  2017. 			invlet = venom_inv;
  2018. 			goto nextclass;
  2019. 		}
  2020. #endif
  2021. 	}
  2022. 	end_menu(win, (char *) 0);
  2023.  
  2024. 	n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
  2025. 	if (n > 0) {
  2026. 	    ret = selected[0].item.a_char;
  2027. 	    if (out_cnt) *out_cnt = selected[0].count;
  2028. 	    free((genericptr_t)selected);
  2029. 	} else
  2030. 	    ret = !n ? '\0' : '\033';	/* cancelled */
  2031.  
  2032. #ifdef PROXY_GRAPHICS
  2033. 	busy--;
  2034. #endif
  2035. 	return ret;
  2036. }
  2037.  
  2038. /*
  2039. * If lets == NULL or "", list all objects in the inventory.  Otherwise,
  2040. * list all objects with object classes that match the order in lets.
  2041. *
  2042. * Returns the letter identifier of a selected item, or 0 if nothing
  2043. * was selected.
  2044. */
  2045. char
  2046. display_inventory(lets, want_reply)
  2047. register const char *lets;
  2048. boolean want_reply;
  2049. {
  2050. 	return display_pickinv(lets, want_reply, (long *)0);
  2051. }
  2052.  
  2053. /*
  2054. * Returns the number of unpaid items within the given list.  This includes
  2055. * contained objects.
  2056. */
  2057. int
  2058. count_unpaid(list)
  2059. struct obj *list;
  2060. {
  2061. int count = 0;
  2062.  
  2063. while (list) {
  2064. 	if (list->unpaid) count++;
  2065. 	if (Has_contents(list))
  2066. 	    count += count_unpaid(list->cobj);
  2067. 	list = list->nobj;
  2068. }
  2069. return count;
  2070. }
  2071.  
  2072. /*
  2073. * Returns the number of items with b/u/c/unknown within the given list.  
  2074. * This does NOT include contained objects.
  2075. */
  2076. int
  2077. count_buc(list, type)
  2078. struct obj *list;
  2079. int type;
  2080. {
  2081. int count = 0;
  2082.  
  2083. while (list) {
  2084. 	if (Role_if(PM_PRIEST)) list->bknown = TRUE;
  2085. 	switch(type) {
  2086. 	    case BUC_BLESSED:
  2087. 		if (list->oclass != COIN_CLASS && list->bknown && list->blessed)
  2088. 		    count++;
  2089. 		break;
  2090. 	    case BUC_CURSED:
  2091. 		if (list->oclass != COIN_CLASS && list->bknown && list->cursed)
  2092. 		    count++;
  2093. 		break;
  2094. 	    case BUC_UNCURSED:
  2095. 		if (list->oclass != COIN_CLASS &&
  2096. 			list->bknown && !list->blessed && !list->cursed)
  2097. 		    count++;
  2098. 		break;
  2099. 	    case BUC_UNKNOWN:
  2100. 		if (list->oclass != COIN_CLASS && !list->bknown)
  2101. 		    count++;
  2102. 		break;
  2103. 	    default:
  2104. 		impossible("need count of curse status %d?", type);
  2105. 		return 0;
  2106. 	}
  2107. 	list = list->nobj;
  2108. }
  2109. return count;
  2110. }
  2111.  
  2112. STATIC_OVL void
  2113. dounpaid()
  2114. {
  2115. winid win;
  2116. struct obj *otmp, *marker;
  2117. register char ilet;
  2118. char *invlet = flags.inv_order;
  2119. int classcount, count, num_so_far;
  2120. int save_unpaid = 0;	/* lint init */
  2121. long cost, totcost;
  2122.  
  2123. count = count_unpaid(invent);
  2124.  
  2125. if (count == 1) {
  2126. 	marker = (struct obj *) 0;
  2127. 	otmp = find_unpaid(invent, &marker);
  2128.  
  2129. 	/* see if the unpaid item is in the top level inventory */
  2130. 	for (marker = invent; marker; marker = marker->nobj)
  2131. 	    if (marker == otmp) break;
  2132.  
  2133. 	pline("%s", xprname(otmp, distant_name(otmp, doname),
  2134. 			    marker ? otmp->invlet : CONTAINED_SYM,
  2135. 			    TRUE, unpaid_cost(otmp), 0L));
  2136. 	return;
  2137. }
  2138.  
  2139. win = create_nhwindow(NHW_MENU);
  2140. cost = totcost = 0;
  2141. num_so_far = 0;	/* count of # printed so far */
  2142. if (!flags.invlet_constant) reassign();
  2143.  
  2144. do {
  2145. 	classcount = 0;
  2146. 	for (otmp = invent; otmp; otmp = otmp->nobj) {
  2147. 	    ilet = otmp->invlet;
  2148. 	    if (otmp->unpaid) {
  2149. 		if (!flags.sortpack || otmp->oclass == *invlet) {
  2150. 		    if (flags.sortpack && !classcount) {
  2151. 			putstr(win, 0, let_to_name(*invlet, TRUE));
  2152. 			classcount++;
  2153. 		    }
  2154.  
  2155. 		    totcost += cost = unpaid_cost(otmp);
  2156. 		    /* suppress "(unpaid)" suffix */
  2157. 		    save_unpaid = otmp->unpaid;
  2158. 		    otmp->unpaid = 0;
  2159. 		    putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
  2160. 					   ilet, TRUE, cost, 0L));
  2161. 		    otmp->unpaid = save_unpaid;
  2162. 		    num_so_far++;
  2163. 		}
  2164. 	    }
  2165. 	}
  2166. } while (flags.sortpack && (*++invlet));
  2167.  
  2168. if (count > num_so_far) {
  2169. 	/* something unpaid is contained */
  2170. 	if (flags.sortpack)
  2171. 	    putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE));
  2172. 	/*
  2173. 	 * Search through the container objects in the inventory for
  2174. 	 * unpaid items.  The top level inventory items have already
  2175. 	 * been listed.
  2176. 	 */
  2177. 	for (otmp = invent; otmp; otmp = otmp->nobj) {
  2178. 	    if (Has_contents(otmp)) {
  2179. 		marker = (struct obj *) 0;	/* haven't found any */
  2180. 		while (find_unpaid(otmp->cobj, &marker)) {
  2181. 		    totcost += cost = unpaid_cost(marker);
  2182. 		    save_unpaid = marker->unpaid;
  2183. 		    marker->unpaid = 0;    /* suppress "(unpaid)" suffix */
  2184. 		    putstr(win, 0,
  2185. 			   xprname(marker, distant_name(marker, doname),
  2186. 				   CONTAINED_SYM, TRUE, cost, 0L));
  2187. 		    marker->unpaid = save_unpaid;
  2188. 		}
  2189. 	    }
  2190. 	}
  2191. }
  2192.  
  2193. putstr(win, 0, "");
  2194. putstr(win, 0, xprname((struct obj *)0, "Total:", '*', FALSE, totcost, 0L));
  2195. display_nhwindow(win, FALSE);
  2196. destroy_nhwindow(win);
  2197. }
  2198.  
  2199.  
  2200. /* query objlist callback: return TRUE if obj type matches "this_type" */
  2201. static int this_type;
  2202.  
  2203. STATIC_OVL boolean
  2204. this_type_only(obj)
  2205. struct obj *obj;
  2206. {
  2207. return (obj->oclass == this_type);
  2208. }
  2209.  
  2210. /* the 'I' command */
  2211. int
  2212. dotypeinv()
  2213. {
  2214. 	char c = '\0';
  2215. 	int n, i = 0;
  2216. 	char *extra_types, types[BUFSZ];
  2217. 	int class_count, oclass, unpaid_count, itemcount;
  2218. 	boolean billx = *u.ushops && doinvbill(0);
  2219. 	menu_item *pick_list;
  2220. 	boolean traditional = TRUE;
  2221. 	const char *prompt = "What type of object do you want an inventory of?";
  2222.  
  2223. #ifndef GOLDOBJ
  2224. 	if (!invent && !u.ugold && !billx) {
  2225. #else
  2226. 	if (!invent && !billx) {
  2227. #endif
  2228. 	    You("aren't carrying anything.");
  2229. 	    return 0;
  2230. 	}
  2231. 	unpaid_count = count_unpaid(invent);
  2232. 	if (flags.menu_style != MENU_TRADITIONAL) {
  2233. 	    if (flags.menu_style == MENU_FULL ||
  2234. 				flags.menu_style == MENU_PARTIAL) {
  2235. 		traditional = FALSE;
  2236. 		i = UNPAID_TYPES;
  2237. 		if (billx) i |= BILLED_TYPES;
  2238. 		n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
  2239. 		if (!n) return 0;
  2240. 		this_type = c = pick_list[0].item.a_int;
  2241. 		free((genericptr_t) pick_list);
  2242. 	    }
  2243. 	}
  2244. 	if (traditional) {
  2245. 	    /* collect a list of classes of objects carried, for use as a prompt */
  2246. 	    types[0] = 0;
  2247. 	    class_count = collect_obj_classes(types, invent,
  2248. 					      FALSE,
  2249. #ifndef GOLDOBJ
  2250. 					      (u.ugold != 0),
  2251. #endif
  2252. 					      (boolean FDECL((*),(OBJ_P))) 0, &itemcount);
  2253. 	    if (unpaid_count) {
  2254. 		Strcat(types, "u");
  2255. 		class_count++;
  2256. 	    }
  2257. 	    if (billx) {
  2258. 		Strcat(types, "x");
  2259. 		class_count++;
  2260. 	    }
  2261. 	    /* add everything not already included; user won't see these */
  2262. 	    extra_types = eos(types);
  2263. 	    *extra_types++ = '\033';
  2264. 	    if (!unpaid_count) *extra_types++ = 'u';
  2265. 	    if (!billx) *extra_types++ = 'x';
  2266. 	    *extra_types = '\0';	/* for index() */
  2267. 	    for (i = 0; i < MAXOCLASSES; i++)
  2268. 		if (!index(types, def_oc_syms[i])) {
  2269. 		    *extra_types++ = def_oc_syms[i];
  2270. 		    *extra_types = '\0';
  2271. 		}
  2272.  
  2273. 	    if(class_count > 1) {
  2274. 		c = yn_function(prompt, types, '\0');
  2275. #ifdef REDO
  2276. 		savech(c);
  2277. #endif
  2278. 		if(c == '\0') {
  2279. 			clear_nhwindow(WIN_MESSAGE);
  2280. 			return 0;
  2281. 		}
  2282. 	    } else {
  2283. 		/* only one thing to itemize */
  2284. 		if (unpaid_count)
  2285. 		    c = 'u';
  2286. 		else if (billx)
  2287. 		    c = 'x';
  2288. 		else
  2289. 		    c = types[0];
  2290. 	    }
  2291. 	}
  2292. 	if (c == 'x') {
  2293. 	    if (billx)
  2294. 		(void) doinvbill(1);
  2295. 	    else
  2296. 		pline("No used-up objects on your shopping bill.");
  2297. 	    return 0;
  2298. 	}
  2299. 	if (c == 'u') {
  2300. 	    if (unpaid_count)
  2301. 		dounpaid();
  2302. 	    else
  2303. 		You("are not carrying any unpaid objects.");
  2304. 	    return 0;
  2305. 	}
  2306. 	if (traditional) {
  2307. 	    oclass = def_char_to_objclass(c); /* change to object class */
  2308. 	    if (oclass == COIN_CLASS) {
  2309. 		return doprgold();
  2310. 	    } else if (index(types, c) > index(types, '\033')) {
  2311. 		You("have no such objects.");
  2312. 		return 0;
  2313. 	    }
  2314. 	    this_type = oclass;
  2315. 	}
  2316. 	if (query_objlist((char *) 0, invent,
  2317. 		    (flags.invlet_constant ? USE_INVLET : 0)|INVORDER_SORT,
  2318. 		    &pick_list, PICK_NONE, this_type_only) > 0)
  2319. 	    free((genericptr_t)pick_list);
  2320. 	return 0;
  2321. }
  2322.  
  2323. /* return a string describing the dungeon feature at <x,y> if there
  2324. is one worth mentioning at that location; otherwise null */
  2325. const char *
  2326. dfeature_at(x, y, buf)
  2327. int x, y;
  2328. char *buf;
  2329. {
  2330. 	struct rm *lev = &levl[x][y];
  2331. 	int ltyp = lev->typ, cmap = -1;
  2332. 	const char *dfeature = 0;
  2333. 	static char altbuf[BUFSZ];
  2334.  
  2335. 	if (IS_DOOR(ltyp)) {
  2336. 	    switch (lev->doormask) {
  2337. 	    case D_NODOOR:	cmap = S_ndoor; break;	/* "doorway" */
  2338. 	    case D_ISOPEN:	cmap = S_vodoor; break;	/* "open door" */
  2339. 	    case D_BROKEN:	dfeature = "broken door"; break;
  2340. 	    default:	cmap = S_vcdoor; break;	/* "closed door" */
  2341. 	    }
  2342. 	    /* override door description for open drawbridge */
  2343. 	    if (is_drawbridge_wall(x, y) >= 0)
  2344. 		dfeature = "open drawbridge portcullis",  cmap = -1;
  2345. 	} else if (IS_FOUNTAIN(ltyp))
  2346. 	    cmap = S_fountain;				/* "fountain" */
  2347. 	else if (IS_THRONE(ltyp))
  2348. 	    cmap = S_throne;				/* "opulent throne" */
  2349. 	else if (is_lava(x,y))
  2350. 	    cmap = S_lava;				/* "molten lava" */
  2351. 	else if (is_ice(x,y))
  2352. 	    cmap = S_ice;				/* "ice" */
  2353. 	else if (is_pool(x,y))
  2354. 	    dfeature = "pool of water";
  2355. #ifdef SINKS
  2356. 	else if (IS_SINK(ltyp))
  2357. 	    cmap = S_sink;				/* "sink" */
  2358. 	else if (IS_TOILET(ltyp))
  2359. 	    cmap = S_toilet;
  2360. #endif
  2361. 	else if (IS_ALTAR(ltyp)) {
  2362. 	    Sprintf(altbuf, "altar to %s (%s)", a_gname(),
  2363. 		    align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
  2364. 	    dfeature = altbuf;
  2365. 	} else if ((x == xupstair && y == yupstair) ||
  2366. 		 (x == sstairs.sx && y == sstairs.sy && sstairs.up))
  2367. 	    cmap = S_upstair;				/* "staircase up" */
  2368. 	else if ((x == xdnstair && y == ydnstair) ||
  2369. 		 (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
  2370. 	    cmap = S_dnstair;				/* "staircase down" */
  2371. 	else if (x == xupladder && y == yupladder)
  2372. 	    cmap = S_upladder;				/* "ladder up" */
  2373. 	else if (x == xdnladder && y == ydnladder)
  2374. 	    cmap = S_dnladder;				/* "ladder down" */
  2375. 	else if (ltyp == DRAWBRIDGE_DOWN)
  2376. 	    cmap = S_vodbridge;			/* "lowered drawbridge" */
  2377. 	else if (ltyp == DBWALL)
  2378. 	    cmap = S_vcdbridge;			/* "raised drawbridge" */
  2379. 	else if (IS_GRAVE(ltyp))
  2380. 	    cmap = S_grave;				/* "grave" */
  2381. 	else if (ltyp == TREE)
  2382. 	    cmap = S_tree;				/* "tree" */
  2383. 	else if (ltyp == IRONBARS)
  2384. 	    dfeature = "set of iron bars";
  2385.  
  2386. 	if (cmap >= 0) dfeature = defsyms[cmap].explanation;
  2387. 	if (dfeature) Strcpy(buf, dfeature);
  2388. 	return dfeature;
  2389. }
  2390.  
  2391. /* look at what is here; if there are many objects (5 or more),
  2392. don't show them unless obj_cnt is 0 */
  2393. int
  2394. look_here(obj_cnt, picked_some)
  2395. int obj_cnt;	/* obj_cnt > 0 implies that autopickup is in progess */
  2396. boolean picked_some;
  2397. {
  2398. 	struct obj *otmp;
  2399. 	struct trap *trap;
  2400. 	const char *verb = Blind ? "feel" : "see";
  2401. 	const char *dfeature = (char*) 0;
  2402. 	char fbuf[BUFSZ], fbuf2[BUFSZ];
  2403. 	winid tmpwin;
  2404. 	boolean skip_objects = (obj_cnt >= 5), felt_cockatrice = FALSE;
  2405.  
  2406. 	if (u.uswallow && u.ustuck) {
  2407. 	    struct monst *mtmp = u.ustuck;
  2408. 	    Sprintf(fbuf, "Contents of %s %s",
  2409. 		s_suffix(mon_nam(mtmp)), mbodypart(mtmp, STOMACH));
  2410. 	    /* Skip "Contents of " by using fbuf index 12 */
  2411. 	    You("%s to %s what is lying in %s.",
  2412. 		Blind ? "try" : "look around", verb, &fbuf[12]);
  2413. 	    otmp = mtmp->minvent;
  2414. 	    if (otmp) {
  2415. 		for ( ; otmp; otmp = otmp->nobj) {
  2416. 			/* If swallower is an animal, it should have become stone but... */
  2417. 			if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
  2418. 		}
  2419. 		if (Blind) Strcpy(fbuf, "You feel");
  2420. 		Strcat(fbuf,":");
  2421. 	    	(void) display_minventory(mtmp, MINV_ALL, fbuf);
  2422. 	    } else {
  2423. 		You("%s no objects here.", verb);
  2424. 	    }
  2425. 	    return(!!Blind);
  2426. 	}
  2427. 	if (!skip_objects && (trap = t_at(u.ux,u.uy)) && trap->tseen)
  2428. 		There("is %s here.",
  2429. 			an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
  2430.  
  2431. 	otmp = level.objects[u.ux][u.uy];
  2432. 	dfeature = dfeature_at(u.ux, u.uy, fbuf2);
  2433. 	if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
  2434. 		dfeature = 0;
  2435.  
  2436. 	if (Blind) {
  2437. 		boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
  2438. 		if (dfeature && !strncmp(dfeature, "altar ", 6)) {
  2439. 		    /* don't say "altar" twice, dfeature has more info */
  2440. 		    You("try to feel what is here.");
  2441. 		} else {
  2442. 		    You("try to feel what is %s%s.",
  2443. 			drift ? "floating here" : "lying here on the ",
  2444. 			drift ? ""		: surface(u.ux, u.uy));
  2445. 		}
  2446. 		if (dfeature && !drift && !strcmp(dfeature, surface(u.ux,u.uy)))
  2447. 			dfeature = 0;		/* ice already identifed */
  2448. 		if (!can_reach_floor()) {
  2449. 			pline("But you can't reach it!");
  2450. 			return(0);
  2451. 		}
  2452. 	}
  2453.  
  2454. 	if (dfeature) {
  2455. 		Sprintf(fbuf, "There is %s here.", an(dfeature));
  2456. 		if (flags.suppress_alert < FEATURE_NOTICE_VER(0,0,7) &&
  2457. 			(IS_FOUNTAIN(levl[u.ux][u.uy].typ) ||
  2458. #ifdef SINKS
  2459. 			 IS_SINK(levl[u.ux][u.uy].typ) ||
  2460. 			 IS_TOILET(levl[u.ux][u.uy].typ)
  2461. #endif
  2462. 			))
  2463. 		    Strcat(fbuf, "  Use \"q.\" to drink from it.");
  2464. 	}
  2465.  
  2466. 	if (!otmp || is_lava(u.ux,u.uy) || (is_pool(u.ux,u.uy) && !Underwater)) {
  2467. 		if (dfeature) pline(fbuf);
  2468. 		sense_engr_at(u.ux, u.uy, FALSE); /* Eric Backus */
  2469. 		if (!skip_objects && (Blind || !dfeature))
  2470. 		    You("%s no objects here.", verb);
  2471. 		return(!!Blind);
  2472. 	}
  2473. 	/* we know there is something here */
  2474.  
  2475. 	if (skip_objects) {
  2476. 	    if (dfeature) pline(fbuf);
  2477. 	    sense_engr_at(u.ux, u.uy, FALSE); /* Eric Backus */
  2478. 	    There("are %s%s objects here.",
  2479. 		  (obj_cnt <= 10) ? "several" : "many",
  2480. 		  picked_some ? " more" : "");
  2481. 	} else if (!otmp->nexthere) {
  2482. 	    /* only one object */
  2483. 	    if (dfeature) pline(fbuf);
  2484. 	    sense_engr_at(u.ux, u.uy, FALSE); /* Eric Backus */
  2485. #ifdef INVISIBLE_OBJECTS
  2486. 	    if (otmp->oinvis && !See_invisible) verb = "feel";
  2487. #endif
  2488. 	    You("%s here %s.", verb, doname(otmp));
  2489. 	    if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
  2490. 	} else {
  2491. 	    display_nhwindow(WIN_MESSAGE, FALSE);
  2492. 	    tmpwin = create_nhwindow(NHW_MENU);
  2493. 	    if(dfeature) {
  2494. 		putstr(tmpwin, 0, fbuf);
  2495. 		putstr(tmpwin, 0, "");
  2496. 	    }
  2497. 	    putstr(tmpwin, 0, Blind ? "Things that you feel here:" :
  2498. 				      "Things that are here:");
  2499. 	    for ( ; otmp; otmp = otmp->nexthere) {
  2500. 		if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
  2501. 			char buf[BUFSZ];
  2502. 			felt_cockatrice = TRUE;
  2503. 			Strcpy(buf, doname(otmp));
  2504. 			Strcat(buf, "...");
  2505. 			putstr(tmpwin, 0, buf);
  2506. 			break;
  2507. 		}
  2508. 		putstr(tmpwin, 0, doname(otmp));
  2509. 	    }
  2510. 	    display_nhwindow(tmpwin, TRUE);
  2511. 	    destroy_nhwindow(tmpwin);
  2512. 	    if (felt_cockatrice) feel_cockatrice(otmp, FALSE);
  2513. 	    sense_engr_at(u.ux, u.uy, FALSE); /* Eric Backus */
  2514. 	}
  2515. 	return(!!Blind);
  2516. }
  2517.  
  2518. /* explicilty look at what is here, including all objects */
  2519. int
  2520. dolook()
  2521. {
  2522. 	return look_here(0, FALSE);
  2523. }
  2524.  
  2525. boolean
  2526. will_feel_cockatrice(otmp, force_touch)
  2527. struct obj *otmp;
  2528. boolean force_touch;
  2529. {
  2530. 	if ((Blind || force_touch) && !uarmg && !Stone_resistance &&
  2531. 		(otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
  2532. 			return TRUE;
  2533. 	return FALSE;
  2534. }
  2535.  
  2536. void
  2537. feel_cockatrice(otmp, force_touch)
  2538. struct obj *otmp;
  2539. boolean force_touch;
  2540. {
  2541. 	char kbuf[BUFSZ];
  2542.  
  2543. 	if (will_feel_cockatrice(otmp, force_touch)) {
  2544. 	    if(poly_when_stoned(youmonst.data))
  2545. 			You("touched the %s corpse with your bare %s.",
  2546. 				mons[otmp->corpsenm].mname, makeplural(body_part(HAND)));
  2547. 	    else
  2548. 			pline("Touching the %s corpse is a fatal mistake...",
  2549. 				mons[otmp->corpsenm].mname);
  2550. 		Sprintf(kbuf, "%s corpse", an(mons[otmp->corpsenm].mname));
  2551. 		instapetrify(kbuf);
  2552. 	}
  2553. }
  2554.  
  2555. #endif /* OVLB */
  2556. #ifdef OVL1
  2557.  
  2558. void
  2559. stackobj(obj)
  2560. struct obj *obj;
  2561. {
  2562. 	struct obj *otmp;
  2563.  
  2564. 	for(otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
  2565. 		if(otmp != obj && merged(&obj,&otmp))
  2566. 			break;
  2567. 	return;
  2568. }
  2569.  
  2570. STATIC_OVL boolean
  2571. mergable(otmp, obj)	/* returns TRUE if obj  & otmp can be merged */
  2572. 	register struct obj *otmp, *obj;
  2573. {
  2574. 	if (obj->otyp != otmp->otyp) return FALSE;
  2575. #ifdef GOLDOBJ
  2576. 	/* coins of the same kind will always merge */
  2577. 	if (obj->oclass == COIN_CLASS) return TRUE;
  2578. #endif
  2579. 	if (obj->unpaid != otmp->unpaid ||
  2580. 	    obj->spe != otmp->spe || obj->dknown != otmp->dknown ||
  2581. 	    (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST)) ||
  2582. 	    obj->cursed != otmp->cursed || obj->blessed != otmp->blessed ||
  2583. 	    obj->no_charge != otmp->no_charge ||
  2584. 	    obj->obroken != otmp->obroken ||
  2585. 	    obj->otrapped != otmp->otrapped ||
  2586. 	    obj->lamplit != otmp->lamplit ||
  2587. 	    flags.pickup_thrown && obj->was_thrown != otmp->was_thrown ||
  2588. #ifdef INVISIBLE_OBJECTS
  2589. 	    obj->oinvis != otmp->oinvis ||
  2590. #endif
  2591. #ifdef UNPOLYPILE
  2592. 	    obj->oldtyp != otmp->oldtyp ||
  2593. #endif
  2594. 	    obj->greased != otmp->greased ||
  2595. 	    obj->oeroded != otmp->oeroded ||
  2596. 	    obj->oeroded2 != otmp->oeroded2 ||
  2597. 	    obj->bypass != otmp->bypass)
  2598. 	    return(FALSE);
  2599.  
  2600. 	if ((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) &&
  2601. 	    (obj->oerodeproof!=otmp->oerodeproof || obj->rknown!=otmp->rknown))
  2602. 	    return FALSE;
  2603.  
  2604. 	if (obj->oclass == FOOD_CLASS && (obj->oeaten != otmp->oeaten ||
  2605. 	  obj->odrained != otmp->odrained || obj->orotten != otmp->orotten))
  2606. 	    return(FALSE);
  2607.  
  2608. 	if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
  2609. 		if (obj->corpsenm != otmp->corpsenm)
  2610. 				return FALSE;
  2611. 	}
  2612.  
  2613. 	/* armed grenades do not merge */
  2614. 	if ((obj->timed || otmp->timed) && is_grenade(obj))
  2615. 	    return FALSE;
  2616.  
  2617. 	/* hatching eggs don't merge; ditto for revivable corpses */
  2618. 	if ((obj->timed || otmp->timed) && (obj->otyp == EGG ||
  2619. 	    (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM &&
  2620. 		 is_reviver(&mons[otmp->corpsenm]))))
  2621. 	    return FALSE;
  2622.  
  2623. 	/* allow candle merging only if their ages are close */
  2624. 	/* see begin_burn() for a reference for the magic "25" */
  2625. 	/* [ALI] Slash'EM can't rely on using 25, because we
  2626. 	 * have chosen to reduce the cost of candles such that
  2627. 	 * the initial age is no longer a multiple of 25. The
  2628. 	 * simplest solution is just to use 20 instead, since
  2629. 	 * initial candle age is always a multiple of 20.
  2630. 	 */
  2631. 	if ((obj->otyp == TORCH || Is_candle(obj)) && obj->age/20 != otmp->age/20)
  2632. 	    return(FALSE);
  2633.  
  2634. 	/* burning potions of oil never merge */
  2635. 	/* MRKR: nor do burning torches */
  2636. 	if ((obj->otyp == POT_OIL || obj->otyp == TORCH) && obj->lamplit)
  2637. 	    return FALSE;
  2638.  
  2639. 	/* don't merge surcharged item with base-cost item */
  2640. 	if (obj->unpaid && !same_price(obj, otmp))
  2641. 	    return FALSE;
  2642.  
  2643. 	/* if they have names, make sure they're the same */
  2644. 	if ( (obj->onamelth != otmp->onamelth &&
  2645. 		((obj->onamelth && otmp->onamelth) || obj->otyp == CORPSE)
  2646. 	     ) ||
  2647. 	    (obj->onamelth && otmp->onamelth &&
  2648. 		    strncmp(ONAME(obj), ONAME(otmp), (int)obj->onamelth)))
  2649. 		return FALSE;
  2650.  
  2651. 	/* for the moment, any additional information is incompatible */
  2652. 	if (obj->oxlth || otmp->oxlth) return FALSE;
  2653.  
  2654. 	if(obj->oartifact != otmp->oartifact) return FALSE;
  2655.  
  2656. 	if(obj->known == otmp->known ||
  2657. 		!objects[otmp->otyp].oc_uses_known) {
  2658. 		return((boolean)(objects[obj->otyp].oc_merge));
  2659. 	} else return(FALSE);
  2660. }
  2661.  
  2662. int
  2663. doprgold()
  2664. {
  2665. 	/* the messages used to refer to "carrying gold", but that didn't
  2666. 	   take containers into account */
  2667. #ifndef GOLDOBJ
  2668. 	if(!u.ugold)
  2669. 	    Your("wallet is empty.");
  2670. 	else
  2671. 	    Your("wallet contains %ld gold piece%s.", u.ugold, plur(u.ugold));
  2672. #else
  2673. long umoney = money_cnt(invent);
  2674. 	if(!umoney)
  2675. 	    Your("wallet is empty.");
  2676. 	else
  2677. 	    Your("wallet contains %ld %s.", umoney, currency(umoney));
  2678. #endif
  2679. 	shopper_financial_report();
  2680. 	return 0;
  2681. }
  2682.  
  2683. #endif /* OVL1 */
  2684. #ifdef OVLB
  2685.  
  2686. int
  2687. doprwep()
  2688. {
  2689. if (!uwep) {
  2690. 	if (!u.twoweap){
  2691. 	You("are empty %s.", body_part(HANDED));
  2692. 	    return 0;
  2693. 	}
  2694. 	/* Avoid printing "right hand empty" and "other hand empty" */
  2695. 	if (!uswapwep) {
  2696. 	    You("are attacking with both %s.", makeplural(body_part(HAND)));
  2697. 	    return 0;
  2698. 	}
  2699. 	Your("right %s is empty.", body_part(HAND));
  2700. } else {
  2701. 	prinv((char *)0, uwep, 0L);
  2702. }
  2703. if (u.twoweap) {
  2704. 	if (uswapwep)
  2705. 	    prinv((char *)0, uswapwep, 0L);
  2706. 	else
  2707. 	    Your("other %s is empty.", body_part(HAND));
  2708. }
  2709. return 0;
  2710. #if 0
  2711. 	if(!uwep && !uswapwep && !uquiver) You("are empty %s.", body_part(HANDED));
  2712. 	else {
  2713. 		char lets[3];
  2714. 		register int ct = 0;
  2715.  
  2716. 		if(uwep) lets[ct++] = obj_to_let(uwep);
  2717. 		if(uswapwep) lets[ct++] = obj_to_let(uswapwep);
  2718. 		if(uquiver) lets[ct++] = obj_to_let(uquiver);
  2719. 		lets[ct] = 0;
  2720. 		(void) display_inventory(lets, FALSE);
  2721. }
  2722. return 0;
  2723. #endif
  2724. }
  2725.  
  2726. int
  2727. doprarm()
  2728. {
  2729. 	if(!wearing_armor())
  2730. 		You("are not wearing any armor.");
  2731. 	else {
  2732. #ifdef TOURIST
  2733. 		char lets[8];
  2734. #else
  2735. 		char lets[7];
  2736. #endif
  2737. 		register int ct = 0;
  2738.  
  2739. #ifdef TOURIST
  2740. 		if(uarmu) lets[ct++] = obj_to_let(uarmu);
  2741. #endif
  2742. 		if(uarm) lets[ct++] = obj_to_let(uarm);
  2743. 		if(uarmc) lets[ct++] = obj_to_let(uarmc);
  2744. 		if(uarmh) lets[ct++] = obj_to_let(uarmh);
  2745. 		if(uarms) lets[ct++] = obj_to_let(uarms);
  2746. 		if(uarmg) lets[ct++] = obj_to_let(uarmg);
  2747. 		if(uarmf) lets[ct++] = obj_to_let(uarmf);
  2748. 		lets[ct] = 0;
  2749. 		(void) display_inventory(lets, FALSE);
  2750. 	}
  2751. 	return 0;
  2752. }
  2753.  
  2754. int
  2755. doprring()
  2756. {
  2757. 	if(!uleft && !uright)
  2758. 		You("are not wearing any rings.");
  2759. 	else {
  2760. 		char lets[3];
  2761. 		register int ct = 0;
  2762.  
  2763. 		if(uleft) lets[ct++] = obj_to_let(uleft);
  2764. 		if(uright) lets[ct++] = obj_to_let(uright);
  2765. 		lets[ct] = 0;
  2766. 		(void) display_inventory(lets, FALSE);
  2767. 	}
  2768. 	return 0;
  2769. }
  2770.  
  2771. int
  2772. dopramulet()
  2773. {
  2774. 	if (!uamul)
  2775. 		You("are not wearing an amulet.");
  2776. 	else
  2777. 		prinv((char *)0, uamul, 0L);
  2778. 	return 0;
  2779. }
  2780.  
  2781. STATIC_OVL boolean
  2782. tool_in_use(obj)
  2783. struct obj *obj;
  2784. {
  2785. 	if ((obj->owornmask & (W_TOOL
  2786. #ifdef STEED
  2787. 			| W_SADDLE
  2788. #endif
  2789. 			)) != 0L) return TRUE;
  2790. 	if (obj->oclass != TOOL_CLASS) return FALSE;
  2791. 	return (boolean)(obj == uwep || obj->lamplit ||
  2792. 				(obj->otyp == LEASH && obj->leashmon));
  2793. }
  2794.  
  2795. int
  2796. doprtool()
  2797. {
  2798. 	struct obj *otmp;
  2799. 	int ct = 0;
  2800. 	char lets[52+1];
  2801.  
  2802. 	for (otmp = invent; otmp; otmp = otmp->nobj)
  2803. 	    if (tool_in_use(otmp))
  2804. 		lets[ct++] = obj_to_let(otmp);
  2805. 	lets[ct] = '\0';
  2806. 	if (!ct) You("are not using any tools.");
  2807. 	else (void) display_inventory(lets, FALSE);
  2808. 	return 0;
  2809. }
  2810.  
  2811. /* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
  2812. show inventory of all currently wielded, worn, or used objects */
  2813. int
  2814. doprinuse()
  2815. {
  2816. 	struct obj *otmp;
  2817. 	int ct = 0;
  2818. 	char lets[52+1];
  2819.  
  2820. 	for (otmp = invent; otmp; otmp = otmp->nobj)
  2821. 	    if (is_worn(otmp) || tool_in_use(otmp))
  2822. 		lets[ct++] = obj_to_let(otmp);
  2823. 	lets[ct] = '\0';
  2824. 	if (!ct) You("are not wearing or wielding anything.");
  2825. 	else (void) display_inventory(lets, FALSE);
  2826. 	return 0;
  2827. }
  2828.  
  2829. /*
  2830. * uses up an object that's on the floor, charging for it as necessary
  2831. */
  2832. void
  2833. useupf(obj, numused)
  2834. register struct obj *obj;
  2835. long numused;
  2836. {
  2837. 	register struct obj *otmp;
  2838. 	boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
  2839.  
  2840. 	/* burn_floor_paper() keeps an object pointer that it tries to
  2841. 	 * useupf() multiple times, so obj must survive if plural */
  2842. 	if (obj->quan > numused) {
  2843. 		otmp = splitobj(obj, numused);
  2844. 		obj->in_use = FALSE;		/* rest no longer in use */
  2845. 	}
  2846. 	else
  2847. 		otmp = obj;
  2848. 	if(costly_spot(otmp->ox, otmp->oy)) {
  2849. 	    if(index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
  2850. 	        addtobill(otmp, FALSE, FALSE, FALSE);
  2851. 	    else (void)stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE,
  2852. 		    TRUE);
  2853. 	}
  2854. 	delobj(otmp);
  2855. 	if (at_u && u.uundetected && hides_under(youmonst.data))
  2856. 	    u.uundetected = OBJ_AT(u.ux, u.uy);
  2857. }
  2858.  
  2859. #endif /* OVLB */
  2860.  
  2861.  
  2862. #ifdef OVL1
  2863.  
  2864. /*
  2865. * Conversion from a class to a string for printing.
  2866. * This must match the object class order.
  2867. */
  2868. STATIC_VAR NEARDATA const char *names[] = { 0,
  2869. 	"Illegal objects", "Weapons", "Armor", "Rings", "Amulets",
  2870. 	"Tools", "Comestibles", "Potions", "Scrolls", "Spellbooks",
  2871. 	"Wands", "Coins", "Gems", "Boulders/Statues", "Iron balls",
  2872. 	"Chains", "Venoms"
  2873. };
  2874.  
  2875. static NEARDATA const char oth_symbols[] = {
  2876. 	CONTAINED_SYM,
  2877. 	'\0'
  2878. };
  2879.  
  2880. static NEARDATA const char *oth_names[] = {
  2881. 	"Bagged/Boxed items"
  2882. };
  2883.  
  2884. static NEARDATA char *invbuf = (char *)0;
  2885. static NEARDATA unsigned invbufsiz = 0;
  2886.  
  2887. char *
  2888. let_to_name(let,unpaid)
  2889. char let;
  2890. boolean unpaid;
  2891. {
  2892. 	const char *class_name;
  2893. 	const char *pos;
  2894. 	int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
  2895. 	unsigned len;
  2896.  
  2897. 	if (oclass)
  2898. 	    class_name = names[oclass];
  2899. 	else if ((pos = index(oth_symbols, let)) != 0)
  2900. 	    class_name = oth_names[pos - oth_symbols];
  2901. 	else
  2902. 	    class_name = names[0];
  2903.  
  2904. 	len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "");
  2905. 	if (len > invbufsiz) {
  2906. 	    if (invbuf) free((genericptr_t)invbuf);
  2907. 	    invbufsiz = len + 10; /* add slop to reduce incremental realloc */
  2908. 	    invbuf = (char *) alloc(invbufsiz);
  2909. 	}
  2910. 	if (unpaid)
  2911. 	    Strcat(strcpy(invbuf, "Unpaid "), class_name);
  2912. 	else
  2913. 	    Strcpy(invbuf, class_name);
  2914. 	return invbuf;
  2915. }
  2916.  
  2917. void
  2918. free_invbuf()
  2919. {
  2920. 	if (invbuf) free((genericptr_t)invbuf),  invbuf = (char *)0;
  2921. 	invbufsiz = 0;
  2922. }
  2923.  
  2924. #endif /* OVL1 */
  2925. #ifdef OVLB
  2926.  
  2927. void
  2928. reassign()
  2929. {
  2930. 	register int i;
  2931. 	register struct obj *obj;
  2932.  
  2933. 	for(obj = invent, i = 0; obj; obj = obj->nobj, i++)
  2934. 		obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26);
  2935. 	lastinvnr = i;
  2936. }
  2937.  
  2938. #endif /* OVLB */
  2939. #ifdef OVL1
  2940.  
  2941. int
  2942. doorganize()	/* inventory organizer by Del Lamb */
  2943. {
  2944. 	struct obj *obj, *otmp;
  2945. 	register int ix, cur;
  2946. 	register char let;
  2947. 	char alphabet[52+1], buf[52+1];
  2948. 	char qbuf[QBUFSZ];
  2949. 	char allowall[2];
  2950. 	const char *adj_type;
  2951.  
  2952. 	if (!flags.invlet_constant) reassign();
  2953. 	/* get a pointer to the object the user wants to organize */
  2954. 	allowall[0] = ALL_CLASSES; allowall[1] = '\0';
  2955. 	if (!(obj = getobj(allowall,"adjust"))) return(0);
  2956.  
  2957. 	/* initialize the list with all upper and lower case letters */
  2958. 	for (let = 'a', ix = 0;  let <= 'z';) alphabet[ix++] = let++;
  2959. 	for (let = 'A', ix = 26; let <= 'Z';) alphabet[ix++] = let++;
  2960. 	alphabet[52] = 0;
  2961.  
  2962. 	/* blank out all the letters currently in use in the inventory */
  2963. 	/* except those that will be merged with the selected object   */
  2964. 	for (otmp = invent; otmp; otmp = otmp->nobj)
  2965. 		if (otmp != obj && !mergable(otmp,obj)) {
  2966. 			if (otmp->invlet <= 'Z')
  2967. 				alphabet[(otmp->invlet) - 'A' + 26] = ' ';
  2968. 			else	alphabet[(otmp->invlet) - 'a']	    = ' ';
  2969. 		}
  2970.  
  2971. 	/* compact the list by removing all the blanks */
  2972. 	for (ix = cur = 0; ix <= 52; ix++)
  2973. 		if (alphabet[ix] != ' ') buf[cur++] = alphabet[ix];
  2974.  
  2975. 	/* and by dashing runs of letters */
  2976. 	if(cur > 5) compactify(buf);
  2977.  
  2978. 	/* get new letter to use as inventory letter */
  2979. 	for (;;) {
  2980. 		Sprintf(qbuf, "Adjust letter to what [%s]?",buf);
  2981. 		let = yn_function(qbuf, (char *)0, '\0');
  2982. 		if(index(quitchars,let)) {
  2983. 			pline(Never_mind);
  2984. 			return(0);
  2985. 		}
  2986. 		if (let == '@' || !letter(let))
  2987. 			pline("Select an inventory slot letter.");
  2988. 		else
  2989. 			break;
  2990. 	}
  2991.  
  2992. 	/* change the inventory and print the resulting item */
  2993. 	adj_type = "Moving:";
  2994.  
  2995. 	/*
  2996. 	 * don't use freeinv/addinv to avoid double-touching artifacts,
  2997. 	 * dousing lamps, losing luck, cursing loadstone, etc.
  2998. 	 */
  2999. 	extract_nobj(obj, &invent);
  3000.  
  3001. 	for (otmp = invent; otmp;)
  3002. 		if (merged(&otmp,&obj)) {
  3003. 			adj_type = "Merging:";
  3004. 			obj = otmp;
  3005. 			otmp = otmp->nobj;
  3006. 			extract_nobj(obj, &invent);
  3007. 		} else {
  3008. 			if (otmp->invlet == let) {
  3009. 				adj_type = "Swapping:";
  3010. 				otmp->invlet = obj->invlet;
  3011. 			}
  3012. 			otmp = otmp->nobj;
  3013. 		}
  3014.  
  3015. 	/* inline addinv (assuming flags.invlet_constant and !merged) */
  3016. 	obj->invlet = let;
  3017. 	obj->nobj = invent; /* insert at beginning */
  3018. 	obj->where = OBJ_INVENT;
  3019. 	invent = obj;
  3020. 	reorder_invent();
  3021.  
  3022. 	prinv(adj_type, obj, 0L);
  3023. 	update_inventory();
  3024. 	return(0);
  3025. }
  3026.  
  3027. /* common to display_minventory and display_cinventory */
  3028. STATIC_OVL void
  3029. invdisp_nothing(hdr, txt)
  3030. const char *hdr, *txt;
  3031. {
  3032. 	winid win;
  3033. 	anything any;
  3034. 	menu_item *selected;
  3035.  
  3036. 	any.a_void = 0;
  3037. 	win = create_nhwindow(NHW_MENU);
  3038. 	start_menu(win);
  3039. 	add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr, MENU_UNSELECTED);
  3040. 	add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
  3041. 	add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
  3042. 	end_menu(win, (char *)0);
  3043. 	if (select_menu(win, PICK_NONE, &selected) > 0)
  3044. 	    free((genericptr_t)selected);
  3045. 	destroy_nhwindow(win);
  3046. 	return;
  3047. }
  3048.  
  3049. /* query_objlist callback: return things that could possibly be worn/wielded */
  3050. STATIC_OVL boolean
  3051. worn_wield_only(obj)
  3052. struct obj *obj;
  3053. {
  3054. return (obj->oclass == WEAPON_CLASS
  3055. 		|| obj->oclass == ARMOR_CLASS
  3056. 		|| obj->oclass == AMULET_CLASS
  3057. 		|| obj->oclass == RING_CLASS
  3058. 		|| obj->oclass == TOOL_CLASS);
  3059. }
  3060.  
  3061. /*
  3062. * Display a monster's inventory.
  3063. * Returns a pointer to the object from the monster's inventory selected
  3064. * or NULL if nothing was selected.
  3065. *
  3066. * By default, only worn and wielded items are displayed.  The caller
  3067. * can pick one.  Modifier flags are:
  3068. *
  3069. *	MINV_NOLET	- nothing selectable
  3070. *	MINV_ALL	- display all inventory
  3071. */
  3072. struct obj *
  3073. display_minventory(mon, dflags, title)
  3074. register struct monst *mon;
  3075. int dflags;
  3076. char *title;
  3077. {
  3078. 	struct obj *ret;
  3079. #ifndef GOLDOBJ
  3080. 	struct obj m_gold;
  3081. #endif
  3082. 	char tmp[QBUFSZ];
  3083. 	int n;
  3084. 	menu_item *selected = 0;
  3085. #ifndef GOLDOBJ
  3086. 	int do_all = (dflags & MINV_ALL) != 0,
  3087. 	    do_gold = (do_all && mon->mgold);
  3088. #else
  3089. 	int do_all = (dflags & MINV_ALL) != 0;
  3090. #endif
  3091.  
  3092. 	Sprintf(tmp,"%s %s:", s_suffix(noit_Monnam(mon)),
  3093. 		do_all ? "possessions" : "armament");
  3094.  
  3095. #ifndef GOLDOBJ
  3096. 	if (do_all ? (mon->minvent || mon->mgold)
  3097. #else
  3098. 	if (do_all ? (mon->minvent != 0)
  3099. #endif
  3100. 		   : (mon->misc_worn_check || MON_WEP(mon))) {
  3101. 	    /* Fool the 'weapon in hand' routine into
  3102. 	     * displaying 'weapon in claw', etc. properly.
  3103. 	     */
  3104. 	    youmonst.data = mon->data;
  3105.  
  3106. #ifndef GOLDOBJ
  3107. 	    if (do_gold) {
  3108. 		/*
  3109. 		 * Make temporary gold object and insert at the head of
  3110. 		 * the mon's inventory.  We can get away with using a
  3111. 		 * stack variable object because monsters don't carry
  3112. 		 * gold in their inventory, so it won't merge.
  3113. 		 */
  3114. 		m_gold = zeroobj;
  3115. 		m_gold.otyp = GOLD_PIECE;  m_gold.oclass = COIN_CLASS;
  3116. 		m_gold.quan = mon->mgold;  m_gold.dknown = 1;
  3117. 		m_gold.where = OBJ_FREE;
  3118. 		/* we had better not merge and free this object... */
  3119. 		if (add_to_minv(mon, &m_gold))
  3120. 		    panic("display_minventory: static object freed.");
  3121. 	    }
  3122.  
  3123. #endif
  3124. 	    n = query_objlist(title ? title : tmp, mon->minvent, INVORDER_SORT, &selected,
  3125. 			(dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
  3126. 			do_all ? allow_all : worn_wield_only);
  3127.  
  3128. #ifndef GOLDOBJ
  3129. 	    if (do_gold) obj_extract_self(&m_gold);
  3130. #endif
  3131.  
  3132. 	    set_uasmon();
  3133. 	} else {
  3134. 	    invdisp_nothing(title ? title : tmp, "(none)");
  3135. 	    n = 0;
  3136. 	}
  3137.  
  3138. 	if (n > 0) {
  3139. 	    ret = selected[0].item.a_obj;
  3140. 	    free((genericptr_t)selected);
  3141. #ifndef GOLDOBJ
  3142. 	    /*
  3143. 	     * Unfortunately, we can't return a pointer to our temporary
  3144. 	     * gold object.  We'll have to work out a scheme where this
  3145. 	     * can happen.  Maybe even put gold in the inventory list...
  3146. 	     */
  3147. 	    if (ret == &m_gold) ret = (struct obj *) 0;
  3148. #endif
  3149. 	} else
  3150. 	    ret = (struct obj *) 0;
  3151. 	return ret;
  3152. }
  3153.  
  3154. /*
  3155. * Display the contents of a container in inventory style.
  3156. * Currently, this is only used for statues, via wand of probing.
  3157. * [ALI] Also used when looting medical kits.
  3158. */
  3159. struct obj *
  3160. display_cinventory(obj)
  3161. register struct obj *obj;
  3162. {
  3163. 	struct obj *ret;
  3164. 	char tmp[QBUFSZ];
  3165. 	int n;
  3166. 	menu_item *selected = 0;
  3167.  
  3168. 	Sprintf(tmp,"Contents of %s:", doname(obj));
  3169.  
  3170. 	if (obj->cobj) {
  3171. 	    n = query_objlist(tmp, obj->cobj, INVORDER_SORT, &selected,
  3172. 			    PICK_NONE, allow_all);
  3173. 	} else {
  3174. 	    invdisp_nothing(tmp, "(empty)");
  3175. 	    n = 0;
  3176. 	}
  3177. 	if (n > 0) {
  3178. 	    ret = selected[0].item.a_obj;
  3179. 	    free((genericptr_t)selected);
  3180. 	} else
  3181. 	    ret = (struct obj *) 0;
  3182. 	return ret;
  3183. }
  3184.  
  3185. /* query objlist callback: return TRUE if obj is at given location */
  3186. static coord only;
  3187.  
  3188. STATIC_OVL boolean
  3189. only_here(obj)
  3190. struct obj *obj;
  3191. {
  3192. return (obj->ox == only.x && obj->oy == only.y);
  3193. }
  3194.  
  3195. /*
  3196. * Display a list of buried items in inventory style.  Return a non-zero
  3197. * value if there were items at that spot.
  3198. *
  3199. * Currently, this is only used with a wand of probing zapped downwards.
  3200. */
  3201. int
  3202. display_binventory(x, y, as_if_seen)
  3203. int x, y;
  3204. boolean as_if_seen;
  3205. {
  3206. 	struct obj *obj;
  3207. 	menu_item *selected = 0;
  3208. 	int n;
  3209.  
  3210. 	/* count # of objects here */
  3211. 	for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
  3212. 	    if (obj->ox == x && obj->oy == y) {
  3213. 		if (as_if_seen) obj->dknown = 1;
  3214. 		n++;
  3215. 	    }
  3216.  
  3217. 	if (n) {
  3218. 	    only.x = x;
  3219. 	    only.y = y;
  3220. 	    if (query_objlist("Things that are buried here:",
  3221. 			      level.buriedobjlist, INVORDER_SORT,
  3222. 			      &selected, PICK_NONE, only_here) > 0)
  3223. 		free((genericptr_t)selected);
  3224. 	    only.x = only.y = 0;
  3225. 	}
  3226. 	return n;
  3227. }
  3228.  
  3229. #endif /* OVL1 */
  3230.  
  3231. /*invent.c*/