1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2: /* hack.shk.c - version 1.0.3 */ 3: 4: #include "hack.h" 5: #ifdef QUEST 6: int shlevel = 0; 7: struct monst *shopkeeper = 0; 8: struct obj *billobjs = 0; 9: obfree(obj,merge) register struct obj *obj, *merge; { 10: free((char *) obj); 11: } 12: inshop(){ return(0); } 13: addtobill(){} 14: subfrombill(){} 15: splitbill(){} 16: dopay(){ return(0); } 17: paybill(){} 18: doinvbill(){ return(0); } 19: shkdead(){} 20: shkcatch(){ return(0); } 21: shk_move(){ return(0); } 22: replshk(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {} 23: char *shkname(){ return(""); } 24: 25: #else QUEST 26: #include "hack.mfndpos.h" 27: #include "def.mkroom.h" 28: #include "def.eshk.h" 29: 30: #define ESHK(mon) ((struct eshk *)(&(mon->mextra[0]))) 31: #define NOTANGRY(mon) mon->mpeaceful 32: #define ANGRY(mon) !NOTANGRY(mon) 33: 34: extern char plname[], *xname(); 35: extern struct obj *o_on(), *bp_to_obj(); 36: 37: /* Descriptor of current shopkeeper. Note that the bill need not be 38: per-shopkeeper, since it is valid only when in a shop. */ 39: static struct monst *shopkeeper = 0; 40: static struct bill_x *bill; 41: static int shlevel = 0; /* level of this shopkeeper */ 42: struct obj *billobjs; /* objects on bill with bp->useup */ 43: /* only accessed here and by save & restore */ 44: static long int total; /* filled by addupbill() */ 45: static long int followmsg; /* last time of follow message */ 46: 47: /* 48: invariants: obj->unpaid iff onbill(obj) [unless bp->useup] 49: obj->quan <= bp->bquan 50: */ 51: 52: 53: char shtypes[] = { /* 8 shoptypes: 7 specialized, 1 mixed */ 54: RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM, 55: POTION_SYM, ARMOR_SYM, 0 56: }; 57: 58: static char *shopnam[] = { 59: "engagement ring", "walking cane", "antique weapon", 60: "delicatessen", "second hand book", "liquor", 61: "used armor", "assorted antiques" 62: }; 63: 64: char * 65: shkname(mtmp) /* called in do_name.c */ 66: register struct monst *mtmp; 67: { 68: return(ESHK(mtmp)->shknam); 69: } 70: 71: shkdead(mtmp) /* called in mon.c */ 72: register struct monst *mtmp; 73: { 74: register struct eshk *eshk = ESHK(mtmp); 75: 76: if(eshk->shoplevel == dlevel) 77: rooms[eshk->shoproom].rtype = 0; 78: if(mtmp == shopkeeper) { 79: setpaid(); 80: shopkeeper = 0; 81: bill = (struct bill_x *) -1000; /* dump core when referenced */ 82: } 83: } 84: 85: replshk(mtmp,mtmp2) 86: register struct monst *mtmp, *mtmp2; 87: { 88: if(mtmp == shopkeeper) { 89: shopkeeper = mtmp2; 90: bill = &(ESHK(shopkeeper)->bill[0]); 91: } 92: } 93: 94: static 95: setpaid(){ /* caller has checked that shopkeeper exists */ 96: /* either we paid or left the shop or he just died */ 97: register struct obj *obj; 98: register struct monst *mtmp; 99: for(obj = invent; obj; obj = obj->nobj) 100: obj->unpaid = 0; 101: for(obj = fobj; obj; obj = obj->nobj) 102: obj->unpaid = 0; 103: for(obj = fcobj; obj; obj = obj->nobj) 104: obj->unpaid = 0; 105: for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 106: for(obj = mtmp->minvent; obj; obj = obj->nobj) 107: obj->unpaid = 0; 108: for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon) 109: for(obj = mtmp->minvent; obj; obj = obj->nobj) 110: obj->unpaid = 0; 111: while(obj = billobjs){ 112: billobjs = obj->nobj; 113: free((char *) obj); 114: } 115: ESHK(shopkeeper)->billct = 0; 116: } 117: 118: static 119: addupbill(){ /* delivers result in total */ 120: /* caller has checked that shopkeeper exists */ 121: register ct = ESHK(shopkeeper)->billct; 122: register struct bill_x *bp = bill; 123: total = 0; 124: while(ct--){ 125: total += bp->price * bp->bquan; 126: bp++; 127: } 128: } 129: 130: inshop(){ 131: register roomno = inroom(u.ux,u.uy); 132: 133: /* Did we just leave a shop? */ 134: if(u.uinshop && 135: (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) { 136: u.uinshop = 0; 137: if(shopkeeper) { 138: if(ESHK(shopkeeper)->billct) { 139: pline("Somehow you escaped the shop without paying!"); 140: addupbill(); 141: pline("You stole for a total worth of %ld zorkmids.", 142: total); 143: ESHK(shopkeeper)->robbed += total; 144: setpaid(); 145: if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL) 146: == (rn2(3) == 0)) 147: ESHK(shopkeeper)->following = 1; 148: } 149: shopkeeper = 0; 150: shlevel = 0; 151: } 152: } 153: 154: /* Did we just enter a zoo of some kind? */ 155: if(roomno >= 0) { 156: register int rt = rooms[roomno].rtype; 157: register struct monst *mtmp; 158: if(rt == ZOO) { 159: pline("Welcome to David's treasure zoo!"); 160: } else 161: if(rt == SWAMP) { 162: pline("It looks rather muddy down here."); 163: } else 164: if(rt == MORGUE) { 165: if(midnight()) 166: pline("Go away! Go away!"); 167: else 168: pline("You get an uncanny feeling ..."); 169: } else 170: rt = 0; 171: if(rt != 0) { 172: rooms[roomno].rtype = 0; 173: for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 174: if(rt != ZOO || !rn2(3)) 175: mtmp->msleep = 0; 176: } 177: } 178: 179: /* Did we just enter a shop? */ 180: if(roomno >= 0 && rooms[roomno].rtype >= 8) { 181: if(shlevel != dlevel || !shopkeeper 182: || ESHK(shopkeeper)->shoproom != roomno) 183: findshk(roomno); 184: if(!shopkeeper) { 185: rooms[roomno].rtype = 0; 186: u.uinshop = 0; 187: } else if(inroom(shopkeeper->mx, shopkeeper->my) != roomno) { 188: u.uinshop = 0; 189: } else if(!u.uinshop){ 190: if(!ESHK(shopkeeper)->visitct || 191: strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){ 192: 193: /* He seems to be new here */ 194: ESHK(shopkeeper)->visitct = 0; 195: ESHK(shopkeeper)->following = 0; 196: (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ); 197: NOTANGRY(shopkeeper) = 1; 198: } 199: if(!ESHK(shopkeeper)->following) { 200: boolean box, pick; 201: 202: pline("Hello %s! Welcome%s to %s's %s shop!", 203: plname, 204: ESHK(shopkeeper)->visitct++ ? " again" : "", 205: shkname(shopkeeper), 206: shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] ); 207: box = carrying(ICE_BOX); 208: pick = carrying(PICK_AXE); 209: if(box || pick) { 210: if(dochug(shopkeeper)) { 211: u.uinshop = 0; /* he died moving */ 212: return(0); 213: } 214: pline("Will you please leave your %s outside?", 215: (box && pick) ? "box and pick-axe" : 216: box ? "box" : "pick-axe"); 217: } 218: } 219: u.uinshop = roomno + 1; 220: } 221: } 222: return(u.uinshop); 223: } 224: 225: static 226: findshk(roomno) 227: register roomno; 228: { 229: register struct monst *mtmp; 230: for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 231: if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno 232: && ESHK(mtmp)->shoplevel == dlevel) { 233: shopkeeper = mtmp; 234: bill = &(ESHK(shopkeeper)->bill[0]); 235: shlevel = dlevel; 236: if(ANGRY(shopkeeper) && 237: strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ)) 238: NOTANGRY(shopkeeper) = 1; 239: /* billobjs = 0; -- this is wrong if we save in a shop */ 240: /* (and it is harmless to have too many things in billobjs) */ 241: return; 242: } 243: shopkeeper = 0; 244: shlevel = 0; 245: bill = (struct bill_x *) -1000; /* dump core when referenced */ 246: } 247: 248: static struct bill_x * 249: onbill(obj) register struct obj *obj; { 250: register struct bill_x *bp; 251: if(!shopkeeper) return(0); 252: for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++) 253: if(bp->bo_id == obj->o_id) { 254: if(!obj->unpaid) pline("onbill: paid obj on bill?"); 255: return(bp); 256: } 257: if(obj->unpaid) pline("onbill: unpaid obj not on bill?"); 258: return(0); 259: } 260: 261: /* called with two args on merge */ 262: obfree(obj,merge) register struct obj *obj, *merge; { 263: register struct bill_x *bp = onbill(obj); 264: register struct bill_x *bpm; 265: if(bp) { 266: if(!merge){ 267: bp->useup = 1; 268: obj->unpaid = 0; /* only for doinvbill */ 269: obj->nobj = billobjs; 270: billobjs = obj; 271: return; 272: } 273: bpm = onbill(merge); 274: if(!bpm){ 275: /* this used to be a rename */ 276: impossible("obfree: not on bill??"); 277: return; 278: } else { 279: /* this was a merger */ 280: bpm->bquan += bp->bquan; 281: ESHK(shopkeeper)->billct--; 282: *bp = bill[ESHK(shopkeeper)->billct]; 283: } 284: } 285: free((char *) obj); 286: } 287: 288: static 289: pay(tmp,shkp) 290: long tmp; 291: register struct monst *shkp; 292: { 293: long robbed = ESHK(shkp)->robbed; 294: 295: u.ugold -= tmp; 296: shkp->mgold += tmp; 297: flags.botl = 1; 298: if(robbed) { 299: robbed -= tmp; 300: if(robbed < 0) robbed = 0; 301: ESHK(shkp)->robbed = robbed; 302: } 303: } 304: 305: dopay(){ 306: long ltmp; 307: register struct bill_x *bp; 308: register struct monst *shkp; 309: int pass, tmp; 310: 311: multi = 0; 312: (void) inshop(); 313: for(shkp = fmon; shkp; shkp = shkp->nmon) 314: if(shkp->isshk && dist(shkp->mx,shkp->my) < 3) 315: break; 316: if(!shkp && u.uinshop && 317: inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom) 318: shkp = shopkeeper; 319: 320: if(!shkp) { 321: pline("There is nobody here to receive your payment."); 322: return(0); 323: } 324: ltmp = ESHK(shkp)->robbed; 325: if(shkp != shopkeeper && NOTANGRY(shkp)) { 326: if(!ltmp) { 327: pline("You do not owe %s anything.", monnam(shkp)); 328: } else 329: if(!u.ugold) { 330: pline("You have no money."); 331: } else { 332: long ugold = u.ugold; 333: 334: if(u.ugold > ltmp) { 335: pline("You give %s the %ld gold pieces he asked for.", 336: monnam(shkp), ltmp); 337: pay(ltmp, shkp); 338: } else { 339: pline("You give %s all your gold.", monnam(shkp)); 340: pay(u.ugold, shkp); 341: } 342: if(ugold < ltmp/2) { 343: pline("Unfortunately, he doesn't look satisfied."); 344: } else { 345: ESHK(shkp)->robbed = 0; 346: ESHK(shkp)->following = 0; 347: if(ESHK(shkp)->shoplevel != dlevel) { 348: /* For convenience's sake, let him disappear */ 349: shkp->minvent = 0; /* %% */ 350: shkp->mgold = 0; 351: mondead(shkp); 352: } 353: } 354: } 355: return(1); 356: } 357: 358: if(!ESHK(shkp)->billct){ 359: pline("You do not owe %s anything.", monnam(shkp)); 360: if(!u.ugold){ 361: pline("Moreover, you have no money."); 362: return(1); 363: } 364: if(ESHK(shkp)->robbed){ 365: #define min(a,b) ((a<b)?a:b) 366: pline("But since his shop has been robbed recently,"); 367: pline("you %srepay %s's expenses.", 368: (u.ugold < ESHK(shkp)->robbed) ? "partially " : "", 369: monnam(shkp)); 370: pay(min(u.ugold, ESHK(shkp)->robbed), shkp); 371: ESHK(shkp)->robbed = 0; 372: return(1); 373: } 374: if(ANGRY(shkp)){ 375: pline("But in order to appease %s,", 376: amonnam(shkp, "angry")); 377: if(u.ugold >= 1000){ 378: ltmp = 1000; 379: pline(" you give him 1000 gold pieces."); 380: } else { 381: ltmp = u.ugold; 382: pline(" you give him all your money."); 383: } 384: pay(ltmp, shkp); 385: if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ) 386: || rn2(3)){ 387: pline("%s calms down.", Monnam(shkp)); 388: NOTANGRY(shkp) = 1; 389: } else pline("%s is as angry as ever.", 390: Monnam(shkp)); 391: } 392: return(1); 393: } 394: if(shkp != shopkeeper) { 395: impossible("dopay: not to shopkeeper?"); 396: if(shopkeeper) setpaid(); 397: return(0); 398: } 399: for(pass = 0; pass <= 1; pass++) { 400: tmp = 0; 401: while(tmp < ESHK(shopkeeper)->billct) { 402: bp = &bill[tmp]; 403: if(!pass && !bp->useup) { 404: tmp++; 405: continue; 406: } 407: if(!dopayobj(bp)) return(1); 408: bill[tmp] = bill[--ESHK(shopkeeper)->billct]; 409: } 410: } 411: pline("Thank you for shopping in %s's %s store!", 412: shkname(shopkeeper), 413: shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]); 414: NOTANGRY(shopkeeper) = 1; 415: return(1); 416: } 417: 418: /* return 1 if paid successfully */ 419: /* 0 if not enough money */ 420: /* -1 if object could not be found (but was paid) */ 421: static 422: dopayobj(bp) register struct bill_x *bp; { 423: register struct obj *obj; 424: long ltmp; 425: 426: /* find the object on one of the lists */ 427: obj = bp_to_obj(bp); 428: 429: if(!obj) { 430: impossible("Shopkeeper administration out of order."); 431: setpaid(); /* be nice to the player */ 432: return(0); 433: } 434: 435: if(!obj->unpaid && !bp->useup){ 436: impossible("Paid object on bill??"); 437: return(1); 438: } 439: obj->unpaid = 0; 440: ltmp = bp->price * bp->bquan; 441: if(ANGRY(shopkeeper)) ltmp += ltmp/3; 442: if(u.ugold < ltmp){ 443: pline("You don't have gold enough to pay %s.", 444: doname(obj)); 445: obj->unpaid = 1; 446: return(0); 447: } 448: pay(ltmp, shopkeeper); 449: pline("You bought %s for %ld gold piece%s.", 450: doname(obj), ltmp, plur(ltmp)); 451: if(bp->useup) { 452: register struct obj *otmp = billobjs; 453: if(obj == billobjs) 454: billobjs = obj->nobj; 455: else { 456: while(otmp && otmp->nobj != obj) otmp = otmp->nobj; 457: if(otmp) otmp->nobj = obj->nobj; 458: else pline("Error in shopkeeper administration."); 459: } 460: free((char *) obj); 461: } 462: return(1); 463: } 464: 465: /* routine called after dying (or quitting) with nonempty bill */ 466: paybill(){ 467: if(shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct){ 468: addupbill(); 469: if(total > u.ugold){ 470: shopkeeper->mgold += u.ugold; 471: u.ugold = 0; 472: pline("%s comes and takes all your possessions.", 473: Monnam(shopkeeper)); 474: } else { 475: u.ugold -= total; 476: shopkeeper->mgold += total; 477: pline("%s comes and takes the %ld zorkmids you owed him.", 478: Monnam(shopkeeper), total); 479: } 480: setpaid(); /* in case we create bones */ 481: } 482: } 483: 484: /* find obj on one of the lists */ 485: struct obj * 486: bp_to_obj(bp) 487: register struct bill_x *bp; 488: { 489: register struct obj *obj; 490: register struct monst *mtmp; 491: register unsigned id = bp->bo_id; 492: 493: if(bp->useup) 494: obj = o_on(id, billobjs); 495: else if(!(obj = o_on(id, invent)) && 496: !(obj = o_on(id, fobj)) && 497: !(obj = o_on(id, fcobj))) { 498: for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 499: if(obj = o_on(id, mtmp->minvent)) 500: break; 501: for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon) 502: if(obj = o_on(id, mtmp->minvent)) 503: break; 504: } 505: return(obj); 506: } 507: 508: /* called in hack.c when we pickup an object */ 509: addtobill(obj) register struct obj *obj; { 510: register struct bill_x *bp; 511: if(!inshop() || 512: (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) || 513: (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y) || 514: onbill(obj) /* perhaps we threw it away earlier */ 515: ) return; 516: if(ESHK(shopkeeper)->billct == BILLSZ){ 517: pline("You got that for free!"); 518: return; 519: } 520: bp = &bill[ESHK(shopkeeper)->billct]; 521: bp->bo_id = obj->o_id; 522: bp->bquan = obj->quan; 523: bp->useup = 0; 524: bp->price = getprice(obj); 525: ESHK(shopkeeper)->billct++; 526: obj->unpaid = 1; 527: } 528: 529: splitbill(obj,otmp) register struct obj *obj, *otmp; { 530: /* otmp has been split off from obj */ 531: register struct bill_x *bp; 532: register int tmp; 533: bp = onbill(obj); 534: if(!bp) { 535: impossible("splitbill: not on bill?"); 536: return; 537: } 538: if(bp->bquan < otmp->quan) { 539: impossible("Negative quantity on bill??"); 540: } 541: if(bp->bquan == otmp->quan) { 542: impossible("Zero quantity on bill??"); 543: } 544: bp->bquan -= otmp->quan; 545: 546: /* addtobill(otmp); */ 547: if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0; 548: else { 549: tmp = bp->price; 550: bp = &bill[ESHK(shopkeeper)->billct]; 551: bp->bo_id = otmp->o_id; 552: bp->bquan = otmp->quan; 553: bp->useup = 0; 554: bp->price = tmp; 555: ESHK(shopkeeper)->billct++; 556: } 557: } 558: 559: subfrombill(obj) register struct obj *obj; { 560: long ltmp; 561: register int tmp; 562: register struct obj *otmp; 563: register struct bill_x *bp; 564: if(!inshop() || (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) || 565: (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y)) 566: return; 567: if((bp = onbill(obj)) != 0){ 568: obj->unpaid = 0; 569: if(bp->bquan > obj->quan){ 570: otmp = newobj(0); 571: *otmp = *obj; 572: bp->bo_id = otmp->o_id = flags.ident++; 573: otmp->quan = (bp->bquan -= obj->quan); 574: otmp->owt = 0; /* superfluous */ 575: otmp->onamelth = 0; 576: bp->useup = 1; 577: otmp->nobj = billobjs; 578: billobjs = otmp; 579: return; 580: } 581: ESHK(shopkeeper)->billct--; 582: *bp = bill[ESHK(shopkeeper)->billct]; 583: return; 584: } 585: if(obj->unpaid){ 586: pline("%s didn't notice.", Monnam(shopkeeper)); 587: obj->unpaid = 0; 588: return; /* %% */ 589: } 590: /* he dropped something of his own - probably wants to sell it */ 591: if(shopkeeper->msleep || shopkeeper->mfroz || 592: inroom(shopkeeper->mx,shopkeeper->my) != ESHK(shopkeeper)->shoproom) 593: return; 594: if(ESHK(shopkeeper)->billct == BILLSZ || 595: ((tmp = shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype-8]) && tmp != obj->olet) 596: || index("_0", obj->olet)) { 597: pline("%s seems not interested.", Monnam(shopkeeper)); 598: return; 599: } 600: ltmp = getprice(obj) * obj->quan; 601: if(ANGRY(shopkeeper)) { 602: ltmp /= 3; 603: NOTANGRY(shopkeeper) = 1; 604: } else ltmp /= 2; 605: if(ESHK(shopkeeper)->robbed){ 606: if((ESHK(shopkeeper)->robbed -= ltmp) < 0) 607: ESHK(shopkeeper)->robbed = 0; 608: pline("Thank you for your contribution to restock this recently plundered shop."); 609: return; 610: } 611: if(ltmp > shopkeeper->mgold) 612: ltmp = shopkeeper->mgold; 613: pay(-ltmp, shopkeeper); 614: if(!ltmp) 615: pline("%s gladly accepts %s but cannot pay you at present.", 616: Monnam(shopkeeper), doname(obj)); 617: else 618: pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp, 619: plur(ltmp)); 620: } 621: 622: doinvbill(mode) 623: int mode; /* 0: deliver count 1: paged */ 624: { 625: register struct bill_x *bp; 626: register struct obj *obj; 627: long totused, thisused; 628: char buf[BUFSZ]; 629: 630: if(mode == 0) { 631: register int cnt = 0; 632: 633: if(shopkeeper) 634: for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) 635: if(bp->useup || 636: ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan)) 637: cnt++; 638: return(cnt); 639: } 640: 641: if(!shopkeeper) { 642: impossible("doinvbill: no shopkeeper?"); 643: return(0); 644: } 645: 646: set_pager(0); 647: if(page_line("Unpaid articles already used up:") || page_line("")) 648: goto quit; 649: 650: totused = 0; 651: for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) { 652: obj = bp_to_obj(bp); 653: if(!obj) { 654: impossible("Bad shopkeeper administration."); 655: goto quit; 656: } 657: if(bp->useup || bp->bquan > obj->quan) { 658: register int cnt, oquan, uquan; 659: 660: oquan = obj->quan; 661: /* KLUDGE -- reg overflow: simplify expression: 662: uquan = (bp->useup ? bp->bquan : bp->bquan - oquan); 663: */ 664: uquan = bp->bquan; 665: if(bp->useup) 666: uquan -= oquan; 667: thisused = bp->price * uquan; 668: totused += thisused; 669: obj->quan = uquan; /* cheat doname */ 670: (void) sprintf(buf, "x - %s", doname(obj)); 671: obj->quan = oquan; /* restore value */ 672: for(cnt = 0; buf[cnt]; cnt++); 673: while(cnt < 50) 674: buf[cnt++] = ' '; 675: (void) sprintf(&buf[cnt], " %5ld zorkmids", thisused); 676: if(page_line(buf)) 677: goto quit; 678: } 679: } 680: (void) sprintf(buf, "Total:%50ld zorkmids", totused); 681: if(page_line("") || page_line(buf)) 682: goto quit; 683: set_pager(1); 684: return(0); 685: quit: 686: set_pager(2); 687: return(0); 688: } 689: 690: static 691: getprice(obj) register struct obj *obj; { 692: register int tmp, ac; 693: switch(obj->olet){ 694: case AMULET_SYM: 695: tmp = 10*rnd(500); 696: break; 697: case TOOL_SYM: 698: tmp = 10*rnd((obj->otyp == EXPENSIVE_CAMERA) ? 150 : 30); 699: break; 700: case RING_SYM: 701: tmp = 10*rnd(100); 702: break; 703: case WAND_SYM: 704: tmp = 10*rnd(100); 705: break; 706: case SCROLL_SYM: 707: tmp = 10*rnd(50); 708: #ifdef MAIL 709: if(obj->otyp == SCR_MAIL) 710: tmp = rnd(5); 711: #endif MAIL 712: break; 713: case POTION_SYM: 714: tmp = 10*rnd(50); 715: break; 716: case FOOD_SYM: 717: tmp = 10*rnd(5 + (2000/realhunger())); 718: break; 719: case GEM_SYM: 720: tmp = 10*rnd(20); 721: break; 722: case ARMOR_SYM: 723: ac = ARM_BONUS(obj); 724: if(ac <= -10) /* probably impossible */ 725: ac = -9; 726: tmp = 100 + ac*ac*rnd(10+ac); 727: break; 728: case WEAPON_SYM: 729: if(obj->otyp < BOOMERANG) 730: tmp = 5*rnd(10); 731: else if(obj->otyp == LONG_SWORD || 732: obj->otyp == TWO_HANDED_SWORD) 733: tmp = 10*rnd(150); 734: else tmp = 10*rnd(75); 735: break; 736: case CHAIN_SYM: 737: pline("Strange ..., carrying a chain?"); 738: case BALL_SYM: 739: tmp = 10; 740: break; 741: default: 742: tmp = 10000; 743: } 744: return(tmp); 745: } 746: 747: static 748: realhunger(){ /* not completely foolproof */ 749: register tmp = u.uhunger; 750: register struct obj *otmp = invent; 751: while(otmp){ 752: if(otmp->olet == FOOD_SYM && !otmp->unpaid) 753: tmp += objects[otmp->otyp].nutrition; 754: otmp = otmp->nobj; 755: } 756: return((tmp <= 0) ? 1 : tmp); 757: } 758: 759: shkcatch(obj) 760: register struct obj *obj; 761: { 762: register struct monst *shkp = shopkeeper; 763: 764: if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep && 765: u.dx && u.dy && 766: inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop && 767: shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y && 768: u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) { 769: pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj)); 770: obj->nobj = shkp->minvent; 771: shkp->minvent = obj; 772: return(1); 773: } 774: return(0); 775: } 776: 777: /* 778: * shk_move: return 1: he moved 0: he didnt -1: let m_move do it 779: */ 780: shk_move(shkp) 781: register struct monst *shkp; 782: { 783: register struct monst *mtmp; 784: register struct permonst *mdat = shkp->data; 785: register xchar gx,gy,omx,omy,nx,ny,nix,niy; 786: register schar appr,i; 787: register int udist; 788: int z; 789: schar shkroom,chi,chcnt,cnt; 790: boolean uondoor, satdoor, avoid, badinv; 791: coord poss[9]; 792: int info[9]; 793: struct obj *ib = 0; 794: 795: omx = shkp->mx; 796: omy = shkp->my; 797: 798: if((udist = dist(omx,omy)) < 3) { 799: if(ANGRY(shkp)) { 800: (void) hitu(shkp, d(mdat->damn, mdat->damd)+1); 801: return(0); 802: } 803: if(ESHK(shkp)->following) { 804: if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)){ 805: pline("Hello %s! I was looking for %s.", 806: plname, ESHK(shkp)->customer); 807: ESHK(shkp)->following = 0; 808: return(0); 809: } 810: if(!ESHK(shkp)->robbed) { /* impossible? */ 811: ESHK(shkp)->following = 0; 812: return(0); 813: } 814: if(moves > followmsg+4) { 815: pline("Hello %s! Didn't you forget to pay?", 816: plname); 817: followmsg = moves; 818: } 819: if(udist < 2) 820: return(0); 821: } 822: } 823: 824: shkroom = inroom(omx,omy); 825: appr = 1; 826: gx = ESHK(shkp)->shk.x; 827: gy = ESHK(shkp)->shk.y; 828: satdoor = (gx == omx && gy == omy); 829: if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){ 830: gx = u.ux; 831: gy = u.uy; 832: if(shkroom < 0 || shkroom != inroom(u.ux,u.uy)) 833: if(udist > 4) 834: return(-1); /* leave it to m_move */ 835: } else if(ANGRY(shkp)) { 836: long saveBlind = Blind; 837: Blind = 0; 838: if(shkp->mcansee && !Invis && cansee(omx,omy)) { 839: gx = u.ux; 840: gy = u.uy; 841: } 842: Blind = saveBlind; 843: avoid = FALSE; 844: } else { 845: #define GDIST(x,y) ((x-gx)*(x-gx)+(y-gy)*(y-gy)) 846: if(Invis) 847: avoid = FALSE; 848: else { 849: uondoor = (u.ux == ESHK(shkp)->shd.x && 850: u.uy == ESHK(shkp)->shd.y); 851: if(uondoor) { 852: if(ESHK(shkp)->billct) 853: pline("Hello %s! Will you please pay before leaving?", 854: plname); 855: badinv = (carrying(PICK_AXE) || carrying(ICE_BOX)); 856: if(satdoor && badinv) 857: return(0); 858: avoid = !badinv; 859: } else { 860: avoid = (u.uinshop && dist(gx,gy) > 8); 861: badinv = FALSE; 862: } 863: 864: if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid) 865: && GDIST(omx,omy) < 3){ 866: if(!badinv && !online(omx,omy)) 867: return(0); 868: if(satdoor) 869: appr = gx = gy = 0; 870: } 871: } 872: } 873: if(omx == gx && omy == gy) 874: return(0); 875: if(shkp->mconf) { 876: avoid = FALSE; 877: appr = 0; 878: } 879: nix = omx; 880: niy = omy; 881: cnt = mfndpos(shkp,poss,info,ALLOW_SSM); 882: if(avoid && uondoor) { /* perhaps we cannot avoid him */ 883: for(i=0; i<cnt; i++) 884: if(!(info[i] & NOTONL)) goto notonl_ok; 885: avoid = FALSE; 886: notonl_ok: 887: ; 888: } 889: chi = -1; 890: chcnt = 0; 891: for(i=0; i<cnt; i++){ 892: nx = poss[i].x; 893: ny = poss[i].y; 894: if(levl[nx][ny].typ == ROOM 895: || shkroom != ESHK(shkp)->shoproom 896: || ESHK(shkp)->following) { 897: #ifdef STUPID 898: /* cater for stupid compilers */ 899: register int zz; 900: #endif STUPID 901: if(uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) { 902: nix = nx; niy = ny; chi = i; break; 903: } 904: if(avoid && (info[i] & NOTONL)) 905: continue; 906: if((!appr && !rn2(++chcnt)) || 907: #ifdef STUPID 908: (appr && (zz = GDIST(nix,niy)) && zz > GDIST(nx,ny)) 909: #else 910: (appr && GDIST(nx,ny) < GDIST(nix,niy)) 911: #endif STUPID 912: ) { 913: nix = nx; 914: niy = ny; 915: chi = i; 916: } 917: } 918: } 919: if(nix != omx || niy != omy){ 920: if(info[chi] & ALLOW_M){ 921: mtmp = m_at(nix,niy); 922: if(hitmm(shkp,mtmp) == 1 && rn2(3) && 923: hitmm(mtmp,shkp) == 2) return(2); 924: return(0); 925: } else if(info[chi] & ALLOW_U){ 926: (void) hitu(shkp, d(mdat->damn, mdat->damd)+1); 927: return(0); 928: } 929: shkp->mx = nix; 930: shkp->my = niy; 931: pmon(shkp); 932: if(ib) { 933: freeobj(ib); 934: mpickobj(shkp, ib); 935: } 936: return(1); 937: } 938: return(0); 939: } 940: #endif QUEST 941: 942: online(x,y) { 943: return(x==u.ux || y==u.uy || 944: (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy)); 945: } 946: 947: /* Does this monster follow me downstairs? */ 948: follower(mtmp) 949: register struct monst *mtmp; 950: { 951: return( mtmp->mtame || index("1TVWZi&, ", mtmp->data->mlet) || 952: (mtmp->isshk && ESHK(mtmp)->following) ); 953: } 954: 955: /* He is digging in the shop. */ 956: shopdig(fall) 957: register int fall; 958: { 959: if(!fall) { 960: if(u.utraptype == TT_PIT) 961: pline("\"Be careful, sir, or you might fall through the floor.\""); 962: else 963: pline("\"Please, do not damage the floor here.\""); 964: } else if(dist(shopkeeper->mx, shopkeeper->my) < 3) { 965: register struct obj *obj, *obj2; 966: 967: pline("%s grabs your backpack!", shkname(shopkeeper)); 968: for(obj = invent; obj; obj = obj2) { 969: obj2 = obj->nobj; 970: if(obj->owornmask) continue; 971: freeinv(obj); 972: obj->nobj = shopkeeper->minvent; 973: shopkeeper->minvent = obj; 974: if(obj->unpaid) 975: subfrombill(obj); 976: } 977: } 978: }