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