summaryrefslogtreecommitdiffstats
path: root/hack/hack.invent.c
diff options
context:
space:
mode:
authorcgd <cgd@NetBSD.org>1993-03-21 09:45:37 +0000
committercgd <cgd@NetBSD.org>1993-03-21 09:45:37 +0000
commit77e3814f0c0e3dea4d0032e25666f77e6f83bfff (patch)
tree7eddfcbf3dd12089e71dc3fafb0a106c5c5766c7 /hack/hack.invent.c
parente81d63576b2e46ab90da7d75fa155ea57ee4d32e (diff)
downloadbsdgames-darwin-77e3814f0c0e3dea4d0032e25666f77e6f83bfff.tar.gz
bsdgames-darwin-77e3814f0c0e3dea4d0032e25666f77e6f83bfff.tar.zst
bsdgames-darwin-77e3814f0c0e3dea4d0032e25666f77e6f83bfff.zip
initial import of 386bsd-0.1 sources
Diffstat (limited to 'hack/hack.invent.c')
-rw-r--r--hack/hack.invent.c863
1 files changed, 863 insertions, 0 deletions
diff --git a/hack/hack.invent.c b/hack/hack.invent.c
new file mode 100644
index 00000000..c4620ca1
--- /dev/null
+++ b/hack/hack.invent.c
@@ -0,0 +1,863 @@
+/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/* hack.invent.c - version 1.0.3 */
+
+#include "hack.h"
+#include <stdio.h>
+extern struct obj *splitobj();
+extern struct obj zeroobj;
+extern char morc;
+extern char quitchars[];
+char *xprname();
+
+#ifndef NOWORM
+#include "def.wseg.h"
+extern struct wseg *wsegs[32];
+#endif NOWORM
+
+#define NOINVSYM '#'
+
+static int lastinvnr = 51; /* 0 ... 51 */
+static
+assigninvlet(otmp)
+register struct obj *otmp;
+{
+ boolean inuse[52];
+ register int i;
+ register struct obj *obj;
+
+ for(i = 0; i < 52; i++) inuse[i] = FALSE;
+ for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
+ i = obj->invlet;
+ if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
+ if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
+ if(i == otmp->invlet) otmp->invlet = 0;
+ }
+ if((i = otmp->invlet) &&
+ (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
+ return;
+ for(i = lastinvnr+1; i != lastinvnr; i++) {
+ if(i == 52) { i = -1; continue; }
+ if(!inuse[i]) break;
+ }
+ otmp->invlet = (inuse[i] ? NOINVSYM :
+ (i < 26) ? ('a'+i) : ('A'+i-26));
+ lastinvnr = i;
+}
+
+struct obj *
+addinv(obj)
+register struct obj *obj;
+{
+ register struct obj *otmp;
+
+ /* merge or attach to end of chain */
+ if(!invent) {
+ invent = obj;
+ otmp = 0;
+ } else
+ for(otmp = invent; /* otmp */; otmp = otmp->nobj) {
+ if(merged(otmp, obj, 0))
+ return(otmp);
+ if(!otmp->nobj) {
+ otmp->nobj = obj;
+ break;
+ }
+ }
+ obj->nobj = 0;
+
+ if(flags.invlet_constant) {
+ assigninvlet(obj);
+ /*
+ * The ordering of the chain is nowhere significant
+ * so in case you prefer some other order than the
+ * historical one, change the code below.
+ */
+ if(otmp) { /* find proper place in chain */
+ otmp->nobj = 0;
+ if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
+ obj->nobj = invent;
+ invent = obj;
+ } else
+ for(otmp = invent; ; otmp = otmp->nobj) {
+ if(!otmp->nobj ||
+ (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){
+ obj->nobj = otmp->nobj;
+ otmp->nobj = obj;
+ break;
+ }
+ }
+ }
+ }
+
+ return(obj);
+}
+
+useup(obj)
+register struct obj *obj;
+{
+ if(obj->quan > 1){
+ obj->quan--;
+ obj->owt = weight(obj);
+ } else {
+ setnotworn(obj);
+ freeinv(obj);
+ obfree(obj, (struct obj *) 0);
+ }
+}
+
+freeinv(obj)
+register struct obj *obj;
+{
+ register struct obj *otmp;
+
+ if(obj == invent)
+ invent = invent->nobj;
+ else {
+ for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
+ if(!otmp->nobj) panic("freeinv");
+ otmp->nobj = obj->nobj;
+ }
+}
+
+/* destroy object in fobj chain (if unpaid, it remains on the bill) */
+delobj(obj) register struct obj *obj; {
+ freeobj(obj);
+ unpobj(obj);
+ obfree(obj, (struct obj *) 0);
+}
+
+/* unlink obj from chain starting with fobj */
+freeobj(obj) register struct obj *obj; {
+ register struct obj *otmp;
+
+ if(obj == fobj) fobj = fobj->nobj;
+ else {
+ for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj)
+ if(!otmp) panic("error in freeobj");
+ otmp->nobj = obj->nobj;
+ }
+}
+
+/* Note: freegold throws away its argument! */
+freegold(gold) register struct gold *gold; {
+ register struct gold *gtmp;
+
+ if(gold == fgold) fgold = gold->ngold;
+ else {
+ for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
+ if(!gtmp) panic("error in freegold");
+ gtmp->ngold = gold->ngold;
+ }
+ free((char *) gold);
+}
+
+deltrap(trap)
+register struct trap *trap;
+{
+ register struct trap *ttmp;
+
+ if(trap == ftrap)
+ ftrap = ftrap->ntrap;
+ else {
+ for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
+ ttmp->ntrap = trap->ntrap;
+ }
+ free((char *) trap);
+}
+
+struct wseg *m_atseg;
+
+struct monst *
+m_at(x,y)
+register x,y;
+{
+ register struct monst *mtmp;
+#ifndef NOWORM
+ register struct wseg *wtmp;
+#endif NOWORM
+
+ m_atseg = 0;
+ for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
+ if(mtmp->mx == x && mtmp->my == y)
+ return(mtmp);
+#ifndef NOWORM
+ if(mtmp->wormno){
+ for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg)
+ if(wtmp->wx == x && wtmp->wy == y){
+ m_atseg = wtmp;
+ return(mtmp);
+ }
+ }
+#endif NOWORM
+ }
+ return(0);
+}
+
+struct obj *
+o_at(x,y)
+register x,y;
+{
+ register struct obj *otmp;
+
+ for(otmp = fobj; otmp; otmp = otmp->nobj)
+ if(otmp->ox == x && otmp->oy == y) return(otmp);
+ return(0);
+}
+
+struct obj *
+sobj_at(n,x,y)
+register n,x,y;
+{
+ register struct obj *otmp;
+
+ for(otmp = fobj; otmp; otmp = otmp->nobj)
+ if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)
+ return(otmp);
+ return(0);
+}
+
+carried(obj) register struct obj *obj; {
+register struct obj *otmp;
+ for(otmp = invent; otmp; otmp = otmp->nobj)
+ if(otmp == obj) return(1);
+ return(0);
+}
+
+carrying(type)
+register int type;
+{
+ register struct obj *otmp;
+
+ for(otmp = invent; otmp; otmp = otmp->nobj)
+ if(otmp->otyp == type)
+ return(TRUE);
+ return(FALSE);
+}
+
+struct obj *
+o_on(id, objchn) unsigned int id; register struct obj *objchn; {
+ while(objchn) {
+ if(objchn->o_id == id) return(objchn);
+ objchn = objchn->nobj;
+ }
+ return((struct obj *) 0);
+}
+
+struct trap *
+t_at(x,y)
+register x,y;
+{
+ register struct trap *trap = ftrap;
+ while(trap) {
+ if(trap->tx == x && trap->ty == y) return(trap);
+ trap = trap->ntrap;
+ }
+ return(0);
+}
+
+struct gold *
+g_at(x,y)
+register x,y;
+{
+ register struct gold *gold = fgold;
+ while(gold) {
+ if(gold->gx == x && gold->gy == y) return(gold);
+ gold = gold->ngold;
+ }
+ return(0);
+}
+
+/* make dummy object structure containing gold - for temporary use only */
+struct obj *
+mkgoldobj(q)
+register long q;
+{
+ register struct obj *otmp;
+
+ otmp = newobj(0);
+ /* should set o_id etc. but otmp will be freed soon */
+ otmp->olet = '$';
+ u.ugold -= q;
+ OGOLD(otmp) = q;
+ flags.botl = 1;
+ return(otmp);
+}
+
+/*
+ * getobj returns:
+ * struct obj *xxx: object to do something with.
+ * (struct obj *) 0 error return: no object.
+ * &zeroobj explicitly no object (as in w-).
+ */
+struct obj *
+getobj(let,word)
+register char *let,*word;
+{
+ register struct obj *otmp;
+ register char ilet,ilet1,ilet2;
+ char buf[BUFSZ];
+ char lets[BUFSZ];
+ register int foo = 0, foo2;
+ register char *bp = buf;
+ xchar allowcnt = 0; /* 0, 1 or 2 */
+ boolean allowgold = FALSE;
+ boolean allowall = FALSE;
+ boolean allownone = FALSE;
+ xchar foox = 0;
+ long cnt;
+
+ if(*let == '0') let++, allowcnt = 1;
+ if(*let == '$') let++, allowgold = TRUE;
+ if(*let == '#') let++, allowall = TRUE;
+ if(*let == '-') let++, allownone = TRUE;
+ if(allownone) *bp++ = '-';
+ if(allowgold) *bp++ = '$';
+ if(bp > buf && bp[-1] == '-') *bp++ = ' ';
+
+ ilet = 'a';
+ for(otmp = invent; otmp; otmp = otmp->nobj){
+ if(!*let || index(let, otmp->olet)) {
+ bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;
+
+ /* ugly check: remove inappropriate things */
+ if((!strcmp(word, "take off") &&
+ !(otmp->owornmask & (W_ARMOR - W_ARM2)))
+ || (!strcmp(word, "wear") &&
+ (otmp->owornmask & (W_ARMOR | W_RING)))
+ || (!strcmp(word, "wield") &&
+ (otmp->owornmask & W_WEP))) {
+ foo--;
+ foox++;
+ }
+ }
+ if(ilet == 'z') ilet = 'A'; else ilet++;
+ }
+ bp[foo] = 0;
+ if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
+ (void) strcpy(lets, bp); /* necessary since we destroy buf */
+ if(foo > 5) { /* compactify string */
+ foo = foo2 = 1;
+ ilet2 = bp[0];
+ ilet1 = bp[1];
+ while(ilet = bp[++foo2] = bp[++foo]){
+ if(ilet == ilet1+1){
+ if(ilet1 == ilet2+1)
+ bp[foo2 - 1] = ilet1 = '-';
+ else if(ilet2 == '-') {
+ bp[--foo2] = ++ilet1;
+ continue;
+ }
+ }
+ ilet2 = ilet1;
+ ilet1 = ilet;
+ }
+ }
+ if(!foo && !allowall && !allowgold && !allownone) {
+ pline("You don't have anything %sto %s.",
+ foox ? "else " : "", word);
+ return(0);
+ }
+ for(;;) {
+ if(!buf[0])
+ pline("What do you want to %s [*]? ", word);
+ else
+ pline("What do you want to %s [%s or ?*]? ",
+ word, buf);
+
+ cnt = 0;
+ ilet = readchar();
+ while(digit(ilet) && allowcnt) {
+ if (cnt < 100000000)
+ cnt = 10*cnt + (ilet - '0');
+ else
+ cnt = 999999999;
+ allowcnt = 2; /* signal presence of cnt */
+ ilet = readchar();
+ }
+ if(digit(ilet)) {
+ pline("No count allowed with this command.");
+ continue;
+ }
+ if(index(quitchars,ilet))
+ return((struct obj *)0);
+ if(ilet == '-') {
+ return(allownone ? &zeroobj : (struct obj *) 0);
+ }
+ if(ilet == '$') {
+ if(!allowgold){
+ pline("You cannot %s gold.", word);
+ continue;
+ }
+ if(!(allowcnt == 2 && cnt < u.ugold))
+ cnt = u.ugold;
+ return(mkgoldobj(cnt));
+ }
+ if(ilet == '?') {
+ doinv(lets);
+ if(!(ilet = morc)) continue;
+ /* he typed a letter (not a space) to more() */
+ } else if(ilet == '*') {
+ doinv((char *) 0);
+ if(!(ilet = morc)) continue;
+ /* ... */
+ }
+ if(flags.invlet_constant) {
+ for(otmp = invent; otmp; otmp = otmp->nobj)
+ if(otmp->invlet == ilet) break;
+ } else {
+ if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;
+ ilet -= 'a';
+ for(otmp = invent; otmp && ilet;
+ ilet--, otmp = otmp->nobj) ;
+ }
+ if(!otmp) {
+ pline("You don't have that object.");
+ continue;
+ }
+ if(cnt < 0 || otmp->quan < cnt) {
+ pline("You don't have that many! [You have %u]"
+ , otmp->quan);
+ continue;
+ }
+ break;
+ }
+ if(!allowall && let && !index(let,otmp->olet)) {
+ pline("That is a silly thing to %s.",word);
+ return(0);
+ }
+ if(allowcnt == 2) { /* cnt given */
+ if(cnt == 0) return(0);
+ if(cnt != otmp->quan) {
+ register struct obj *obj;
+ obj = splitobj(otmp, (int) cnt);
+ if(otmp == uwep) setuwep(obj);
+ }
+ }
+ return(otmp);
+}
+
+ckunpaid(otmp) register struct obj *otmp; {
+ return( otmp->unpaid );
+}
+
+/* interactive version of getobj - used for Drop and Identify */
+/* return the number of times fn was called successfully */
+ggetobj(word, fn, max)
+char *word;
+int (*fn)(), max;
+{
+char buf[BUFSZ];
+register char *ip;
+register char sym;
+register int oletct = 0, iletct = 0;
+register boolean allflag = FALSE;
+char olets[20], ilets[20];
+int (*ckfn)() = (int (*)()) 0;
+xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */
+ if(!invent && !allowgold){
+ pline("You have nothing to %s.", word);
+ return(0);
+ } else {
+ register struct obj *otmp = invent;
+ register int uflg = 0;
+
+ if(allowgold) ilets[iletct++] = '$';
+ ilets[iletct] = 0;
+ while(otmp) {
+ if(!index(ilets, otmp->olet)){
+ ilets[iletct++] = otmp->olet;
+ ilets[iletct] = 0;
+ }
+ if(otmp->unpaid) uflg = 1;
+ otmp = otmp->nobj;
+ }
+ ilets[iletct++] = ' ';
+ if(uflg) ilets[iletct++] = 'u';
+ if(invent) ilets[iletct++] = 'a';
+ ilets[iletct] = 0;
+ }
+ pline("What kinds of thing do you want to %s? [%s] ",
+ word, ilets);
+ getlin(buf);
+ if(buf[0] == '\033') {
+ clrlin();
+ return(0);
+ }
+ ip = buf;
+ olets[0] = 0;
+ while(sym = *ip++){
+ if(sym == ' ') continue;
+ if(sym == '$') {
+ if(allowgold == 1)
+ (*fn)(mkgoldobj(u.ugold));
+ else if(!u.ugold)
+ pline("You have no gold.");
+ allowgold = 2;
+ } else
+ if(sym == 'a' || sym == 'A') allflag = TRUE; else
+ if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else
+ if(index("!%?[()=*/\"0", sym)){
+ if(!index(olets, sym)){
+ olets[oletct++] = sym;
+ olets[oletct] = 0;
+ }
+ }
+ else pline("You don't have any %c's.", sym);
+ }
+ if(allowgold == 2 && !oletct)
+ return(1); /* he dropped gold (or at least tried to) */
+ else
+ return(askchain(invent, olets, allflag, fn, ckfn, max));
+}
+
+/*
+ * Walk through the chain starting at objchn and ask for all objects
+ * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)
+ * whether the action in question (i.e., fn) has to be performed.
+ * If allflag then no questions are asked. Max gives the max nr of
+ * objects to be treated. Return the number of objects treated.
+ */
+askchain(objchn, olets, allflag, fn, ckfn, max)
+struct obj *objchn;
+register char *olets;
+int allflag;
+int (*fn)(), (*ckfn)();
+int max;
+{
+register struct obj *otmp, *otmp2;
+register char sym, ilet;
+register int cnt = 0;
+ ilet = 'a'-1;
+ for(otmp = objchn; otmp; otmp = otmp2){
+ if(ilet == 'z') ilet = 'A'; else ilet++;
+ otmp2 = otmp->nobj;
+ if(olets && *olets && !index(olets, otmp->olet)) continue;
+ if(ckfn && !(*ckfn)(otmp)) continue;
+ if(!allflag) {
+ pline(xprname(otmp, ilet));
+ addtopl(" [nyaq]? ");
+ sym = readchar();
+ }
+ else sym = 'y';
+
+ switch(sym){
+ case 'a':
+ allflag = 1;
+ case 'y':
+ cnt += (*fn)(otmp);
+ if(--max == 0) goto ret;
+ case 'n':
+ default:
+ break;
+ case 'q':
+ goto ret;
+ }
+ }
+ pline(cnt ? "That was all." : "No applicable objects.");
+ret:
+ return(cnt);
+}
+
+obj_to_let(obj) /* should of course only be called for things in invent */
+register struct obj *obj;
+{
+ register struct obj *otmp;
+ register char ilet;
+
+ if(flags.invlet_constant)
+ return(obj->invlet);
+ ilet = 'a';
+ for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)
+ if(++ilet > 'z') ilet = 'A';
+ return(otmp ? ilet : NOINVSYM);
+}
+
+prinv(obj)
+register struct obj *obj;
+{
+ pline(xprname(obj, obj_to_let(obj)));
+}
+
+static char *
+xprname(obj,let)
+register struct obj *obj;
+register char let;
+{
+ static char li[BUFSZ];
+
+ (void) sprintf(li, "%c - %s.",
+ flags.invlet_constant ? obj->invlet : let,
+ doname(obj));
+ return(li);
+}
+
+ddoinv()
+{
+ doinv((char *) 0);
+ return(0);
+}
+
+/* called with 0 or "": all objects in inventory */
+/* otherwise: all objects with (serial) letter in lets */
+doinv(lets)
+register char *lets;
+{
+ register struct obj *otmp;
+ register char ilet;
+ int ct = 0;
+ char any[BUFSZ];
+
+ morc = 0; /* just to be sure */
+
+ if(!invent){
+ pline("Not carrying anything.");
+ return;
+ }
+
+ cornline(0, (char *) 0);
+ ilet = 'a';
+ for(otmp = invent; otmp; otmp = otmp->nobj) {
+ if(flags.invlet_constant) ilet = otmp->invlet;
+ if(!lets || !*lets || index(lets, ilet)) {
+ cornline(1, xprname(otmp, ilet));
+ any[ct++] = ilet;
+ }
+ if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
+ }
+ any[ct] = 0;
+ cornline(2, any);
+}
+
+dotypeinv () /* free after Robert Viduya */
+/* Changed to one type only, so he doesnt have to type cr */
+{
+ char c, ilet;
+ char stuff[BUFSZ];
+ register int stct;
+ register struct obj *otmp;
+ boolean billx = inshop() && doinvbill(0);
+ boolean unpd = FALSE;
+
+ if (!invent && !u.ugold && !billx) {
+ pline ("You aren't carrying anything.");
+ return(0);
+ }
+
+ stct = 0;
+ if(u.ugold) stuff[stct++] = '$';
+ stuff[stct] = 0;
+ for(otmp = invent; otmp; otmp = otmp->nobj) {
+ if (!index (stuff, otmp->olet)) {
+ stuff[stct++] = otmp->olet;
+ stuff[stct] = 0;
+ }
+ if(otmp->unpaid)
+ unpd = TRUE;
+ }
+ if(unpd) stuff[stct++] = 'u';
+ if(billx) stuff[stct++] = 'x';
+ stuff[stct] = 0;
+
+ if(stct > 1) {
+ pline ("What type of object [%s] do you want an inventory of? ",
+ stuff);
+ c = readchar();
+ if(index(quitchars,c)) return(0);
+ } else
+ c = stuff[0];
+
+ if(c == '$')
+ return(doprgold());
+
+ if(c == 'x' || c == 'X') {
+ if(billx)
+ (void) doinvbill(1);
+ else
+ pline("No used-up objects on the shopping bill.");
+ return(0);
+ }
+
+ if((c == 'u' || c == 'U') && !unpd) {
+ pline("You are not carrying any unpaid objects.");
+ return(0);
+ }
+
+ stct = 0;
+ ilet = 'a';
+ for (otmp = invent; otmp; otmp = otmp -> nobj) {
+ if(flags.invlet_constant) ilet = otmp->invlet;
+ if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))
+ stuff[stct++] = ilet;
+ if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
+ }
+ stuff[stct] = '\0';
+ if(stct == 0)
+ pline("You have no such objects.");
+ else
+ doinv (stuff);
+
+ return(0);
+}
+
+/* look at what is here */
+dolook() {
+ register struct obj *otmp, *otmp0;
+ register struct gold *gold;
+ char *verb = Blind ? "feel" : "see";
+ int ct = 0;
+
+ if(!u.uswallow) {
+ if(Blind) {
+ pline("You try to feel what is lying here on the floor.");
+ if(Levitation) { /* ab@unido */
+ pline("You cannot reach the floor!");
+ return(1);
+ }
+ }
+ otmp0 = o_at(u.ux, u.uy);
+ gold = g_at(u.ux, u.uy);
+ }
+
+ if(u.uswallow || (!otmp0 && !gold)) {
+ pline("You %s no objects here.", verb);
+ return(!!Blind);
+ }
+
+ cornline(0, "Things that are here:");
+ for(otmp = otmp0; otmp; otmp = otmp->nobj) {
+ if(otmp->ox == u.ux && otmp->oy == u.uy) {
+ ct++;
+ cornline(1, doname(otmp));
+ if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) {
+ pline("Touching the dead cockatrice is a fatal mistake ...");
+ pline("You die ...");
+ killer = "dead cockatrice";
+ done("died");
+ }
+ }
+ }
+
+ if(gold) {
+ char gbuf[30];
+
+ (void) sprintf(gbuf, "%ld gold piece%s",
+ gold->amount, plur(gold->amount));
+ if(!ct++)
+ pline("You %s here %s.", verb, gbuf);
+ else
+ cornline(1, gbuf);
+ }
+
+ if(ct == 1 && !gold) {
+ pline("You %s here %s.", verb, doname(otmp0));
+ cornline(3, (char *) 0);
+ }
+ if(ct > 1)
+ cornline(2, (char *) 0);
+ return(!!Blind);
+}
+
+stackobj(obj) register struct obj *obj; {
+register struct obj *otmp = fobj;
+ for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj)
+ if(otmp->ox == obj->ox && otmp->oy == obj->oy &&
+ merged(obj,otmp,1))
+ return;
+}
+
+/* merge obj with otmp and delete obj if types agree */
+merged(otmp,obj,lose) register struct obj *otmp, *obj; {
+ if(obj->otyp == otmp->otyp &&
+ obj->unpaid == otmp->unpaid &&
+ obj->spe == otmp->spe &&
+ obj->dknown == otmp->dknown &&
+ obj->cursed == otmp->cursed &&
+ (index("%*?!", obj->olet) ||
+ (obj->known == otmp->known &&
+ (obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) {
+ otmp->quan += obj->quan;
+ otmp->owt += obj->owt;
+ if(lose) freeobj(obj);
+ obfree(obj,otmp); /* free(obj), bill->otmp */
+ return(1);
+ } else return(0);
+}
+
+/*
+ * Gold is no longer displayed; in fact, when you have a lot of money,
+ * it may take a while before you have counted it all.
+ * [Bug: d$ and pickup still tell you how much it was.]
+ */
+extern int (*occupation)();
+extern char *occtxt;
+static long goldcounted;
+
+countgold(){
+ if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {
+ long eps = 0;
+ if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));
+ pline("You probably have about %ld gold pieces.",
+ u.ugold + eps);
+ return(0); /* done */
+ }
+ return(1); /* continue */
+}
+
+doprgold(){
+ if(!u.ugold)
+ pline("You do not carry any gold.");
+ else if(u.ugold <= 500)
+ pline("You are carrying %ld gold pieces.", u.ugold);
+ else {
+ pline("You sit down in order to count your gold pieces.");
+ goldcounted = 500;
+ occupation = countgold;
+ occtxt = "counting your gold";
+ }
+ return(1);
+}
+
+/* --- end of gold counting section --- */
+
+doprwep(){
+ if(!uwep) pline("You are empty handed.");
+ else prinv(uwep);
+ return(0);
+}
+
+doprarm(){
+ if(!uarm && !uarmg && !uarms && !uarmh)
+ pline("You are not wearing any armor.");
+ else {
+ char lets[6];
+ register int ct = 0;
+
+ if(uarm) lets[ct++] = obj_to_let(uarm);
+ if(uarm2) lets[ct++] = obj_to_let(uarm2);
+ if(uarmh) lets[ct++] = obj_to_let(uarmh);
+ if(uarms) lets[ct++] = obj_to_let(uarms);
+ if(uarmg) lets[ct++] = obj_to_let(uarmg);
+ lets[ct] = 0;
+ doinv(lets);
+ }
+ return(0);
+}
+
+doprring(){
+ if(!uleft && !uright)
+ pline("You are not wearing any rings.");
+ else {
+ char lets[3];
+ register int ct = 0;
+
+ if(uleft) lets[ct++] = obj_to_let(uleft);
+ if(uright) lets[ct++] = obj_to_let(uright);
+ lets[ct] = 0;
+ doinv(lets);
+ }
+ return(0);
+}
+
+digit(c) char c; {
+ return(c >= '0' && c <= '9');
+}