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