xref: /original-bsd/games/hack/hack.invent.c (revision 0c5e0add)
1*0c5e0addSbostic /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2*0c5e0addSbostic /* hack.invent.c - version 1.0.3 */
3*0c5e0addSbostic 
4*0c5e0addSbostic #include	"hack.h"
5*0c5e0addSbostic #include	<stdio.h>
6*0c5e0addSbostic extern struct obj *splitobj();
7*0c5e0addSbostic extern struct obj zeroobj;
8*0c5e0addSbostic extern char morc;
9*0c5e0addSbostic extern char quitchars[];
10*0c5e0addSbostic char *xprname();
11*0c5e0addSbostic 
12*0c5e0addSbostic #ifndef NOWORM
13*0c5e0addSbostic #include	"def.wseg.h"
14*0c5e0addSbostic extern struct wseg *wsegs[32];
15*0c5e0addSbostic #endif NOWORM
16*0c5e0addSbostic 
17*0c5e0addSbostic #define	NOINVSYM	'#'
18*0c5e0addSbostic 
19*0c5e0addSbostic static int lastinvnr = 51;	/* 0 ... 51 */
20*0c5e0addSbostic static
21*0c5e0addSbostic assigninvlet(otmp)
22*0c5e0addSbostic register struct obj *otmp;
23*0c5e0addSbostic {
24*0c5e0addSbostic 	boolean inuse[52];
25*0c5e0addSbostic 	register int i;
26*0c5e0addSbostic 	register struct obj *obj;
27*0c5e0addSbostic 
28*0c5e0addSbostic 	for(i = 0; i < 52; i++) inuse[i] = FALSE;
29*0c5e0addSbostic 	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
30*0c5e0addSbostic 		i = obj->invlet;
31*0c5e0addSbostic 		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
32*0c5e0addSbostic 		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
33*0c5e0addSbostic 		if(i == otmp->invlet) otmp->invlet = 0;
34*0c5e0addSbostic 	}
35*0c5e0addSbostic 	if((i = otmp->invlet) &&
36*0c5e0addSbostic 	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
37*0c5e0addSbostic 		return;
38*0c5e0addSbostic 	for(i = lastinvnr+1; i != lastinvnr; i++) {
39*0c5e0addSbostic 		if(i == 52) { i = -1; continue; }
40*0c5e0addSbostic 		if(!inuse[i]) break;
41*0c5e0addSbostic 	}
42*0c5e0addSbostic 	otmp->invlet = (inuse[i] ? NOINVSYM :
43*0c5e0addSbostic 			(i < 26) ? ('a'+i) : ('A'+i-26));
44*0c5e0addSbostic 	lastinvnr = i;
45*0c5e0addSbostic }
46*0c5e0addSbostic 
47*0c5e0addSbostic struct obj *
48*0c5e0addSbostic addinv(obj)
49*0c5e0addSbostic register struct obj *obj;
50*0c5e0addSbostic {
51*0c5e0addSbostic 	register struct obj *otmp;
52*0c5e0addSbostic 
53*0c5e0addSbostic 	/* merge or attach to end of chain */
54*0c5e0addSbostic 	if(!invent) {
55*0c5e0addSbostic 		invent = obj;
56*0c5e0addSbostic 		otmp = 0;
57*0c5e0addSbostic 	} else
58*0c5e0addSbostic 	for(otmp = invent; /* otmp */; otmp = otmp->nobj) {
59*0c5e0addSbostic 		if(merged(otmp, obj, 0))
60*0c5e0addSbostic 			return(otmp);
61*0c5e0addSbostic 		if(!otmp->nobj) {
62*0c5e0addSbostic 			otmp->nobj = obj;
63*0c5e0addSbostic 			break;
64*0c5e0addSbostic 		}
65*0c5e0addSbostic 	}
66*0c5e0addSbostic 	obj->nobj = 0;
67*0c5e0addSbostic 
68*0c5e0addSbostic 	if(flags.invlet_constant) {
69*0c5e0addSbostic 		assigninvlet(obj);
70*0c5e0addSbostic 		/*
71*0c5e0addSbostic 		 * The ordering of the chain is nowhere significant
72*0c5e0addSbostic 		 * so in case you prefer some other order than the
73*0c5e0addSbostic 		 * historical one, change the code below.
74*0c5e0addSbostic 		 */
75*0c5e0addSbostic 		if(otmp) {	/* find proper place in chain */
76*0c5e0addSbostic 			otmp->nobj = 0;
77*0c5e0addSbostic 			if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
78*0c5e0addSbostic 				obj->nobj = invent;
79*0c5e0addSbostic 				invent = obj;
80*0c5e0addSbostic 			} else
81*0c5e0addSbostic 			for(otmp = invent; ; otmp = otmp->nobj) {
82*0c5e0addSbostic 			    if(!otmp->nobj ||
83*0c5e0addSbostic 				(otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){
84*0c5e0addSbostic 				obj->nobj = otmp->nobj;
85*0c5e0addSbostic 				otmp->nobj = obj;
86*0c5e0addSbostic 				break;
87*0c5e0addSbostic 			    }
88*0c5e0addSbostic 			}
89*0c5e0addSbostic 		}
90*0c5e0addSbostic 	}
91*0c5e0addSbostic 
92*0c5e0addSbostic 	return(obj);
93*0c5e0addSbostic }
94*0c5e0addSbostic 
95*0c5e0addSbostic useup(obj)
96*0c5e0addSbostic register struct obj *obj;
97*0c5e0addSbostic {
98*0c5e0addSbostic 	if(obj->quan > 1){
99*0c5e0addSbostic 		obj->quan--;
100*0c5e0addSbostic 		obj->owt = weight(obj);
101*0c5e0addSbostic 	} else {
102*0c5e0addSbostic 		setnotworn(obj);
103*0c5e0addSbostic 		freeinv(obj);
104*0c5e0addSbostic 		obfree(obj, (struct obj *) 0);
105*0c5e0addSbostic 	}
106*0c5e0addSbostic }
107*0c5e0addSbostic 
108*0c5e0addSbostic freeinv(obj)
109*0c5e0addSbostic register struct obj *obj;
110*0c5e0addSbostic {
111*0c5e0addSbostic 	register struct obj *otmp;
112*0c5e0addSbostic 
113*0c5e0addSbostic 	if(obj == invent)
114*0c5e0addSbostic 		invent = invent->nobj;
115*0c5e0addSbostic 	else {
116*0c5e0addSbostic 		for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
117*0c5e0addSbostic 			if(!otmp->nobj) panic("freeinv");
118*0c5e0addSbostic 		otmp->nobj = obj->nobj;
119*0c5e0addSbostic 	}
120*0c5e0addSbostic }
121*0c5e0addSbostic 
122*0c5e0addSbostic /* destroy object in fobj chain (if unpaid, it remains on the bill) */
123*0c5e0addSbostic delobj(obj) register struct obj *obj; {
124*0c5e0addSbostic 	freeobj(obj);
125*0c5e0addSbostic 	unpobj(obj);
126*0c5e0addSbostic 	obfree(obj, (struct obj *) 0);
127*0c5e0addSbostic }
128*0c5e0addSbostic 
129*0c5e0addSbostic /* unlink obj from chain starting with fobj */
130*0c5e0addSbostic freeobj(obj) register struct obj *obj; {
131*0c5e0addSbostic 	register struct obj *otmp;
132*0c5e0addSbostic 
133*0c5e0addSbostic 	if(obj == fobj) fobj = fobj->nobj;
134*0c5e0addSbostic 	else {
135*0c5e0addSbostic 		for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj)
136*0c5e0addSbostic 			if(!otmp) panic("error in freeobj");
137*0c5e0addSbostic 		otmp->nobj = obj->nobj;
138*0c5e0addSbostic 	}
139*0c5e0addSbostic }
140*0c5e0addSbostic 
141*0c5e0addSbostic /* Note: freegold throws away its argument! */
142*0c5e0addSbostic freegold(gold) register struct gold *gold; {
143*0c5e0addSbostic 	register struct gold *gtmp;
144*0c5e0addSbostic 
145*0c5e0addSbostic 	if(gold == fgold) fgold = gold->ngold;
146*0c5e0addSbostic 	else {
147*0c5e0addSbostic 		for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
148*0c5e0addSbostic 			if(!gtmp) panic("error in freegold");
149*0c5e0addSbostic 		gtmp->ngold = gold->ngold;
150*0c5e0addSbostic 	}
151*0c5e0addSbostic 	free((char *) gold);
152*0c5e0addSbostic }
153*0c5e0addSbostic 
154*0c5e0addSbostic deltrap(trap)
155*0c5e0addSbostic register struct trap *trap;
156*0c5e0addSbostic {
157*0c5e0addSbostic 	register struct trap *ttmp;
158*0c5e0addSbostic 
159*0c5e0addSbostic 	if(trap == ftrap)
160*0c5e0addSbostic 		ftrap = ftrap->ntrap;
161*0c5e0addSbostic 	else {
162*0c5e0addSbostic 		for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
163*0c5e0addSbostic 		ttmp->ntrap = trap->ntrap;
164*0c5e0addSbostic 	}
165*0c5e0addSbostic 	free((char *) trap);
166*0c5e0addSbostic }
167*0c5e0addSbostic 
168*0c5e0addSbostic struct wseg *m_atseg;
169*0c5e0addSbostic 
170*0c5e0addSbostic struct monst *
171*0c5e0addSbostic m_at(x,y)
172*0c5e0addSbostic register x,y;
173*0c5e0addSbostic {
174*0c5e0addSbostic 	register struct monst *mtmp;
175*0c5e0addSbostic #ifndef NOWORM
176*0c5e0addSbostic 	register struct wseg *wtmp;
177*0c5e0addSbostic #endif NOWORM
178*0c5e0addSbostic 
179*0c5e0addSbostic 	m_atseg = 0;
180*0c5e0addSbostic 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
181*0c5e0addSbostic 		if(mtmp->mx == x && mtmp->my == y)
182*0c5e0addSbostic 			return(mtmp);
183*0c5e0addSbostic #ifndef NOWORM
184*0c5e0addSbostic 		if(mtmp->wormno){
185*0c5e0addSbostic 		    for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)
186*0c5e0addSbostic 		    if(wtmp->wx == x && wtmp->wy == y){
187*0c5e0addSbostic 			m_atseg = wtmp;
188*0c5e0addSbostic 			return(mtmp);
189*0c5e0addSbostic 		    }
190*0c5e0addSbostic 		}
191*0c5e0addSbostic #endif NOWORM
192*0c5e0addSbostic 	}
193*0c5e0addSbostic 	return(0);
194*0c5e0addSbostic }
195*0c5e0addSbostic 
196*0c5e0addSbostic struct obj *
197*0c5e0addSbostic o_at(x,y)
198*0c5e0addSbostic register x,y;
199*0c5e0addSbostic {
200*0c5e0addSbostic 	register struct obj *otmp;
201*0c5e0addSbostic 
202*0c5e0addSbostic 	for(otmp = fobj; otmp; otmp = otmp->nobj)
203*0c5e0addSbostic 		if(otmp->ox == x && otmp->oy == y) return(otmp);
204*0c5e0addSbostic 	return(0);
205*0c5e0addSbostic }
206*0c5e0addSbostic 
207*0c5e0addSbostic struct obj *
208*0c5e0addSbostic sobj_at(n,x,y)
209*0c5e0addSbostic register n,x,y;
210*0c5e0addSbostic {
211*0c5e0addSbostic 	register struct obj *otmp;
212*0c5e0addSbostic 
213*0c5e0addSbostic 	for(otmp = fobj; otmp; otmp = otmp->nobj)
214*0c5e0addSbostic 		if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)
215*0c5e0addSbostic 			return(otmp);
216*0c5e0addSbostic 	return(0);
217*0c5e0addSbostic }
218*0c5e0addSbostic 
219*0c5e0addSbostic carried(obj) register struct obj *obj; {
220*0c5e0addSbostic register struct obj *otmp;
221*0c5e0addSbostic 	for(otmp = invent; otmp; otmp = otmp->nobj)
222*0c5e0addSbostic 		if(otmp == obj) return(1);
223*0c5e0addSbostic 	return(0);
224*0c5e0addSbostic }
225*0c5e0addSbostic 
226*0c5e0addSbostic carrying(type)
227*0c5e0addSbostic register int type;
228*0c5e0addSbostic {
229*0c5e0addSbostic 	register struct obj *otmp;
230*0c5e0addSbostic 
231*0c5e0addSbostic 	for(otmp = invent; otmp; otmp = otmp->nobj)
232*0c5e0addSbostic 		if(otmp->otyp == type)
233*0c5e0addSbostic 			return(TRUE);
234*0c5e0addSbostic 	return(FALSE);
235*0c5e0addSbostic }
236*0c5e0addSbostic 
237*0c5e0addSbostic struct obj *
238*0c5e0addSbostic o_on(id, objchn) unsigned int id; register struct obj *objchn; {
239*0c5e0addSbostic 	while(objchn) {
240*0c5e0addSbostic 		if(objchn->o_id == id) return(objchn);
241*0c5e0addSbostic 		objchn = objchn->nobj;
242*0c5e0addSbostic 	}
243*0c5e0addSbostic 	return((struct obj *) 0);
244*0c5e0addSbostic }
245*0c5e0addSbostic 
246*0c5e0addSbostic struct trap *
247*0c5e0addSbostic t_at(x,y)
248*0c5e0addSbostic register x,y;
249*0c5e0addSbostic {
250*0c5e0addSbostic 	register struct trap *trap = ftrap;
251*0c5e0addSbostic 	while(trap) {
252*0c5e0addSbostic 		if(trap->tx == x && trap->ty == y) return(trap);
253*0c5e0addSbostic 		trap = trap->ntrap;
254*0c5e0addSbostic 	}
255*0c5e0addSbostic 	return(0);
256*0c5e0addSbostic }
257*0c5e0addSbostic 
258*0c5e0addSbostic struct gold *
259*0c5e0addSbostic g_at(x,y)
260*0c5e0addSbostic register x,y;
261*0c5e0addSbostic {
262*0c5e0addSbostic 	register struct gold *gold = fgold;
263*0c5e0addSbostic 	while(gold) {
264*0c5e0addSbostic 		if(gold->gx == x && gold->gy == y) return(gold);
265*0c5e0addSbostic 		gold = gold->ngold;
266*0c5e0addSbostic 	}
267*0c5e0addSbostic 	return(0);
268*0c5e0addSbostic }
269*0c5e0addSbostic 
270*0c5e0addSbostic /* make dummy object structure containing gold - for temporary use only */
271*0c5e0addSbostic struct obj *
272*0c5e0addSbostic mkgoldobj(q)
273*0c5e0addSbostic register long q;
274*0c5e0addSbostic {
275*0c5e0addSbostic 	register struct obj *otmp;
276*0c5e0addSbostic 
277*0c5e0addSbostic 	otmp = newobj(0);
278*0c5e0addSbostic 	/* should set o_id etc. but otmp will be freed soon */
279*0c5e0addSbostic 	otmp->olet = '$';
280*0c5e0addSbostic 	u.ugold -= q;
281*0c5e0addSbostic 	OGOLD(otmp) = q;
282*0c5e0addSbostic 	flags.botl = 1;
283*0c5e0addSbostic 	return(otmp);
284*0c5e0addSbostic }
285*0c5e0addSbostic 
286*0c5e0addSbostic /*
287*0c5e0addSbostic  * getobj returns:
288*0c5e0addSbostic  *	struct obj *xxx:	object to do something with.
289*0c5e0addSbostic  *	(struct obj *) 0	error return: no object.
290*0c5e0addSbostic  *	&zeroobj		explicitly no object (as in w-).
291*0c5e0addSbostic  */
292*0c5e0addSbostic struct obj *
293*0c5e0addSbostic getobj(let,word)
294*0c5e0addSbostic register char *let,*word;
295*0c5e0addSbostic {
296*0c5e0addSbostic 	register struct obj *otmp;
297*0c5e0addSbostic 	register char ilet,ilet1,ilet2;
298*0c5e0addSbostic 	char buf[BUFSZ];
299*0c5e0addSbostic 	char lets[BUFSZ];
300*0c5e0addSbostic 	register int foo = 0, foo2;
301*0c5e0addSbostic 	register char *bp = buf;
302*0c5e0addSbostic 	xchar allowcnt = 0;	/* 0, 1 or 2 */
303*0c5e0addSbostic 	boolean allowgold = FALSE;
304*0c5e0addSbostic 	boolean allowall = FALSE;
305*0c5e0addSbostic 	boolean allownone = FALSE;
306*0c5e0addSbostic 	xchar foox = 0;
307*0c5e0addSbostic 	long cnt;
308*0c5e0addSbostic 
309*0c5e0addSbostic 	if(*let == '0') let++, allowcnt = 1;
310*0c5e0addSbostic 	if(*let == '$') let++, allowgold = TRUE;
311*0c5e0addSbostic 	if(*let == '#') let++, allowall = TRUE;
312*0c5e0addSbostic 	if(*let == '-') let++, allownone = TRUE;
313*0c5e0addSbostic 	if(allownone) *bp++ = '-';
314*0c5e0addSbostic 	if(allowgold) *bp++ = '$';
315*0c5e0addSbostic 	if(bp > buf && bp[-1] == '-') *bp++ = ' ';
316*0c5e0addSbostic 
317*0c5e0addSbostic 	ilet = 'a';
318*0c5e0addSbostic 	for(otmp = invent; otmp; otmp = otmp->nobj){
319*0c5e0addSbostic 	    if(!*let || index(let, otmp->olet)) {
320*0c5e0addSbostic 		bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;
321*0c5e0addSbostic 
322*0c5e0addSbostic 		/* ugly check: remove inappropriate things */
323*0c5e0addSbostic 		if((!strcmp(word, "take off") &&
324*0c5e0addSbostic 		    !(otmp->owornmask & (W_ARMOR - W_ARM2)))
325*0c5e0addSbostic 		|| (!strcmp(word, "wear") &&
326*0c5e0addSbostic 		    (otmp->owornmask & (W_ARMOR | W_RING)))
327*0c5e0addSbostic 		|| (!strcmp(word, "wield") &&
328*0c5e0addSbostic 		    (otmp->owornmask & W_WEP))) {
329*0c5e0addSbostic 			foo--;
330*0c5e0addSbostic 			foox++;
331*0c5e0addSbostic 		}
332*0c5e0addSbostic 	    }
333*0c5e0addSbostic 	    if(ilet == 'z') ilet = 'A'; else ilet++;
334*0c5e0addSbostic 	}
335*0c5e0addSbostic 	bp[foo] = 0;
336*0c5e0addSbostic 	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
337*0c5e0addSbostic 	(void) strcpy(lets, bp);	/* necessary since we destroy buf */
338*0c5e0addSbostic 	if(foo > 5) {			/* compactify string */
339*0c5e0addSbostic 		foo = foo2 = 1;
340*0c5e0addSbostic 		ilet2 = bp[0];
341*0c5e0addSbostic 		ilet1 = bp[1];
342*0c5e0addSbostic 		while(ilet = bp[++foo2] = bp[++foo]){
343*0c5e0addSbostic 			if(ilet == ilet1+1){
344*0c5e0addSbostic 				if(ilet1 == ilet2+1)
345*0c5e0addSbostic 					bp[foo2 - 1] = ilet1 = '-';
346*0c5e0addSbostic 				else if(ilet2 == '-') {
347*0c5e0addSbostic 					bp[--foo2] = ++ilet1;
348*0c5e0addSbostic 					continue;
349*0c5e0addSbostic 				}
350*0c5e0addSbostic 			}
351*0c5e0addSbostic 			ilet2 = ilet1;
352*0c5e0addSbostic 			ilet1 = ilet;
353*0c5e0addSbostic 		}
354*0c5e0addSbostic 	}
355*0c5e0addSbostic 	if(!foo && !allowall && !allowgold && !allownone) {
356*0c5e0addSbostic 		pline("You don't have anything %sto %s.",
357*0c5e0addSbostic 			foox ? "else " : "", word);
358*0c5e0addSbostic 		return(0);
359*0c5e0addSbostic 	}
360*0c5e0addSbostic 	for(;;) {
361*0c5e0addSbostic 		if(!buf[0])
362*0c5e0addSbostic 			pline("What do you want to %s [*]? ", word);
363*0c5e0addSbostic 		else
364*0c5e0addSbostic 			pline("What do you want to %s [%s or ?*]? ",
365*0c5e0addSbostic 				word, buf);
366*0c5e0addSbostic 
367*0c5e0addSbostic 		cnt = 0;
368*0c5e0addSbostic 		ilet = readchar();
369*0c5e0addSbostic 		while(digit(ilet) && allowcnt) {
370*0c5e0addSbostic 			if (cnt < 100000000)
371*0c5e0addSbostic 			    cnt = 10*cnt + (ilet - '0');
372*0c5e0addSbostic 			else
373*0c5e0addSbostic 			    cnt = 999999999;
374*0c5e0addSbostic 			allowcnt = 2;	/* signal presence of cnt */
375*0c5e0addSbostic 			ilet = readchar();
376*0c5e0addSbostic 		}
377*0c5e0addSbostic 		if(digit(ilet)) {
378*0c5e0addSbostic 			pline("No count allowed with this command.");
379*0c5e0addSbostic 			continue;
380*0c5e0addSbostic 		}
381*0c5e0addSbostic 		if(index(quitchars,ilet))
382*0c5e0addSbostic 			return((struct obj *)0);
383*0c5e0addSbostic 		if(ilet == '-') {
384*0c5e0addSbostic 			return(allownone ? &zeroobj : (struct obj *) 0);
385*0c5e0addSbostic 		}
386*0c5e0addSbostic 		if(ilet == '$') {
387*0c5e0addSbostic 			if(!allowgold){
388*0c5e0addSbostic 				pline("You cannot %s gold.", word);
389*0c5e0addSbostic 				continue;
390*0c5e0addSbostic 			}
391*0c5e0addSbostic 			if(!(allowcnt == 2 && cnt < u.ugold))
392*0c5e0addSbostic 				cnt = u.ugold;
393*0c5e0addSbostic 			return(mkgoldobj(cnt));
394*0c5e0addSbostic 		}
395*0c5e0addSbostic 		if(ilet == '?') {
396*0c5e0addSbostic 			doinv(lets);
397*0c5e0addSbostic 			if(!(ilet = morc)) continue;
398*0c5e0addSbostic 			/* he typed a letter (not a space) to more() */
399*0c5e0addSbostic 		} else if(ilet == '*') {
400*0c5e0addSbostic 			doinv((char *) 0);
401*0c5e0addSbostic 			if(!(ilet = morc)) continue;
402*0c5e0addSbostic 			/* ... */
403*0c5e0addSbostic 		}
404*0c5e0addSbostic 		if(flags.invlet_constant) {
405*0c5e0addSbostic 			for(otmp = invent; otmp; otmp = otmp->nobj)
406*0c5e0addSbostic 				if(otmp->invlet == ilet) break;
407*0c5e0addSbostic 		} else {
408*0c5e0addSbostic 			if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;
409*0c5e0addSbostic 			ilet -= 'a';
410*0c5e0addSbostic 			for(otmp = invent; otmp && ilet;
411*0c5e0addSbostic 					ilet--, otmp = otmp->nobj) ;
412*0c5e0addSbostic 		}
413*0c5e0addSbostic 		if(!otmp) {
414*0c5e0addSbostic 			pline("You don't have that object.");
415*0c5e0addSbostic 			continue;
416*0c5e0addSbostic 		}
417*0c5e0addSbostic 		if(cnt < 0 || otmp->quan < cnt) {
418*0c5e0addSbostic 			pline("You don't have that many! [You have %u]"
419*0c5e0addSbostic 			, otmp->quan);
420*0c5e0addSbostic 			continue;
421*0c5e0addSbostic 		}
422*0c5e0addSbostic 		break;
423*0c5e0addSbostic 	}
424*0c5e0addSbostic 	if(!allowall && let && !index(let,otmp->olet)) {
425*0c5e0addSbostic 		pline("That is a silly thing to %s.",word);
426*0c5e0addSbostic 		return(0);
427*0c5e0addSbostic 	}
428*0c5e0addSbostic 	if(allowcnt == 2) {	/* cnt given */
429*0c5e0addSbostic 		if(cnt == 0) return(0);
430*0c5e0addSbostic 		if(cnt != otmp->quan) {
431*0c5e0addSbostic 			register struct obj *obj;
432*0c5e0addSbostic 			obj = splitobj(otmp, (int) cnt);
433*0c5e0addSbostic 			if(otmp == uwep) setuwep(obj);
434*0c5e0addSbostic 		}
435*0c5e0addSbostic 	}
436*0c5e0addSbostic 	return(otmp);
437*0c5e0addSbostic }
438*0c5e0addSbostic 
439*0c5e0addSbostic ckunpaid(otmp) register struct obj *otmp; {
440*0c5e0addSbostic 	return( otmp->unpaid );
441*0c5e0addSbostic }
442*0c5e0addSbostic 
443*0c5e0addSbostic /* interactive version of getobj - used for Drop and Identify */
444*0c5e0addSbostic /* return the number of times fn was called successfully */
445*0c5e0addSbostic ggetobj(word, fn, max)
446*0c5e0addSbostic char *word;
447*0c5e0addSbostic int (*fn)(),  max;
448*0c5e0addSbostic {
449*0c5e0addSbostic char buf[BUFSZ];
450*0c5e0addSbostic register char *ip;
451*0c5e0addSbostic register char sym;
452*0c5e0addSbostic register int oletct = 0, iletct = 0;
453*0c5e0addSbostic register boolean allflag = FALSE;
454*0c5e0addSbostic char olets[20], ilets[20];
455*0c5e0addSbostic int (*ckfn)() = (int (*)()) 0;
456*0c5e0addSbostic xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0;	/* BAH */
457*0c5e0addSbostic 	if(!invent && !allowgold){
458*0c5e0addSbostic 		pline("You have nothing to %s.", word);
459*0c5e0addSbostic 		return(0);
460*0c5e0addSbostic 	} else {
461*0c5e0addSbostic 		register struct obj *otmp = invent;
462*0c5e0addSbostic 		register int uflg = 0;
463*0c5e0addSbostic 
464*0c5e0addSbostic 		if(allowgold) ilets[iletct++] = '$';
465*0c5e0addSbostic 		ilets[iletct] = 0;
466*0c5e0addSbostic 		while(otmp) {
467*0c5e0addSbostic 			if(!index(ilets, otmp->olet)){
468*0c5e0addSbostic 				ilets[iletct++] = otmp->olet;
469*0c5e0addSbostic 				ilets[iletct] = 0;
470*0c5e0addSbostic 			}
471*0c5e0addSbostic 			if(otmp->unpaid) uflg = 1;
472*0c5e0addSbostic 			otmp = otmp->nobj;
473*0c5e0addSbostic 		}
474*0c5e0addSbostic 		ilets[iletct++] = ' ';
475*0c5e0addSbostic 		if(uflg) ilets[iletct++] = 'u';
476*0c5e0addSbostic 		if(invent) ilets[iletct++] = 'a';
477*0c5e0addSbostic 		ilets[iletct] = 0;
478*0c5e0addSbostic 	}
479*0c5e0addSbostic 	pline("What kinds of thing do you want to %s? [%s] ",
480*0c5e0addSbostic 		word, ilets);
481*0c5e0addSbostic 	getlin(buf);
482*0c5e0addSbostic 	if(buf[0] == '\033') {
483*0c5e0addSbostic 		clrlin();
484*0c5e0addSbostic 		return(0);
485*0c5e0addSbostic 	}
486*0c5e0addSbostic 	ip = buf;
487*0c5e0addSbostic 	olets[0] = 0;
488*0c5e0addSbostic 	while(sym = *ip++){
489*0c5e0addSbostic 		if(sym == ' ') continue;
490*0c5e0addSbostic 		if(sym == '$') {
491*0c5e0addSbostic 			if(allowgold == 1)
492*0c5e0addSbostic 				(*fn)(mkgoldobj(u.ugold));
493*0c5e0addSbostic 			else if(!u.ugold)
494*0c5e0addSbostic 				pline("You have no gold.");
495*0c5e0addSbostic 			allowgold = 2;
496*0c5e0addSbostic 		} else
497*0c5e0addSbostic 		if(sym == 'a' || sym == 'A') allflag = TRUE; else
498*0c5e0addSbostic 		if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else
499*0c5e0addSbostic 		if(index("!%?[()=*/\"0", sym)){
500*0c5e0addSbostic 			if(!index(olets, sym)){
501*0c5e0addSbostic 				olets[oletct++] = sym;
502*0c5e0addSbostic 				olets[oletct] = 0;
503*0c5e0addSbostic 			}
504*0c5e0addSbostic 		}
505*0c5e0addSbostic 		else pline("You don't have any %c's.", sym);
506*0c5e0addSbostic 	}
507*0c5e0addSbostic 	if(allowgold == 2 && !oletct)
508*0c5e0addSbostic 		return(1);	/* he dropped gold (or at least tried to) */
509*0c5e0addSbostic 	else
510*0c5e0addSbostic 		return(askchain(invent, olets, allflag, fn, ckfn, max));
511*0c5e0addSbostic }
512*0c5e0addSbostic 
513*0c5e0addSbostic /*
514*0c5e0addSbostic  * Walk through the chain starting at objchn and ask for all objects
515*0c5e0addSbostic  * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)
516*0c5e0addSbostic  * whether the action in question (i.e., fn) has to be performed.
517*0c5e0addSbostic  * If allflag then no questions are asked. Max gives the max nr of
518*0c5e0addSbostic  * objects to be treated. Return the number of objects treated.
519*0c5e0addSbostic  */
520*0c5e0addSbostic askchain(objchn, olets, allflag, fn, ckfn, max)
521*0c5e0addSbostic struct obj *objchn;
522*0c5e0addSbostic register char *olets;
523*0c5e0addSbostic int allflag;
524*0c5e0addSbostic int (*fn)(), (*ckfn)();
525*0c5e0addSbostic int max;
526*0c5e0addSbostic {
527*0c5e0addSbostic register struct obj *otmp, *otmp2;
528*0c5e0addSbostic register char sym, ilet;
529*0c5e0addSbostic register int cnt = 0;
530*0c5e0addSbostic 	ilet = 'a'-1;
531*0c5e0addSbostic 	for(otmp = objchn; otmp; otmp = otmp2){
532*0c5e0addSbostic 		if(ilet == 'z') ilet = 'A'; else ilet++;
533*0c5e0addSbostic 		otmp2 = otmp->nobj;
534*0c5e0addSbostic 		if(olets && *olets && !index(olets, otmp->olet)) continue;
535*0c5e0addSbostic 		if(ckfn && !(*ckfn)(otmp)) continue;
536*0c5e0addSbostic 		if(!allflag) {
537*0c5e0addSbostic 			pline(xprname(otmp, ilet));
538*0c5e0addSbostic 			addtopl(" [nyaq]? ");
539*0c5e0addSbostic 			sym = readchar();
540*0c5e0addSbostic 		}
541*0c5e0addSbostic 		else	sym = 'y';
542*0c5e0addSbostic 
543*0c5e0addSbostic 		switch(sym){
544*0c5e0addSbostic 		case 'a':
545*0c5e0addSbostic 			allflag = 1;
546*0c5e0addSbostic 		case 'y':
547*0c5e0addSbostic 			cnt += (*fn)(otmp);
548*0c5e0addSbostic 			if(--max == 0) goto ret;
549*0c5e0addSbostic 		case 'n':
550*0c5e0addSbostic 		default:
551*0c5e0addSbostic 			break;
552*0c5e0addSbostic 		case 'q':
553*0c5e0addSbostic 			goto ret;
554*0c5e0addSbostic 		}
555*0c5e0addSbostic 	}
556*0c5e0addSbostic 	pline(cnt ? "That was all." : "No applicable objects.");
557*0c5e0addSbostic ret:
558*0c5e0addSbostic 	return(cnt);
559*0c5e0addSbostic }
560*0c5e0addSbostic 
561*0c5e0addSbostic obj_to_let(obj)	/* should of course only be called for things in invent */
562*0c5e0addSbostic register struct obj *obj;
563*0c5e0addSbostic {
564*0c5e0addSbostic 	register struct obj *otmp;
565*0c5e0addSbostic 	register char ilet;
566*0c5e0addSbostic 
567*0c5e0addSbostic 	if(flags.invlet_constant)
568*0c5e0addSbostic 		return(obj->invlet);
569*0c5e0addSbostic 	ilet = 'a';
570*0c5e0addSbostic 	for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)
571*0c5e0addSbostic 		if(++ilet > 'z') ilet = 'A';
572*0c5e0addSbostic 	return(otmp ? ilet : NOINVSYM);
573*0c5e0addSbostic }
574*0c5e0addSbostic 
575*0c5e0addSbostic prinv(obj)
576*0c5e0addSbostic register struct obj *obj;
577*0c5e0addSbostic {
578*0c5e0addSbostic 	pline(xprname(obj, obj_to_let(obj)));
579*0c5e0addSbostic }
580*0c5e0addSbostic 
581*0c5e0addSbostic static char *
582*0c5e0addSbostic xprname(obj,let)
583*0c5e0addSbostic register struct obj *obj;
584*0c5e0addSbostic register char let;
585*0c5e0addSbostic {
586*0c5e0addSbostic 	static char li[BUFSZ];
587*0c5e0addSbostic 
588*0c5e0addSbostic 	(void) sprintf(li, "%c - %s.",
589*0c5e0addSbostic 		flags.invlet_constant ? obj->invlet : let,
590*0c5e0addSbostic 		doname(obj));
591*0c5e0addSbostic 	return(li);
592*0c5e0addSbostic }
593*0c5e0addSbostic 
594*0c5e0addSbostic ddoinv()
595*0c5e0addSbostic {
596*0c5e0addSbostic 	doinv((char *) 0);
597*0c5e0addSbostic 	return(0);
598*0c5e0addSbostic }
599*0c5e0addSbostic 
600*0c5e0addSbostic /* called with 0 or "": all objects in inventory */
601*0c5e0addSbostic /* otherwise: all objects with (serial) letter in lets */
602*0c5e0addSbostic doinv(lets)
603*0c5e0addSbostic register char *lets;
604*0c5e0addSbostic {
605*0c5e0addSbostic 	register struct obj *otmp;
606*0c5e0addSbostic 	register char ilet;
607*0c5e0addSbostic 	int ct = 0;
608*0c5e0addSbostic 	char any[BUFSZ];
609*0c5e0addSbostic 
610*0c5e0addSbostic 	morc = 0;		/* just to be sure */
611*0c5e0addSbostic 
612*0c5e0addSbostic 	if(!invent){
613*0c5e0addSbostic 		pline("Not carrying anything.");
614*0c5e0addSbostic 		return;
615*0c5e0addSbostic 	}
616*0c5e0addSbostic 
617*0c5e0addSbostic 	cornline(0, (char *) 0);
618*0c5e0addSbostic 	ilet = 'a';
619*0c5e0addSbostic 	for(otmp = invent; otmp; otmp = otmp->nobj) {
620*0c5e0addSbostic 	    if(flags.invlet_constant) ilet = otmp->invlet;
621*0c5e0addSbostic 	    if(!lets || !*lets || index(lets, ilet)) {
622*0c5e0addSbostic 		    cornline(1, xprname(otmp, ilet));
623*0c5e0addSbostic 		    any[ct++] = ilet;
624*0c5e0addSbostic 	    }
625*0c5e0addSbostic 	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
626*0c5e0addSbostic 	}
627*0c5e0addSbostic 	any[ct] = 0;
628*0c5e0addSbostic 	cornline(2, any);
629*0c5e0addSbostic }
630*0c5e0addSbostic 
631*0c5e0addSbostic dotypeinv ()				/* free after Robert Viduya */
632*0c5e0addSbostic /* Changed to one type only, so he doesnt have to type cr */
633*0c5e0addSbostic {
634*0c5e0addSbostic     char c, ilet;
635*0c5e0addSbostic     char stuff[BUFSZ];
636*0c5e0addSbostic     register int stct;
637*0c5e0addSbostic     register struct obj *otmp;
638*0c5e0addSbostic     boolean billx = inshop() && doinvbill(0);
639*0c5e0addSbostic     boolean unpd = FALSE;
640*0c5e0addSbostic 
641*0c5e0addSbostic 	if (!invent && !u.ugold && !billx) {
642*0c5e0addSbostic 	    pline ("You aren't carrying anything.");
643*0c5e0addSbostic 	    return(0);
644*0c5e0addSbostic 	}
645*0c5e0addSbostic 
646*0c5e0addSbostic 	stct = 0;
647*0c5e0addSbostic 	if(u.ugold) stuff[stct++] = '$';
648*0c5e0addSbostic 	stuff[stct] = 0;
649*0c5e0addSbostic 	for(otmp = invent; otmp; otmp = otmp->nobj) {
650*0c5e0addSbostic 	    if (!index (stuff, otmp->olet)) {
651*0c5e0addSbostic 		stuff[stct++] = otmp->olet;
652*0c5e0addSbostic 		stuff[stct] = 0;
653*0c5e0addSbostic 	    }
654*0c5e0addSbostic 	    if(otmp->unpaid)
655*0c5e0addSbostic 		unpd = TRUE;
656*0c5e0addSbostic 	}
657*0c5e0addSbostic 	if(unpd) stuff[stct++] = 'u';
658*0c5e0addSbostic 	if(billx) stuff[stct++] = 'x';
659*0c5e0addSbostic 	stuff[stct] = 0;
660*0c5e0addSbostic 
661*0c5e0addSbostic 	if(stct > 1) {
662*0c5e0addSbostic 	    pline ("What type of object [%s] do you want an inventory of? ",
663*0c5e0addSbostic 		stuff);
664*0c5e0addSbostic 	    c = readchar();
665*0c5e0addSbostic 	    if(index(quitchars,c)) return(0);
666*0c5e0addSbostic 	} else
667*0c5e0addSbostic 	    c = stuff[0];
668*0c5e0addSbostic 
669*0c5e0addSbostic 	if(c == '$')
670*0c5e0addSbostic 	    return(doprgold());
671*0c5e0addSbostic 
672*0c5e0addSbostic 	if(c == 'x' || c == 'X') {
673*0c5e0addSbostic 	    if(billx)
674*0c5e0addSbostic 		(void) doinvbill(1);
675*0c5e0addSbostic 	    else
676*0c5e0addSbostic 		pline("No used-up objects on the shopping bill.");
677*0c5e0addSbostic 	    return(0);
678*0c5e0addSbostic 	}
679*0c5e0addSbostic 
680*0c5e0addSbostic 	if((c == 'u' || c == 'U') && !unpd) {
681*0c5e0addSbostic 		pline("You are not carrying any unpaid objects.");
682*0c5e0addSbostic 		return(0);
683*0c5e0addSbostic 	}
684*0c5e0addSbostic 
685*0c5e0addSbostic 	stct = 0;
686*0c5e0addSbostic 	ilet = 'a';
687*0c5e0addSbostic 	for (otmp = invent; otmp; otmp = otmp -> nobj) {
688*0c5e0addSbostic 	    if(flags.invlet_constant) ilet = otmp->invlet;
689*0c5e0addSbostic 	    if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))
690*0c5e0addSbostic 		stuff[stct++] = ilet;
691*0c5e0addSbostic 	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
692*0c5e0addSbostic 	}
693*0c5e0addSbostic 	stuff[stct] = '\0';
694*0c5e0addSbostic 	if(stct == 0)
695*0c5e0addSbostic 		pline("You have no such objects.");
696*0c5e0addSbostic 	else
697*0c5e0addSbostic 		doinv (stuff);
698*0c5e0addSbostic 
699*0c5e0addSbostic 	return(0);
700*0c5e0addSbostic }
701*0c5e0addSbostic 
702*0c5e0addSbostic /* look at what is here */
703*0c5e0addSbostic dolook() {
704*0c5e0addSbostic     register struct obj *otmp, *otmp0;
705*0c5e0addSbostic     register struct gold *gold;
706*0c5e0addSbostic     char *verb = Blind ? "feel" : "see";
707*0c5e0addSbostic     int	ct = 0;
708*0c5e0addSbostic 
709*0c5e0addSbostic     if(!u.uswallow) {
710*0c5e0addSbostic 	if(Blind) {
711*0c5e0addSbostic 	    pline("You try to feel what is lying here on the floor.");
712*0c5e0addSbostic 	    if(Levitation) {				/* ab@unido */
713*0c5e0addSbostic 		pline("You cannot reach the floor!");
714*0c5e0addSbostic 		return(1);
715*0c5e0addSbostic 	    }
716*0c5e0addSbostic 	}
717*0c5e0addSbostic 	otmp0 = o_at(u.ux, u.uy);
718*0c5e0addSbostic 	gold = g_at(u.ux, u.uy);
719*0c5e0addSbostic     }
720*0c5e0addSbostic 
721*0c5e0addSbostic     if(u.uswallow || (!otmp0 && !gold)) {
722*0c5e0addSbostic 	pline("You %s no objects here.", verb);
723*0c5e0addSbostic 	return(!!Blind);
724*0c5e0addSbostic     }
725*0c5e0addSbostic 
726*0c5e0addSbostic     cornline(0, "Things that are here:");
727*0c5e0addSbostic     for(otmp = otmp0; otmp; otmp = otmp->nobj) {
728*0c5e0addSbostic 	if(otmp->ox == u.ux && otmp->oy == u.uy) {
729*0c5e0addSbostic 	    ct++;
730*0c5e0addSbostic 	    cornline(1, doname(otmp));
731*0c5e0addSbostic 	    if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) {
732*0c5e0addSbostic 		pline("Touching the dead cockatrice is a fatal mistake ...");
733*0c5e0addSbostic 		pline("You die ...");
734*0c5e0addSbostic 		killer = "dead cockatrice";
735*0c5e0addSbostic 		done("died");
736*0c5e0addSbostic 	    }
737*0c5e0addSbostic 	}
738*0c5e0addSbostic     }
739*0c5e0addSbostic 
740*0c5e0addSbostic     if(gold) {
741*0c5e0addSbostic 	char gbuf[30];
742*0c5e0addSbostic 
743*0c5e0addSbostic 	(void) sprintf(gbuf, "%ld gold piece%s",
744*0c5e0addSbostic 		gold->amount, plur(gold->amount));
745*0c5e0addSbostic 	if(!ct++)
746*0c5e0addSbostic 	    pline("You %s here %s.", verb, gbuf);
747*0c5e0addSbostic 	else
748*0c5e0addSbostic 	    cornline(1, gbuf);
749*0c5e0addSbostic     }
750*0c5e0addSbostic 
751*0c5e0addSbostic     if(ct == 1 && !gold) {
752*0c5e0addSbostic 	pline("You %s here %s.", verb, doname(otmp0));
753*0c5e0addSbostic 	cornline(3, (char *) 0);
754*0c5e0addSbostic     }
755*0c5e0addSbostic     if(ct > 1)
756*0c5e0addSbostic 	cornline(2, (char *) 0);
757*0c5e0addSbostic     return(!!Blind);
758*0c5e0addSbostic }
759*0c5e0addSbostic 
760*0c5e0addSbostic stackobj(obj) register struct obj *obj; {
761*0c5e0addSbostic register struct obj *otmp = fobj;
762*0c5e0addSbostic 	for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj)
763*0c5e0addSbostic 	if(otmp->ox == obj->ox && otmp->oy == obj->oy &&
764*0c5e0addSbostic 		merged(obj,otmp,1))
765*0c5e0addSbostic 			return;
766*0c5e0addSbostic }
767*0c5e0addSbostic 
768*0c5e0addSbostic /* merge obj with otmp and delete obj if types agree */
769*0c5e0addSbostic merged(otmp,obj,lose) register struct obj *otmp, *obj; {
770*0c5e0addSbostic 	if(obj->otyp == otmp->otyp &&
771*0c5e0addSbostic 	  obj->unpaid == otmp->unpaid &&
772*0c5e0addSbostic 	  obj->spe == otmp->spe &&
773*0c5e0addSbostic 	  obj->dknown == otmp->dknown &&
774*0c5e0addSbostic 	  obj->cursed == otmp->cursed &&
775*0c5e0addSbostic 	  (index("%*?!", obj->olet) ||
776*0c5e0addSbostic 	    (obj->known == otmp->known &&
777*0c5e0addSbostic 		(obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) {
778*0c5e0addSbostic 		otmp->quan += obj->quan;
779*0c5e0addSbostic 		otmp->owt += obj->owt;
780*0c5e0addSbostic 		if(lose) freeobj(obj);
781*0c5e0addSbostic 		obfree(obj,otmp);	/* free(obj), bill->otmp */
782*0c5e0addSbostic 		return(1);
783*0c5e0addSbostic 	} else	return(0);
784*0c5e0addSbostic }
785*0c5e0addSbostic 
786*0c5e0addSbostic /*
787*0c5e0addSbostic  * Gold is no longer displayed; in fact, when you have a lot of money,
788*0c5e0addSbostic  * it may take a while before you have counted it all.
789*0c5e0addSbostic  * [Bug: d$ and pickup still tell you how much it was.]
790*0c5e0addSbostic  */
791*0c5e0addSbostic extern int (*occupation)();
792*0c5e0addSbostic extern char *occtxt;
793*0c5e0addSbostic static long goldcounted;
794*0c5e0addSbostic 
795*0c5e0addSbostic countgold(){
796*0c5e0addSbostic 	if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {
797*0c5e0addSbostic 		long eps = 0;
798*0c5e0addSbostic 		if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));
799*0c5e0addSbostic 		pline("You probably have about %ld gold pieces.",
800*0c5e0addSbostic 			u.ugold + eps);
801*0c5e0addSbostic 		return(0);	/* done */
802*0c5e0addSbostic 	}
803*0c5e0addSbostic 	return(1);		/* continue */
804*0c5e0addSbostic }
805*0c5e0addSbostic 
806*0c5e0addSbostic doprgold(){
807*0c5e0addSbostic 	if(!u.ugold)
808*0c5e0addSbostic 		pline("You do not carry any gold.");
809*0c5e0addSbostic 	else if(u.ugold <= 500)
810*0c5e0addSbostic 		pline("You are carrying %ld gold pieces.", u.ugold);
811*0c5e0addSbostic 	else {
812*0c5e0addSbostic 		pline("You sit down in order to count your gold pieces.");
813*0c5e0addSbostic 		goldcounted = 500;
814*0c5e0addSbostic 		occupation = countgold;
815*0c5e0addSbostic 		occtxt = "counting your gold";
816*0c5e0addSbostic 	}
817*0c5e0addSbostic 	return(1);
818*0c5e0addSbostic }
819*0c5e0addSbostic 
820*0c5e0addSbostic /* --- end of gold counting section --- */
821*0c5e0addSbostic 
822*0c5e0addSbostic doprwep(){
823*0c5e0addSbostic 	if(!uwep) pline("You are empty handed.");
824*0c5e0addSbostic 	else prinv(uwep);
825*0c5e0addSbostic 	return(0);
826*0c5e0addSbostic }
827*0c5e0addSbostic 
828*0c5e0addSbostic doprarm(){
829*0c5e0addSbostic 	if(!uarm && !uarmg && !uarms && !uarmh)
830*0c5e0addSbostic 		pline("You are not wearing any armor.");
831*0c5e0addSbostic 	else {
832*0c5e0addSbostic 		char lets[6];
833*0c5e0addSbostic 		register int ct = 0;
834*0c5e0addSbostic 
835*0c5e0addSbostic 		if(uarm) lets[ct++] = obj_to_let(uarm);
836*0c5e0addSbostic 		if(uarm2) lets[ct++] = obj_to_let(uarm2);
837*0c5e0addSbostic 		if(uarmh) lets[ct++] = obj_to_let(uarmh);
838*0c5e0addSbostic 		if(uarms) lets[ct++] = obj_to_let(uarms);
839*0c5e0addSbostic 		if(uarmg) lets[ct++] = obj_to_let(uarmg);
840*0c5e0addSbostic 		lets[ct] = 0;
841*0c5e0addSbostic 		doinv(lets);
842*0c5e0addSbostic 	}
843*0c5e0addSbostic 	return(0);
844*0c5e0addSbostic }
845*0c5e0addSbostic 
846*0c5e0addSbostic doprring(){
847*0c5e0addSbostic 	if(!uleft && !uright)
848*0c5e0addSbostic 		pline("You are not wearing any rings.");
849*0c5e0addSbostic 	else {
850*0c5e0addSbostic 		char lets[3];
851*0c5e0addSbostic 		register int ct = 0;
852*0c5e0addSbostic 
853*0c5e0addSbostic 		if(uleft) lets[ct++] = obj_to_let(uleft);
854*0c5e0addSbostic 		if(uright) lets[ct++] = obj_to_let(uright);
855*0c5e0addSbostic 		lets[ct] = 0;
856*0c5e0addSbostic 		doinv(lets);
857*0c5e0addSbostic 	}
858*0c5e0addSbostic 	return(0);
859*0c5e0addSbostic }
860*0c5e0addSbostic 
861*0c5e0addSbostic digit(c) char c; {
862*0c5e0addSbostic 	return(c >= '0' && c <= '9');
863*0c5e0addSbostic }
864