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