home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / nethack2.3 / part05 / invent.c < prev    next >
C/C++ Source or Header  |  1988-10-17  |  23KB  |  1,061 lines

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