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