]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - games/hack/hack.invent.c
This commit was generated by cvs2svn to compensate for changes in r44743,
[FreeBSD/FreeBSD.git] / games / hack / hack.invent.c
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
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 *
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
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
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) */
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 */
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! */
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
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 *
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 *
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 *
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
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
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 *
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 *
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 *
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 *
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 *
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
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 */
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
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
575 prinv(obj)
576 register struct obj *obj;
577 {
578         pline(xprname(obj, obj_to_let(obj)));
579 }
580
581 static char *
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
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 */
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
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 */
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
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 */
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
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
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
822 doprwep(){
823         if(!uwep) pline("You are empty handed.");
824         else prinv(uwep);
825         return(0);
826 }
827
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
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
861 digit(c) char c; {
862         return(c >= '0' && c <= '9');
863 }