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