Fandom

Wikihack

Source:NetHack 3.2.0/invent.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

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

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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)invent.c	3.2	96/03/03	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    #include "artifact.h"
7.    
8.    #define NOINVSYM	'#'
9.    #define CONTAINED_SYM	'>'	/* designator for inside a container */
10.   
11.   #ifdef OVL1
12.   static void NDECL(reorder_invent);
13.   static boolean FDECL(mergable,(struct obj *,struct obj *));
14.   static void FDECL(invdisp_nothing, (const char *,const char *));
15.   static boolean FDECL(worn_wield_only, (struct obj *));
16.   static boolean FDECL(only_here, (struct obj *));
17.   #endif /* OVL1 */
18.   STATIC_DCL void FDECL(compactify,(char *));
19.   STATIC_PTR int FDECL(ckunpaid,(struct obj *));
20.   #ifdef OVLB
21.   static boolean FDECL(this_type_only, (struct obj *));
22.   static void NDECL(dounpaid);
23.   static struct obj *FDECL(find_unpaid,(struct obj *,struct obj **));
24.   static void FDECL(fully_identify_obj, (struct obj *));
25.   static void FDECL(menu_identify, (int));
26.   static void FDECL(feel_cockatrice, (struct obj *));
27.   #endif /* OVLB */
28.   STATIC_DCL char FDECL(obj_to_let,(struct obj *));
29.   
30.   
31.   #ifdef OVLB
32.   
33.   static int lastinvnr = 51;	/* 0 ... 51 (never saved&restored) */
34.   
35.   #ifdef WIZARD
36.   /* wizards can wish for venom, which will become an invisible inventory
37.    * item without this.  putting it in inv_order would mean venom would
38.    * suddenly become a choice for all the inventory-class commands, which
39.    * would probably cause mass confusion.  the test for inventory venom
40.    * is only WIZARD and not wizard because the wizard can leave venom lying
41.    * around on a bones level for normal players to find.
42.    */
43.   static char venom_inv[] = { VENOM_CLASS, 0 };	/* (constant) */
44.   #endif
45.   
46.   void
47.   assigninvlet(otmp)
48.   register struct obj *otmp;
49.   {
50.   	boolean inuse[52];
51.   	register int i;
52.   	register struct obj *obj;
53.   
54.   	for(i = 0; i < 52; i++) inuse[i] = FALSE;
55.   	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
56.   		i = obj->invlet;
57.   		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
58.   		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
59.   		if(i == otmp->invlet) otmp->invlet = 0;
60.   	}
61.   	if((i = otmp->invlet) &&
62.   	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
63.   		return;
64.   	for(i = lastinvnr+1; i != lastinvnr; i++) {
65.   		if(i == 52) { i = -1; continue; }
66.   		if(!inuse[i]) break;
67.   	}
68.   	otmp->invlet = (inuse[i] ? NOINVSYM :
69.   			(i < 26) ? ('a'+i) : ('A'+i-26));
70.   	lastinvnr = i;
71.   }
72.   
73.   #endif /* OVLB */
74.   #ifdef OVL1
75.   
76.   /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
77.   #define inv_rank(o) ((o)->invlet ^ 040)
78.   
79.   /* sort the inventory; used by addinv() and doorganize() */
80.   static void
81.   reorder_invent()
82.   {
83.   	struct obj *otmp, *prev, *next;
84.   	boolean need_more_sorting;
85.   
86.   	do {
87.   	    /*
88.   	     * We expect at most one item to be out of order, so this
89.   	     * isn't nearly as inefficient as it may first appear.
90.   	     */
91.   	    need_more_sorting = FALSE;
92.   	    for (otmp = invent, prev = 0; otmp; ) {
93.   		next = otmp->nobj;
94.   		if (next && inv_rank(next) < inv_rank(otmp)) {
95.   		    need_more_sorting = TRUE;
96.   		    if (prev) prev->nobj = next;
97.   		    else      invent = next;
98.   		    otmp->nobj = next->nobj;
99.   		    next->nobj = otmp;
100.  		    prev = next;
101.  		} else {
102.  		    prev = otmp;
103.  		    otmp = next;
104.  		}
105.  	    }
106.  	} while (need_more_sorting);
107.  }
108.  
109.  #undef inv_rank
110.  
111.  /* scan a list of objects to see whether another object will merge with
112.     one of them; used in pickup.c */
113.  struct obj *
114.  merge_choice(objlist, obj)
115.  struct obj *objlist, *obj;
116.  {
117.  	if (obj->otyp == SCR_SCARE_MONSTER)	/* punt on these */
118.  	    return (struct obj *)0;
119.  	while (objlist) {
120.  	    if (mergable(objlist, obj)) return objlist;
121.  	    objlist = objlist->nobj;
122.  	}
123.  	return (struct obj *)0;
124.  }
125.  
126.  /* merge obj with otmp and delete obj if types agree */
127.  int
128.  merged(potmp, pobj)
129.  struct obj **potmp, **pobj;
130.  {
131.  	register struct obj *otmp = *potmp, *obj = *pobj;
132.  
133.  	if(mergable(otmp, obj)) {
134.  		/* Approximate age: we do it this way because if we were to
135.  		 * do it "accurately" (merge only when ages are identical)
136.  		 * we'd wind up never merging any corpses.
137.  		 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
138.  		 *
139.  		 * Don't do the age manipulation if lit.  We would need
140.  		 * to stop the burn on both items, then merge the age,
141.  		 * then restart the burn.
142.  		 */
143.  		if (!obj->lamplit)
144.  		    otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan))
145.  			    / (otmp->quan + obj->quan);
146.  
147.  		otmp->quan += obj->quan;
148.  		otmp->owt += obj->owt;
149.  		if(!otmp->onamelth && obj->onamelth)
150.  			otmp = *potmp = oname(otmp, ONAME(obj));
151.  		obj_extract_self(obj);
152.  
153.  		/* really should merge the timeouts */
154.  		if (obj->lamplit) end_burn(obj, TRUE);
155.  		if (obj->timed) obj_stop_timers(obj);	/* follows end_burn */
156.  
157.  		/* fixup for `#adjust' merging wielded darts, daggers, &c */
158.  		if (obj->owornmask) {
159.  			otmp->owornmask |= obj->owornmask;
160.  			/* (it isn't necessary to "unwear" `obj' first) */
161.  			if (otmp->where == OBJ_INVENT)
162.  			    setworn(otmp, otmp->owornmask);
163.  #if 0
164.  			/* (this should never be necessary, since items
165.  			    already in a monster's inventory don't ever get
166.  			    merged into other objects [only vice versa]) */
167.  			else if (otmp->where == OBJ_MINVENT) {
168.  			    if (obj == MON_WEP(otmp->ocarry))
169.  				MON_WEP(otmp->ocarry) = otmp;
170.  			}
171.  #endif
172.  		}
173.  		obfree(obj,otmp);	/* free(obj), bill->otmp */
174.  		return(1);
175.  	}
176.  	return 0;
177.  }
178.  
179.  struct obj *
180.  addinv(obj)
181.  struct obj *obj;
182.  {
183.  	struct obj *otmp, *prev;
184.  
185.  	if (obj->where != OBJ_FREE)
186.  		panic("addinv: obj not free");
187.  
188.  	if (obj->oclass == GOLD_CLASS) {
189.  		u.ugold += obj->quan;
190.  		flags.botl = 1;
191.  		return obj;
192.  	} else if (obj->otyp == AMULET_OF_YENDOR) {
193.  		if (u.uhave.amulet) impossible ("already have amulet?");
194.  		u.uhave.amulet = 1;
195.  	} else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
196.  		if (u.uhave.menorah) impossible ("already have candelabrum?");
197.  		u.uhave.menorah = 1;
198.  	} else if (obj->otyp == BELL_OF_OPENING) {
199.  		if (u.uhave.bell) impossible ("already have silver bell?");
200.  		u.uhave.bell = 1;
201.  	} else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
202.  		if (u.uhave.book) impossible ("already have the book?");
203.  		u.uhave.book = 1;
204.  	} else if (is_quest_artifact(obj)) {
205.  		if (u.uhave.questart) impossible ("already have the artifact?");
206.  		u.uhave.questart = 1;
207.  		artitouch();
208.  		set_artifact_intrinsic(obj, 1, W_ART);
209.  	} else if(obj->oartifact) {
210.  		set_artifact_intrinsic(obj, 1, W_ART);
211.  	}
212.  	/* merge if possible; find end of chain in the process */
213.  	for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
214.  	    if (merged(&otmp, &obj)) {
215.  		obj = otmp;
216.  		goto added;
217.  	    }
218.  	/* didn't merge, so insert into chain */
219.  	if (flags.invlet_constant || !prev) {
220.  	    if (flags.invlet_constant) assigninvlet(obj);
221.  	    obj->nobj = invent;		/* insert at beginning */
222.  	    invent = obj;
223.  	    if (flags.invlet_constant) reorder_invent();
224.  	} else {
225.  	    prev->nobj = obj;		/* insert at end */
226.  	    obj->nobj = 0;
227.  	}
228.  	obj->where = OBJ_INVENT;
229.  
230.  added:
231.  	if (obj->otyp == LUCKSTONE
232.  	    || (obj->oartifact && spec_ability(obj, SPFX_LUCK))) {
233.  		/* new luckstone must be in inventory by this point
234.  		 * for correct calculation */
235.  		set_moreluck();
236.  	}
237.  	update_inventory();
238.  	return(obj);
239.  }
240.  
241.  #endif /* OVL1 */
242.  #ifdef OVLB
243.  
244.  /* Add an item to the inventory unless we're fumbling, and give a message.
245.   * If there aren't any free inventory slots, we'll drop it instead.
246.   * If both success and failure messages are NULL, then we're just doing the
247.   * fumbling/slot-limit checking for a silent grab.
248.   */
249.  struct obj *
250.  hold_another_object(obj, drop_fmt, drop_arg, hold_msg)
251.  struct obj *obj;
252.  const char *drop_fmt, *drop_arg, *hold_msg;
253.  {
254.  	if (!Blind) obj->dknown = 1;	/* maximize mergibility */
255.  	if (Fumbling) {
256.  		if (drop_fmt) pline(drop_fmt, drop_arg);
257.  		dropy(obj);
258.  	} else {
259.  		long oquan = obj->quan;
260.  		int prev_encumbr = near_capacity();	/* before addinv() */
261.  		/* encumbrance only matters if it would now become worse
262.  		   than max( current_value, stressed ) */
263.  		if (prev_encumbr < MOD_ENCUMBER) prev_encumbr = MOD_ENCUMBER;
264.  		obj = addinv(obj);
265.  		if (inv_cnt() > 52
266.  		    || ((obj->otyp != LOADSTONE || !obj->cursed)
267.  			&& near_capacity() > prev_encumbr)) {
268.  			if (drop_fmt) pline(drop_fmt, drop_arg);
269.  			/* undo any merge which took place */
270.  			if (obj->quan > oquan) {
271.  			    struct obj *otmp = splitobj(obj, oquan);
272.  			    /* might have merged with weapon */
273.  			    if (obj->owornmask)
274.  				setworn(otmp, obj->owornmask);
275.  			}
276.  			dropx(obj);
277.  		} else {
278.  			if (hold_msg || drop_fmt) prinv(hold_msg, obj, oquan);
279.  		}
280.  	}
281.  	return obj;
282.  }
283.  
284.  void
285.  useup(obj)
286.  register struct obj *obj;
287.  {
288.  	/*  Note:  This works correctly for containers because they */
289.  	/*	   (containers) don't merge.			    */
290.  	if(obj->quan > 1L){
291.  #ifndef NO_SIGNAL
292.  		obj->in_use = FALSE;	/* no longer in use */
293.  #endif
294.  		obj->quan--;
295.  		obj->owt = weight(obj);
296.  		update_inventory();
297.  	} else {
298.  		setnotworn(obj);
299.  		freeinv(obj);
300.  		obfree(obj, (struct obj *) 0);	/* deletes contents also */
301.  	}
302.  }
303.  
304.  #endif /* OVLB */
305.  #ifdef OVL3
306.  
307.  void
308.  freeinv(obj)
309.  register struct obj *obj;
310.  {
311.  	extract_nobj(obj, &invent);
312.  
313.  	if (obj->oclass == GOLD_CLASS) {
314.  		u.ugold -= obj->quan;
315.  		flags.botl = 1;
316.  		return;
317.  	} else if (obj->otyp == AMULET_OF_YENDOR) {
318.  		if (!u.uhave.amulet) impossible ("don't have amulet?");
319.  		u.uhave.amulet = 0;
320.  	} else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
321.  		if (!u.uhave.menorah) impossible ("don't have candelabrum?");
322.  		u.uhave.menorah = 0;
323.  	} else if (obj->otyp == BELL_OF_OPENING) {
324.  		if (!u.uhave.bell) impossible ("don't have silver bell?");
325.  		u.uhave.bell = 0;
326.  	} else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
327.  		if (!u.uhave.book) impossible ("don't have the book?");
328.  		u.uhave.book = 0;
329.  	} else if (is_quest_artifact(obj)) {
330.  		if(!u.uhave.questart) impossible ("don't have the artifact?");
331.  		u.uhave.questart = 0;
332.  		set_artifact_intrinsic(obj, 0, W_ART);
333.  	} else if (obj->oartifact) {
334.  		set_artifact_intrinsic(obj, 0, W_ART);
335.  	} else if (obj->otyp == LOADSTONE) {
336.  		curse(obj);
337.  	} else if (obj->otyp == LUCKSTONE
338.  		   || (obj->oartifact && spec_ability(obj, SPFX_LUCK))) {
339.  		set_moreluck();
340.  		flags.botl = 1;
341.  	}
342.  	update_inventory();
343.  }
344.  
345.  void
346.  delallobj(x, y)
347.  int x, y;
348.  {
349.  	struct obj *otmp, *otmp2;
350.  
351.  	for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
352.  		if (otmp == uball)
353.  			unpunish();
354.  		/* after unpunish(), or might get deallocated chain */
355.  		otmp2 = otmp->nexthere;
356.  		if (otmp == uchain)
357.  			continue;
358.  		delobj(otmp);
359.  	}
360.  }
361.  
362.  #endif /* OVL3 */
363.  #ifdef OVL2
364.  
365.  /* destroy object in fobj chain (if unpaid, it remains on the bill) */
366.  void
367.  delobj(obj)
368.  register struct obj *obj;
369.  {
370.  	if(obj->otyp == LEASH && obj->leashmon != 0) o_unleash(obj);
371.  	if (obj->otyp == AMULET_OF_YENDOR ||
372.  			obj->otyp == CANDELABRUM_OF_INVOCATION ||
373.  			obj->otyp == BELL_OF_OPENING ||
374.  			obj->otyp == SPE_BOOK_OF_THE_DEAD) {
375.  		/* player might be doing something stupid, but we
376.  		 * can't guarantee that.  assume special artifacts
377.  		 * are indestructible via drawbridges, and exploding
378.  		 * chests, and golem creation, and ...
379.  		 */
380.  		return;
381.  	}
382.  	obj_extract_self(obj);
383.  	newsym(obj->ox,obj->oy);
384.  	obfree(obj, (struct obj *) 0);	/* frees contents also */
385.  }
386.  
387.  #endif /* OVL2 */
388.  #ifdef OVL0
389.  
390.  struct obj *
391.  sobj_at(n,x,y)
392.  register int n, x, y;
393.  {
394.  	register struct obj *otmp;
395.  
396.  	for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
397.  		if(otmp->otyp == n)
398.  		    return(otmp);
399.  	return((struct obj *)0);
400.  }
401.  
402.  #endif /* OVL0 */
403.  #ifdef OVLB
404.  
405.  struct obj *
406.  carrying(type)
407.  register int type;
408.  {
409.  	register struct obj *otmp;
410.  
411.  	for(otmp = invent; otmp; otmp = otmp->nobj)
412.  		if(otmp->otyp == type)
413.  			return(otmp);
414.  	return((struct obj *) 0);
415.  }
416.  
417.  boolean
418.  have_lizard()
419.  {
420.  	register struct obj *otmp;
421.  
422.  	for(otmp = invent; otmp; otmp = otmp->nobj)
423.  		if(otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
424.  			return(TRUE);
425.  	return(FALSE);
426.  }
427.  
428.  struct obj *
429.  o_on(id, objchn)
430.  unsigned int id;
431.  register struct obj *objchn;
432.  {
433.  	struct obj *temp;
434.  
435.  	while(objchn) {
436.  		if(objchn->o_id == id) return(objchn);
437.  		if (Has_contents(objchn) && (temp = o_on(id,objchn->cobj)))
438.  			return temp;
439.  		objchn = objchn->nobj;
440.  	}
441.  	return((struct obj *) 0);
442.  }
443.  
444.  boolean
445.  obj_here(obj, x, y)
446.  register struct obj *obj;
447.  int x, y;
448.  {
449.  	register struct obj *otmp;
450.  
451.  	for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
452.  		if(obj == otmp) return(TRUE);
453.  	return(FALSE);
454.  }
455.  
456.  #endif /* OVLB */
457.  #ifdef OVL2
458.  
459.  struct obj *
460.  g_at(x,y)
461.  register int x, y;
462.  {
463.  	register struct obj *obj = level.objects[x][y];
464.  	while(obj) {
465.  	    if (obj->oclass == GOLD_CLASS) return obj;
466.  	    obj = obj->nexthere;
467.  	}
468.  	return((struct obj *)0);
469.  }
470.  
471.  #endif /* OVL2 */
472.  #ifdef OVLB
473.  
474.  /* Make a gold object from the hero's gold. */
475.  struct obj *
476.  mkgoldobj(q)
477.  register long q;
478.  {
479.  	register struct obj *otmp;
480.  
481.  	otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
482.  	u.ugold -= q;
483.  	otmp->quan = q;
484.  	otmp->owt = weight(otmp);
485.  	flags.botl = 1;
486.  	return(otmp);
487.  }
488.  
489.  #endif /* OVLB */
490.  #ifdef OVL1
491.  
492.  STATIC_OVL void
493.  compactify(buf)
494.  register char *buf;
495.  /* compact a string of inventory letters by dashing runs of letters */
496.  {
497.  	register int i1 = 1, i2 = 1;
498.  	register char ilet, ilet1, ilet2;
499.  
500.  	ilet2 = buf[0];
501.  	ilet1 = buf[1];
502.  	buf[++i2] = buf[++i1];
503.  	ilet = buf[i1];
504.  	while(ilet) {
505.  		if(ilet == ilet1+1) {
506.  			if(ilet1 == ilet2+1)
507.  				buf[i2 - 1] = ilet1 = '-';
508.  			else if(ilet2 == '-') {
509.  				buf[i2 - 1] = ++ilet1;
510.  				buf[i2] = buf[++i1];
511.  				ilet = buf[i1];
512.  				continue;
513.  			}
514.  		}
515.  		ilet2 = ilet1;
516.  		ilet1 = ilet;
517.  		buf[++i2] = buf[++i1];
518.  		ilet = buf[i1];
519.  	}
520.  }
521.  
522.  /*
523.   * getobj returns:
524.   *	struct obj *xxx:	object to do something with.
525.   *	(struct obj *) 0	error return: no object.
526.   *	&zeroobj		explicitly no object (as in w-).
527.   */
528.  struct obj *
529.  getobj(let,word)
530.  register const char *let,*word;
531.  {
532.  	register struct obj *otmp;
533.  	register char ilet;
534.  	char buf[BUFSZ], qbuf[QBUFSZ];
535.  	char lets[BUFSZ];
536.  	register int foo = 0;
537.  	register char *bp = buf;
538.  	xchar allowcnt = 0;	/* 0, 1 or 2 */
539.  	boolean allowgold = FALSE, usegold = FALSE;
540.  		/* Two possibilities: they can't use gold because it's illegal,
541.  		 * or they can't use gold because they don't have any.
542.  		 */
543.  	boolean allowall = FALSE;
544.  	boolean allownone = FALSE;
545.  	xchar foox = 0;
546.  	long cnt;
547.  	boolean prezero = FALSE;
548.  
549.  	if(*let == ALLOW_COUNT) let++, allowcnt = 1;
550.  	if(*let == GOLD_CLASS) let++,
551.  		usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE);
552.  
553.  	/* Equivalent of an "ugly check" for gold */
554.  	if (usegold && !strcmp(word, "eat") && !metallivorous(uasmon))
555.  		usegold = allowgold = FALSE;
556.  
557.  	if(*let == ALL_CLASSES) let++, allowall = TRUE;
558.  	if(*let == ALLOW_NONE) let++, allownone = TRUE;
559.  	/* "ugly check" for reading fortune cookies, part 1 */
560.  	/* The normal 'ugly check' keeps the object on the inventory list.
561.  	 * We don't want to do that for shirts/cookies, so the check for
562.  	 * them is handled a bit differently (and also requires that we set
563.  	 * allowall in the caller)
564.  	 */
565.  	if(allowall && !strcmp(word, "read")) allowall = FALSE;
566.  
567.  	if(allownone) *bp++ = '-';
568.  	if(allowgold) *bp++ = def_oc_syms[GOLD_CLASS];
569.  	if(bp > buf && bp[-1] == '-') *bp++ = ' ';
570.  
571.  	ilet = 'a';
572.  	for (otmp = invent; otmp; otmp = otmp->nobj) {
573.  	    if (!flags.invlet_constant) otmp->invlet = ilet;	/* reassign() */
574.  	    if (!*let || index(let, otmp->oclass)) {
575.  		register int otyp = otmp->otyp;
576.  		bp[foo++] = otmp->invlet;
577.  
578.  		/* ugly check: remove inappropriate things */
579.  		if((!strcmp(word, "take off") &&
580.  		    (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))
581.  		     || (otmp==uarm && uarmc)
582.  #ifdef TOURIST
583.  		     || (otmp==uarmu && (uarm || uarmc))
584.  #endif
585.  		    ))
586.  		|| (!strcmp(word, "wear") &&
587.  		     (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
588.  							/* already worn */
589.  		|| (!strcmp(word, "wield") &&
590.  		    (otmp->owornmask & W_WEP))
591.  		    ) {
592.  			foo--;
593.  			foox++;
594.  		}
595.  
596.  		/* Second ugly check; unlike the first it won't trigger an
597.  		 * "else" in "you don't have anything else to ___".
598.  		 */
599.  		else if ((!strcmp(word, "wear") &&
600.  		    (otmp->oclass == TOOL_CLASS &&
601.  		     otyp != BLINDFOLD && otyp != TOWEL))
602.  		|| (!strcmp(word, "wield") &&
603.  		    (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
604.  		|| (!strcmp(word, "eat") && !is_edible(otmp))
605.  		|| (!strcmp(word, "sacrifice") &&
606.  		    (otyp != CORPSE &&
607.  		     otyp != AMULET_OF_YENDOR && otyp != FAKE_AMULET_OF_YENDOR))
608.  		|| (!strcmp(word, "write with") &&
609.  		    (otmp->oclass == TOOL_CLASS &&
610.  		     otyp != MAGIC_MARKER && otyp != TOWEL))
611.  		|| (!strcmp(word, "tin") &&
612.  		    (otyp != CORPSE || !tinnable(otmp)))
613.  		|| (!strcmp(word, "rub") &&
614.  		    (otmp->oclass == TOOL_CLASS &&
615.  		     otyp != OIL_LAMP && otyp != MAGIC_LAMP &&
616.  		     otyp != BRASS_LANTERN))
617.  		|| ((!strcmp(word, "use or apply") ||
618.  			!strcmp(word, "untrap with")) &&
619.  		     /* only applicable weapon is BULLWHIP */
620.  		    ((otmp->oclass == WEAPON_CLASS && otyp != BULLWHIP)
621.  		|| (otmp->oclass == POTION_CLASS &&
622.  		     /* only applicable potion is oil, and it will only
623.  			be offered as a choice when already discovered */
624.  		     (otyp != POT_OIL || !otmp->dknown ||
625.  		      !objects[POT_OIL].oc_name_known))))
626.  		|| (!strcmp(word, "invoke") &&
627.  		    (!otmp->oartifact && !objects[otyp].oc_unique &&
628.  		     (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) &&
629.  		     otyp != CRYSTAL_BALL &&	/* #invoke synonym for apply */
630.  		   /* note: presenting the possibility of invoking non-artifact
631.  		      mirrors and/or lamps is a simply a cruel deception... */
632.  		     otyp != MIRROR && otyp != MAGIC_LAMP &&
633.  		     (otyp != OIL_LAMP ||	/* don't list known oil lamp */
634.  		      (otmp->dknown && objects[OIL_LAMP].oc_name_known))))
635.  		|| (!strcmp(word, "untrap with") &&
636.  		    (otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE))
637.  		|| (!strcmp(word, "charge") && !is_chargeable(otmp))
638.  		    )
639.  			foo--;
640.  	    } else {
641.  
642.  		/* "ugly check" for reading fortune cookies, part 2 */
643.  		if ((!strcmp(word, "read") &&
644.  		    (otmp->otyp == FORTUNE_COOKIE
645.  #ifdef TOURIST
646.  			|| otmp->otyp == T_SHIRT
647.  #endif
648.  		    )))
649.  			allowall = TRUE;
650.  	    }
651.  
652.  	    if(ilet == 'z') ilet = 'A'; else ilet++;
653.  	}
654.  	bp[foo] = 0;
655.  	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
656.  	Strcpy(lets, bp);	/* necessary since we destroy buf */
657.  	if(foo > 5)			/* compactify string */
658.  		compactify(bp);
659.  
660.  	if(!foo && !allowall && !allowgold && !allownone) {
661.  		You("don't have anything %sto %s.",
662.  			foox ? "else " : "", word);
663.  		return((struct obj *)0);
664.  	}
665.  	for(;;) {
666.  		cnt = 0;
667.  		if (allowcnt == 2) allowcnt = 1;  /* abort previous count */
668.  		if(!buf[0]) {
669.  			Sprintf(qbuf, "What do you want to %s? [*]", word);
670.  		} else {
671.  			Sprintf(qbuf, "What do you want to %s? [%s or ?*]",
672.  				word, buf);
673.  		}
674.  #ifdef REDO
675.  		if (in_doagain)
676.  		    ilet = readchar();
677.  		else
678.  #endif
679.  		    ilet = yn_function(qbuf, (char *)0, '\0');
680.  		if(ilet == '0') prezero = TRUE;
681.  		while(digit(ilet) && allowcnt) {
682.  #ifdef REDO
683.  			if (ilet != '?' && ilet != '*')	savech(ilet);
684.  #endif
685.  			cnt = 10*cnt + (ilet - '0');
686.  			allowcnt = 2;	/* signal presence of cnt */
687.  			ilet = readchar();
688.  		}
689.  		if(digit(ilet)) {
690.  			pline("No count allowed with this command.");
691.  			continue;
692.  		}
693.  		if(index(quitchars,ilet)) {
694.  		    if(flags.verbose)
695.  			pline("Never mind.");
696.  		    return((struct obj *)0);
697.  		}
698.  		if(ilet == '-') {
699.  			return(allownone ? &zeroobj : (struct obj *) 0);
700.  		}
701.  		if(ilet == def_oc_syms[GOLD_CLASS]) {
702.  			if(!usegold){
703.  				You("cannot %s gold.", word);
704.  				return(struct obj *)0;
705.  			} else if (!allowgold) {
706.  				You("are not carrying any gold.");
707.  				return(struct obj *)0;
708.  			}
709.  			if(cnt == 0 && prezero) return((struct obj *)0);
710.  			/* Historic note: early Nethack had a bug which was
711.  			 * first reported for Larn, where trying to drop 2^32-n
712.  			 * gold pieces was allowed, and did interesting things
713.  			 * to your money supply.  The LRS is the tax bureau
714.  			 * from Larn.
715.  			 */
716.  			if(cnt < 0) {
717.  	pline_The("LRS would be very interested to know you have that much.");
718.  				return(struct obj *)0;
719.  			}
720.  
721.  			if(!(allowcnt == 2 && cnt < u.ugold))
722.  				cnt = u.ugold;
723.  			return(mkgoldobj(cnt));
724.  		}
725.  		if(allowcnt == 2 && !strcmp(word,"throw")) {
726.  			/* permit counts for throwing gold, but don't accept
727.  			 * counts for other things since the throw code will
728.  			 * split off a single item anyway */
729.  			allowcnt = 1;
730.  			if(cnt == 0 && prezero) return((struct obj *)0);
731.  			if(cnt > 1) {
732.  			    You("can only throw one item at a time.");
733.  			    continue;
734.  			}
735.  		}
736.  		if(ilet == '?' || ilet == '*') {
737.  		    ilet = display_inventory(ilet=='?' ? lets:(char *)0, TRUE);
738.  		    if(!ilet) continue;
739.  		    if(ilet == '\033') {
740.  			if(flags.verbose)
741.  			    pline("Never mind.");
742.  			return((struct obj *)0);
743.  		    }
744.  		    /* they typed a letter (not a space) at the prompt */
745.  		}
746.  #ifdef REDO
747.  		savech(ilet);
748.  #endif
749.  		for (otmp = invent; otmp; otmp = otmp->nobj)
750.  			if (otmp->invlet == ilet) break;
751.  		if(!otmp) {
752.  			You("don't have that object.");
753.  #ifdef REDO
754.  			if (in_doagain) return((struct obj *) 0);
755.  #endif
756.  			continue;
757.  		} else if (cnt < 0 || otmp->quan < cnt) {
758.  			You("don't have that many!  You have only %ld.",
759.  			    otmp->quan);
760.  #ifdef REDO
761.  			if (in_doagain) return((struct obj *) 0);
762.  #endif
763.  			continue;
764.  		}
765.  		break;
766.  	}
767.  	if(!allowall && let && !index(let,otmp->oclass)) {
768.  		pline(silly_thing_to, word);
769.  		return((struct obj *)0);
770.  	}
771.  	if(allowcnt == 2) {	/* cnt given */
772.  		if(cnt == 0) return (struct obj *)0;
773.  		if(cnt != otmp->quan) {
774.  			register struct obj *obj = splitobj(otmp, cnt);
775.  		/* Very ugly kludge necessary to prevent someone from trying
776.  		 * to drop one of several loadstones and having the loadstone
777.  		 * now be separate.
778.  		 */
779.  			if (!strcmp(word, "drop") &&
780.  			    obj->otyp == LOADSTONE && obj->cursed)
781.  				otmp->corpsenm = obj->invlet;
782.  			if(otmp == uwep) setuwep(obj);
783.  		}
784.  	}
785.  	return(otmp);
786.  }
787.  
788.  #endif /* OVL1 */
789.  #ifdef OVLB
790.  
791.  STATIC_PTR int
792.  ckunpaid(otmp)
793.  register struct obj *otmp;
794.  {
795.  	return((int)(otmp->unpaid));
796.  }
797.  
798.  boolean
799.  wearing_armor()
800.  {
801.  	return((boolean)(uarm || uarmc || uarmf || uarmg || uarmh || uarms
802.  #ifdef TOURIST
803.  		|| uarmu
804.  #endif
805.  		));
806.  }
807.  
808.  boolean
809.  is_worn(otmp)
810.  register struct obj *otmp;
811.  {
812.      return((boolean)(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP))));
813.  }
814.  
815.  static NEARDATA const char removeables[] =
816.  	{ ARMOR_CLASS, WEAPON_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, 0 };
817.  
818.  /* interactive version of getobj - used for Drop, Identify and */
819.  /* Takeoff (A). Return the number of times fn was called successfully */
820.  /* If combo is TRUE, we just use this to get a category list */
821.  int
822.  ggetobj(word, fn, mx, combo)
823.  const char *word;
824.  int FDECL((*fn),(OBJ_P)), mx;
825.  boolean combo;		/* combination menu flag */
826.  {
827.  	int FDECL((*ckfn),(OBJ_P)) = (int FDECL((*),(OBJ_P))) 0;
828.  	boolean FDECL((*filter),(OBJ_P)) = (boolean FDECL((*),(OBJ_P))) 0;
829.  	boolean takeoff, ident, allflag, m_seen;
830.  	int oletct, iletct, allowgold, unpaid, oc_of_sym;
831.  	char sym, *ip, olets[MAXOCLASSES+5], ilets[MAXOCLASSES+5];
832.  	char buf[BUFSZ], qbuf[QBUFSZ];
833.  
834.  	allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0;
835.  	takeoff = ident = allflag = m_seen = FALSE;
836.  	if(!invent && !allowgold){
837.  		You("have nothing to %s.", word);
838.  		return(0);
839.  	}
840.  	if (combo) add_valid_menu_class(0);	/* reset */
841.  	if (!strcmp(word, "take off")) {
842.  	    takeoff = TRUE;
843.  	    filter = is_worn;
844.  	} else if (!strcmp(word, "identify")) {
845.  	    ident = TRUE;
846.  	    filter = not_fully_identified;
847.  	}
848.  
849.  	iletct = collect_obj_classes(ilets, invent,
850.  				     FALSE, (allowgold != 0), filter);
851.  	unpaid = count_unpaid(invent);
852.  
853.  	if (ident && !iletct) {
854.  	    return -1;		/* no further identifications */
855.  	} else if (!takeoff && (unpaid || invent)) {
856.  	    ilets[iletct++] = ' ';
857.  	    if (unpaid) ilets[iletct++] = 'u';
858.  	    if (invent) ilets[iletct++] = 'a';
859.  	} else if (takeoff && invent) {
860.  	    ilets[iletct++] = ' ';
861.  	}
862.  	ilets[iletct++] = 'i';
863.  	if (!combo)
864.  	    ilets[iletct++] = 'm';	/* allow menu presentation on request */
865.  	ilets[iletct] = '\0';
866.  
867.  	for (;;) {
868.  	    Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
869.  		    word, ilets);
870.  	    getlin(qbuf, buf);
871.  	    if (buf[0] == '\033') return(0);
872.  	    if (index(buf, 'i'))
873.  		(void) display_inventory((char *)0, FALSE);
874.  	    else
875.  		break;
876.  	}
877.  
878.  	ip = buf;
879.  	olets[oletct = 0] = '\0';
880.  	while ((sym = *ip++) != '\0') {
881.  	    if (sym == ' ') continue;
882.  	    oc_of_sym = def_char_to_objclass(sym);
883.  	    if (takeoff && !(uwep && oc_of_sym == uwep->oclass) &&
884.  		    (oc_of_sym != MAXOCLASSES)) {
885.  		if (!index(removeables, oc_of_sym)) {
886.  		    pline("Not applicable.");
887.  		    return 0;
888.  		} else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
889.  		    You("are not wearing any armor.");
890.  		    return 0;
891.  		} else if (oc_of_sym == WEAPON_CLASS && !uwep) {
892.  		    You("are not wielding anything.");
893.  		    return 0;
894.  		} else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
895.  		    You("are not wearing rings.");
896.  		    return 0;
897.  		} else if (oc_of_sym == AMULET_CLASS && !uamul) {
898.  		    You("are not wearing an amulet.");
899.  		    return 0;
900.  		} else if (oc_of_sym == TOOL_CLASS && !ublindf) {
901.  		    You("are not wearing a blindfold.");
902.  		    return 0;
903.  		}
904.  	    }
905.  
906.  	    if (oc_of_sym == GOLD_CLASS && !combo) {
907.  		if (allowgold == 1)
908.  		    (*fn)(mkgoldobj(u.ugold));
909.  		else if (!u.ugold)
910.  		    You("have no gold.");
911.  		allowgold = 2;
912.  	    } else if (sym == 'a' || sym == 'A') {
913.  		allflag = TRUE;
914.  	    } else if (sym == 'u' || sym == 'U') {
915.  		add_valid_menu_class('u');
916.  		ckfn = ckunpaid;
917.  	    } else if (sym == 'm') {
918.  		m_seen = TRUE;
919.  	    } else if (oc_of_sym == MAXOCLASSES) {
920.  		You("don't have any %c's.", sym);
921.  	    } else if (oc_of_sym != VENOM_CLASS) {	/* suppress venom */
922.  		if (!index(olets, oc_of_sym)) {
923.  		    add_valid_menu_class(oc_of_sym);
924.  		    olets[oletct++] = oc_of_sym;
925.  		    olets[oletct] = 0;
926.  		}
927.  	    }
928.  	}
929.  
930.  	if (m_seen)
931.  	    return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
932.  	else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag)
933.  	    return 0;
934.  	else if (allowgold == 2 && !oletct)
935.  	    return 1;	/* you dropped gold (or at least tried to) */
936.  	else
937.  	    return askchain(&invent, olets, allflag, fn, ckfn, mx, word);
938.  }
939.  
940.  /*
941.   * Walk through the chain starting at objchn and ask for all objects
942.   * with olet in olets (if nonNULL) and satisfying ckfn (if nonnull)
943.   * whether the action in question (i.e., fn) has to be performed.
944.   * If allflag then no questions are asked. Max gives the max nr of
945.   * objects to be treated. Return the number of objects treated.
946.   */
947.  int
948.  askchain(objchn, olets, allflag, fn, ckfn, mx, word)
949.  struct obj **objchn;
950.  register int allflag, mx;
951.  register const char *olets, *word;	/* olets is an Obj Class char array */
952.  register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P));
953.  {
954.  	register struct obj *otmp, *otmp2;
955.  	register char sym, ilet;
956.  	register int cnt = 0, dud = 0, tmp;
957.  	boolean takeoff, nodot, ident, ininv;
958.  	char qbuf[QBUFSZ];
959.  
960.  	takeoff = !strcmp(word, "take off");
961.  	ident = !strcmp(word, "identify");
962.  	nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
963.  		 ident || takeoff);
964.  	ininv = (*objchn == invent);
965.  	/* Changed so the askchain is interrogated in the order specified.
966.  	 * For example, if a person specifies =/ then first all rings will be
967.  	 * asked about followed by all wands -dgk
968.  	 */
969.  nextclass:
970.  	ilet = 'a'-1;
971.  	if (*objchn && (*objchn)->oclass == GOLD_CLASS)
972.  		ilet--;		/* extra iteration */
973.  	for (otmp = *objchn; otmp; otmp = otmp2) {
974.  		if(ilet == 'z') ilet = 'A'; else ilet++;
975.  		otmp2 = otmp->nobj;
976.  		if (olets && *olets && otmp->oclass != *olets) continue;
977.  		if (takeoff && !is_worn(otmp)) continue;
978.  		if (ident && !not_fully_identified(otmp)) continue;
979.  		if (ckfn && !(*ckfn)(otmp)) continue;
980.  		if (!allflag) {
981.  			Strcpy(qbuf, !ininv ? doname(otmp) :
982.  				xprname(otmp, (char *)0, ilet, !nodot, 0L));
983.  			Strcat(qbuf, "?");
984.  			sym = (takeoff || ident || otmp->quan < 2L) ?
985.  				nyaq(qbuf) : nyNaq(qbuf);
986.  		}
987.  		else	sym = 'y';
988.  
989.  		if (sym == '#') {
990.  		 /* Number was entered; split the object unless it corresponds
991.  		    to 'none' or 'all'.  2 special cases: cursed loadstones and
992.  		    welded weapons (eg, multiple daggers) will remain as merged
993.  		    unit; done to avoid splitting an object that won't be
994.  		    droppable (even if we're picking up rather than dropping).
995.  		  */
996.  		    if (!yn_number)
997.  			sym = 'n';
998.  		    else {
999.  			sym = 'y';
1000. 			if (yn_number < otmp->quan && !welded(otmp) &&
1001. 			    (!otmp->cursed || otmp->otyp != LOADSTONE)) {
1002. 			    struct obj *otmpx = splitobj(otmp, yn_number);
1003. 			    if (!otmpx || otmpx->nobj != otmp2)
1004. 				impossible("bad object split in askchain");
1005. 			    /* assume other worn items aren't mergable */
1006. 			    if (otmp == uwep) setuwep(otmpx);
1007. 			}
1008. 		    }
1009. 		}
1010. 		switch(sym){
1011. 		case 'a':
1012. 			allflag = 1;
1013. 		case 'y':
1014. 			tmp = (*fn)(otmp);
1015. 			if(tmp < 0) goto ret;
1016. 			cnt += tmp;
1017. 			if(--mx == 0) goto ret;
1018. 		case 'n':
1019. 			if(nodot) dud++;
1020. 		default:
1021. 			break;
1022. 		case 'q':
1023. 			/* special case for seffects() */
1024. 			if (ident) cnt = -1;
1025. 			goto ret;
1026. 		}
1027. 	}
1028. 	if (olets && *olets && *++olets)
1029. 		goto nextclass;
1030. 	if(!takeoff && (dud || cnt)) pline("That was all.");
1031. 	else if(!dud && !cnt) pline("No applicable objects.");
1032. ret:
1033. 	return(cnt);
1034. }
1035. 
1036. 
1037. /*
1038.  *	Object identification routines:
1039.  */
1040. 
1041. /* make an object actually be identified; no display updating */
1042. static void
1043. fully_identify_obj(otmp)
1044. struct obj *otmp;
1045. {
1046.     makeknown(otmp->otyp);
1047.     otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
1048.     if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
1049. 	learn_egg_type(otmp->corpsenm);
1050. }
1051. 
1052. /* ggetobj callback routine; identify an object and give immediate feedback */
1053. int
1054. identify(otmp)
1055. struct obj *otmp;
1056. {
1057.     fully_identify_obj(otmp);
1058.     prinv((char *)0, otmp, 0L);
1059.     return 1;
1060. }
1061. 
1062. /* menu of unidentified objects; select and identify up to id_limit of them */
1063. static void
1064. menu_identify(id_limit)
1065. int id_limit;
1066. {
1067.     menu_item *pick_list;
1068.     int n, i, first = 1;
1069.     char buf[BUFSZ];
1070.     /* assumptions:  id_limit > 0 and at least one unID'd item is present */
1071. 
1072.     while (id_limit) {
1073. 	Sprintf(buf, "What would you like to identify %s?",
1074. 		first ? "first" : "next");
1075. 	n = query_objlist(buf, invent, SIGNAL_NOMENU|USE_INVLET|INVORDER_SORT,
1076. 		&pick_list, PICK_ANY, not_fully_identified);
1077. 
1078. 	if (n > 0) {
1079. 	    if (n > id_limit) n = id_limit;
1080. 	    for (i = 0; i < n; i++, id_limit--)
1081. 		(void) identify(pick_list[i].item.a_obj);
1082. 	    free((genericptr_t) pick_list);
1083. 	    mark_synch(); /* Before we loop to pop open another menu */
1084. 	} else {
1085. 	    if (n < 0) pline("That was all.");
1086. 	    id_limit = 0; /* Stop now */
1087. 	}
1088. 	first = 0;
1089.     }
1090. }
1091. 
1092. /* dialog with user to identify a given number of items; 0 means all */
1093. void
1094. identify_pack(id_limit)
1095. int id_limit;
1096. {
1097.     struct obj *obj, *the_obj;
1098.     int n, unid_cnt;
1099. 
1100.     unid_cnt = 0;
1101.     the_obj = 0;		/* if unid_cnt ends up 1, this will be it */
1102.     for (obj = invent; obj; obj = obj->nobj)
1103. 	if (not_fully_identified(obj)) ++unid_cnt, the_obj = obj;
1104. 
1105.     if (!unid_cnt) {
1106. 	You("have already identified all of your possessions.");
1107.     } else if (!id_limit) {
1108. 	/* identify everything */
1109. 	if (unid_cnt == 1) {
1110. 	    (void) identify(the_obj);
1111. 	} else {
1112. 
1113. 	    /* TODO:  use fully_identify_obj and cornline/menu/whatever here */
1114. 	    for (obj = invent; obj; obj = obj->nobj)
1115. 		if (not_fully_identified(obj)) (void) identify(obj);
1116. 
1117. 	}
1118.     } else {
1119. 	/* identify up to `id_limit' items */
1120. 	n = 0;
1121. 	if (flags.menu_style == MENU_TRADITIONAL)
1122. 	    do {
1123. 		n = ggetobj("identify", identify, id_limit, FALSE);
1124. 		if (n < 0) break; /* quit or no eligible items */
1125. 	    } while ((id_limit -= n) > 0);
1126. 	if (n == 0 || n < -1)
1127. 	    menu_identify(id_limit);
1128.     }
1129.     update_inventory();
1130. }
1131. 
1132. #endif /* OVLB */
1133. #ifdef OVL2
1134. 
1135. STATIC_OVL char
1136. obj_to_let(obj)	/* should of course only be called for things in invent */
1137. register struct obj *obj;
1138. {
1139. 	if (obj->oclass == GOLD_CLASS)
1140. 		return GOLD_SYM;
1141. 	if (!flags.invlet_constant) {
1142. 		obj->invlet = NOINVSYM;
1143. 		reassign();
1144. 	}
1145. 	return obj->invlet;
1146. }
1147. 
1148. /*
1149.  * Print the indicated quantity of the given object.  If quan == 0L then use
1150.  * the current quantity.
1151.  */
1152. void
1153. prinv(prefix, obj, quan)
1154. const char *prefix;
1155. register struct obj *obj;
1156. long quan;
1157. {
1158. 	long savequan = obj->quan;
1159. 	if (quan) obj->quan = quan;
1160. 	if (!prefix) prefix = "";
1161. 	pline("%s%s%s",
1162. 	      prefix, *prefix ? " " : "",
1163. 	      xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L));
1164. 	if (quan) obj->quan = savequan;
1165. }
1166. 
1167. #endif /* OVL2 */
1168. #ifdef OVL1
1169. 
1170. char *
1171. xprname(obj, txt, let, dot, cost)
1172. struct obj *obj;
1173. const char *txt;	/* text to print instead of obj */
1174. char let;		/* inventory letter */
1175. boolean dot;		/* append period; (dot && cost => Iu) */
1176. long cost;		/* cost (for inventory of unpaid or expended items) */
1177. {
1178. #ifdef LINT	/* handle static char li[BUFSZ]; */
1179. 	char li[BUFSZ];
1180. #else
1181. 	static char li[BUFSZ];
1182. #endif
1183. 	boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
1184.     /*
1185.      * If let is:
1186.      *	*  Then obj == null and we are printing a total amount.
1187.      *	>  Then the object is contained and doesn't have an inventory letter.
1188.      */
1189.     if (cost != 0 || let == '*') {
1190. 	/* if dot is true, we're doing Iu, otherwise Ix */
1191. 	Sprintf(li, "%c - %-45s %6ld zorkmid%s",
1192. 		(dot && use_invlet ? obj->invlet : let),
1193. 		(txt ? txt : doname(obj)), cost, plur(cost));
1194.     } else if (obj->oclass == GOLD_CLASS) {
1195. 	Sprintf(li, "%ld gold piece%s%s", obj->quan, plur(obj->quan),
1196. 		(dot ? "." : ""));
1197.     } else {
1198. 	/* ordinary inventory display or pickup message */
1199. 	Sprintf(li, "%c - %s%s",
1200. 		(use_invlet ? obj->invlet : let),
1201. 		(txt ? txt : doname(obj)), (dot ? "." : ""));
1202.     }
1203.     return li;
1204. }
1205. 
1206. #endif /* OVL1 */
1207. #ifdef OVLB
1208. 
1209. /* the 'i' command */
1210. int
1211. ddoinv()
1212. {
1213. 	(void) display_inventory((char *)0, FALSE);
1214. 	return 0;
1215. }
1216. 
1217. /*
1218.  * find_unpaid()
1219.  *
1220.  * Scan the given list of objects.  If last_found is NULL, return the first
1221.  * unpaid object found.  If last_found is not NULL, then skip over unpaid
1222.  * objects until last_found is reached, then set last_found to NULL so the
1223.  * next unpaid object is returned.  This routine recursively follows
1224.  * containers.
1225.  */
1226. static struct obj *
1227. find_unpaid(list, last_found)
1228.     struct obj *list, **last_found;
1229. {
1230.     struct obj *obj;
1231. 
1232.     while (list) {
1233. 	if (list->unpaid) {
1234. 	    if (*last_found) {
1235. 		/* still looking for previous unpaid object */
1236. 		if (list == *last_found)
1237. 		    *last_found = (struct obj *) 0;
1238. 	    } else
1239. 		return (*last_found = list);
1240. 	}
1241. 	if (Has_contents(list)) {
1242. 	    if ((obj = find_unpaid(list->cobj, last_found)) != 0)
1243. 		return obj;
1244. 	}
1245. 	list = list->nobj;
1246.     }
1247.     return (struct obj *) 0;
1248. }
1249. 
1250. /*
1251.  * If lets == NULL or "", list all objects in the inventory.  Otherwise,
1252.  * list all objects with object classes that match the order in lets.
1253.  *
1254.  * Returns the letter identifier of a selected item, or 0 if nothing
1255.  * was selected.
1256.  */
1257. char
1258. display_inventory(lets, want_reply)
1259. register const char *lets;
1260. boolean want_reply;
1261. {
1262. 	struct obj *otmp;
1263. 	char ilet, ret;
1264. 	char *invlet = flags.inv_order;
1265. 	int n, classcount;
1266. 	winid win;				/* windows being used */
1267. 	static winid local_win = WIN_ERR;	/* window for partial menus */
1268. 	anything any;
1269. 	menu_item *selected;
1270. 
1271. 	/* overriden by global flag */
1272. 	if (flags.perm_invent) {
1273. 	    win = (lets && *lets) ? local_win : WIN_INVEN;
1274. 	    /* create the first time used */
1275. 	    if (win == WIN_ERR)
1276. 		win = local_win = create_nhwindow(NHW_MENU);
1277. 	} else
1278. 	    win = WIN_INVEN;
1279. 
1280. 	if (!invent) {
1281. 	    pline("Not carrying anything%s.", u.ugold ? " except gold" : "");
1282. 	    return 0;
1283. 	}
1284. 
1285. 	/* oxymoron? temporarily assign permanent inventory letters */
1286. 	if (!flags.invlet_constant) reassign();
1287. 
1288. 	if (lets && strlen(lets) == 1) {
1289. 	    /* when only one item of interest, use pline instead of menus;
1290. 	       we actually use a fake message-line menu in order to allow
1291. 	       the user to perform selection at the --More-- prompt for tty */
1292. 	    ret = '\0';
1293. 	    for (otmp = invent; otmp; otmp = otmp->nobj) {
1294. 		if (otmp->invlet == lets[0]) {
1295. 		    ret = message_menu(lets[0],
1296. 				  want_reply ? PICK_ONE : PICK_NONE,
1297. 				  xprname(otmp, (char *)0, lets[0], TRUE, 0L));
1298. 		    break;
1299. 		}
1300. 	    }
1301. 	    return ret;
1302. 	}
1303. 
1304. 	start_menu(win);
1305. nextclass:
1306. 	classcount = 0;
1307. 	any.a_void = 0;		/* set all bits to zero */
1308. 	for(otmp = invent; otmp; otmp = otmp->nobj) {
1309. 		ilet = otmp->invlet;
1310. 		if(!lets || !*lets || index(lets, ilet)) {
1311. 			if (!flags.sortpack || otmp->oclass == *invlet) {
1312. 			    if (flags.sortpack && !classcount) {
1313. 				any.a_void = 0;		/* zero */
1314. 				add_menu(win, NO_GLYPH, &any, 0, ATR_INVERSE,
1315. 				    let_to_name(*invlet, FALSE), MENU_UNSELECTED);
1316. 				classcount++;
1317. 			    }
1318. 			    any.a_char = ilet;
1319. 			    add_menu(win, obj_to_glyph(otmp),
1320. 					&any, ilet, ATR_NONE, doname(otmp),
1321. 					MENU_UNSELECTED);
1322. 			}
1323. 		}
1324. 	}
1325. 	if (flags.sortpack) {
1326. 		if (*++invlet) goto nextclass;
1327. #ifdef WIZARD
1328. 		if (--invlet != venom_inv) {
1329. 			invlet = venom_inv;
1330. 			goto nextclass;
1331. 		}
1332. #endif
1333. 	}
1334. 	end_menu(win, (char *) 0);
1335. 
1336. 	n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
1337. 	if (n > 0) {
1338. 	    ret = selected[0].item.a_char;
1339. 	    free((genericptr_t)selected);
1340. 	} else
1341. 	    ret = !n ? '\0' : '\033';	/* cancelled */
1342. 
1343. 	return ret;
1344. }
1345. 
1346. /*
1347.  * Returns the number of unpaid items within the given list.  This includes
1348.  * contained objects.
1349.  */
1350. int
1351. count_unpaid(list)
1352.     struct obj *list;
1353. {
1354.     int count = 0;
1355. 
1356.     while (list) {
1357. 	if (list->unpaid) count++;
1358. 	if (Has_contents(list))
1359. 	    count += count_unpaid(list->cobj);
1360. 	list = list->nobj;
1361.     }
1362.     return count;
1363. }
1364. 
1365. static void
1366. dounpaid()
1367. {
1368.     winid win;
1369.     struct obj *otmp, *marker;
1370.     register char ilet;
1371.     char *invlet = flags.inv_order;
1372.     int classcount, count, num_so_far;
1373.     int save_unpaid = 0;	/* lint init */
1374.     long cost, totcost;
1375. 
1376.     count = count_unpaid(invent);
1377. 
1378.     if (count == 1) {
1379. 	marker = (struct obj *) 0;
1380. 	otmp = find_unpaid(invent, &marker);
1381. 
1382. 	/* see if the unpaid item is in the top level inventory */
1383. 	for (marker = invent; marker; marker = marker->nobj)
1384. 	    if (marker == otmp) break;
1385. 
1386. 	pline("%s", xprname(otmp, distant_name(otmp, doname),
1387. 			    marker ? otmp->invlet : CONTAINED_SYM,
1388. 			    TRUE, unpaid_cost(otmp)));
1389. 	return;
1390.     }
1391. 
1392.     win = create_nhwindow(NHW_MENU);
1393.     cost = totcost = 0;
1394.     num_so_far = 0;	/* count of # printed so far */
1395.     if (!flags.invlet_constant) reassign();
1396. 
1397.     do {
1398. 	classcount = 0;
1399. 	for (otmp = invent; otmp; otmp = otmp->nobj) {
1400. 	    ilet = otmp->invlet;
1401. 	    if (otmp->unpaid) {
1402. 		if (!flags.sortpack || otmp->oclass == *invlet) {
1403. 		    if (flags.sortpack && !classcount) {
1404. 			putstr(win, 0, let_to_name(*invlet, TRUE));
1405. 			classcount++;
1406. 		    }
1407. 
1408. 		    totcost += cost = unpaid_cost(otmp);
1409. 		    /* suppress "(unpaid)" suffix */
1410. 		    save_unpaid = otmp->unpaid;
1411. 		    otmp->unpaid = 0;
1412. 		    putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
1413. 					   ilet, TRUE, cost));
1414. 		    otmp->unpaid = save_unpaid;
1415. 		    num_so_far++;
1416. 		}
1417. 	    }
1418. 	}
1419.     } while (flags.sortpack && (*++invlet));
1420. 
1421.     if (count > num_so_far) {
1422. 	/* something unpaid is contained */
1423. 	if (flags.sortpack)
1424. 	    putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE));
1425. 	/*
1426. 	 * Search through the container objects in the inventory for
1427. 	 * unpaid items.  The top level inventory items have already
1428. 	 * been listed.
1429. 	 */
1430. 	for (otmp = invent; otmp; otmp = otmp->nobj) {
1431. 	    if (Has_contents(otmp)) {
1432. 		marker = (struct obj *) 0;	/* haven't found any */
1433. 		while (find_unpaid(otmp->cobj, &marker)) {
1434. 		    totcost += cost = unpaid_cost(marker);
1435. 		    save_unpaid = marker->unpaid;
1436. 		    marker->unpaid = 0;    /* suppress "(unpaid)" suffix */
1437. 		    putstr(win, 0,
1438. 			   xprname(marker, distant_name(marker, doname),
1439. 				   CONTAINED_SYM, TRUE, cost));
1440. 		    marker->unpaid = save_unpaid;
1441. 		}
1442. 	    }
1443. 	}
1444.     }
1445. 
1446.     putstr(win, 0, "");
1447.     putstr(win, 0, xprname((struct obj *)0, "Total:", '*', FALSE, totcost));
1448.     display_nhwindow(win, FALSE);
1449.     destroy_nhwindow(win);
1450. }
1451. 
1452. 
1453. /* query objlist callback: return TRUE if obj type matches "this_type" */
1454. static int this_type;
1455. 
1456. static boolean
1457. this_type_only(obj)
1458.     struct obj *obj;
1459. {
1460.     return (obj->oclass == this_type);
1461. }
1462. 
1463. /* the 'I' command */
1464. int
1465. dotypeinv()
1466. {
1467. 	char c = '\0';
1468. 	int n, i = 0;
1469. 	char *extra_types, types[BUFSZ];
1470. 	int class_count, oclass, unpaid_count;
1471. 	boolean billx = *u.ushops && doinvbill(0);
1472. 	menu_item *pick_list;
1473. 	boolean traditional = TRUE;
1474. 	const char *prompt = "What type of object do you want an inventory of?";
1475. 
1476. 	if (!invent && !u.ugold && !billx) {
1477. 	    You("aren't carrying anything.");
1478. 	    return 0;
1479. 	}
1480. 	unpaid_count = count_unpaid(invent);
1481. 	if (flags.menu_style != MENU_TRADITIONAL) {
1482. 	    if (flags.menu_style == MENU_FULL ||
1483. 				flags.menu_style == MENU_PARTIAL) {
1484. 		traditional = FALSE;
1485. 		i = UNPAID_TYPES;
1486. 		if (billx) i |= BILLED_TYPES;
1487. 		n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
1488. 		if (!n) return 0;
1489. 		this_type = c = pick_list[0].item.a_int;
1490. 		free((genericptr_t) pick_list);
1491. 	    }
1492. 	}
1493. 	if (traditional) {
1494. 	    /* collect a list of classes of objects carried, for use as a prompt */
1495. 	    types[0] = 0;
1496. 	    class_count = collect_obj_classes(types, invent,
1497. 					      FALSE, (u.ugold != 0),
1498. 					      (boolean FDECL((*),(OBJ_P))) 0);
1499. 	    if (unpaid_count) {
1500. 		Strcat(types, "u");
1501. 		class_count++;
1502. 	    }
1503. 	    if (billx) {
1504. 		Strcat(types, "x");
1505. 		class_count++;
1506. 	    }
1507. 	    /* add everything not already included; user won't see these */
1508. 	    extra_types = eos(types);
1509. 	    *extra_types++ = '\033';
1510. 	    if (!unpaid_count) *extra_types++ = 'u';
1511. 	    if (!billx) *extra_types++ = 'x';
1512. 	    *extra_types = '\0';	/* for index() */
1513. 	    for (i = 0; i < MAXOCLASSES; i++)
1514. 		if (!index(types, def_oc_syms[i])) {
1515. 		    *extra_types++ = def_oc_syms[i];
1516. 		    *extra_types = '\0';
1517. 		}
1518. 
1519. 	    if(class_count > 1) {
1520. 		c = yn_function(prompt, types, '\0');
1521. #ifdef REDO
1522. 		savech(c);
1523. #endif
1524. 		if(c == '\0') {
1525. 			clear_nhwindow(WIN_MESSAGE);
1526. 			return 0;
1527. 		}
1528. 	    } else {
1529. 		/* only one thing to itemize */
1530. 		if (unpaid_count)
1531. 		    c = 'u';
1532. 		else if (billx)
1533. 		    c = 'x';
1534. 		else
1535. 		    c = types[0];
1536. 	    }
1537. 	}
1538. 	if (c == 'x') {
1539. 	    if (billx)
1540. 		(void) doinvbill(1);
1541. 	    else
1542. 		pline("No used-up objects on your shopping bill.");
1543. 	    return 0;
1544. 	}
1545. 	if (c == 'u') {
1546. 	    if (unpaid_count)
1547. 		dounpaid();
1548. 	    else
1549. 		You("are not carrying any unpaid objects.");
1550. 	    return 0;
1551. 	}
1552. 	if (traditional) {
1553. 	    oclass = def_char_to_objclass(c); /* change to object class */
1554. 	    if (oclass == GOLD_CLASS) {
1555. 		return doprgold();
1556. 	    } else if (index(types, c) > index(types, '\033')) {
1557. 		You("have no such objects.");
1558. 		return 0;
1559. 	    }
1560. 	    this_type = oclass;
1561. 	}
1562. 	if (query_objlist((char *) 0, invent,
1563. 		    (flags.invlet_constant ? USE_INVLET : 0)|INVORDER_SORT,
1564. 		    &pick_list, PICK_NONE, this_type_only) > 0)
1565. 	    free((genericptr_t)pick_list);
1566. 	return 0;
1567. }
1568. 
1569. /* look at what is here */
1570. int
1571. dolook()
1572. {
1573. 	register struct obj *otmp, *otmp0;
1574. 	struct trap *trap;
1575. 	const char *verb = Blind ? "feel" : "see";
1576. 	const char *dfeature = (char*) 0;
1577. 	char fbuf[BUFSZ], fbuf2[BUFSZ];
1578. 	boolean no_article = FALSE;
1579. 	winid tmpwin;
1580. 
1581. 	if(u.uswallow) {
1582. 		You("%s no objects here.", verb);
1583. 		return(!!Blind);
1584. 	}
1585. 	read_engr_at(u.ux, u.uy); /* Eric Backus */
1586. 	if ((trap = t_at(u.ux,u.uy)) && trap->tseen)
1587. 		pline("There is %s here.",
1588. 			an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
1589. 
1590. 	otmp0 = level.objects[u.ux][u.uy];
1591. 
1592. 	if(IS_DOOR(levl[u.ux][u.uy].typ))  {
1593. 		switch(levl[u.ux][u.uy].doormask) {
1594. 		    case D_NODOOR:
1595. 			dfeature = "doorway"; break;
1596. 		    case D_ISOPEN:
1597. 			dfeature = "open door"; break;
1598. 		    case D_BROKEN:
1599. 			dfeature = "broken door"; break;
1600. 		    default:
1601. 			dfeature = "closed door";
1602. 		}
1603. 		/* override door description for open drawbridge */
1604. 		if (is_drawbridge_wall(u.ux, u.uy) >= 0)
1605. 			dfeature = "open drawbridge portcullis";
1606. 	} else if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))
1607. 		/* added by GAN 10/30/86 */
1608. 		dfeature = "fountain";
1609. 	else if(IS_THRONE(levl[u.ux][u.uy].typ))
1610. 		dfeature = "opulent throne";
1611. 	else if(is_lava(u.ux,u.uy))
1612. 		dfeature = "molten lava",  no_article = TRUE;
1613. 	else if(is_ice(u.ux,u.uy))
1614. 		dfeature = "ice",  no_article = TRUE;
1615. 	else if(is_pool(u.ux,u.uy) && !Underwater)
1616. 		dfeature = "pool of water";
1617. #ifdef SINKS
1618. 	else if(IS_SINK(levl[u.ux][u.uy].typ))
1619. 		dfeature = "kitchen sink";
1620. #endif
1621. 	else if(IS_ALTAR(levl[u.ux][u.uy].typ))  {
1622. 		Sprintf(fbuf2, "altar to %s (%s)",
1623. 			a_gname(),
1624. 			align_str(Amask2align(levl[u.ux][u.uy].altarmask
1625. 							    & ~AM_SHRINE)));
1626. 		dfeature = fbuf2;
1627. 	} else if(u.ux == xupstair && u.uy == yupstair)
1628. 		dfeature = "stairway up";
1629. 	else if(u.ux == xdnstair && u.uy == ydnstair)
1630. 		dfeature = "stairway down";
1631. 	else if(u.ux == sstairs.sx && u.uy == sstairs.sy) {
1632. 		if (sstairs.up)
1633. 			dfeature = "stairway up";
1634. 		else
1635. 			dfeature = "stairway down";
1636. 	} else if(u.ux == xupladder && u.uy == yupladder)
1637. 		dfeature = "ladder up";
1638. 	else if(u.ux == xdnladder && u.uy == ydnladder)
1639. 		dfeature = "ladder down";
1640. 	else if (levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN)
1641. 		dfeature = "lowered drawbridge";
1642. 	else if (levl[u.ux][u.uy].typ == DBWALL)
1643. 		dfeature = "raised drawbridge";
1644. 
1645. 	if (Blind) {
1646. 		boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
1647. 		You("try to feel what is %s%s.",
1648. 		    drift ? "floating here" : "lying here on the ",
1649. 		    drift ?	""	    : surface(u.ux, u.uy));
1650. 		if (dfeature && !drift && !strcmp(dfeature, surface(u.ux,u.uy)))
1651. 			dfeature = 0;		/* ice already identifed */
1652. 		if (!can_reach_floor()) {
1653. 			pline("But you can't reach it!");
1654. 			return(0);
1655. 		}
1656. 	}
1657. 
1658. 	if (dfeature)
1659. 		Sprintf(fbuf, "There is %s%s here.",
1660. 			no_article ? "" :
1661. 				index(vowels,dfeature[0]) ? "an " : "a ",
1662. 			dfeature);
1663. 
1664. 	if(!otmp0 || (is_pool(u.ux,u.uy) && !Underwater)) {
1665. 		if (dfeature) pline(fbuf);
1666. 		if (Blind || !dfeature) You("%s no objects here.", verb);
1667. 		return(!!Blind);
1668. 	}
1669. 	/* we know there is something here */
1670. 
1671. 	if (!otmp0->nexthere) {
1672. 	    /* only one object */
1673. 	    if (dfeature) pline(fbuf);
1674. 	    You("%s here %s.", verb, doname(otmp0));
1675. 	    feel_cockatrice(otmp0);
1676. 	} else {
1677. 	    display_nhwindow(WIN_MESSAGE, FALSE);
1678. 	    tmpwin = create_nhwindow(NHW_MENU);
1679. 	    if(dfeature) {
1680. 		putstr(tmpwin, 0, fbuf);
1681. 		putstr(tmpwin, 0, "");
1682. 	    }
1683. 	    putstr(tmpwin, 0, "Things that are here:");
1684. 	    for(otmp = otmp0; otmp; otmp = otmp->nexthere) {
1685. 		putstr(tmpwin, 0, doname(otmp));
1686. 		feel_cockatrice(otmp);
1687. 	    }
1688. 	    display_nhwindow(tmpwin, TRUE);
1689. 	    destroy_nhwindow(tmpwin);
1690. 	}
1691. 	return(!!Blind);
1692. }
1693. 
1694. static void
1695. feel_cockatrice(otmp)
1696. struct obj *otmp;
1697. {
1698. 	if(Blind  && !uarmg && !resists_ston(&youmonst) &&
1699. 	    (otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE)) {
1700. 	    if(poly_when_stoned(uasmon))
1701. 		You("touched the cockatrice corpse with your bare %s.",
1702. 			makeplural(body_part(HAND)));
1703. 	    else
1704. 		pline("Touching the cockatrice corpse is a fatal mistake...");
1705. 	    instapetrify("cockatrice corpse");
1706. 	}
1707. }
1708. 
1709. #endif /* OVLB */
1710. #ifdef OVL1
1711. 
1712. void
1713. stackobj(obj)
1714. struct obj *obj;
1715. {
1716. 	struct obj *otmp;
1717. 
1718. 	for(otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
1719. 		if(otmp != obj && merged(&obj,&otmp))
1720. 			break;
1721. 	return;
1722. }
1723. 
1724. static boolean
1725. mergable(otmp, obj)	/* returns TRUE if obj  & otmp can be merged */
1726. 	register struct obj *otmp, *obj;
1727. {
1728. 	if (obj->otyp != otmp->otyp || obj->unpaid != otmp->unpaid ||
1729. 	    obj->spe != otmp->spe || obj->dknown != otmp->dknown ||
1730. 	    (obj->bknown != otmp->bknown && !Role_is('P')) ||
1731. 	    obj->cursed != otmp->cursed || obj->blessed != otmp->blessed ||
1732. 	    obj->no_charge != otmp->no_charge ||
1733. 	    obj->obroken != otmp->obroken ||
1734. 	    obj->otrapped != otmp->otrapped ||
1735. 	    obj->lamplit != otmp->lamplit ||
1736. 	    obj->oeroded != otmp->oeroded)
1737. 	    return(FALSE);
1738. 
1739. 	if ((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) &&
1740. 	    (obj->oerodeproof!=otmp->oerodeproof || obj->rknown!=otmp->rknown))
1741. 	    return FALSE;
1742. 
1743. 	if (obj->oclass == FOOD_CLASS && (obj->oeaten != otmp->oeaten ||
1744. 					  obj->orotten != otmp->orotten))
1745. 	    return(FALSE);
1746. 
1747. 	if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
1748. 		if((obj->corpsenm != otmp->corpsenm) ||
1749. 			(ONAME(obj) && strcmp(ONAME(obj), ONAME(otmp))))
1750. 				return FALSE;
1751. 	}
1752. 
1753. 	/* hatching eggs don't merge; ditto for revivable corpses */
1754. 	if ((obj->otyp == EGG && (obj->timed || otmp->timed)) ||
1755. 	    (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM &&
1756. 		mons[otmp->corpsenm].mlet == S_TROLL))
1757. 	    return FALSE;
1758. 
1759. 	/* allow candle merging only if their ages are close */
1760. 	/* see begin_burn() for a reference for the magic "25" */
1761. 	if (Is_candle(obj) && obj->age/25 != otmp->age/25)
1762. 	    return(FALSE);
1763. 
1764. 	/* burning potions of oil never merge */
1765. 	if (obj->otyp == POT_OIL && obj->lamplit)
1766. 	    return FALSE;
1767. 
1768. 	/* don't merge surcharged item with base-cost item */
1769. 	if (obj->unpaid && !same_price(obj, otmp))
1770. 	    return FALSE;
1771. 
1772. /* if they have names, make sure they're the same */
1773. 	if ( (obj->onamelth != otmp->onamelth &&
1774. 		((obj->onamelth && otmp->onamelth) || obj->otyp == CORPSE)
1775. 	     ) ||
1776. 	    (obj->onamelth && otmp->onamelth &&
1777. 		    strncmp(ONAME(obj), ONAME(otmp), (int)obj->onamelth)))
1778. 		return FALSE;
1779. 
1780. 	if(obj->oartifact != otmp->oartifact) return FALSE;
1781. 
1782. 	if(obj->known == otmp->known ||
1783. 		!objects[otmp->otyp].oc_uses_known) {
1784. 		return((boolean)(objects[obj->otyp].oc_merge));
1785. 	} else return(FALSE);
1786. }
1787. 
1788. int
1789. doprgold()
1790. {
1791. 	/* the messages used to refer to "carrying gold", but that didn't
1792. 	   take containers into account */
1793. 	if(!u.ugold)
1794. 	    Your("wallet is empty.");
1795. 	else
1796. 	    Your("wallet contains %ld gold piece%s.", u.ugold, plur(u.ugold));
1797. 	shopper_financial_report();
1798. 	return 0;
1799. }
1800. 
1801. #endif /* OVL1 */
1802. #ifdef OVLB
1803. 
1804. int
1805. doprwep()
1806. {
1807. 	if(!uwep) You("are empty %s.", body_part(HANDED));
1808. 	else prinv((char *)0, uwep, 0L);
1809. 	return 0;
1810. }
1811. 
1812. int
1813. doprarm()
1814. {
1815. 	if(!wearing_armor())
1816. 		You("are not wearing any armor.");
1817. 	else {
1818. #ifdef TOURIST
1819. 		char lets[8];
1820. #else
1821. 		char lets[7];
1822. #endif
1823. 		register int ct = 0;
1824. 
1825. #ifdef TOURIST
1826. 		if(uarmu) lets[ct++] = obj_to_let(uarmu);
1827. #endif
1828. 		if(uarm) lets[ct++] = obj_to_let(uarm);
1829. 		if(uarmc) lets[ct++] = obj_to_let(uarmc);
1830. 		if(uarmh) lets[ct++] = obj_to_let(uarmh);
1831. 		if(uarms) lets[ct++] = obj_to_let(uarms);
1832. 		if(uarmg) lets[ct++] = obj_to_let(uarmg);
1833. 		if(uarmf) lets[ct++] = obj_to_let(uarmf);
1834. 		lets[ct] = 0;
1835. 		(void) display_inventory(lets, FALSE);
1836. 	}
1837. 	return 0;
1838. }
1839. 
1840. int
1841. doprring()
1842. {
1843. 	if(!uleft && !uright)
1844. 		You("are not wearing any rings.");
1845. 	else {
1846. 		char lets[3];
1847. 		register int ct = 0;
1848. 
1849. 		if(uleft) lets[ct++] = obj_to_let(uleft);
1850. 		if(uright) lets[ct++] = obj_to_let(uright);
1851. 		lets[ct] = 0;
1852. 		(void) display_inventory(lets, FALSE);
1853. 	}
1854. 	return 0;
1855. }
1856. 
1857. int
1858. dopramulet()
1859. {
1860. 	if (!uamul)
1861. 		You("are not wearing an amulet.");
1862. 	else
1863. 		prinv((char *)0, uamul, 0L);
1864. 	return 0;
1865. }
1866. 
1867. int
1868. doprtool()
1869. {
1870. 	register struct obj *otmp;
1871. 	register int ct=0;
1872. 	char lets[52+1];
1873. 
1874. 	for(otmp = invent; otmp; otmp = otmp->nobj) {
1875. 		if ((otmp->owornmask & W_TOOL) ||
1876. 		    (otmp->oclass == TOOL_CLASS &&
1877. 			(otmp == uwep || otmp->lamplit)) ||
1878. 		    (otmp->otyp == LEASH && otmp->leashmon))
1879. 			lets[ct++] = obj_to_let(otmp);
1880. 	}
1881. 	lets[ct] = 0;
1882. 	if (!ct) You("are not using any tools.");
1883. 	else (void) display_inventory(lets, FALSE);
1884. 	return 0;
1885. }
1886. 
1887. /*
1888.  * uses up an object that's on the floor, charging for it as necessary
1889.  */
1890. void
1891. useupf(obj)
1892. register struct obj *obj;
1893. {
1894. 	register struct obj *otmp;
1895. 
1896. 	/* burn_floor_paper() keeps an object pointer that it tries to
1897. 	 * useupf() multiple times, so obj must survive if plural */
1898. 	if(obj->quan > 1L)
1899. 		otmp = splitobj(obj, obj->quan - 1L);
1900. 	else
1901. 		otmp = obj;
1902. 	if(costly_spot(otmp->ox, otmp->oy)) {
1903. 	    if(index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
1904. 	        addtobill(otmp, FALSE, FALSE, FALSE);
1905. 	    else (void)stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
1906. 	}
1907. 	delobj(otmp);
1908. }
1909. 
1910. #endif /* OVLB */
1911. 
1912. 
1913. #ifdef OVL1
1914. 
1915. /*
1916.  * Conversion from a class to a string for printing.
1917.  * This must match the object class order.
1918.  */
1919. STATIC_VAR NEARDATA const char *names[] = { 0,
1920. 	"Illegal objects", "Weapons", "Armor", "Rings", "Amulets",
1921. 	"Tools", "Comestibles", "Potions", "Scrolls", "Spellbooks",
1922. 	"Wands", "Coins", "Gems", "Boulders/Statues", "Iron balls",
1923. 	"Chains", "Venoms"
1924. };
1925. 
1926. static NEARDATA const char oth_symbols[] = {
1927. 	CONTAINED_SYM,
1928. 	'\0'
1929. };
1930. 
1931. static NEARDATA const char *oth_names[] = {
1932. 	"Bagged/Boxed items"
1933. };
1934. 
1935. char *
1936. let_to_name(let,unpaid)
1937. char let;
1938. boolean unpaid;
1939. {
1940. 	const char *class_name;
1941. 	const char *pos;
1942. 	int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
1943. 	unsigned len;
1944. 	static NEARDATA char *buf = (char *)0;
1945. 	static NEARDATA unsigned bufsiz = 0;
1946. 
1947. 	if (oclass)
1948. 	    class_name = names[oclass];
1949. 	else if ((pos = index(oth_symbols, let)) != 0)
1950. 	    class_name = oth_names[pos - oth_symbols];
1951. 	else
1952. 	    class_name = names[0];
1953. 
1954. 	len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "");
1955. 	if (len > bufsiz) {
1956. 	    if (buf)  free((genericptr_t)buf),  buf = (char *)0;
1957. 	    bufsiz = len + 10; /* add slop to reduce incremental realloc */
1958. 	    buf = (char *) alloc(bufsiz);
1959. 	}
1960. 	if (unpaid)
1961. 	    Strcat(strcpy(buf, "Unpaid "), class_name);
1962. 	else
1963. 	    Strcpy(buf, class_name);
1964. 	return (buf);
1965. }
1966. 
1967. #endif /* OVL1 */
1968. #ifdef OVLB
1969. 
1970. void
1971. reassign()
1972. {
1973. 	register int i;
1974. 	register struct obj *obj;
1975. 
1976. 	for(obj = invent, i = 0; obj; obj = obj->nobj, i++)
1977. 		obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26);
1978. 	lastinvnr = i;
1979. }
1980. 
1981. #endif /* OVLB */
1982. #ifdef OVL1
1983. 
1984. int
1985. doorganize()	/* inventory organizer by Del Lamb */
1986. {
1987. 	struct obj *obj, *otmp;
1988. 	register int ix, cur;
1989. 	register char let;
1990. 	char alphabet[52+1], buf[52+1];
1991. 	char qbuf[QBUFSZ];
1992. 	char allowall[2];
1993. 	const char *adj_type;
1994. 
1995. 	if (!flags.invlet_constant) reassign();
1996. 	/* get a pointer to the object the user wants to organize */
1997. 	allowall[0] = ALL_CLASSES; allowall[1] = '\0';
1998. 	if (!(obj = getobj(allowall,"adjust"))) return(0);
1999. 
2000. 	/* initialize the list with all upper and lower case letters */
2001. 	for (let = 'a', ix = 0;  let <= 'z';) alphabet[ix++] = let++;
2002. 	for (let = 'A', ix = 26; let <= 'Z';) alphabet[ix++] = let++;
2003. 	alphabet[52] = 0;
2004. 
2005. 	/* blank out all the letters currently in use in the inventory */
2006. 	/* except those that will be merged with the selected object   */
2007. 	for (otmp = invent; otmp; otmp = otmp->nobj)
2008. 		if (otmp != obj && !mergable(otmp,obj))
2009. 			if (otmp->invlet <= 'Z')
2010. 				alphabet[(otmp->invlet) - 'A' + 26] = ' ';
2011. 			else	alphabet[(otmp->invlet) - 'a']	    = ' ';
2012. 
2013. 	/* compact the list by removing all the blanks */
2014. 	for (ix = cur = 0; ix <= 52; ix++)
2015. 		if (alphabet[ix] != ' ') buf[cur++] = alphabet[ix];
2016. 
2017. 	/* and by dashing runs of letters */
2018. 	if(cur > 5) compactify(buf);
2019. 
2020. 	/* get new letter to use as inventory letter */
2021. 	for (;;) {
2022. 		Sprintf(qbuf, "Adjust letter to what [%s]?",buf);
2023. 		let = yn_function(qbuf, (char *)0, '\0');
2024. 		if(index(quitchars,let)) {
2025. 			pline("Never mind.");
2026. 			return(0);
2027. 		}
2028. 		if (let == '@' || !letter(let))
2029. 			pline("Select an inventory slot letter.");
2030. 		else
2031. 			break;
2032. 	}
2033. 
2034. 	/* change the inventory and print the resulting item */
2035. 	adj_type = "Moving:";
2036. 
2037. 	/*
2038. 	 * don't use freeinv/addinv to avoid double-touching artifacts,
2039. 	 * dousing lamps, losing luck, cursing loadstone, etc.
2040. 	 */
2041. 	extract_nobj(obj, &invent);
2042. 
2043. 	for (otmp = invent; otmp;)
2044. 		if (merged(&otmp,&obj)) {
2045. 			adj_type = "Merging:";
2046. 			obj = otmp;
2047. 			otmp = otmp->nobj;
2048. 			extract_nobj(obj, &invent);
2049. 		} else {
2050. 			if (otmp->invlet == let) {
2051. 				adj_type = "Swapping:";
2052. 				otmp->invlet = obj->invlet;
2053. 			}
2054. 			otmp = otmp->nobj;
2055. 		}
2056. 
2057. 	/* inline addinv (assuming flags.invlet_constant and !merged) */
2058. 	obj->invlet = let;
2059. 	obj->nobj = invent; /* insert at beginning */
2060. 	obj->where = OBJ_INVENT;
2061. 	invent = obj;
2062. 	reorder_invent();
2063. 
2064. 	prinv(adj_type, obj, 0L);
2065. 	update_inventory();
2066. 	return(0);
2067. }
2068. 
2069. /* common to display_minventory and display_cinventory */
2070. static void
2071. invdisp_nothing(hdr, txt)
2072. const char *hdr, *txt;
2073. {
2074. 	winid win;
2075. 	anything any;
2076. 	menu_item *selected;
2077. 
2078. 	any.a_void = 0;
2079. 	win = create_nhwindow(NHW_MENU);
2080. 	start_menu(win);
2081. 	add_menu(win, NO_GLYPH, &any, 0, ATR_INVERSE, hdr, MENU_UNSELECTED);
2082. 	add_menu(win, NO_GLYPH, &any, 0, ATR_NONE, "", MENU_UNSELECTED);
2083. 	add_menu(win, NO_GLYPH, &any, 0, ATR_NONE, txt, MENU_UNSELECTED);
2084. 	end_menu(win, (char *)0);
2085. 	if (select_menu(win, PICK_NONE, &selected) > 0)
2086. 	    free((genericptr_t)selected);
2087. 	destroy_nhwindow(win);
2088. 	return;
2089. }
2090. 
2091. /* query_objlist callback: return things that could possibly be worn/wielded */
2092. static boolean
2093. worn_wield_only(obj)
2094. struct obj *obj;
2095. {
2096.     return (obj->oclass == WEAPON_CLASS
2097. 		|| obj->oclass == ARMOR_CLASS
2098. 		|| obj->oclass == AMULET_CLASS
2099. 		|| obj->oclass == RING_CLASS
2100. 		|| obj->oclass == TOOL_CLASS);
2101. }
2102. 
2103. /*
2104.  * Display a monster's inventory.
2105.  * Returns a pointer to the object from the monster's inventory selected
2106.  * or NULL if nothing was selected.
2107.  *
2108.  * By default, only worn and wielded items are displayed.  The caller
2109.  * can pick one.  Modifier flags are:
2110.  *
2111.  *	MINV_NOLET	- nothing selectable
2112.  *	MINV_ALL	- display all inventory
2113.  */
2114. struct obj *
2115. display_minventory(mon, dflags)
2116. register struct monst *mon;
2117. int dflags;
2118. {
2119. 	struct obj *ret, m_gold;
2120. 	char tmp[QBUFSZ];
2121. 	int n;
2122. 	menu_item *selected = 0;
2123. 	int do_all = (dflags & MINV_ALL) != 0,
2124. 	    do_gold = (do_all && mon->mgold);
2125. 
2126. 	Sprintf(tmp,"%s %s:", s_suffix(Monnam(mon)),
2127. 		do_all ? "possessions" : "armament");
2128. 
2129. 	if (do_all ? (mon->minvent || mon->mgold)
2130. 		   : (mon->misc_worn_check || MON_WEP(mon))) {
2131. 	    /* Fool the 'weapon in hand' routine into
2132. 	     * displaying 'weapon in claw', etc. properly.
2133. 	     */
2134. 	    char save_usym = u.usym;
2135. 
2136. 	    u.usym = mon->data->mlet;
2137. 	    uasmon = mon->data;
2138. 
2139. 	    if (do_gold) {
2140. 		/* make temporary gold object & insert at head of inventory */
2141. 		m_gold = zeroobj;
2142. 		m_gold.otyp = GOLD_PIECE;  m_gold.oclass = GOLD_CLASS;
2143. 		m_gold.quan = mon->mgold;  m_gold.dknown = 1;
2144. 		m_gold.where = OBJ_FREE;
2145. 		add_to_minv(mon, &m_gold);
2146. 	    }
2147. 
2148. 	    n = query_objlist(tmp, mon->minvent, INVORDER_SORT, &selected,
2149. 			(dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
2150. 			do_all ? allow_all : worn_wield_only);
2151. 
2152. 	    if (do_gold) obj_extract_self(&m_gold);
2153. 
2154. 	    u.usym = save_usym;
2155. 	    set_uasmon();
2156. 	} else {
2157. 	    invdisp_nothing(tmp, "(none)");
2158. 	    n = 0;
2159. 	}
2160. 
2161. 	if (n > 0) {
2162. 	    ret = selected[0].item.a_obj;
2163. 	    free((genericptr_t)selected);
2164. 	    /*
2165. 	     * Unfortunately, we can't return a pointer to our temporary
2166. 	     * gold object.  We'll have to work out a scheme where this
2167. 	     * can happen.  Maybe even put gold in the inventory list...
2168. 	     */
2169. 	    if (ret == &m_gold) ret = (struct obj *) 0;
2170. 	} else
2171. 	    ret = (struct obj *) 0;
2172. 	return ret;
2173. }
2174. 
2175. /*
2176.  * Display the contents of a container in inventory style.
2177.  * Currently, this is only used for statues, via wand of probing.
2178.  */
2179. struct obj *
2180. display_cinventory(obj)
2181. register struct obj *obj;
2182. {
2183. 	struct obj *ret;
2184. 	char tmp[QBUFSZ];
2185. 	int n;
2186. 	menu_item *selected = 0;
2187. 
2188. 	Sprintf(tmp,"Contents of %s:", doname(obj));
2189. 
2190. 	if (obj->cobj) {
2191. 	    n = query_objlist(tmp, obj->cobj, INVORDER_SORT, &selected,
2192. 			    PICK_NONE, allow_all);
2193. 	} else {
2194. 	    invdisp_nothing(tmp, "(empty)");
2195. 	    n = 0;
2196. 	}
2197. 	if (n > 0) {
2198. 	    ret = selected[0].item.a_obj;
2199. 	    free((genericptr_t)selected);
2200. 	} else
2201. 	    ret = (struct obj *) 0;
2202. 	return ret;
2203. }
2204. 
2205. /* query objlist callback: return TRUE if obj is at given location */
2206. static coord only;
2207. 
2208. static boolean
2209. only_here(obj)
2210.     struct obj *obj;
2211. {
2212.     return (obj->ox == only.x && obj->oy == only.y);
2213. }
2214. 
2215. /*
2216.  * Display a list of buried items in inventory style.  Return a non-zero
2217.  * value if there were items at that spot.
2218.  *
2219.  * Currently, this is only used with a wand of probing zapped downwards.
2220.  */
2221. int
2222. display_binventory(x, y, as_if_seen)
2223. int x, y;
2224. boolean as_if_seen;
2225. {
2226. 	struct obj *obj;
2227. 	menu_item *selected = 0;
2228. 	int n;
2229. 
2230. 	/* count # of objects here */
2231. 	for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
2232. 	    if (obj->ox == x && obj->oy == y) {
2233. 		if (as_if_seen) obj->dknown = 1;
2234. 		n++;
2235. 	    }
2236. 
2237. 	if (n) {
2238. 	    only.x = x;
2239. 	    only.y = y;
2240. 	    if (query_objlist("Things that are buried here:",
2241. 			      level.buriedobjlist, INVORDER_SORT,
2242. 			      &selected, PICK_NONE, only_here) > 0)
2243. 		free((genericptr_t)selected);
2244. 	    only.x = only.y = 0;
2245. 	}
2246. 	return n;
2247. }
2248. 
2249. #endif /* OVL1 */
2250. 
2251. /*invent.c*/

Also on Fandom

Random Wiki