home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / hack / hack.invent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  18.5 KB  |  864 lines

  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. 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. }
  864.