Source:NetHack 3.0.0/invent.c

From NetHackWiki
(Redirected from NetHack 3.0.0/invent.c)
Jump to navigation Jump to search

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

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.0	88/10/22
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.    #ifdef WORM
8.    #include "lev.h"
9.    #include "wseg.h"
10.   #endif
11.   
12.   #define	NOINVSYM	'#'
13.   
14.   static boolean mergable();
15.   
16.   int lastinvnr = 51;	/* 0 ... 51 */
17.   static char *xprname();
18.   
19.   char inv_order[] = {
20.   	AMULET_SYM, WEAPON_SYM, ARMOR_SYM, FOOD_SYM, SCROLL_SYM,
21.   #ifdef SPELLS
22.   	SPBOOK_SYM,
23.   #endif
24.   	POTION_SYM, RING_SYM, WAND_SYM, TOOL_SYM, GEM_SYM,
25.   	ROCK_SYM, BALL_SYM, CHAIN_SYM, 0 };
26.   
27.   static void
28.   assigninvlet(otmp)
29.   register struct obj *otmp;
30.   {
31.   	boolean inuse[52];
32.   	register int i;
33.   	register struct obj *obj;
34.   
35.   	for(i = 0; i < 52; i++) inuse[i] = FALSE;
36.   	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
37.   		i = obj->invlet;
38.   		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
39.   		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
40.   		if(i == otmp->invlet) otmp->invlet = 0;
41.   	}
42.   	if((i = otmp->invlet) &&
43.   	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
44.   		return;
45.   	for(i = lastinvnr+1; i != lastinvnr; i++) {
46.   		if(i == 52) { i = -1; continue; }
47.   		if(!inuse[i]) break;
48.   	}
49.   	otmp->invlet = (inuse[i] ? NOINVSYM :
50.   			(i < 26) ? ('a'+i) : ('A'+i-26));
51.   	lastinvnr = i;
52.   }
53.   
54.   /* merge obj with otmp and delete obj if types agree */
55.   static int
56.   merged(otmp, obj, lose)
57.   register struct obj *otmp, *obj;
58.   register int lose;
59.   {
60.   	if(mergable(otmp, obj)) {
61.   		/* Approximate age: we do it this way because if we were to
62.   		 * do it "accurately" (merge only when ages are identical)
63.   		 * we'd wind up never merging any corpses.
64.   		 * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
65.   		 */
66.   		otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan))
67.   			/ (otmp->quan + obj->quan);
68.   		otmp->quan += obj->quan;
69.   		otmp->owt += obj->owt;
70.   		if(lose) freeobj(obj);
71.   		obfree(obj,otmp);	/* free(obj), bill->otmp */
72.   		return(1);
73.   	} else	return(0);
74.   }
75.   
76.   struct obj *
77.   addinv(obj)
78.   register struct obj *obj;
79.   {
80.   	register struct obj *otmp;
81.   
82.   	if (obj->otyp == AMULET_OF_YENDOR && !obj->spe) {
83.   		if (u.uhave_amulet) impossible ("already have amulet?");
84.   		u.uhave_amulet = 1;
85.   	}
86.   	/* merge or attach to end of chain */
87.   	if(!invent) {
88.   		invent = obj;
89.   		otmp = 0;
90.   	} else
91.   	for(otmp = invent; /* otmp */; otmp = otmp->nobj) {
92.   		if(merged(otmp, obj, 0)) {
93.   			obj = otmp;
94.   			goto added;
95.   		}
96.   		if(!otmp->nobj) {
97.   			otmp->nobj = obj;
98.   			break;
99.   		}
100.  	}
101.  	obj->nobj = 0;
102.  
103.  	if(flags.invlet_constant) {
104.  		assigninvlet(obj);
105.  		/*
106.  		 * The ordering of the chain is nowhere significant
107.  		 * so in case you prefer some other order than the
108.  		 * historical one, change the code below.
109.  		 */
110.  		if(otmp) {	/* find proper place in chain */
111.  			otmp->nobj = 0;
112.  			if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
113.  				obj->nobj = invent;
114.  				invent = obj;
115.  			} else
116.  			for(otmp = invent; ; otmp = otmp->nobj) {
117.  			    if(!otmp->nobj ||
118.  				(otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){
119.  				obj->nobj = otmp->nobj;
120.  				otmp->nobj = obj;
121.  				break;
122.  			    }
123.  			}
124.  		}
125.  	}
126.  
127.  added:
128.  	if (obj->otyp == LUCKSTONE) {
129.  		/* new luckstone must be in inventory by this point
130.  		 * for correct calculation */
131.  		if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD;
132.  		else u.moreluck = -LUCKADD;
133.  		flags.botl = 1;
134.  	}
135.  	return(obj);
136.  }
137.  
138.  void
139.  useup(obj)
140.  register struct obj *obj;
141.  {
142.  	if(obj->quan > 1){
143.  		obj->quan--;
144.  		obj->owt = weight(obj);
145.  	} else {
146.  		setnotworn(obj);
147.  		freeinv(obj);
148.  		obfree(obj, (struct obj *) 0);
149.  	}
150.  }
151.  
152.  void
153.  freeinv(obj)
154.  register struct obj *obj;
155.  {
156.  	register struct obj *otmp;
157.  
158.  	if(obj == invent)
159.  		invent = invent->nobj;
160.  	else {
161.  		for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
162.  			if(!otmp->nobj) panic("freeinv");
163.  		otmp->nobj = obj->nobj;
164.  	}
165.  	if (obj->otyp == AMULET_OF_YENDOR && !obj->spe) {
166.  		if (!u.uhave_amulet) impossible ("don't have amulet?");
167.  		u.uhave_amulet = 0;
168.  	}
169.  	if (obj->otyp == LOADSTONE)
170.  		curse(obj);
171.  	if (obj->otyp == LUCKSTONE) {
172.  		if (!carrying(LUCKSTONE)) u.moreluck = 0;
173.  		else if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD;
174.  		else u.moreluck = -LUCKADD;
175.  		flags.botl = 1;
176.  	}
177.  }
178.  
179.  /* destroy object in fobj chain (if unpaid, it remains on the bill) */
180.  void
181.  delobj(obj)
182.  register struct obj *obj;
183.  {
184.  #ifdef WALKIES
185.  	if(obj->otyp == LEASH && obj->leashmon != 0) o_unleash(obj);
186.  #endif
187.  	freeobj(obj);
188.  	unpobj(obj);
189.  
190.  /*	if contained in something else, decrease the container weight */
191.  	if(obj->cobj) dec_cwt(obj->cobj, obj);
192.  
193.  	obfree(obj, (struct obj *) 0);
194.  }
195.  
196.  /* unlink obj from chain starting with fobj */
197.  void
198.  freeobj(obj)
199.  register struct obj *obj;
200.  {
201.  	register struct obj *otmp;
202.  	register int found = 0;
203.  	register struct rm *lev = &levl[obj->ox][obj->oy];
204.  
205.    	lev->omask = 0;
206.  
207.  	if(obj == fobj) {
208.  		fobj = fobj->nobj;
209.  		found = 1;
210.  	}
211.  	for(otmp = fobj; otmp; otmp = otmp->nobj) {
212.   	    if (otmp->nobj == obj) {
213.  		otmp->nobj = obj->nobj;
214.  		found = 1;
215.  	    }
216.  	    if (otmp->ox == obj->ox && otmp->oy == obj->oy) {
217.  		lev->omask = 1;
218.  	    }
219.  	}
220.    	if (!found) panic("error in freeobj");
221.  #ifdef POLYSELF
222.  	if (!levl[u.ux][u.uy].omask && !levl[u.ux][u.uy].gmask) {
223.  		u.uundetected = 0;
224.  		if (!Invisible) pru();
225.  	}
226.  #endif
227.  }
228.  
229.  /* Note: freegold throws away its argument! */
230.  void
231.  freegold(gold)
232.  register struct gold *gold;
233.  {
234.  	register struct gold *gtmp;
235.  
236.  	levl[gold->gx][gold->gy].gmask = 0;
237.  
238.  	if(gold == fgold) fgold = gold->ngold;
239.  	else {
240.  		for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
241.  			if(!gtmp) panic("error in freegold");
242.  		gtmp->ngold = gold->ngold;
243.  	}
244.  	free((genericptr_t) gold);
245.  #ifdef POLYSELF
246.  	if (!levl[u.ux][u.uy].omask && !levl[u.ux][u.uy].gmask) {
247.  		u.uundetected = 0;
248.  		if (!Invisible) pru();
249.  	}
250.  #endif
251.  }
252.  
253.  struct monst *
254.  m_at(x,y)
255.  register int x, y;
256.  {
257.  	register struct monst *mtmp;
258.  #ifdef WORM
259.  	register struct wseg *wtmp;
260.  	m_atseg = 0;
261.  #endif
262.  
263.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
264.  		if(mtmp->mx == x && mtmp->my == y)
265.  			return(mtmp);
266.  #ifdef WORM
267.  		if(mtmp->wormno){
268.  		    for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)
269.  		    if(wtmp->wx == x && wtmp->wy == y){
270.  			m_atseg = wtmp;
271.  			return(mtmp);
272.  		    }
273.  		}
274.  #endif
275.  	}
276.  	return((struct monst *)0);
277.  }
278.  
279.  struct obj *
280.  o_at(x,y)
281.  register int x, y;
282.  {
283.  	register struct obj *otmp;
284.  
285.  	for(otmp = fobj; otmp; otmp = otmp->nobj)
286.  		if(otmp->ox == x && otmp->oy == y) return(otmp);
287.  	return((struct obj *)0);
288.  }
289.  
290.  struct obj *
291.  sobj_at(n,x,y)
292.  register int n, x, y;
293.  {
294.  	register struct obj *otmp;
295.  
296.  	if(levl[x][y].omask)
297.  	    for(otmp = fobj; otmp; otmp = otmp->nobj)
298.  		if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)
299.  		    return(otmp);
300.  	return((struct obj *)0);
301.  }
302.  
303.  int
304.  carried(obj)
305.  register struct obj *obj;
306.  {
307.  	register struct obj *otmp;
308.  
309.  	for(otmp = invent; otmp; otmp = otmp->nobj)
310.  		if(otmp == obj) return(1);
311.  	return(0);
312.  }
313.  
314.  struct obj *
315.  carrying(type)
316.  register int type;
317.  {
318.  	register struct obj *otmp;
319.  
320.  	for(otmp = invent; otmp; otmp = otmp->nobj)
321.  		if(otmp->otyp == type)
322.  			return(otmp);
323.  	return((struct obj *) 0);
324.  }
325.  
326.  struct obj *
327.  o_on(id, objchn)
328.  unsigned int id;
329.  register struct obj *objchn;
330.  {
331.  	while(objchn) {
332.  		if(objchn->o_id == id) return(objchn);
333.  		objchn = objchn->nobj;
334.  	}
335.  	return((struct obj *) 0);
336.  }
337.  
338.  struct gold *
339.  g_at(x,y)
340.  register int x, y;
341.  {
342.  	register struct gold *gold = fgold;
343.  	while(gold) {
344.  		if(gold->gx == x && gold->gy == y) return(gold);
345.  		gold = gold->ngold;
346.  	}
347.  	return((struct gold *)0);
348.  }
349.  
350.  /* make dummy object structure containing gold - for temporary use only */
351.  static
352.  struct obj *
353.  mkgoldobj(q)
354.  register long q;
355.  {
356.  	register struct obj *otmp;
357.  
358.  	otmp = newobj(0);
359.  	/* should set o_id etc. but otmp will be freed soon */
360.  	otmp->olet = GOLD_SYM;
361.  	u.ugold -= q;
362.  	OGOLD(otmp) = q;
363.  	flags.botl = 1;
364.  	return(otmp);
365.  }
366.  
367.  /*
368.   * getobj returns:
369.   *	struct obj *xxx:	object to do something with.
370.   *	(struct obj *) 0	error return: no object.
371.   *	&zeroobj		explicitly no object (as in w-).
372.   */
373.  struct obj *
374.  getobj(let,word)
375.  register char *let,*word;
376.  {
377.  	register struct obj *otmp;
378.  	register char ilet,ilet1,ilet2;
379.  	char buf[BUFSZ];
380.  	char lets[BUFSZ];
381.  	register int foo = 0, foo2;
382.  	register char *bp = buf;
383.  	xchar allowcnt = 0;	/* 0, 1 or 2 */
384.  	boolean allowgold = FALSE, usegold = FALSE;
385.  		/* usegold is needed so that they are given a different message
386.  		 * if gold is prohibited because it's inappropriate, or because
387.  		 * it's appropriate if only they had any.
388.  		 */
389.  	boolean allowall = FALSE;
390.  	boolean allownone = FALSE;
391.  	xchar foox = 0;
392.  	long cnt;
393.  
394.  	if(*let == '0') let++, allowcnt = 1;
395.  	if(*let == GOLD_SYM) let++,
396.  		usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE);
397.  	if(*let == '#') let++, allowall = TRUE;
398.  	if(*let == '-') let++, allownone = TRUE;
399.  	if(allownone) *bp++ = '-';
400.  	if(allowgold) *bp++ = GOLD_SYM;
401.  	if(bp > buf && bp[-1] == '-') *bp++ = ' ';
402.  
403.  	ilet = 'a';
404.  	for(otmp = invent; otmp; otmp = otmp->nobj){
405.  	    if(!*let || index(let, otmp->olet)) {
406.  		bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;
407.  
408.  		/* ugly check: remove inappropriate things */
409.  		if((!strcmp(word, "take off") &&
410.  		    (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))
411.  		     || (otmp==uarm && uarmc)
412.  #ifdef SHIRT
413.  		     || (otmp==uarmu && (uarm || uarmc))
414.  #endif
415.  		    ))
416.  		|| (!strcmp(word, "wear") &&
417.  		     (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
418.  							/* already worn */
419.  		|| (!strcmp(word, "wield") &&
420.  		    (otmp->owornmask & W_WEP))
421.  		    ) {
422.  			foo--;
423.  			foox++;
424.  		}
425.  
426.  		/* Second ugly check; unlike the first it won't trigger an
427.  		 * "else" in "you don't have anything else to ___".
428.  		 */
429.  		if ((!strcmp(word, "wear") &&
430.  		    (otmp->olet == TOOL_SYM && otmp->otyp != BLINDFOLD))
431.  		|| (!strcmp(word, "can") &&
432.  		    (otmp->otyp != CORPSE))
433.  		|| (!strcmp(word, "write with") &&
434.  		    (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))
435.  		|| (!strcmp(word, "rub") &&
436.  		    (otmp->olet == TOOL_SYM &&
437.  		     otmp->otyp != LAMP && otmp->otyp != MAGIC_LAMP))
438.  		    )
439.  			foo--;
440.  	    }
441.  	    if(ilet == 'z') ilet = 'A'; else ilet++;
442.  	}
443.  	bp[foo] = 0;
444.  	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
445.  	Strcpy(lets, bp);	/* necessary since we destroy buf */
446.  	if(foo > 5) {			/* compactify string */
447.  		foo = foo2 = 1;
448.  		ilet2 = bp[0];
449.  		ilet1 = bp[1];
450.  		while(ilet = bp[++foo2] = bp[++foo]){
451.  			if(ilet == ilet1+1){
452.  				if(ilet1 == ilet2+1)
453.  					bp[foo2 - 1] = ilet1 = '-';
454.  				else if(ilet2 == '-') {
455.  					bp[--foo2] = ++ilet1;
456.  					continue;
457.  				}
458.  			}
459.  			ilet2 = ilet1;
460.  			ilet1 = ilet;
461.  		}
462.  	}
463.  	if(!foo && !allowall && !allowgold && !allownone) {
464.  		You("don't have anything %sto %s.",
465.  			foox ? "else " : "", word);
466.  		return((struct obj *)0);
467.  	}
468.  	for(;;) {
469.  		if(!buf[0]) {
470.  #ifdef REDO
471.  		    if(!in_doagain)
472.  #endif
473.  			pline("What do you want to %s? [*] ", word);
474.  		} else {
475.  #ifdef REDO
476.  		    if(!in_doagain)
477.  #endif
478.  			pline("What do you want to %s? [%s or ?*] ",
479.  				word, buf);
480.  		}
481.  		cnt = 0;
482.  		ilet = readchar();
483.  		while(digit(ilet) && allowcnt) {
484.  #ifdef REDO
485.  			if (ilet != '?' && ilet != '*')	savech(ilet);
486.  #endif
487.  			cnt = 10*cnt + (ilet - '0');
488.  			allowcnt = 2;	/* signal presence of cnt */
489.  			ilet = readchar();
490.  		}
491.  		if(digit(ilet)) {
492.  			pline("No count allowed with this command.");
493.  			continue;
494.  		}
495.  		if(index(quitchars,ilet)) {
496.  		    if(flags.verbose)
497.  			pline("Never mind.");
498.  		    return((struct obj *)0);
499.  		}
500.  		if(ilet == '-') {
501.  			return(allownone ? &zeroobj : (struct obj *) 0);
502.  		}
503.  		if(ilet == GOLD_SYM) {
504.  			if(!usegold){
505.  				You("cannot %s gold.", word);
506.  				return(struct obj *)0;
507.  			} else if (!allowgold) {
508.  				You("are not carrying any gold.");
509.  				return(struct obj *)0;
510.  			}
511.  			if(!(allowcnt == 2 && cnt < u.ugold))
512.  				cnt = u.ugold;
513.  			return(mkgoldobj(cnt));
514.  		}
515.  		if(allowcnt == 2 && !strcmp(word,"throw")) {
516.  			/* permit counts for throwing gold, but don't accept
517.  			 * counts for other things since the throw code will
518.  			 * split off a single item anyway */
519.  			allowcnt = 1;
520.  			if(cnt != 1) {
521.  			    pline("You can only throw one item at a time.");
522.  			    continue;
523.  			}
524.  		}
525.  		if(ilet == '?') {
526.  			doinv(lets);
527.  			if(!(ilet = morc)) continue;
528.  			/* he typed a letter (not a space) to more() */
529.  		} else if(ilet == '*') {
530.  			doinv(NULL);
531.  			if(!(ilet = morc)) continue;
532.  			/* ... */
533.  		}
534.  #ifdef REDO
535.  		if (ilet != '?' && ilet != '*')	savech(ilet);
536.  #endif
537.  		if(flags.invlet_constant) {
538.  			for(otmp = invent; otmp; otmp = otmp->nobj)
539.  				if(otmp->invlet == ilet) break;
540.  		} else {
541.  			if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;
542.  			ilet -= 'a';
543.  			for(otmp = invent; otmp && ilet;
544.  					ilet--, otmp = otmp->nobj) ;
545.  		}
546.  		if(!otmp) {
547.  			You("don't have that object.");
548.  			continue;
549.  		}
550.  		if(cnt < 0 || otmp->quan < cnt) {
551.  			You("don't have that many!  You have only %u."
552.  			, otmp->quan);
553.  			continue;
554.  		}
555.  		break;
556.  	}
557.  	if(!allowall && let && !index(let,otmp->olet)) {
558.  		pline("That is a silly thing to %s.",word);
559.  		return((struct obj *)0);
560.  	}
561.  	if(allowcnt == 2) {	/* cnt given */
562.  		if(cnt == 0) return (struct obj *)0;
563.  		if(cnt != otmp->quan) {
564.  			register struct obj *obj;
565.  #ifdef LINT	/*splitobj for (long )cnt > 30000 && sizeof(int) == 2*/
566.  			obj = (struct obj *)0;
567.  #else
568.  			if (sizeof(int) == 2)
569.  				obj = splitobj(otmp,
570.  					(int )(cnt >30000 ? 30000 : cnt));
571.  			else
572.  				obj = splitobj(otmp, (int) cnt);
573.  #endif
574.  			if(otmp == uwep) setuwep(obj);
575.  		}
576.  	}
577.  	return(otmp);
578.  }
579.  
580.  static int
581.  ckunpaid(otmp)
582.  register struct obj *otmp;
583.  {
584.  	return((int)(otmp->unpaid));
585.  }
586.  
587.  static boolean
588.  wearing_armor() {
589.  	return(uarm || uarmc || uarmf || uarmg || uarmh || uarms
590.  #ifdef SHIRT
591.  		|| uarmu
592.  #endif
593.  		);
594.  }
595.  
596.  static boolean
597.  is_worn(otmp)
598.  register struct obj *otmp;
599.  {
600.      return(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP)));
601.  }
602.  
603.  static const char removeables[] =
604.  	{ ARMOR_SYM, WEAPON_SYM, RING_SYM, AMULET_SYM, TOOL_SYM, ' ', 0 };
605.  
606.  /* interactive version of getobj - used for Drop, Identify and */
607.  /* Takeoff (A). Return the number of times fn was called successfully */
608.  int
609.  ggetobj(word, fn, mx)
610.  register char *word;
611.  register int (*fn)(), mx;
612.  {
613.  	char buf[BUFSZ];
614.  	register char *ip;
615.  	register char sym;
616.  	register int oletct = 0, iletct = 0;
617.  	register boolean allflag = FALSE;
618.  	char olets[20], ilets[20];
619.  	int (*ckfn)() = (int (*)()) 0;
620.  	xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */
621.  	register boolean takeoff = !strcmp(word, "take off");
622.  
623.  	if(takeoff && !wearing_armor() && !uwep && !uamul &&
624.  			!uleft && !uright && !ublindf) {
625.  		You("are not wearing anything.");
626.  		return(0);
627.  	}
628.  	if(!invent && !allowgold){
629.  		You("have nothing to %s.", word);
630.  		return(0);
631.  	} else {
632.  		register struct obj *otmp = invent;
633.  		register int uflg = 0;
634.  
635.  		if(allowgold) ilets[iletct++] = GOLD_SYM;
636.  		ilets[iletct] = 0;
637.  		while(otmp) {
638.  			if(!index(ilets, otmp->olet)){
639.  			    if(!takeoff || is_worn(otmp))
640.  				ilets[iletct++] = otmp->olet;
641.  			    ilets[iletct] = 0;
642.  			}
643.  			if(otmp->unpaid) uflg = 1;
644.  			otmp = otmp->nobj;
645.  		}
646.  		ilets[iletct++] = ' ';
647.  		if(uflg && !takeoff) ilets[iletct++] = 'u';
648.  		if(invent && !takeoff) ilets[iletct++] = 'a';
649.  		ilets[iletct] = 0;
650.  	}
651.  	pline("What kinds of thing do you want to %s? [%s] ",
652.  		word, ilets);
653.  	getlin(buf);
654.  	if(buf[0] == '\033') {
655.  		clrlin();
656.  		return(0);
657.  	}
658.  	ip = buf;
659.  	olets[0] = 0;
660.  	while(sym = *ip++){
661.  		if(sym == ' ') continue;
662.  		if(takeoff) {
663.  		    if(!index(removeables,sym)) {
664.  			pline("Not applicable.");
665.  			return(0);
666.  		    } else if(sym == ARMOR_SYM && !wearing_armor()) {
667.  			You("are not wearing any armor.");
668.  			return(0);
669.  		    } else if(sym == WEAPON_SYM && !uwep) {
670.  			You("are not wielding anything.");
671.  			return(0);
672.  		    } else if(sym == RING_SYM && !uright && !uleft) {
673.  			You("are not wearing rings.");
674.  			return(0);
675.  		    } else if(sym == AMULET_SYM && !uamul) {
676.  			You("are not wearing an amulet.");
677.  			return(0);
678.  		    } else if(sym == TOOL_SYM && !ublindf) {
679.  			You("are not wearing a blindfold.");
680.  			return(0);
681.  		    }
682.  		}
683.  		if(sym == GOLD_SYM) {
684.  			if(allowgold == 1)
685.  				(*fn)(mkgoldobj(u.ugold));
686.  			else if(!u.ugold)
687.  				You("have no gold.");
688.  			allowgold = 2;
689.  		} else if(sym == 'a' || sym == 'A')
690.  			allflag = TRUE;
691.  		else if(sym == 'u' || sym == 'U')
692.  			ckfn = ckunpaid;
693.  		else if(index(inv_order, sym)) {
694.  			if(!index(olets, sym)) {
695.  				olets[oletct++] = sym;
696.  				olets[oletct] = 0;
697.  			}
698.  		} else You("don't have any %c's.", sym);
699.  	}
700.  	if(allowgold == 2 && !oletct)
701.  		return(1);	/* he dropped gold (or at least tried to) */
702.  	else
703.  		return(askchain(invent, TRUE, olets, allflag, fn, ckfn, mx, word));
704.  }
705.  
706.  /*
707.   * Walk through the chain starting at objchn and ask for all objects
708.   * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)
709.   * whether the action in question (i.e., fn) has to be performed.
710.   * If allflag then no questions are asked. Max gives the max nr of
711.   * objects to be treated. Return the number of objects treated.
712.   * If ininv is TRUE, the objects are in the player's inventory.
713.   */
714.  int
715.  askchain(objchn, ininv, olets, allflag, fn, ckfn, mx, word)
716.  register struct obj *objchn;
717.  register int ininv, allflag, mx;
718.  register char *olets, *word;
719.  register int (*fn)(), (*ckfn)();
720.  {
721.  	register struct obj *otmp, *otmp2;
722.  	register char sym, ilet;
723.  	register int cnt = 0, dud = 0;
724.  	register boolean takeoff, nodot;
725.  
726.  	takeoff = !strcmp(word, "take off");
727.  	nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
728.  	   		!strcmp(word, "identify") || takeoff);
729.  	/* changes so the askchain is interrogated in the order specified.
730.  	 * For example, if a person specifies =/ then first all rings will be
731.  	 * asked about followed by all wands -dgk
732.  	 */
733.  nextclass:
734.  	ilet = 'a'-1;
735.  	for(otmp = (ininv ? invent : objchn); otmp; otmp = otmp2){
736.  		if(ilet == 'z') ilet = 'A'; else ilet++;
737.  		otmp2 = otmp->nobj;
738.  		if (olets && *olets && otmp->olet != *olets) continue;
739.  		if(takeoff && !is_worn(otmp)) continue;
740.  		if(ckfn && !(*ckfn)(otmp)) continue;
741.  		if(!allflag) {
742.  			if(ininv) {
743.  			    if (nodot)
744.  				 pline(xprname(otmp, ilet, FALSE));
745.  			    else pline(xprname(otmp, ilet, TRUE));
746.  			}
747.  			else
748.  			    pline(doname(otmp));
749.  			addtopl("? ");
750.  			sym = nyaq();
751.  		}
752.  		else	sym = 'y';
753.  
754.  		switch(sym){
755.  		case 'a':
756.  			allflag = 1;
757.  		case 'y':
758.  			cnt += (*fn)(otmp);
759.  			if(--mx == 0) goto ret;
760.  		case 'n':
761.  			if(nodot) dud++;
762.  		default:
763.  			break;
764.  		case 'q':
765.  			goto ret;
766.  		}
767.  	}
768.  	if (olets && *olets && *++olets)
769.  		goto nextclass;
770.  	if(!takeoff && (dud || cnt)) pline("That was all.");
771.  	else if(!dud && !cnt) pline("No applicable objects.");
772.  ret:
773.  	return(cnt);
774.  }
775.  
776.  static char
777.  obj_to_let(obj)	/* should of course only be called for things in invent */
778.  register struct obj *obj;
779.  {
780.  	register struct obj *otmp;
781.  	register char ilet;
782.  
783.  	if(flags.invlet_constant)
784.  		return(obj->invlet);
785.  	ilet = 'a';
786.  	for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)
787.  		if(++ilet > 'z') ilet = 'A';
788.  	return(otmp ? ilet : NOINVSYM);
789.  }
790.  
791.  void
792.  prinv(obj)
793.  register struct obj *obj;
794.  {
795.  	pline(xprname(obj, obj_to_let(obj), TRUE));
796.  }
797.  
798.  static char *
799.  xprname(obj,let,dot)
800.  register struct obj *obj;
801.  register char let;
802.  register boolean dot;
803.  {
804.  #ifdef LINT	/* handle static char li[BUFSZ]; */
805.  	char li[BUFSZ];
806.  #else
807.  	static char li[BUFSZ];
808.  #endif
809.  
810.  	Sprintf(li, "%c - %s",
811.  		(flags.invlet_constant ? obj->invlet : let),
812.  		doname(obj));
813.  	if(dot) Sprintf(eos(li),".");
814.  	return(li);
815.  }
816.  
817.  int
818.  ddoinv()
819.  {
820.  	doinv(NULL);
821.  	return 0;
822.  }
823.  
824.  /* called with 0 or "": all objects in inventory */
825.  /* otherwise: all objects with (serial) letter in lets */
826.  void
827.  doinv(lets)
828.  register char *lets;
829.  {
830.  	register struct obj *otmp;
831.  	register char ilet;
832.  	int ct = 0;
833.  	char any[BUFSZ];
834.  	char *invlet = inv_order;
835.  	int classcount = 0;
836.  
837.  	morc = 0;		/* just to be sure */
838.  
839.  	if(!invent){
840.  		pline("Not carrying anything.");
841.  		return;
842.  	}
843.  	if (lets != NULL) {
844.  		for(ct=0; lets[ct]; ct++) {
845.  			if (ct >= 52) {
846.  				impossible("bad lets contents");
847.  				break;
848.  			}
849.  		}
850.  		if (ct==1) {
851.  			ilet = 'a';
852.  			for(otmp = invent; otmp; otmp = otmp->nobj) {
853.  				if(flags.invlet_constant) ilet = otmp->invlet;
854.  
855.  				if (ilet == lets[0])
856.  					pline(xprname(otmp, lets[0], TRUE));
857.  
858.  				if(!flags.invlet_constant)
859.  					if(++ilet > 'z') ilet = 'A';
860.  			}
861.  			return;
862.  		}
863.  	}
864.  	ct = 0;
865.  
866.  	cornline(0, NULL);
867.  nextclass:
868.  	classcount = 0;
869.  	ilet = 'a';
870.  	for(otmp = invent; otmp; otmp = otmp->nobj) {
871.  		if(flags.invlet_constant) ilet = otmp->invlet;
872.  		if(!lets || !*lets || index(lets, ilet)) {
873.  			if (!flags.sortpack || otmp->olet == *invlet) {
874.  				if (flags.sortpack && !classcount) {
875.  					cornline(1, let_to_name(*invlet));
876.  					classcount++;
877.  				}
878.  				cornline(1, xprname(otmp, ilet, TRUE));
879.  				any[ct++] = ilet;
880.  			}
881.  		}
882.  		if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
883.  	}
884.  	if (flags.sortpack && *++invlet) goto nextclass;
885.  	any[ct] = 0;
886.  	cornline(2, any);
887.  }
888.  
889.  int
890.  dotypeinv()				/* free after Robert Viduya */
891.  /* Changed to one type only, so he doesn't have to type cr */
892.  {
893.      	char c, ilet;
894.      	char stuff[BUFSZ];
895.      	register int stct;
896.      	register struct obj *otmp;
897.      	boolean billx = inshop() && doinvbill(0);
898.      	boolean unpd = FALSE;
899.  
900.  	if (!invent && !u.ugold && !billx) {
901.  	    You("aren't carrying anything.");
902.  	    return 0;
903.  	}
904.  
905.  	stct = 0;
906.  	if(u.ugold) stuff[stct++] = GOLD_SYM;
907.  	stuff[stct] = 0;
908.  	for(otmp = invent; otmp; otmp = otmp->nobj) {
909.  	    if (!index (stuff, otmp->olet)) {
910.  		stuff[stct++] = otmp->olet;
911.  		stuff[stct] = 0;
912.  	    }
913.  	    if(otmp->unpaid)
914.  		unpd = TRUE;
915.  	}
916.  	if(unpd) stuff[stct++] = 'u';
917.  	if(billx) stuff[stct++] = 'x';
918.  	stuff[stct] = 0;
919.  
920.  	if(stct > 1) {
921.  #ifdef REDO
922.  	  if (!in_doagain)
923.  #endif
924.  	    pline ("What type of object do you want an inventory of? [%s] ",
925.  			stuff);
926.  	    c = readchar();
927.  #ifdef REDO
928.  	    savech(c);
929.  #endif
930.  	    if(index(quitchars,c)) {
931.  	    	    clrlin();
932.  	    	    return 0;
933.  	    }
934.  	} else
935.  	    c = stuff[0];
936.  
937.  	if(c == GOLD_SYM)
938.  	    return(doprgold());
939.  
940.  	if(c == 'x' || c == 'X') {
941.  	    if(billx)
942.  		(void) doinvbill(1);
943.  	    else
944.  		pline("No used-up objects on the shopping bill.");
945.  	    return(0);
946.  	}
947.  
948.  	if((c == 'u' || c == 'U') && !unpd) {
949.  		You("are not carrying any unpaid objects.");
950.  		return(0);
951.  	}
952.  
953.  	stct = 0;
954.  	ilet = 'a';
955.  	for (otmp = invent; otmp; otmp = otmp -> nobj) {
956.  	    if(flags.invlet_constant) ilet = otmp->invlet;
957.  	    if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))
958.  		stuff[stct++] = ilet;
959.  	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
960.  	}
961.  	stuff[stct] = '\0';
962.  	if(stct == 0)
963.  		You("have no such objects.");
964.  	else
965.  		doinv (stuff);
966.  
967.  	return(0);
968.  }
969.  
970.  /* look at what is here */
971.  int
972.  dolook() {
973.      	register struct obj *otmp, *otmp0;
974.      	register struct gold *gold;
975.      	char *verb = Blind ? "feel" : "see";
976.      	int ct = 0;
977.      	int fd = 0;
978.  
979.      	read_engr_at(u.ux, u.uy); /* Eric Backus */
980.      	if(!u.uswallow) {
981.  		otmp0 = o_at(u.ux, u.uy);
982.  		gold = g_at(u.ux, u.uy);
983.      	}  else  {
984.  		You("%s no objects here.", verb);
985.  		return(!!Blind);
986.      	}
987.  
988.  	if(IS_DOOR(levl[u.ux][u.uy].typ))  {
989.  		fd++;
990.  		switch(levl[u.ux][u.uy].doormask) {
991.  		    case D_NODOOR:
992.  			pline("There is a doorway here."); break;
993.  		    case D_ISOPEN:
994.  			pline("There is an open door here."); break;
995.  		    case D_BROKEN:
996.  			pline("There is a broken door here."); break;
997.  		    default:
998.  			pline("There is a closed door here.");
999.  		}
1000. 	}
1001.     	/* added by GAN 10/30/86 */
1002. #ifdef FOUNTAINS
1003.     	if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))  {
1004. 		fd++;
1005. 		pline("There is a fountain here.");
1006.     	}
1007. #endif
1008. #ifdef THRONES
1009.     	if(IS_THRONE(levl[u.ux][u.uy].typ))  {
1010. 		fd++;
1011. 		pline("There is an opulent throne here.");
1012.     	}
1013. #endif
1014. #ifdef SINKS
1015.     	if(IS_SINK(levl[u.ux][u.uy].typ))  {
1016. 		fd++;
1017. 		pline("There is a kitchen sink here.");
1018.     	}
1019. #endif
1020. #ifdef ALTARS
1021.     	if(IS_ALTAR(levl[u.ux][u.uy].typ))  {
1022. 		char *al;
1023. 
1024. 		fd++;
1025. 		switch (levl[u.ux][u.uy].altarmask & ~A_SHRINE) {
1026. 			case 0: al = "chaotic"; break;
1027. 			case 1: al = "neutral"; break;
1028. 			default: al = "lawful"; break;
1029. 		}
1030. 		pline("There is an altar to %s here (%s).", a_gname(), al);
1031.     	}
1032. #endif
1033. 
1034.     	if(u.ux == xupstair && u.uy == yupstair)  {
1035. 		fd++;
1036. 		pline("There is a stairway up here.");
1037.     	}
1038.     	if(u.ux == xdnstair && u.uy == ydnstair)  {
1039. 		fd++;
1040. 		pline("There is a stairway down here.");
1041.     	}
1042. #ifdef STRONGHOLD
1043.     	if(u.ux == xupladder && u.uy == yupladder)	{
1044. 		fd++;
1045. 		pline("There is a ladder up here.");
1046.     	}
1047.     	if(u.ux == xdnladder && u.uy == ydnladder)	{
1048. 		fd++;
1049. 		pline("There is a ladder down here.");
1050.     	}
1051.     	if (levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN) {
1052. 		fd++;
1053. 		pline("There is a lowered drawbridge here.");
1054.     	}
1055. #endif /* STRONGHOLD /**/
1056. 
1057.     	if(Blind)  {
1058. 		You("try to feel what is lying here on the floor.");
1059. 	 	if(Levitation)  {
1060. 			pline("But you can't reach it!");
1061. 			return(0);
1062. 	 	}
1063.     	}
1064. 
1065.     	if(!otmp0 && !gold) {
1066. 		if(Blind || !fd)
1067. 			You("%s no objects here.", verb);
1068. 		return(!!Blind);
1069.     	}
1070. 
1071.     	cornline(0, "Things that are here:");
1072.     	for(otmp = otmp0; otmp; otmp = otmp->nobj) {
1073. 		if(otmp->ox == u.ux && otmp->oy == u.uy) {
1074. 	    		ct++;
1075. 	    		cornline(1, doname(otmp));
1076. 
1077. 	    		if(Blind  && !uarmg &&
1078. #ifdef POLYSELF
1079. 			!resists_ston(uasmon) &&
1080. #endif
1081. 	       		(otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE)) {
1082. 			    pline("Touching the dead cockatrice is a fatal mistake...");
1083. 			    You("turn to stone...");
1084. 			    killer = "dead cockatrice";
1085. 		 	    done("stoned");
1086. 	    		}
1087. 		}
1088.     	}
1089. 
1090.     	if(gold) {
1091. 		char gbuf[30];
1092. 
1093. 		Sprintf(gbuf, "%ld gold piece%s",
1094. 			gold->amount, plur(gold->amount));
1095. 		if(!ct++)
1096. 	    		You("%s here %s.", verb, gbuf);
1097. 		else
1098. 	    		cornline(1, gbuf);
1099.     	}
1100. 
1101.     	if(ct == 1 && !gold) {
1102. 		You("%s here %s.", verb, doname(otmp0));
1103. 		cornline(3, NULL);
1104.     	}
1105.     	if(ct > 1)
1106. 		cornline(2, NULL);
1107.     	return(!!Blind);
1108. }
1109. 
1110. void
1111. stackobj(obj)
1112. register struct obj *obj;
1113. {
1114. 	register struct obj *otmp = fobj;
1115. 	for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj)
1116. 		if(otmp->ox == obj->ox && otmp->oy == obj->oy &&
1117. 			merged(obj,otmp,1))
1118. 				break;
1119. 	return;
1120. }
1121. 
1122. static boolean
1123. mergable(otmp, obj)	/* returns TRUE if obj  & otmp can be merged */
1124. 	register struct obj *otmp, *obj;
1125. {
1126. 	if(obj->otyp != otmp->otyp || obj->unpaid != otmp->unpaid ||
1127. 	   obj->spe != otmp->spe || obj->dknown != otmp->dknown ||
1128. 	   (obj->bknown != otmp->bknown && pl_character[0] != 'P') ||
1129. 	   obj->cursed != otmp->cursed || obj->blessed != otmp->blessed ||
1130. 	   obj->no_charge != otmp->no_charge || 
1131. 	   obj->otrapped != otmp->otrapped)
1132. 	    return(FALSE);
1133. 
1134. 	else if((obj->olet==WEAPON_SYM || obj->olet==ARMOR_SYM) &&
1135. 		obj->rustfree != otmp->rustfree) return FALSE;
1136. 
1137. 	else if(obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN)
1138. 		return( (obj->corpsenm == otmp->corpsenm) &&
1139. 			(!ONAME(obj) || !strcmp(ONAME(obj), ONAME(otmp))) );
1140. 
1141. 	else if(obj->known == otmp->known) {
1142. 		return(objects[obj->otyp].oc_merge);
1143. 	} else return(FALSE);
1144. }
1145. 
1146. int
1147. doprgold(){
1148. 	if(!u.ugold)
1149. 		You("do not carry any gold.");
1150. 	else
1151. 		You("are carrying %ld gold piece%s.", u.ugold, plur(u.ugold));
1152. 	return 0;
1153. }
1154. 
1155. int
1156. doprwep()
1157. {
1158. 	if(!uwep) You("are empty %s.", body_part(HANDED));
1159. 	else prinv(uwep);
1160. 	return 0;
1161. }
1162. 
1163. int
1164. doprarm(){
1165. 	if(!wearing_armor())
1166. 		You("are not wearing any armor.");
1167. 	else {
1168. #ifdef SHIRT
1169. 		char lets[8];
1170. #else
1171. 		char lets[7];
1172. #endif
1173. 		register int ct = 0;
1174. 
1175. #ifdef SHIRT
1176. 		if(uarmu) lets[ct++] = obj_to_let(uarmu);
1177. #endif
1178. 		if(uarm) lets[ct++] = obj_to_let(uarm);
1179. 		if(uarmc) lets[ct++] = obj_to_let(uarmc);
1180. 		if(uarmh) lets[ct++] = obj_to_let(uarmh);
1181. 		if(uarms) lets[ct++] = obj_to_let(uarms);
1182. 		if(uarmg) lets[ct++] = obj_to_let(uarmg);
1183. 		if(uarmf) lets[ct++] = obj_to_let(uarmf);
1184. 		lets[ct] = 0;
1185. 		doinv(lets);
1186. 	}
1187. 	return 0;
1188. }
1189. 
1190. int
1191. doprring(){
1192. 	if(!uleft && !uright)
1193. 		You("are not wearing any rings.");
1194. 	else {
1195. 		char lets[3];
1196. 		register int ct = 0;
1197. 
1198. 		if(uleft) lets[ct++] = obj_to_let(uleft);
1199. 		if(uright) lets[ct++] = obj_to_let(uright);
1200. 		lets[ct] = 0;
1201. 		doinv(lets);
1202. 	}
1203. 	return 0;
1204. }
1205. 
1206. int
1207. dopramulet(){
1208. 	if (!uamul)
1209. 		You("are not wearing an amulet.");
1210. 	else
1211. 		prinv(uamul);
1212. 	return 0;
1213. }
1214. 
1215. int
1216. doprtool(){
1217. 	register struct obj *otmp;
1218. 	register int ct=0;
1219. 	char lets[3]; /* Maximum: pick-axe, blindfold */
1220. 
1221. 	for(otmp = invent; otmp; otmp = otmp->nobj) {
1222. 		if (((otmp->owornmask & W_TOOL) && otmp->olet==TOOL_SYM)
1223. 		   || (otmp==uwep &&
1224. 		   (otmp->otyp==PICK_AXE || otmp->otyp==TIN_OPENER)))
1225. 			lets[ct++] = obj_to_let(otmp);
1226. 	}
1227. 	lets[ct] = 0;
1228. 	if (!ct) You("are not using any tools.");
1229. 	else doinv(lets);
1230. 	return 0;
1231. }
1232. 
1233. int
1234. digit(c)
1235. char c;
1236. {
1237. 	return(c >= '0' && c <= '9');
1238. }
1239. 
1240. /*
1241.  * useupf(obj)
1242.  * uses up an object that's on the floor
1243.  */
1244. void
1245. useupf(obj)
1246. register struct obj *obj;
1247. {
1248. 	if(obj->quan > 1)  {
1249. 		obj->quan--;
1250. 		obj->owt = weight(obj);
1251. 	}  else delobj(obj);
1252. }
1253. 
1254. /*
1255.  * Convert from a symbol to a string for printing object classes
1256.  *
1257.  * Names from objects.h
1258.  * char obj_symbols[] = {
1259.  *	ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM,
1260.  *	BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM,
1261.  *	WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 };
1262.  */
1263. 
1264. static const char *names[] = {
1265. 	"Illegal objects", "Amulets", "Comestibles", "Weapons",
1266. 	"Tools", "Iron balls", "Chains", "Boulders/Statues", "Armor",
1267. 	"Potions", "Scrolls", "Wands",
1268. #ifdef SPELLS
1269. 	"Spellbooks",
1270. #endif
1271. 	"Rings", "Gems"};
1272. 
1273. char *
1274. let_to_name(let)
1275. char let;
1276. {
1277. 	char *pos = index(obj_symbols, let);
1278. 	/* arbitrary buffer size by Tom May (tom@uw-warp) */
1279. 	static char *buf = NULL;
1280. 
1281. 	if (buf == NULL)
1282. 	    buf = (char *) alloc ((unsigned)(strlen(HI)+strlen(HE)+15+1));
1283. 
1284. 	if (pos == NULL) pos = obj_symbols;
1285. 	if (HI && HE)
1286. 	    Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE);
1287. 	else
1288. 	    Sprintf(buf, "%s", names[pos - obj_symbols]);
1289. 	return (buf);
1290. }
1291. 
1292. void
1293. reassign()
1294. {
1295. 	register int i;
1296. 	register struct obj *obj;
1297. 
1298. 	for(obj = invent, i = 0; obj; obj = obj->nobj, i++)
1299. 		obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26);
1300. 	lastinvnr = i;
1301. }