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