1/* SCCS Id: @(#)shk.c 3.4 2003/12/04 */ 2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5#include "hack.h" 6#include "eshk.h" 7 8/*#define DEBUG*/ 9 10#define PAY_SOME 2 11#define PAY_BUY 1 12#define PAY_CANT 0 /* too poor */ 13#define PAY_SKIP (-1) 14#define PAY_BROKE (-2) 15 16#ifdef KOPS 17STATIC_DCL void FDECL(makekops, (coord *)); 18STATIC_DCL void FDECL(call_kops, (struct monst *,BOOLEAN_P)); 19# ifdef OVLB 20STATIC_DCL void FDECL(kops_gone, (BOOLEAN_P)); 21# endif /* OVLB */ 22#endif /* KOPS */ 23 24#define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE) 25 26extern const struct shclass shtypes[]; /* defined in shknam.c */ 27extern struct obj *thrownobj; /* defined in dothrow.c */ 28 29STATIC_VAR NEARDATA long int followmsg; /* last time of follow message */ 30 31STATIC_DCL void FDECL(setpaid, (struct monst *)); 32STATIC_DCL long FDECL(addupbill, (struct monst *)); 33STATIC_DCL void FDECL(pacify_shk, (struct monst *)); 34STATIC_DCL struct bill_x *FDECL(onbill, (struct obj *, struct monst *, BOOLEAN_P)); 35STATIC_DCL struct monst *FDECL(next_shkp, (struct monst *, BOOLEAN_P)); 36STATIC_DCL long FDECL(shop_debt, (struct eshk *)); 37STATIC_DCL char *FDECL(shk_owns, (char *,struct obj *)); 38STATIC_DCL char *FDECL(mon_owns, (char *,struct obj *)); 39STATIC_DCL void FDECL(clear_unpaid,(struct obj *)); 40STATIC_DCL long FDECL(check_credit, (long, struct monst *)); 41STATIC_DCL void FDECL(pay, (long, struct monst *)); 42STATIC_DCL long FDECL(get_cost, (struct obj *, struct monst *)); 43STATIC_DCL long FDECL(set_cost, (struct obj *, struct monst *)); 44STATIC_DCL const char *FDECL(shk_embellish, (struct obj *, long)); 45STATIC_DCL long FDECL(cost_per_charge, (struct monst *,struct obj *,BOOLEAN_P)); 46STATIC_DCL long FDECL(cheapest_item, (struct monst *)); 47STATIC_DCL int FDECL(dopayobj, (struct monst *, struct bill_x *, 48 struct obj **, int, BOOLEAN_P)); 49STATIC_DCL long FDECL(stolen_container, (struct obj *, struct monst *, long, 50 BOOLEAN_P)); 51STATIC_DCL long FDECL(getprice, (struct obj *,BOOLEAN_P)); 52STATIC_DCL void FDECL(shk_names_obj, 53 (struct monst *,struct obj *,const char *,long,const char *)); 54STATIC_DCL struct obj *FDECL(bp_to_obj, (struct bill_x *)); 55STATIC_DCL boolean FDECL(inherits, (struct monst *,int,int)); 56STATIC_DCL void FDECL(set_repo_loc, (struct eshk *)); 57STATIC_DCL boolean NDECL(angry_shk_exists); 58STATIC_DCL void FDECL(rile_shk, (struct monst *)); 59STATIC_DCL void FDECL(rouse_shk, (struct monst *,BOOLEAN_P)); 60STATIC_DCL void FDECL(remove_damage, (struct monst *, BOOLEAN_P)); 61STATIC_DCL void FDECL(sub_one_frombill, (struct obj *, struct monst *)); 62STATIC_DCL void FDECL(add_one_tobill, (struct obj *, BOOLEAN_P)); 63STATIC_DCL void FDECL(dropped_container, (struct obj *, struct monst *, 64 BOOLEAN_P)); 65STATIC_DCL void FDECL(add_to_billobjs, (struct obj *)); 66STATIC_DCL void FDECL(bill_box_content, (struct obj *, BOOLEAN_P, BOOLEAN_P, 67 struct monst *)); 68#ifdef OVL1 69static boolean FDECL(rob_shop, (struct monst *)); 70#endif 71 72#ifdef OVLB 73/* 74 invariants: obj->unpaid iff onbill(obj) [unless bp->useup] 75 obj->quan <= bp->bquan 76 */ 77 78 79#ifdef GOLDOBJ 80/* 81 Transfer money from inventory to monster when paying 82 shopkeepers, priests, oracle, succubus, & other demons. 83 Simple with only gold coins. 84 This routine will handle money changing when multiple 85 coin types is implemented, only appropriate 86 monsters will pay change. (Peaceful shopkeepers, priests 87 & the oracle try to maintain goodwill while selling 88 their wares or services. Angry monsters and all demons 89 will keep anything they get their hands on. 90 Returns the amount actually paid, so we can know 91 if the monster kept the change. 92 */ 93long 94money2mon(mon, amount) 95struct monst *mon; 96long amount; 97{ 98 struct obj *ygold = findgold(invent); 99 100 if (amount <= 0) { 101 impossible("%s payment in money2mon!", amount ? "negative" : "zero"); 102 return 0L; 103 } 104 if (!ygold || ygold->quan < amount) { 105 impossible("Paying without %s money?", ygold ? "enough" : ""); 106 return 0L; 107 } 108 109 if (ygold->quan > amount) 110 ygold = splitobj(ygold, amount); 111 else if (ygold->owornmask) 112 remove_worn_item(ygold, FALSE); /* quiver */ 113 freeinv(ygold); 114 add_to_minv(mon, ygold); 115 flags.botl = 1; 116 return amount; 117} 118 119 120/* 121 Transfer money from monster to inventory. 122 Used when the shopkeeper pay for items, and when 123 the priest gives you money for an ale. 124 */ 125void 126money2u(mon, amount) 127struct monst *mon; 128long amount; 129{ 130 struct obj *mongold = findgold(mon->minvent); 131 132 if (amount <= 0) { 133 impossible("%s payment in money2u!", amount ? "negative" : "zero"); 134 return; 135 } 136 if (!mongold || mongold->quan < amount) { 137 impossible("%s paying without %s money?", a_monnam(mon), 138 mongold ? "enough" : ""); 139 return; 140 } 141 142 if (mongold->quan > amount) mongold = splitobj(mongold, amount); 143 obj_extract_self(mongold); 144 145 if (!merge_choice(invent, mongold) && inv_cnt() >= 52) { 146 You("have no room for the money!"); 147 dropy(mongold); 148 } else { 149 addinv(mongold); 150 flags.botl = 1; 151 } 152} 153 154#endif /* GOLDOBJ */ 155 156STATIC_OVL struct monst * 157next_shkp(shkp, withbill) 158register struct monst *shkp; 159register boolean withbill; 160{ 161 for (; shkp; shkp = shkp->nmon) { 162 if (DEADMONSTER(shkp)) continue; 163 if (shkp->isshk && (ESHK(shkp)->billct || !withbill)) break; 164 } 165 166 if (shkp) { 167 if (NOTANGRY(shkp)) { 168 if (ESHK(shkp)->surcharge) pacify_shk(shkp); 169 } else { 170 if (!ESHK(shkp)->surcharge) rile_shk(shkp); 171 } 172 } 173 return(shkp); 174} 175 176char * 177shkname(mtmp) /* called in do_name.c */ 178register struct monst *mtmp; 179{ 180 return(ESHK(mtmp)->shknam); 181} 182 183void 184shkgone(mtmp) /* called in mon.c */ 185struct monst *mtmp; 186{ 187 struct eshk *eshk = ESHK(mtmp); 188 struct mkroom *sroom = &rooms[eshk->shoproom - ROOMOFFSET]; 189 struct obj *otmp; 190 char *p; 191 int sx, sy; 192 193 /* [BUG: some of this should be done on the shop level */ 194 /* even when the shk dies on a different level.] */ 195 if (on_level(&eshk->shoplevel, &u.uz)) { 196 remove_damage(mtmp, TRUE); 197 sroom->resident = (struct monst *)0; 198 if (!search_special(ANY_SHOP)) 199 level.flags.has_shop = 0; 200 201 /* items on shop floor revert to ordinary objects */ 202 for (sx = sroom->lx; sx <= sroom->hx; sx++) 203 for (sy = sroom->ly; sy <= sroom->hy; sy++) 204 for (otmp = level.objects[sx][sy]; otmp; otmp = otmp->nexthere) 205 otmp->no_charge = 0; 206 207 /* Make sure bill is set only when the 208 dead shk is the resident shk. */ 209 if ((p = index(u.ushops, eshk->shoproom)) != 0) { 210 setpaid(mtmp); 211 eshk->bill_p = (struct bill_x *)0; 212 /* remove eshk->shoproom from u.ushops */ 213 do { *p = *(p + 1); } while (*++p); 214 } 215 } 216} 217 218void 219set_residency(shkp, zero_out) 220register struct monst *shkp; 221register boolean zero_out; 222{ 223 if (on_level(&(ESHK(shkp)->shoplevel), &u.uz)) 224 rooms[ESHK(shkp)->shoproom - ROOMOFFSET].resident = 225 (zero_out)? (struct monst *)0 : shkp; 226} 227 228void 229replshk(mtmp,mtmp2) 230register struct monst *mtmp, *mtmp2; 231{ 232 rooms[ESHK(mtmp2)->shoproom - ROOMOFFSET].resident = mtmp2; 233 if (inhishop(mtmp) && *u.ushops == ESHK(mtmp)->shoproom) { 234 ESHK(mtmp2)->bill_p = &(ESHK(mtmp2)->bill[0]); 235 } 236} 237 238/* do shopkeeper specific structure munging -dlc */ 239void 240restshk(shkp, ghostly) 241struct monst *shkp; 242boolean ghostly; 243{ 244 if (u.uz.dlevel) { 245 struct eshk *eshkp = ESHK(shkp); 246 247 if (eshkp->bill_p != (struct bill_x *) -1000) 248 eshkp->bill_p = &eshkp->bill[0]; 249 /* shoplevel can change as dungeons move around */ 250 /* savebones guarantees that non-homed shk's will be gone */ 251 if (ghostly) { 252 assign_level(&eshkp->shoplevel, &u.uz); 253 if (ANGRY(shkp) && strncmpi(eshkp->customer, plname, PL_NSIZ)) 254 pacify_shk(shkp); 255 } 256 } 257} 258 259#endif /* OVLB */ 260#ifdef OVL3 261 262/* Clear the unpaid bit on all of the objects in the list. */ 263STATIC_OVL void 264clear_unpaid(list) 265register struct obj *list; 266{ 267 while (list) { 268 if (Has_contents(list)) clear_unpaid(list->cobj); 269 list->unpaid = 0; 270 list = list->nobj; 271 } 272} 273#endif /*OVL3*/ 274#ifdef OVLB 275 276/* either you paid or left the shop or the shopkeeper died */ 277STATIC_OVL void 278setpaid(shkp) 279register struct monst *shkp; 280{ 281 register struct obj *obj; 282 register struct monst *mtmp; 283 284 /* FIXME: object handling should be limited to 285 items which are on this particular shk's bill */ 286 287 clear_unpaid(invent); 288 clear_unpaid(fobj); 289 clear_unpaid(level.buriedobjlist); 290 if (thrownobj) thrownobj->unpaid = 0; 291 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 292 clear_unpaid(mtmp->minvent); 293 for(mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) 294 clear_unpaid(mtmp->minvent); 295 296 while ((obj = billobjs) != 0) { 297 obj_extract_self(obj); 298 dealloc_obj(obj); 299 } 300 if(shkp) { 301 ESHK(shkp)->billct = 0; 302 ESHK(shkp)->credit = 0L; 303 ESHK(shkp)->debit = 0L; 304 ESHK(shkp)->loan = 0L; 305 } 306} 307 308STATIC_OVL long 309addupbill(shkp) 310register struct monst *shkp; 311{ 312 register int ct = ESHK(shkp)->billct; 313 register struct bill_x *bp = ESHK(shkp)->bill_p; 314 register long total = 0L; 315 316 while(ct--){ 317 total += bp->price * bp->bquan; 318 bp++; 319 } 320 return(total); 321} 322 323#endif /* OVLB */ 324#ifdef OVL1 325 326#ifdef KOPS 327STATIC_OVL void 328call_kops(shkp, nearshop) 329register struct monst *shkp; 330register boolean nearshop; 331{ 332 /* Keystone Kops srt@ucla */ 333 register boolean nokops; 334 335 if(!shkp) return; 336 337 if (flags.soundok) 338 pline("An alarm sounds!"); 339 340 nokops = ((mvitals[PM_KEYSTONE_KOP].mvflags & G_GONE) && 341 (mvitals[PM_KOP_SERGEANT].mvflags & G_GONE) && 342 (mvitals[PM_KOP_LIEUTENANT].mvflags & G_GONE) && 343 (mvitals[PM_KOP_KAPTAIN].mvflags & G_GONE)); 344 345 if(!angry_guards(!flags.soundok) && nokops) { 346 if(flags.verbose && flags.soundok) 347 pline("But no one seems to respond to it."); 348 return; 349 } 350 351 if(nokops) return; 352 353 { 354 coord mm; 355 356 if (nearshop) { 357 /* Create swarm around you, if you merely "stepped out" */ 358 if (flags.verbose) 359 pline_The("Keystone Kops appear!"); 360 mm.x = u.ux; 361 mm.y = u.uy; 362 makekops(&mm); 363 return; 364 } 365 if (flags.verbose) 366 pline_The("Keystone Kops are after you!"); 367 /* Create swarm near down staircase (hinders return to level) */ 368 mm.x = xdnstair; 369 mm.y = ydnstair; 370 makekops(&mm); 371 /* Create swarm near shopkeeper (hinders return to shop) */ 372 mm.x = shkp->mx; 373 mm.y = shkp->my; 374 makekops(&mm); 375 } 376} 377#endif /* KOPS */ 378 379/* x,y is strictly inside shop */ 380char 381inside_shop(x, y) 382register xchar x, y; 383{ 384 register char rno; 385 386 rno = levl[x][y].roomno; 387 if ((rno < ROOMOFFSET) || levl[x][y].edge || !IS_SHOP(rno-ROOMOFFSET)) 388 return(NO_ROOM); 389 else 390 return(rno); 391} 392 393void 394u_left_shop(leavestring, newlev) 395char *leavestring; 396boolean newlev; 397{ 398 struct monst *shkp; 399 struct eshk *eshkp; 400 401 /* 402 * IF player 403 * ((didn't leave outright) AND 404 * ((he is now strictly-inside the shop) OR 405 * (he wasn't strictly-inside last turn anyway))) 406 * THEN (there's nothing to do, so just return) 407 */ 408 if(!*leavestring && 409 (!levl[u.ux][u.uy].edge || levl[u.ux0][u.uy0].edge)) 410 return; 411 412 shkp = shop_keeper(*u.ushops0); 413 if (!shkp || !inhishop(shkp)) 414 return; /* shk died, teleported, changed levels... */ 415 416 eshkp = ESHK(shkp); 417 if (!eshkp->billct && !eshkp->debit) /* bill is settled */ 418 return; 419 420 if (!*leavestring && shkp->mcanmove && !shkp->msleeping) { 421 /* 422 * Player just stepped onto shop-boundary (known from above logic). 423 * Try to intimidate him into paying his bill 424 */ 425 verbalize(NOTANGRY(shkp) ? 426 "%s! Please pay before leaving." : 427 "%s! Don't you leave without paying!", 428 plname); 429 return; 430 } 431 432 if (rob_shop(shkp)) { 433#ifdef KOPS 434 call_kops(shkp, (!newlev && levl[u.ux0][u.uy0].edge)); 435#else 436 (void) angry_guards(FALSE); 437#endif 438 } 439} 440 441/* robbery from outside the shop via telekinesis or grappling hook */ 442void 443remote_burglary(x, y) 444xchar x, y; 445{ 446 struct monst *shkp; 447 struct eshk *eshkp; 448 449 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)); 450 if (!shkp || !inhishop(shkp)) 451 return; /* shk died, teleported, changed levels... */ 452 453 eshkp = ESHK(shkp); 454 if (!eshkp->billct && !eshkp->debit) /* bill is settled */ 455 return; 456 457 if (rob_shop(shkp)) { 458#ifdef KOPS 459 /*[might want to set 2nd arg based on distance from shop doorway]*/ 460 call_kops(shkp, FALSE); 461#else 462 (void) angry_guards(FALSE); 463#endif 464 } 465} 466 467/* shop merchandise has been taken; pay for it with any credit available; 468 return false if the debt is fully covered by credit, true otherwise */ 469static boolean 470rob_shop(shkp) 471struct monst *shkp; 472{ 473 struct eshk *eshkp; 474 long total; 475 476 eshkp = ESHK(shkp); 477 rouse_shk(shkp, TRUE); 478 total = (addupbill(shkp) + eshkp->debit); 479 if (eshkp->credit >= total) { 480 Your("credit of %ld %s is used to cover your shopping bill.", 481 eshkp->credit, currency(eshkp->credit)); 482 total = 0L; /* credit gets cleared by setpaid() */ 483 } else { 484 You("escaped the shop without paying!"); 485 total -= eshkp->credit; 486 } 487 setpaid(shkp); 488 if (!total) return FALSE; 489 490 /* by this point, we know an actual robbery has taken place */ 491 eshkp->robbed += total; 492 You("stole %ld %s worth of merchandise.", 493 total, currency(total)); 494 if (!Role_if(PM_ROGUE)) /* stealing is unlawful */ 495 adjalign(-sgn(u.ualign.type)); 496 497 hot_pursuit(shkp); 498 return TRUE; 499} 500 501void 502u_entered_shop(enterstring) 503register char *enterstring; 504{ 505 506 register int rt; 507 register struct monst *shkp; 508 register struct eshk *eshkp; 509 static const char no_shk[] = "This shop appears to be deserted."; 510 static char empty_shops[5]; 511 512 if(!*enterstring) 513 return; 514 515 if(!(shkp = shop_keeper(*enterstring))) { 516 if (!index(empty_shops, *enterstring) && 517 in_rooms(u.ux, u.uy, SHOPBASE) != 518 in_rooms(u.ux0, u.uy0, SHOPBASE)) 519 pline(no_shk); 520 Strcpy(empty_shops, u.ushops); 521 u.ushops[0] = '\0'; 522 return; 523 } 524 525 eshkp = ESHK(shkp); 526 527 if (!inhishop(shkp)) { 528 /* dump core when referenced */ 529 eshkp->bill_p = (struct bill_x *) -1000; 530 if (!index(empty_shops, *enterstring)) 531 pline(no_shk); 532 Strcpy(empty_shops, u.ushops); 533 u.ushops[0] = '\0'; 534 return; 535 } 536 537 eshkp->bill_p = &(eshkp->bill[0]); 538 539 if ((!eshkp->visitct || *eshkp->customer) && 540 strncmpi(eshkp->customer, plname, PL_NSIZ)) { 541 /* You seem to be new here */ 542 eshkp->visitct = 0; 543 eshkp->following = 0; 544 (void) strncpy(eshkp->customer,plname,PL_NSIZ); 545 pacify_shk(shkp); 546 } 547 548 if (shkp->msleeping || !shkp->mcanmove || eshkp->following) 549 return; /* no dialog */ 550 551 if (Invis) { 552 pline("%s senses your presence.", shkname(shkp)); 553 verbalize("Invisible customers are not welcome!"); 554 return; 555 } 556 557 rt = rooms[*enterstring - ROOMOFFSET].rtype; 558 559 if (ANGRY(shkp)) { 560 verbalize("So, %s, you dare return to %s %s?!", 561 plname, 562 s_suffix(shkname(shkp)), 563 shtypes[rt - SHOPBASE].name); 564 } else if (eshkp->robbed) { 565 pline("%s mutters imprecations against shoplifters.", shkname(shkp)); 566 } else { 567 verbalize("%s, %s! Welcome%s to %s %s!", 568 Hello(shkp), plname, 569 eshkp->visitct++ ? " again" : "", 570 s_suffix(shkname(shkp)), 571 shtypes[rt - SHOPBASE].name); 572 } 573 /* can't do anything about blocking if teleported in */ 574 if (!inside_shop(u.ux, u.uy)) { 575 boolean should_block; 576 int cnt; 577 const char *tool; 578 struct obj *pick = carrying(PICK_AXE), 579 *mattock = carrying(DWARVISH_MATTOCK); 580 581 if (pick || mattock) { 582 cnt = 1; /* so far */ 583 if (pick && mattock) { /* carrying both types */ 584 tool = "digging tool"; 585 cnt = 2; /* `more than 1' is all that matters */ 586 } else if (pick) { 587 tool = "pick-axe"; 588 /* hack: `pick' already points somewhere into inventory */ 589 while ((pick = pick->nobj) != 0) 590 if (pick->otyp == PICK_AXE) ++cnt; 591 } else { /* assert(mattock != 0) */ 592 tool = "mattock"; 593 while ((mattock = mattock->nobj) != 0) 594 if (mattock->otyp == DWARVISH_MATTOCK) ++cnt; 595 /* [ALI] Shopkeeper identifies mattock(s) */ 596 if (!Blind) makeknown(DWARVISH_MATTOCK); 597 } 598 verbalize(NOTANGRY(shkp) ? 599 "Will you please leave your %s%s outside?" : 600 "Leave the %s%s outside.", 601 tool, plur(cnt)); 602 should_block = TRUE; 603#ifdef STEED 604 } else if (u.usteed) { 605 verbalize(NOTANGRY(shkp) ? 606 "Will you please leave %s outside?" : 607 "Leave %s outside.", y_monnam(u.usteed)); 608 should_block = TRUE; 609#endif 610 } else { 611 should_block = (Fast && (sobj_at(PICK_AXE, u.ux, u.uy) || 612 sobj_at(DWARVISH_MATTOCK, u.ux, u.uy))); 613 } 614 if (should_block) (void) dochug(shkp); /* shk gets extra move */ 615 } 616 return; 617} 618 619/* 620 Decide whether two unpaid items are mergable; caller is responsible for 621 making sure they're unpaid and the same type of object; we check the price 622 quoted by the shopkeeper and also that they both belong to the same shk. 623 */ 624boolean 625same_price(obj1, obj2) 626struct obj *obj1, *obj2; 627{ 628 register struct monst *shkp1, *shkp2; 629 register struct bill_x *bp1 = 0, *bp2 = 0; 630 register boolean are_mergable = FALSE; 631 632 /* look up the first object by finding shk whose bill it's on */ 633 for (shkp1 = next_shkp(fmon, TRUE); shkp1; 634 shkp1 = next_shkp(shkp1->nmon, TRUE)) 635 if ((bp1 = onbill(obj1, shkp1, TRUE)) != 0) break; 636 /* second object is probably owned by same shk; if not, look harder */ 637 if (shkp1 && (bp2 = onbill(obj2, shkp1, TRUE)) != 0) { 638 shkp2 = shkp1; 639 } else { 640 for (shkp2 = next_shkp(fmon, TRUE); shkp2; 641 shkp2 = next_shkp(shkp2->nmon, TRUE)) 642 if ((bp2 = onbill(obj2, shkp2, TRUE)) != 0) break; 643 } 644 645 if (!bp1 || !bp2) impossible("same_price: object wasn't on any bill!"); 646 else are_mergable = (shkp1 == shkp2 && bp1->price == bp2->price); 647 return are_mergable; 648} 649 650/* 651 * Figure out how much is owed to a given shopkeeper. 652 * At present, we ignore any amount robbed from the shop, to avoid 653 * turning the `$' command into a way to discover that the current 654 * level is bones data which has a shk on the warpath. 655 */ 656STATIC_OVL long 657shop_debt(eshkp) 658struct eshk *eshkp; 659{ 660 struct bill_x *bp; 661 int ct; 662 long debt = eshkp->debit; 663 664 for (bp = eshkp->bill_p, ct = eshkp->billct; ct > 0; bp++, ct--) 665 debt += bp->price * bp->bquan; 666 return debt; 667} 668 669/* called in response to the `$' command */ 670void 671shopper_financial_report() 672{ 673 struct monst *shkp, *this_shkp = shop_keeper(inside_shop(u.ux, u.uy)); 674 struct eshk *eshkp; 675 long amt; 676 int pass; 677 678 if (this_shkp && 679 !(ESHK(this_shkp)->credit || shop_debt(ESHK(this_shkp)))) { 680 You("have no credit or debt in here."); 681 this_shkp = 0; /* skip first pass */ 682 } 683 684 /* pass 0: report for the shop we're currently in, if any; 685 pass 1: report for all other shops on this level. */ 686 for (pass = this_shkp ? 0 : 1; pass <= 1; pass++) 687 for (shkp = next_shkp(fmon, FALSE); 688 shkp; shkp = next_shkp(shkp->nmon, FALSE)) { 689 if ((shkp != this_shkp) ^ pass) continue; 690 eshkp = ESHK(shkp); 691 if ((amt = eshkp->credit) != 0) 692 You("have %ld %s credit at %s %s.", 693 amt, currency(amt), s_suffix(shkname(shkp)), 694 shtypes[eshkp->shoptype - SHOPBASE].name); 695 else if (shkp == this_shkp) 696 You("have no credit in here."); 697 if ((amt = shop_debt(eshkp)) != 0) 698 You("owe %s %ld %s.", 699 shkname(shkp), amt, currency(amt)); 700 else if (shkp == this_shkp) 701 You("don't owe any money here."); 702 } 703} 704 705#endif /* OVL1 */ 706#ifdef OVLB 707 708int 709inhishop(mtmp) 710register struct monst *mtmp; 711{ 712 return(index(in_rooms(mtmp->mx, mtmp->my, SHOPBASE), 713 ESHK(mtmp)->shoproom) && 714 on_level(&(ESHK(mtmp)->shoplevel), &u.uz)); 715} 716 717struct monst * 718shop_keeper(rmno) 719register char rmno; 720{ 721 struct monst *shkp = rmno >= ROOMOFFSET ? 722 rooms[rmno - ROOMOFFSET].resident : 0; 723 724 if (shkp) { 725 if (NOTANGRY(shkp)) { 726 if (ESHK(shkp)->surcharge) pacify_shk(shkp); 727 } else { 728 if (!ESHK(shkp)->surcharge) rile_shk(shkp); 729 } 730 } 731 return shkp; 732} 733 734boolean 735tended_shop(sroom) 736register struct mkroom *sroom; 737{ 738 register struct monst *mtmp = sroom->resident; 739 740 if (!mtmp) 741 return(FALSE); 742 else 743 return((boolean)(inhishop(mtmp))); 744} 745 746STATIC_OVL struct bill_x * 747onbill(obj, shkp, silent) 748register struct obj *obj; 749register struct monst *shkp; 750register boolean silent; 751{ 752 if (shkp) { 753 register struct bill_x *bp = ESHK(shkp)->bill_p; 754 register int ct = ESHK(shkp)->billct; 755 756 while (--ct >= 0) 757 if (bp->bo_id == obj->o_id) { 758 if (!obj->unpaid) pline("onbill: paid obj on bill?"); 759 return bp; 760 } else bp++; 761 } 762 if(obj->unpaid & !silent) pline("onbill: unpaid obj not on bill?"); 763 return (struct bill_x *)0; 764} 765 766/* Delete the contents of the given object. */ 767void 768delete_contents(obj) 769register struct obj *obj; 770{ 771 register struct obj *curr; 772 773 while ((curr = obj->cobj) != 0) { 774 obj_extract_self(curr); 775 obfree(curr, (struct obj *)0); 776 } 777} 778 779/* called with two args on merge */ 780void 781obfree(obj, merge) 782register struct obj *obj, *merge; 783{ 784 register struct bill_x *bp; 785 register struct bill_x *bpm; 786 register struct monst *shkp; 787 788 if (obj->otyp == LEASH && obj->leashmon) o_unleash(obj); 789 if (obj->oclass == FOOD_CLASS) food_disappears(obj); 790 if (obj->oclass == SPBOOK_CLASS) book_disappears(obj); 791 if (Has_contents(obj)) delete_contents(obj); 792 793 shkp = 0; 794 if (obj->unpaid) { 795 /* look for a shopkeeper who owns this object */ 796 for (shkp = next_shkp(fmon, TRUE); shkp; 797 shkp = next_shkp(shkp->nmon, TRUE)) 798 if (onbill(obj, shkp, TRUE)) break; 799 } 800 /* sanity check, more or less */ 801 if (!shkp) shkp = shop_keeper(*u.ushops); 802 /* 803 * Note: `shkp = shop_keeper(*u.ushops)' used to be 804 * unconditional. But obfree() is used all over 805 * the place, so making its behavior be dependent 806 * upon player location doesn't make much sense. 807 */ 808 809 if ((bp = onbill(obj, shkp, FALSE)) != 0) { 810 if(!merge){ 811 bp->useup = 1; 812 obj->unpaid = 0; /* only for doinvbill */ 813 add_to_billobjs(obj); 814 return; 815 } 816 bpm = onbill(merge, shkp, FALSE); 817 if(!bpm){ 818 /* this used to be a rename */ 819 impossible("obfree: not on bill??"); 820 return; 821 } else { 822 /* this was a merger */ 823 bpm->bquan += bp->bquan; 824 ESHK(shkp)->billct--; 825#ifdef DUMB 826 { 827 /* DRS/NS 2.2.6 messes up -- Peter Kendell */ 828 int indx = ESHK(shkp)->billct; 829 *bp = ESHK(shkp)->bill_p[indx]; 830 } 831#else 832 *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct]; 833#endif 834 } 835 } 836 dealloc_obj(obj); 837} 838#endif /* OVLB */ 839#ifdef OVL3 840 841STATIC_OVL long 842check_credit(tmp, shkp) 843long tmp; 844register struct monst *shkp; 845{ 846 long credit = ESHK(shkp)->credit; 847 848 if(credit == 0L) return(tmp); 849 if(credit >= tmp) { 850 pline_The("price is deducted from your credit."); 851 ESHK(shkp)->credit -=tmp; 852 tmp = 0L; 853 } else { 854 pline_The("price is partially covered by your credit."); 855 ESHK(shkp)->credit = 0L; 856 tmp -= credit; 857 } 858 return(tmp); 859} 860 861STATIC_OVL void 862pay(tmp,shkp) 863long tmp; 864register struct monst *shkp; 865{ 866 long robbed = ESHK(shkp)->robbed; 867 long balance = ((tmp <= 0L) ? tmp : check_credit(tmp, shkp)); 868 869#ifndef GOLDOBJ 870 u.ugold -= balance; 871 shkp->mgold += balance; 872#else 873 if (balance > 0) money2mon(shkp, balance); 874 else if (balance < 0) money2u(shkp, -balance); 875#endif 876 flags.botl = 1; 877 if(robbed) { 878 robbed -= tmp; 879 if(robbed < 0) robbed = 0L; 880 ESHK(shkp)->robbed = robbed; 881 } 882} 883#endif /*OVL3*/ 884#ifdef OVLB 885 886/* return shkp to home position */ 887void 888home_shk(shkp, killkops) 889register struct monst *shkp; 890register boolean killkops; 891{ 892 register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y; 893 894 (void) mnearto(shkp, x, y, TRUE); 895 level.flags.has_shop = 1; 896 if (killkops) { 897#ifdef KOPS 898 kops_gone(TRUE); 899#else 900 You_feel("vaguely apprehensive."); 901#endif 902 pacify_guards(); 903 } 904 after_shk_move(shkp); 905} 906 907STATIC_OVL boolean 908angry_shk_exists() 909{ 910 register struct monst *shkp; 911 912 for (shkp = next_shkp(fmon, FALSE); 913 shkp; shkp = next_shkp(shkp->nmon, FALSE)) 914 if (ANGRY(shkp)) return(TRUE); 915 return(FALSE); 916} 917 918/* remove previously applied surcharge from all billed items */ 919STATIC_OVL void 920pacify_shk(shkp) 921register struct monst *shkp; 922{ 923 NOTANGRY(shkp) = TRUE; /* make peaceful */ 924 if (ESHK(shkp)->surcharge) { 925 register struct bill_x *bp = ESHK(shkp)->bill_p; 926 register int ct = ESHK(shkp)->billct; 927 928 ESHK(shkp)->surcharge = FALSE; 929 while (ct-- > 0) { 930 register long reduction = (bp->price + 3L) / 4L; 931 bp->price -= reduction; /* undo 33% increase */ 932 bp++; 933 } 934 } 935} 936 937/* add aggravation surcharge to all billed items */ 938STATIC_OVL void 939rile_shk(shkp) 940register struct monst *shkp; 941{ 942 NOTANGRY(shkp) = FALSE; /* make angry */ 943 if (!ESHK(shkp)->surcharge) { 944 register struct bill_x *bp = ESHK(shkp)->bill_p; 945 register int ct = ESHK(shkp)->billct; 946 947 ESHK(shkp)->surcharge = TRUE; 948 while (ct-- > 0) { 949 register long surcharge = (bp->price + 2L) / 3L; 950 bp->price += surcharge; 951 bp++; 952 } 953 } 954} 955 956/* wakeup and/or unparalyze shopkeeper */ 957STATIC_OVL void 958rouse_shk(shkp, verbosely) 959struct monst *shkp; 960boolean verbosely; 961{ 962 if (!shkp->mcanmove || shkp->msleeping) { 963 /* greed induced recovery... */ 964 if (verbosely && canspotmon(shkp)) 965 pline("%s %s.", Monnam(shkp), 966 shkp->msleeping ? "wakes up" : "can move again"); 967 shkp->msleeping = 0; 968 shkp->mfrozen = 0; 969 shkp->mcanmove = 1; 970 } 971} 972 973void 974make_happy_shk(shkp, silentkops) 975register struct monst *shkp; 976register boolean silentkops; 977{ 978 boolean wasmad = ANGRY(shkp); 979 struct eshk *eshkp = ESHK(shkp); 980 981 pacify_shk(shkp); 982 eshkp->following = 0; 983 eshkp->robbed = 0L; 984 if (!Role_if(PM_ROGUE)) 985 adjalign(sgn(u.ualign.type)); 986 if(!inhishop(shkp)) { 987 char shk_nam[BUFSZ]; 988 boolean vanished = canseemon(shkp); 989 990 Strcpy(shk_nam, mon_nam(shkp)); 991 if (on_level(&eshkp->shoplevel, &u.uz)) { 992 home_shk(shkp, FALSE); 993 /* didn't disappear if shk can still be seen */ 994 if (canseemon(shkp)) vanished = FALSE; 995 } else { 996 /* if sensed, does disappear regardless whether seen */ 997 if (sensemon(shkp)) vanished = TRUE; 998 /* can't act as porter for the Amulet, even if shk 999 happens to be going farther down rather than up */ 1000 mdrop_special_objs(shkp); 1001 /* arrive near shop's door */ 1002 migrate_to_level(shkp, ledger_no(&eshkp->shoplevel), 1003 MIGR_APPROX_XY, &eshkp->shd); 1004 } 1005 if (vanished) 1006 pline("Satisfied, %s suddenly disappears!", shk_nam); 1007 } else if(wasmad) 1008 pline("%s calms down.", Monnam(shkp)); 1009 1010 if(!angry_shk_exists()) { 1011#ifdef KOPS 1012 kops_gone(silentkops); 1013#endif 1014 pacify_guards(); 1015 } 1016} 1017 1018void 1019hot_pursuit(shkp) 1020register struct monst *shkp; 1021{ 1022 if(!shkp->isshk) return; 1023 1024 rile_shk(shkp); 1025 (void) strncpy(ESHK(shkp)->customer, plname, PL_NSIZ); 1026 ESHK(shkp)->following = 1; 1027} 1028 1029/* used when the shkp is teleported or falls (ox == 0) out of his shop, 1030 * or when the player is not on a costly_spot and he 1031 * damages something inside the shop. these conditions 1032 * must be checked by the calling function. 1033 */ 1034void 1035make_angry_shk(shkp, ox, oy) 1036register struct monst *shkp; 1037register xchar ox,oy; 1038{ 1039 xchar sx, sy; 1040 struct eshk *eshkp = ESHK(shkp); 1041 1042 /* all pending shop transactions are now "past due" */ 1043 if (eshkp->billct || eshkp->debit || eshkp->loan || eshkp->credit) { 1044 eshkp->robbed += (addupbill(shkp) + eshkp->debit + eshkp->loan); 1045 eshkp->robbed -= eshkp->credit; 1046 if (eshkp->robbed < 0L) eshkp->robbed = 0L; 1047 /* billct, debit, loan, and credit will be cleared by setpaid */ 1048 setpaid(shkp); 1049 } 1050 1051 /* If you just used a wand of teleportation to send the shk away, you 1052 might not be able to see her any more. Monnam would yield "it", 1053 which makes this message look pretty silly, so temporarily restore 1054 her original location during the call to Monnam. */ 1055 sx = shkp->mx, sy = shkp->my; 1056 if (isok(ox, oy) && cansee(ox, oy) && !cansee(sx, sy)) 1057 shkp->mx = ox, shkp->my = oy; 1058 pline("%s %s!", Monnam(shkp), 1059 !ANGRY(shkp) ? "gets angry" : "is furious"); 1060 shkp->mx = sx, shkp->my = sy; 1061 hot_pursuit(shkp); 1062} 1063 1064STATIC_VAR const char no_money[] = "Moreover, you%s have no money."; 1065STATIC_VAR const char not_enough_money[] = 1066 "Besides, you don't have enough to interest %s."; 1067 1068#else 1069STATIC_VAR const char no_money[]; 1070STATIC_VAR const char not_enough_money[]; 1071#endif /*OVLB*/ 1072 1073#ifdef OVL3 1074 1075STATIC_OVL long 1076cheapest_item(shkp) /* delivers the cheapest item on the list */ 1077register struct monst *shkp; 1078{ 1079 register int ct = ESHK(shkp)->billct; 1080 register struct bill_x *bp = ESHK(shkp)->bill_p; 1081 register long gmin = (bp->price * bp->bquan); 1082 1083 while(ct--){ 1084 if(bp->price * bp->bquan < gmin) 1085 gmin = bp->price * bp->bquan; 1086 bp++; 1087 } 1088 return(gmin); 1089} 1090#endif /*OVL3*/ 1091#ifdef OVL0 1092 1093int 1094dopay() 1095{ 1096 register struct eshk *eshkp; 1097 register struct monst *shkp; 1098 struct monst *nxtm, *resident; 1099 long ltmp; 1100#ifdef GOLDOBJ 1101 long umoney; 1102#endif 1103 int pass, tmp, sk = 0, seensk = 0; 1104 boolean paid = FALSE, stashed_gold = (hidden_gold() > 0L); 1105 1106 multi = 0; 1107 1108 /* find how many shk's there are, how many are in */ 1109 /* sight, and are you in a shop room with one. */ 1110 nxtm = resident = 0; 1111 for (shkp = next_shkp(fmon, FALSE); 1112 shkp; shkp = next_shkp(shkp->nmon, FALSE)) { 1113 sk++; 1114 if (ANGRY(shkp) && distu(shkp->mx, shkp->my) <= 2) nxtm = shkp; 1115 if (canspotmon(shkp)) seensk++; 1116 if (inhishop(shkp) && (*u.ushops == ESHK(shkp)->shoproom)) 1117 resident = shkp; 1118 } 1119 1120 if (nxtm) { /* Player should always appease an */ 1121 shkp = nxtm; /* irate shk standing next to them. */ 1122 goto proceed; 1123 } 1124 1125 if ((!sk && (!Blind || Blind_telepat)) || (!Blind && !seensk)) { 1126 There("appears to be no shopkeeper here to receive your payment."); 1127 return(0); 1128 } 1129 1130 if(!seensk) { 1131 You_cant("see..."); 1132 return(0); 1133 } 1134 1135 /* the usual case. allow paying at a distance when */ 1136 /* inside a tended shop. should we change that? */ 1137 if(sk == 1 && resident) { 1138 shkp = resident; 1139 goto proceed; 1140 } 1141 1142 if (seensk == 1) { 1143 for (shkp = next_shkp(fmon, FALSE); 1144 shkp; shkp = next_shkp(shkp->nmon, FALSE)) 1145 if (canspotmon(shkp)) break; 1146 if (shkp != resident && distu(shkp->mx, shkp->my) > 2) { 1147 pline("%s is not near enough to receive your payment.", 1148 Monnam(shkp)); 1149 return(0); 1150 } 1151 } else { 1152 struct monst *mtmp; 1153 coord cc; 1154 int cx, cy; 1155 1156 pline("Pay whom?"); 1157 cc.x = u.ux; 1158 cc.y = u.uy; 1159 if (getpos(&cc, TRUE, "the creature you want to pay") < 0) 1160 return 0; /* player pressed ESC */ 1161 cx = cc.x; 1162 cy = cc.y; 1163 if(cx < 0) { 1164 pline("Try again..."); 1165 return(0); 1166 } 1167 if(u.ux == cx && u.uy == cy) { 1168 You("are generous to yourself."); 1169 return(0); 1170 } 1171 mtmp = m_at(cx, cy); 1172 if(!mtmp) { 1173 There("is no one there to receive your payment."); 1174 return(0); 1175 } 1176 if(!mtmp->isshk) { 1177 pline("%s is not interested in your payment.", 1178 Monnam(mtmp)); 1179 return(0); 1180 } 1181 if (mtmp != resident && distu(mtmp->mx, mtmp->my) > 2) { 1182 pline("%s is too far to receive your payment.", 1183 Monnam(mtmp)); 1184 return(0); 1185 } 1186 shkp = mtmp; 1187 } 1188 1189 if(!shkp) { 1190#ifdef NETHACK_DEBUG 1191 pline("dopay: null shkp."); 1192#endif 1193 return(0); 1194 } 1195proceed: 1196 eshkp = ESHK(shkp); 1197 ltmp = eshkp->robbed; 1198 1199 /* wake sleeping shk when someone who owes money offers payment */ 1200 if (ltmp || eshkp->billct || eshkp->debit) 1201 rouse_shk(shkp, TRUE); 1202 1203 if (!shkp->mcanmove || shkp->msleeping) { /* still asleep/paralyzed */ 1204 pline("%s %s.", Monnam(shkp), 1205 rn2(2) ? "seems to be napping" : "doesn't respond"); 1206 return 0; 1207 } 1208 1209 if(shkp != resident && NOTANGRY(shkp)) { 1210#ifdef GOLDOBJ 1211 umoney = money_cnt(invent); 1212#endif 1213 if(!ltmp) 1214 You("do not owe %s anything.", mon_nam(shkp)); 1215#ifndef GOLDOBJ 1216 else if(!u.ugold) { 1217#else 1218 else if(!umoney) { 1219#endif 1220 You("%shave no money.", stashed_gold ? "seem to " : ""); 1221 if(stashed_gold) 1222 pline("But you have some gold stashed away."); 1223 } else { 1224#ifndef GOLDOBJ 1225 long ugold = u.ugold; 1226 if(ugold > ltmp) { 1227#else 1228 if(umoney > ltmp) { 1229#endif 1230 You("give %s the %ld gold piece%s %s asked for.", 1231 mon_nam(shkp), ltmp, plur(ltmp), mhe(shkp)); 1232 pay(ltmp, shkp); 1233 } else { 1234 You("give %s all your%s gold.", mon_nam(shkp), 1235 stashed_gold ? " openly kept" : ""); 1236#ifndef GOLDOBJ 1237 pay(u.ugold, shkp); 1238#else 1239 pay(umoney, shkp); 1240#endif 1241 if (stashed_gold) pline("But you have hidden gold!"); 1242 } 1243#ifndef GOLDOBJ 1244 if((ugold < ltmp/2L) || (ugold < ltmp && stashed_gold)) 1245#else 1246 if((umoney < ltmp/2L) || (umoney < ltmp && stashed_gold)) 1247#endif 1248 pline("Unfortunately, %s doesn't look satisfied.", 1249 mhe(shkp)); 1250 else 1251 make_happy_shk(shkp, FALSE); 1252 } 1253 return(1); 1254 } 1255 1256 /* ltmp is still eshkp->robbed here */ 1257 if (!eshkp->billct && !eshkp->debit) { 1258#ifdef GOLDOBJ 1259 umoney = money_cnt(invent); 1260#endif 1261 if(!ltmp && NOTANGRY(shkp)) { 1262 You("do not owe %s anything.", mon_nam(shkp)); 1263#ifndef GOLDOBJ 1264 if (!u.ugold) 1265#else 1266 if (!umoney) 1267#endif 1268 pline(no_money, stashed_gold ? " seem to" : ""); 1269 } else if(ltmp) { 1270 pline("%s is after blood, not money!", Monnam(shkp)); 1271#ifndef GOLDOBJ 1272 if(u.ugold < ltmp/2L || 1273 (u.ugold < ltmp && stashed_gold)) { 1274 if (!u.ugold) 1275#else 1276 if(umoney < ltmp/2L || 1277 (umoney < ltmp && stashed_gold)) { 1278 if (!umoney) 1279#endif 1280 pline(no_money, stashed_gold ? " seem to" : ""); 1281 else pline(not_enough_money, mhim(shkp)); 1282 return(1); 1283 } 1284 pline("But since %s shop has been robbed recently,", 1285 mhis(shkp)); 1286 pline("you %scompensate %s for %s losses.", 1287#ifndef GOLDOBJ 1288 (u.ugold < ltmp) ? 1289#else 1290 (umoney < ltmp) ? 1291#endif 1292 "partially " : "", 1293 mon_nam(shkp), mhis(shkp)); 1294#ifndef GOLDOBJ 1295 pay(u.ugold < ltmp ? u.ugold : ltmp, shkp); 1296#else 1297 pay(umoney < ltmp ? umoney : ltmp, shkp); 1298#endif 1299 make_happy_shk(shkp, FALSE); 1300 } else { 1301 /* shopkeeper is angry, but has not been robbed -- 1302 * door broken, attacked, etc. */ 1303 pline("%s is after your hide, not your money!", 1304 Monnam(shkp)); 1305#ifndef GOLDOBJ 1306 if(u.ugold < 1000L) { 1307 if (!u.ugold) 1308#else 1309 if(umoney < 1000L) { 1310 if (!umoney) 1311#endif 1312 pline(no_money, stashed_gold ? " seem to" : ""); 1313 else pline(not_enough_money, mhim(shkp)); 1314 return(1); 1315 } 1316 You("try to appease %s by giving %s 1000 gold pieces.", 1317 x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE), 1318 mhim(shkp)); 1319 pay(1000L,shkp); 1320 if (strncmp(eshkp->customer, plname, PL_NSIZ) || rn2(3)) 1321 make_happy_shk(shkp, FALSE); 1322 else 1323 pline("But %s is as angry as ever.", mon_nam(shkp)); 1324 } 1325 return(1); 1326 } 1327 if(shkp != resident) { 1328 impossible("dopay: not to shopkeeper?"); 1329 if(resident) setpaid(resident); 1330 return(0); 1331 } 1332 /* pay debt, if any, first */ 1333 if(eshkp->debit) { 1334 long dtmp = eshkp->debit; 1335 long loan = eshkp->loan; 1336 char sbuf[BUFSZ]; 1337#ifdef GOLDOBJ 1338 umoney = money_cnt(invent); 1339#endif 1340 Sprintf(sbuf, "You owe %s %ld %s ", 1341 shkname(shkp), dtmp, currency(dtmp)); 1342 if(loan) { 1343 if(loan == dtmp) 1344 Strcat(sbuf, "you picked up in the store."); 1345 else Strcat(sbuf, 1346 "for gold picked up and the use of merchandise."); 1347 } else Strcat(sbuf, "for the use of merchandise."); 1348 pline(sbuf); 1349#ifndef GOLDOBJ 1350 if (u.ugold + eshkp->credit < dtmp) { 1351#else 1352 if (umoney + eshkp->credit < dtmp) { 1353#endif 1354 pline("But you don't%s have enough gold%s.", 1355 stashed_gold ? " seem to" : "", 1356 eshkp->credit ? " or credit" : ""); 1357 return(1); 1358 } else { 1359 if (eshkp->credit >= dtmp) { 1360 eshkp->credit -= dtmp; 1361 eshkp->debit = 0L; 1362 eshkp->loan = 0L; 1363 Your("debt is covered by your credit."); 1364 } else if (!eshkp->credit) { 1365#ifndef GOLDOBJ 1366 u.ugold -= dtmp; 1367 shkp->mgold += dtmp; 1368#else 1369 money2mon(shkp, dtmp); 1370#endif 1371 eshkp->debit = 0L; 1372 eshkp->loan = 0L; 1373 You("pay that debt."); 1374 flags.botl = 1; 1375 } else { 1376 dtmp -= eshkp->credit; 1377 eshkp->credit = 0L; 1378#ifndef GOLDOBJ 1379 u.ugold -= dtmp; 1380 shkp->mgold += dtmp; 1381#else 1382 money2mon(shkp, dtmp); 1383#endif 1384 eshkp->debit = 0L; 1385 eshkp->loan = 0L; 1386 pline("That debt is partially offset by your credit."); 1387 You("pay the remainder."); 1388 flags.botl = 1; 1389 } 1390 paid = TRUE; 1391 } 1392 } 1393 /* now check items on bill */ 1394 if (eshkp->billct) { 1395 register boolean itemize; 1396#ifndef GOLDOBJ 1397 if (!u.ugold && !eshkp->credit) { 1398#else 1399 umoney = money_cnt(invent); 1400 if (!umoney && !eshkp->credit) { 1401#endif 1402 You("%shave no money or credit%s.", 1403 stashed_gold ? "seem to " : "", 1404 paid ? " left" : ""); 1405 return(0); 1406 } 1407#ifndef GOLDOBJ 1408 if ((u.ugold + eshkp->credit) < cheapest_item(shkp)) { 1409#else 1410 if ((umoney + eshkp->credit) < cheapest_item(shkp)) { 1411#endif 1412 You("don't have enough money to buy%s the item%s you picked.", 1413 eshkp->billct > 1 ? " any of" : "", plur(eshkp->billct)); 1414 if(stashed_gold) 1415 pline("Maybe you have some gold stashed away?"); 1416 return(0); 1417 } 1418 1419 /* this isn't quite right; it itemizes without asking if the 1420 * single item on the bill is partly used up and partly unpaid */ 1421 itemize = (eshkp->billct > 1 ? yn("Itemized billing?") == 'y' : 1); 1422 1423 for (pass = 0; pass <= 1; pass++) { 1424 tmp = 0; 1425 while (tmp < eshkp->billct) { 1426 struct obj *otmp; 1427 register struct bill_x *bp = &(eshkp->bill_p[tmp]); 1428 1429 /* find the object on one of the lists */ 1430 if ((otmp = bp_to_obj(bp)) != 0) { 1431 /* if completely used up, object quantity is stale; 1432 restoring it to its original value here avoids 1433 making the partly-used-up code more complicated */ 1434 if (bp->useup) otmp->quan = bp->bquan; 1435 } else { 1436 impossible("Shopkeeper administration out of order."); 1437 setpaid(shkp); /* be nice to the player */ 1438 return 1; 1439 } 1440 if (pass == bp->useup && otmp->quan == bp->bquan) { 1441 /* pay for used-up items on first pass and others 1442 * on second, so player will be stuck in the store 1443 * less often; things which are partly used up 1444 * are processed on both passes */ 1445 tmp++; 1446 } else { 1447 switch (dopayobj(shkp, bp, &otmp, pass, itemize)) { 1448 case PAY_CANT: 1449 return 1; /*break*/ 1450 case PAY_BROKE: 1451 paid = TRUE; 1452 goto thanks; /*break*/ 1453 case PAY_SKIP: 1454 tmp++; 1455 continue; /*break*/ 1456 case PAY_SOME: 1457 paid = TRUE; 1458 if (itemize) bot(); 1459 continue; /*break*/ 1460 case PAY_BUY: 1461 paid = TRUE; 1462 break; 1463 } 1464 if (itemize) bot(); 1465 *bp = eshkp->bill_p[--eshkp->billct]; 1466 } 1467 } 1468 } 1469 thanks: 1470 if (!itemize) 1471 update_inventory(); /* Done in dopayobj() if itemize. */ 1472 } 1473 if(!ANGRY(shkp) && paid) 1474 verbalize("Thank you for shopping in %s %s!", 1475 s_suffix(shkname(shkp)), 1476 shtypes[eshkp->shoptype - SHOPBASE].name); 1477 return(1); 1478} 1479#endif /*OVL0*/ 1480#ifdef OVL3 1481 1482/* return 2 if used-up portion paid */ 1483/* 1 if paid successfully */ 1484/* 0 if not enough money */ 1485/* -1 if skip this object */ 1486/* -2 if no money/credit left */ 1487STATIC_OVL int 1488dopayobj(shkp, bp, obj_p, which, itemize) 1489register struct monst *shkp; 1490register struct bill_x *bp; 1491struct obj **obj_p; 1492int which; /* 0 => used-up item, 1 => other (unpaid or lost) */ 1493boolean itemize; 1494{ 1495 register struct obj *obj = *obj_p; 1496 long ltmp, quan, save_quan; 1497#ifdef GOLDOBJ 1498 long umoney = money_cnt(invent); 1499#endif 1500 int buy; 1501 boolean stashed_gold = (hidden_gold() > 0L), 1502 consumed = (which == 0); 1503 1504 if(!obj->unpaid && !bp->useup){ 1505 impossible("Paid object on bill??"); 1506 return PAY_BUY; 1507 } 1508#ifndef GOLDOBJ 1509 if(itemize && u.ugold + ESHK(shkp)->credit == 0L){ 1510#else 1511 if(itemize && umoney + ESHK(shkp)->credit == 0L){ 1512#endif 1513 You("%shave no money or credit left.", 1514 stashed_gold ? "seem to " : ""); 1515 return PAY_BROKE; 1516 } 1517 /* we may need to temporarily adjust the object, if part of the 1518 original quantity has been used up but part remains unpaid */ 1519 save_quan = obj->quan; 1520 if (consumed) { 1521 /* either completely used up (simple), or split needed */ 1522 quan = bp->bquan; 1523 if (quan > obj->quan) /* difference is amount used up */ 1524 quan -= obj->quan; 1525 } else { 1526 /* dealing with ordinary unpaid item */ 1527 quan = obj->quan; 1528 } 1529 obj->quan = quan; /* to be used by doname() */ 1530 obj->unpaid = 0; /* ditto */ 1531 ltmp = bp->price * quan; 1532 buy = PAY_BUY; /* flag; if changed then return early */ 1533 1534 if (itemize) { 1535 char qbuf[BUFSZ]; 1536 Sprintf(qbuf,"%s for %ld %s. Pay?", quan == 1L ? 1537 Doname2(obj) : doname(obj), ltmp, currency(ltmp)); 1538 if (yn(qbuf) == 'n') { 1539 buy = PAY_SKIP; /* don't want to buy */ 1540 } else if (quan < bp->bquan && !consumed) { /* partly used goods */ 1541 obj->quan = bp->bquan - save_quan; /* used up amount */ 1542 verbalize("%s for the other %s before buying %s.", 1543 ANGRY(shkp) ? "Pay" : "Please pay", xname(obj), 1544 save_quan > 1L ? "these" : "this one"); 1545 buy = PAY_SKIP; /* shk won't sell */ 1546 } 1547 } 1548#ifndef GOLDOBJ 1549 if (buy == PAY_BUY && u.ugold + ESHK(shkp)->credit < ltmp) { 1550#else 1551 if (buy == PAY_BUY && umoney + ESHK(shkp)->credit < ltmp) { 1552#endif 1553 You("don't%s have gold%s enough to pay for %s.", 1554 stashed_gold ? " seem to" : "", 1555 (ESHK(shkp)->credit > 0L) ? " or credit" : "", 1556 doname(obj)); 1557 buy = itemize ? PAY_SKIP : PAY_CANT; 1558 } 1559 1560 if (buy != PAY_BUY) { 1561 /* restore unpaid object to original state */ 1562 obj->quan = save_quan; 1563 obj->unpaid = 1; 1564 return buy; 1565 } 1566 1567 pay(ltmp, shkp); 1568 shk_names_obj(shkp, obj, consumed ? 1569 "paid for %s at a cost of %ld gold piece%s.%s" : 1570 "bought %s for %ld gold piece%s.%s", ltmp, ""); 1571 obj->quan = save_quan; /* restore original count */ 1572 /* quan => amount just bought, save_quan => remaining unpaid count */ 1573 if (consumed) { 1574 if (quan != bp->bquan) { 1575 /* eliminate used-up portion; remainder is still unpaid */ 1576 bp->bquan = obj->quan; 1577 obj->unpaid = 1; 1578 bp->useup = 0; 1579 buy = PAY_SOME; 1580 } else { /* completely used-up, so get rid of it */ 1581 obj_extract_self(obj); 1582 /* assert( obj == *obj_p ); */ 1583 dealloc_obj(obj); 1584 *obj_p = 0; /* destroy pointer to freed object */ 1585 } 1586 } else if (itemize) 1587 update_inventory(); /* Done just once in dopay() if !itemize. */ 1588 return buy; 1589} 1590#endif /*OVL3*/ 1591#ifdef OVLB 1592 1593static coord repo_location; /* repossession context */ 1594 1595/* routine called after dying (or quitting) */ 1596boolean 1597paybill(croaked) 1598int croaked; /* -1: escaped dungeon; 0: quit; 1: died */ 1599{ 1600 register struct monst *mtmp, *mtmp2, *resident= (struct monst *)0; 1601 register boolean taken = FALSE; 1602 register int numsk = 0; 1603 1604 /* if we escaped from the dungeon, shopkeepers can't reach us; 1605 shops don't occur on level 1, but this could happen if hero 1606 level teleports out of the dungeon and manages not to die */ 1607 if (croaked < 0) return FALSE; 1608 1609 /* this is where inventory will end up if any shk takes it */ 1610 repo_location.x = repo_location.y = 0; 1611 1612 /* give shopkeeper first crack */ 1613 if ((mtmp = shop_keeper(*u.ushops)) && inhishop(mtmp)) { 1614 numsk++; 1615 resident = mtmp; 1616 taken = inherits(resident, numsk, croaked); 1617 } 1618 for (mtmp = next_shkp(fmon, FALSE); 1619 mtmp; mtmp = next_shkp(mtmp2, FALSE)) { 1620 mtmp2 = mtmp->nmon; 1621 if (mtmp != resident) { 1622 /* for bones: we don't want a shopless shk around */ 1623 if(!on_level(&(ESHK(mtmp)->shoplevel), &u.uz)) 1624 mongone(mtmp); 1625 else { 1626 numsk++; 1627 taken |= inherits(mtmp, numsk, croaked); 1628 } 1629 } 1630 } 1631 if(numsk == 0) return(FALSE); 1632 return(taken); 1633} 1634 1635STATIC_OVL boolean 1636inherits(shkp, numsk, croaked) 1637struct monst *shkp; 1638int numsk; 1639int croaked; 1640{ 1641 long loss = 0L; 1642#ifdef GOLDOBJ 1643 long umoney; 1644#endif 1645 struct eshk *eshkp = ESHK(shkp); 1646 boolean take = FALSE, taken = FALSE; 1647 int roomno = *u.ushops; 1648 char takes[BUFSZ]; 1649 1650 /* the simplifying principle is that first-come */ 1651 /* already took everything you had. */ 1652 if (numsk > 1) { 1653 if (cansee(shkp->mx, shkp->my && croaked)) 1654 pline("%s %slooks at your corpse%s and %s.", 1655 Monnam(shkp), 1656 (!shkp->mcanmove || shkp->msleeping) ? "wakes up, " : "", 1657 !rn2(2) ? (shkp->female ? ", shakes her head," : 1658 ", shakes his head,") : "", 1659 !inhishop(shkp) ? "disappears" : "sighs"); 1660 rouse_shk(shkp, FALSE); /* wake shk for bones */ 1661 taken = (roomno == eshkp->shoproom); 1662 goto skip; 1663 } 1664 1665 /* get one case out of the way: you die in the shop, the */ 1666 /* shopkeeper is peaceful, nothing stolen, nothing owed. */ 1667 if(roomno == eshkp->shoproom && inhishop(shkp) && 1668 !eshkp->billct && !eshkp->robbed && !eshkp->debit && 1669 NOTANGRY(shkp) && !eshkp->following) { 1670 if (invent) 1671 pline("%s gratefully inherits all your possessions.", 1672 shkname(shkp)); 1673 set_repo_loc(eshkp); 1674 goto clear; 1675 } 1676 1677 if (eshkp->billct || eshkp->debit || eshkp->robbed) { 1678 if (roomno == eshkp->shoproom && inhishop(shkp)) 1679 loss = addupbill(shkp) + eshkp->debit; 1680 if (loss < eshkp->robbed) loss = eshkp->robbed; 1681 take = TRUE; 1682 } 1683 1684 if (eshkp->following || ANGRY(shkp) || take) { 1685#ifndef GOLDOBJ 1686 if (!invent && !u.ugold) goto skip; 1687#else 1688 if (!invent) goto skip; 1689 umoney = money_cnt(invent); 1690#endif 1691 takes[0] = '\0'; 1692 if (!shkp->mcanmove || shkp->msleeping) 1693 Strcat(takes, "wakes up and "); 1694 if (distu(shkp->mx, shkp->my) > 2) 1695 Strcat(takes, "comes and "); 1696 Strcat(takes, "takes"); 1697 1698#ifndef GOLDOBJ 1699 if (loss > u.ugold || !loss || roomno == eshkp->shoproom) { 1700 eshkp->robbed -= u.ugold; 1701 if (eshkp->robbed < 0L) eshkp->robbed = 0L; 1702 shkp->mgold += u.ugold; 1703 u.ugold = 0L; 1704#else 1705 if (loss > umoney || !loss || roomno == eshkp->shoproom) { 1706 eshkp->robbed -= umoney; 1707 if (eshkp->robbed < 0L) eshkp->robbed = 0L; 1708 if (umoney > 0) money2mon(shkp, umoney); 1709#endif 1710 flags.botl = 1; 1711 pline("%s %s all your possessions.", 1712 shkname(shkp), takes); 1713 taken = TRUE; 1714 /* where to put player's invent (after disclosure) */ 1715 set_repo_loc(eshkp); 1716 } else { 1717#ifndef GOLDOBJ 1718 shkp->mgold += loss; 1719 u.ugold -= loss; 1720#else 1721 money2mon(shkp, loss); 1722#endif 1723 flags.botl = 1; 1724 pline("%s %s the %ld %s %sowed %s.", 1725 Monnam(shkp), takes, 1726 loss, currency(loss), 1727 strncmp(eshkp->customer, plname, PL_NSIZ) ? 1728 "" : "you ", 1729 shkp->female ? "her" : "him"); 1730 /* shopkeeper has now been paid in full */ 1731 pacify_shk(shkp); 1732 eshkp->following = 0; 1733 eshkp->robbed = 0L; 1734 } 1735skip: 1736 /* in case we create bones */ 1737 rouse_shk(shkp, FALSE); /* wake up */ 1738 if (!inhishop(shkp)) 1739 home_shk(shkp, FALSE); 1740 } 1741clear: 1742 setpaid(shkp); 1743 return(taken); 1744} 1745 1746STATIC_OVL void 1747set_repo_loc(eshkp) 1748struct eshk *eshkp; 1749{ 1750 register xchar ox, oy; 1751 1752 /* if you're not in this shk's shop room, or if you're in its doorway 1753 or entry spot, then your gear gets dumped all the way inside */ 1754 if (*u.ushops != eshkp->shoproom || 1755 IS_DOOR(levl[u.ux][u.uy].typ) || 1756 (u.ux == eshkp->shk.x && u.uy == eshkp->shk.y)) { 1757 /* shk.x,shk.y is the position immediately in 1758 * front of the door -- move in one more space 1759 */ 1760 ox = eshkp->shk.x; 1761 oy = eshkp->shk.y; 1762 ox += sgn(ox - eshkp->shd.x); 1763 oy += sgn(oy - eshkp->shd.y); 1764 } else { /* already inside this shk's shop */ 1765 ox = u.ux; 1766 oy = u.uy; 1767 } 1768 /* finish_paybill will deposit invent here */ 1769 repo_location.x = ox; 1770 repo_location.y = oy; 1771} 1772 1773/* called at game exit, after inventory disclosure but before making bones */ 1774void 1775finish_paybill() 1776{ 1777 register struct obj *otmp; 1778 int ox = repo_location.x, 1779 oy = repo_location.y; 1780 1781#if 0 /* don't bother */ 1782 if (ox == 0 && oy == 0) impossible("finish_paybill: no location"); 1783#endif 1784 /* normally done by savebones(), but that's too late in this case */ 1785 unleash_all(); 1786 /* transfer all of the character's inventory to the shop floor */ 1787 while ((otmp = invent) != 0) { 1788 otmp->owornmask = 0L; /* perhaps we should call setnotworn? */ 1789 otmp->lamplit = 0; /* avoid "goes out" msg from freeinv */ 1790 if (rn2(5)) curse(otmp); /* normal bones treatment for invent */ 1791 obj_extract_self(otmp); 1792 place_object(otmp, ox, oy); 1793 } 1794} 1795 1796/* find obj on one of the lists */ 1797STATIC_OVL struct obj * 1798bp_to_obj(bp) 1799register struct bill_x *bp; 1800{ 1801 register struct obj *obj; 1802 register unsigned int id = bp->bo_id; 1803 1804 if(bp->useup) 1805 obj = o_on(id, billobjs); 1806 else 1807 obj = find_oid(id); 1808 return obj; 1809} 1810 1811/* 1812 * Look for o_id on all lists but billobj. Return obj or NULL if not found. 1813 * Its OK for restore_timers() to call this function, there should not 1814 * be any timeouts on the billobjs chain. 1815 */ 1816struct obj * 1817find_oid(id) 1818unsigned id; 1819{ 1820 struct obj *obj; 1821 struct monst *mon, *mmtmp[3]; 1822 int i; 1823 1824 /* first check various obj lists directly */ 1825 if ((obj = o_on(id, invent)) != 0) return obj; 1826 if ((obj = o_on(id, fobj)) != 0) return obj; 1827 if ((obj = o_on(id, level.buriedobjlist)) != 0) return obj; 1828 if ((obj = o_on(id, migrating_objs)) != 0) return obj; 1829 1830 /* not found yet; check inventory for members of various monst lists */ 1831 mmtmp[0] = fmon; 1832 mmtmp[1] = migrating_mons; 1833 mmtmp[2] = mydogs; /* for use during level changes */ 1834 for (i = 0; i < 3; i++) 1835 for (mon = mmtmp[i]; mon; mon = mon->nmon) 1836 if ((obj = o_on(id, mon->minvent)) != 0) return obj; 1837 1838 /* not found at all */ 1839 return (struct obj *)0; 1840} 1841#endif /*OVLB*/ 1842#ifdef OVL3 1843 1844/* calculate the value that the shk will charge for [one of] an object */ 1845STATIC_OVL long 1846get_cost(obj, shkp) 1847register struct obj *obj; 1848register struct monst *shkp; /* if angry, impose a surcharge */ 1849{ 1850 register long tmp = getprice(obj, FALSE); 1851 1852 if (!tmp) tmp = 5L; 1853 /* shopkeeper may notice if the player isn't very knowledgeable - 1854 especially when gem prices are concerned */ 1855 if (!obj->dknown || !objects[obj->otyp].oc_name_known) { 1856 if (obj->oclass == GEM_CLASS && 1857 objects[obj->otyp].oc_material == GLASS) { 1858 int i; 1859 /* get a value that's 'random' from game to game, but the 1860 same within the same game */ 1861 boolean pseudorand = 1862 (((int)u.ubirthday % obj->otyp) >= obj->otyp/2); 1863 1864 /* all gems are priced high - real or not */ 1865 switch(obj->otyp - LAST_GEM) { 1866 case 1: /* white */ 1867 i = pseudorand ? DIAMOND : OPAL; 1868 break; 1869 case 2: /* blue */ 1870 i = pseudorand ? SAPPHIRE : AQUAMARINE; 1871 break; 1872 case 3: /* red */ 1873 i = pseudorand ? RUBY : JASPER; 1874 break; 1875 case 4: /* yellowish brown */ 1876 i = pseudorand ? AMBER : TOPAZ; 1877 break; 1878 case 5: /* orange */ 1879 i = pseudorand ? JACINTH : AGATE; 1880 break; 1881 case 6: /* yellow */ 1882 i = pseudorand ? CITRINE : CHRYSOBERYL; 1883 break; 1884 case 7: /* black */ 1885 i = pseudorand ? BLACK_OPAL : JET; 1886 break; 1887 case 8: /* green */ 1888 i = pseudorand ? EMERALD : JADE; 1889 break; 1890 case 9: /* violet */ 1891 i = pseudorand ? AMETHYST : FLUORITE; 1892 break; 1893 default: impossible("bad glass gem %d?", obj->otyp); 1894 i = STRANGE_OBJECT; 1895 break; 1896 } 1897 tmp = (long) objects[i].oc_cost; 1898 } else if (!(obj->o_id % 4)) /* arbitrarily impose surcharge */ 1899 tmp += tmp / 3L; 1900 } 1901#ifdef TOURIST 1902 if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2)) 1903 || (uarmu && !uarm && !uarmc)) /* touristy shirt visible */ 1904 tmp += tmp / 3L; 1905 else 1906#endif 1907 if (uarmh && uarmh->otyp == DUNCE_CAP) 1908 tmp += tmp / 3L; 1909 1910 if (ACURR(A_CHA) > 18) tmp /= 2L; 1911 else if (ACURR(A_CHA) > 17) tmp -= tmp / 3L; 1912 else if (ACURR(A_CHA) > 15) tmp -= tmp / 4L; 1913 else if (ACURR(A_CHA) < 6) tmp *= 2L; 1914 else if (ACURR(A_CHA) < 8) tmp += tmp / 2L; 1915 else if (ACURR(A_CHA) < 11) tmp += tmp / 3L; 1916 if (tmp <= 0L) tmp = 1L; 1917 else if (obj->oartifact) tmp *= 4L; 1918 /* anger surcharge should match rile_shk's */ 1919 if (shkp && ESHK(shkp)->surcharge) tmp += (tmp + 2L) / 3L; 1920 return tmp; 1921} 1922#endif /*OVL3*/ 1923#ifdef OVLB 1924 1925/* returns the price of a container's content. the price 1926 * of the "top" container is added in the calling functions. 1927 * a different price quoted for selling as vs. buying. 1928 */ 1929long 1930contained_cost(obj, shkp, price, usell, unpaid_only) 1931register struct obj *obj; 1932register struct monst *shkp; 1933long price; 1934register boolean usell; 1935register boolean unpaid_only; 1936{ 1937 register struct obj *otmp; 1938 1939 /* the price of contained objects */ 1940 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) { 1941 if (otmp->oclass == COIN_CLASS) continue; 1942 /* the "top" container is evaluated by caller */ 1943 if (usell) { 1944 if (saleable(shkp, otmp) && 1945 !otmp->unpaid && otmp->oclass != BALL_CLASS && 1946 !(otmp->oclass == FOOD_CLASS && otmp->oeaten) && 1947 !(Is_candle(otmp) && otmp->age < 1948 20L * (long)objects[otmp->otyp].oc_cost)) 1949 price += set_cost(otmp, shkp); 1950 } else if (!otmp->no_charge && 1951 (!unpaid_only || (unpaid_only && otmp->unpaid))) { 1952 price += get_cost(otmp, shkp) * otmp->quan; 1953 } 1954 1955 if (Has_contents(otmp)) 1956 price += contained_cost(otmp, shkp, price, usell, unpaid_only); 1957 } 1958 1959 return(price); 1960} 1961 1962long 1963contained_gold(obj) 1964register struct obj *obj; 1965{ 1966 register struct obj *otmp; 1967 register long value = 0L; 1968 1969 /* accumulate contained gold */ 1970 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) 1971 if (otmp->oclass == COIN_CLASS) 1972 value += otmp->quan; 1973 else if (Has_contents(otmp)) 1974 value += contained_gold(otmp); 1975 1976 return(value); 1977} 1978 1979STATIC_OVL void 1980dropped_container(obj, shkp, sale) 1981register struct obj *obj; 1982register struct monst *shkp; 1983register boolean sale; 1984{ 1985 register struct obj *otmp; 1986 1987 /* the "top" container is treated in the calling fn */ 1988 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) { 1989 if (otmp->oclass == COIN_CLASS) continue; 1990 1991 if (!otmp->unpaid && !(sale && saleable(shkp, otmp))) 1992 otmp->no_charge = 1; 1993 1994 if (Has_contents(otmp)) 1995 dropped_container(otmp, shkp, sale); 1996 } 1997} 1998 1999void 2000picked_container(obj) 2001register struct obj *obj; 2002{ 2003 register struct obj *otmp; 2004 2005 /* the "top" container is treated in the calling fn */ 2006 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) { 2007 if (otmp->oclass == COIN_CLASS) continue; 2008 2009 if (otmp->no_charge) 2010 otmp->no_charge = 0; 2011 2012 if (Has_contents(otmp)) 2013 picked_container(otmp); 2014 } 2015} 2016#endif /*OVLB*/ 2017#ifdef OVL3 2018 2019/* calculate how much the shk will pay when buying [all of] an object */ 2020STATIC_OVL long 2021set_cost(obj, shkp) 2022register struct obj *obj; 2023register struct monst *shkp; 2024{ 2025 long tmp = getprice(obj, TRUE) * obj->quan; 2026 2027#ifdef TOURIST 2028 if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2)) 2029 || (uarmu && !uarm && !uarmc)) /* touristy shirt visible */ 2030 tmp /= 3L; 2031 else 2032#endif 2033 if (uarmh && uarmh->otyp == DUNCE_CAP) 2034 tmp /= 3L; 2035 else 2036 tmp /= 2L; 2037 2038 /* shopkeeper may notice if the player isn't very knowledgeable - 2039 especially when gem prices are concerned */ 2040 if (!obj->dknown || !objects[obj->otyp].oc_name_known) { 2041 if (obj->oclass == GEM_CLASS) { 2042 /* different shop keepers give different prices */ 2043 if (objects[obj->otyp].oc_material == GEMSTONE || 2044 objects[obj->otyp].oc_material == GLASS) { 2045 tmp = (obj->otyp % (6 - shkp->m_id % 3)); 2046 tmp = (tmp + 3) * obj->quan; 2047 } 2048 } else if (tmp > 1L && !rn2(4)) 2049 tmp -= tmp / 4L; 2050 } 2051 return tmp; 2052} 2053 2054#endif /*OVL3*/ 2055#ifdef OVLB 2056 2057/* called from doinv(invent.c) for inventory of unpaid objects */ 2058long 2059unpaid_cost(unp_obj) 2060register struct obj *unp_obj; /* known to be unpaid */ 2061{ 2062 register struct bill_x *bp = (struct bill_x *)0; 2063 register struct monst *shkp; 2064 2065 for(shkp = next_shkp(fmon, TRUE); shkp; 2066 shkp = next_shkp(shkp->nmon, TRUE)) 2067 if ((bp = onbill(unp_obj, shkp, TRUE)) != 0) break; 2068 2069 /* onbill() gave no message if unexpected problem occurred */ 2070 if(!bp) impossible("unpaid_cost: object wasn't on any bill!"); 2071 2072 return bp ? unp_obj->quan * bp->price : 0L; 2073} 2074 2075STATIC_OVL void 2076add_one_tobill(obj, dummy) 2077register struct obj *obj; 2078register boolean dummy; 2079{ 2080 register struct monst *shkp; 2081 register struct bill_x *bp; 2082 register int bct; 2083 register char roomno = *u.ushops; 2084 2085 if (!roomno) return; 2086 if (!(shkp = shop_keeper(roomno))) return; 2087 if (!inhishop(shkp)) return; 2088 2089 if (onbill(obj, shkp, FALSE) || /* perhaps thrown away earlier */ 2090 (obj->oclass == FOOD_CLASS && obj->oeaten)) 2091 return; 2092 2093 if (ESHK(shkp)->billct == BILLSZ) { 2094 You("got that for free!"); 2095 return; 2096 } 2097 2098 /* To recognize objects the shopkeeper is not interested in. -dgk 2099 */ 2100 if (obj->no_charge) { 2101 obj->no_charge = 0; 2102 return; 2103 } 2104 2105 bct = ESHK(shkp)->billct; 2106 bp = &(ESHK(shkp)->bill_p[bct]); 2107 bp->bo_id = obj->o_id; 2108 bp->bquan = obj->quan; 2109 if(dummy) { /* a dummy object must be inserted into */ 2110 bp->useup = 1; /* the billobjs chain here. crucial for */ 2111 add_to_billobjs(obj); /* eating floorfood in shop. see eat.c */ 2112 } else bp->useup = 0; 2113 bp->price = get_cost(obj, shkp); 2114 ESHK(shkp)->billct++; 2115 obj->unpaid = 1; 2116} 2117 2118STATIC_OVL void 2119add_to_billobjs(obj) 2120 struct obj *obj; 2121{ 2122 if (obj->where != OBJ_FREE) 2123 panic("add_to_billobjs: obj not free"); 2124 if (obj->timed) 2125 obj_stop_timers(obj); 2126 2127 obj->nobj = billobjs; 2128 billobjs = obj; 2129 obj->where = OBJ_ONBILL; 2130} 2131 2132/* recursive billing of objects within containers. */ 2133STATIC_OVL void 2134bill_box_content(obj, ininv, dummy, shkp) 2135register struct obj *obj; 2136register boolean ininv, dummy; 2137register struct monst *shkp; 2138{ 2139 register struct obj *otmp; 2140 2141 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) { 2142 if (otmp->oclass == COIN_CLASS) continue; 2143 2144 /* the "top" box is added in addtobill() */ 2145 if (!otmp->no_charge) 2146 add_one_tobill(otmp, dummy); 2147 if (Has_contents(otmp)) 2148 bill_box_content(otmp, ininv, dummy, shkp); 2149 } 2150 2151} 2152 2153/* shopkeeper tells you what you bought or sold, sometimes partly IDing it */ 2154STATIC_OVL void 2155shk_names_obj(shkp, obj, fmt, amt, arg) 2156struct monst *shkp; 2157struct obj *obj; 2158const char *fmt; /* "%s %ld %s %s", doname(obj), amt, plur(amt), arg */ 2159long amt; 2160const char *arg; 2161{ 2162 char *obj_name, fmtbuf[BUFSZ]; 2163 boolean was_unknown = !obj->dknown; 2164 2165 obj->dknown = TRUE; 2166 /* Use real name for ordinary weapons/armor, and spell-less 2167 * scrolls/books (that is, blank and mail), but only if the 2168 * object is within the shk's area of interest/expertise. 2169 */ 2170 if (!objects[obj->otyp].oc_magic && saleable(shkp, obj) && 2171 (obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS || 2172 obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS || 2173 obj->otyp == MIRROR)) { 2174 was_unknown |= !objects[obj->otyp].oc_name_known; 2175 makeknown(obj->otyp); 2176 } 2177 obj_name = doname(obj); 2178 /* Use an alternate message when extra information is being provided */ 2179 if (was_unknown) { 2180 Sprintf(fmtbuf, "%%s; you %s", fmt); 2181 obj_name[0] = highc(obj_name[0]); 2182 pline(fmtbuf, obj_name, (obj->quan > 1) ? "them" : "it", 2183 amt, plur(amt), arg); 2184 } else { 2185 You(fmt, obj_name, amt, plur(amt), arg); 2186 } 2187} 2188 2189void 2190addtobill(obj, ininv, dummy, silent) 2191register struct obj *obj; 2192register boolean ininv, dummy, silent; 2193{ 2194 register struct monst *shkp; 2195 register char roomno = *u.ushops; 2196 long ltmp = 0L, cltmp = 0L, gltmp = 0L; 2197 register boolean container = Has_contents(obj); 2198 2199 if(!*u.ushops) return; 2200 2201 if(!(shkp = shop_keeper(roomno))) return; 2202 2203 if(!inhishop(shkp)) return; 2204 2205 if(/* perhaps we threw it away earlier */ 2206 onbill(obj, shkp, FALSE) || 2207 (obj->oclass == FOOD_CLASS && obj->oeaten) 2208 ) return; 2209 2210 if(ESHK(shkp)->billct == BILLSZ) { 2211 You("got that for free!"); 2212 return; 2213 } 2214 2215 if(obj->oclass == COIN_CLASS) { 2216 costly_gold(obj->ox, obj->oy, obj->quan); 2217 return; 2218 } 2219 2220 if(!obj->no_charge) 2221 ltmp = get_cost(obj, shkp); 2222 2223 if (obj->no_charge && !container) { 2224 obj->no_charge = 0; 2225 return; 2226 } 2227 2228 if(container) { 2229 if(obj->cobj == (struct obj *)0) { 2230 if(obj->no_charge) { 2231 obj->no_charge = 0; 2232 return; 2233 } else { 2234 add_one_tobill(obj, dummy); 2235 goto speak; 2236 } 2237 } else { 2238 cltmp += contained_cost(obj, shkp, cltmp, FALSE, FALSE); 2239 gltmp += contained_gold(obj); 2240 } 2241 2242 if(ltmp) add_one_tobill(obj, dummy); 2243 if(cltmp) bill_box_content(obj, ininv, dummy, shkp); 2244 picked_container(obj); /* reset contained obj->no_charge */ 2245 2246 ltmp += cltmp; 2247 2248 if(gltmp) { 2249 costly_gold(obj->ox, obj->oy, gltmp); 2250 if(!ltmp) return; 2251 } 2252 2253 if(obj->no_charge) 2254 obj->no_charge = 0; 2255 2256 } else /* i.e., !container */ 2257 add_one_tobill(obj, dummy); 2258speak: 2259 if (shkp->mcanmove && !shkp->msleeping && !silent) { 2260 char buf[BUFSZ]; 2261 2262 if(!ltmp) { 2263 pline("%s has no interest in %s.", Monnam(shkp), 2264 the(xname(obj))); 2265 return; 2266 } 2267 Strcpy(buf, "\"For you, "); 2268 if (ANGRY(shkp)) Strcat(buf, "scum "); 2269 else { 2270 static const char *honored[5] = { 2271 "good", "honored", "most gracious", "esteemed", 2272 "most renowned and sacred" 2273 }; 2274 Strcat(buf, honored[rn2(4) + u.uevent.udemigod]); 2275 if (!is_human(youmonst.data)) Strcat(buf, " creature"); 2276 else 2277 Strcat(buf, (flags.female) ? " lady" : " sir"); 2278 } 2279 if(ininv) { 2280 long quan = obj->quan; 2281 obj->quan = 1L; /* fool xname() into giving singular */ 2282 pline("%s; only %ld %s %s.\"", buf, ltmp, 2283 (quan > 1L) ? "per" : "for this", xname(obj)); 2284 obj->quan = quan; 2285 } else 2286 pline("%s will cost you %ld %s%s.", 2287 The(xname(obj)), ltmp, currency(ltmp), 2288 (obj->quan > 1L) ? " each" : ""); 2289 } else if(!silent) { 2290 if(ltmp) pline_The("list price of %s is %ld %s%s.", 2291 the(xname(obj)), ltmp, currency(ltmp), 2292 (obj->quan > 1L) ? " each" : ""); 2293 else pline("%s does not notice.", Monnam(shkp)); 2294 } 2295} 2296 2297void 2298splitbill(obj, otmp) 2299register struct obj *obj, *otmp; 2300{ 2301 /* otmp has been split off from obj */ 2302 register struct bill_x *bp; 2303 register long tmp; 2304 register struct monst *shkp = shop_keeper(*u.ushops); 2305 2306 if(!shkp || !inhishop(shkp)) { 2307 impossible("splitbill: no resident shopkeeper??"); 2308 return; 2309 } 2310 bp = onbill(obj, shkp, FALSE); 2311 if(!bp) { 2312 impossible("splitbill: not on bill?"); 2313 return; 2314 } 2315 if(bp->bquan < otmp->quan) { 2316 impossible("Negative quantity on bill??"); 2317 } 2318 if(bp->bquan == otmp->quan) { 2319 impossible("Zero quantity on bill??"); 2320 } 2321 bp->bquan -= otmp->quan; 2322 2323 if(ESHK(shkp)->billct == BILLSZ) otmp->unpaid = 0; 2324 else { 2325 tmp = bp->price; 2326 bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]); 2327 bp->bo_id = otmp->o_id; 2328 bp->bquan = otmp->quan; 2329 bp->useup = 0; 2330 bp->price = tmp; 2331 ESHK(shkp)->billct++; 2332 } 2333} 2334 2335STATIC_OVL void 2336sub_one_frombill(obj, shkp) 2337register struct obj *obj; 2338register struct monst *shkp; 2339{ 2340 register struct bill_x *bp; 2341 2342 if((bp = onbill(obj, shkp, FALSE)) != 0) { 2343 register struct obj *otmp; 2344 2345 obj->unpaid = 0; 2346 if(bp->bquan > obj->quan){ 2347 otmp = newobj(0); 2348 *otmp = *obj; 2349 bp->bo_id = otmp->o_id = flags.ident++; 2350 otmp->where = OBJ_FREE; 2351 otmp->quan = (bp->bquan -= obj->quan); 2352 otmp->owt = 0; /* superfluous */ 2353 otmp->onamelth = 0; 2354 otmp->oxlth = 0; 2355 otmp->oattached = OATTACHED_NOTHING; 2356 bp->useup = 1; 2357 add_to_billobjs(otmp); 2358 return; 2359 } 2360 ESHK(shkp)->billct--; 2361#ifdef DUMB 2362 { 2363 /* DRS/NS 2.2.6 messes up -- Peter Kendell */ 2364 int indx = ESHK(shkp)->billct; 2365 *bp = ESHK(shkp)->bill_p[indx]; 2366 } 2367#else 2368 *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct]; 2369#endif 2370 return; 2371 } else if (obj->unpaid) { 2372 impossible("sub_one_frombill: unpaid object not on bill"); 2373 obj->unpaid = 0; 2374 } 2375} 2376 2377/* recursive check of unpaid objects within nested containers. */ 2378void 2379subfrombill(obj, shkp) 2380register struct obj *obj; 2381register struct monst *shkp; 2382{ 2383 register struct obj *otmp; 2384 2385 sub_one_frombill(obj, shkp); 2386 2387 if (Has_contents(obj)) 2388 for(otmp = obj->cobj; otmp; otmp = otmp->nobj) { 2389 if(otmp->oclass == COIN_CLASS) continue; 2390 2391 if (Has_contents(otmp)) 2392 subfrombill(otmp, shkp); 2393 else 2394 sub_one_frombill(otmp, shkp); 2395 } 2396} 2397 2398#endif /*OVLB*/ 2399#ifdef OVL3 2400 2401STATIC_OVL long 2402stolen_container(obj, shkp, price, ininv) 2403register struct obj *obj; 2404register struct monst *shkp; 2405long price; 2406register boolean ininv; 2407{ 2408 register struct obj *otmp; 2409 2410 if(ininv && obj->unpaid) 2411 price += get_cost(obj, shkp); 2412 else { 2413 if(!obj->no_charge) 2414 price += get_cost(obj, shkp); 2415 obj->no_charge = 0; 2416 } 2417 2418 /* the price of contained objects, if any */ 2419 for(otmp = obj->cobj; otmp; otmp = otmp->nobj) { 2420 2421 if(otmp->oclass == COIN_CLASS) continue; 2422 2423 if (!Has_contents(otmp)) { 2424 if(ininv) { 2425 if(otmp->unpaid) 2426 price += otmp->quan * get_cost(otmp, shkp); 2427 } else { 2428 if(!otmp->no_charge) { 2429 if(otmp->oclass != FOOD_CLASS || !otmp->oeaten) 2430 price += otmp->quan * get_cost(otmp, shkp); 2431 } 2432 otmp->no_charge = 0; 2433 } 2434 } else 2435 price += stolen_container(otmp, shkp, price, ininv); 2436 } 2437 2438 return(price); 2439} 2440#endif /*OVL3*/ 2441#ifdef OVLB 2442 2443long 2444stolen_value(obj, x, y, peaceful, silent) 2445register struct obj *obj; 2446register xchar x, y; 2447register boolean peaceful, silent; 2448{ 2449 register long value = 0L, gvalue = 0L; 2450 register struct monst *shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)); 2451 2452 if (!shkp || !inhishop(shkp)) 2453 return (0L); 2454 2455 if(obj->oclass == COIN_CLASS) { 2456 gvalue += obj->quan; 2457 } else if (Has_contents(obj)) { 2458 register boolean ininv = !!count_unpaid(obj->cobj); 2459 2460 value += stolen_container(obj, shkp, value, ininv); 2461 if(!ininv) gvalue += contained_gold(obj); 2462 } else if (!obj->no_charge && saleable(shkp, obj)) { 2463 value += get_cost(obj, shkp); 2464 } 2465 2466 if(gvalue + value == 0L) return(0L); 2467 2468 value += gvalue; 2469 2470 if(peaceful) { 2471 boolean credit_use = !!ESHK(shkp)->credit; 2472 value = check_credit(value, shkp); 2473 /* 'peaceful' affects general treatment, but doesn't affect 2474 * the fact that other code expects that all charges after the 2475 * shopkeeper is angry are included in robbed, not debit */ 2476 if (ANGRY(shkp)) 2477 ESHK(shkp)->robbed += value; 2478 else 2479 ESHK(shkp)->debit += value; 2480 2481 if(!silent) { 2482 const char *still = ""; 2483 2484 if (credit_use) { 2485 if (ESHK(shkp)->credit) { 2486 You("have %ld %s credit remaining.", 2487 ESHK(shkp)->credit, currency(ESHK(shkp)->credit)); 2488 return value; 2489 } else if (!value) { 2490 You("have no credit remaining."); 2491 return 0; 2492 } 2493 still = "still "; 2494 } 2495 if(obj->oclass == COIN_CLASS) 2496 You("%sowe %s %ld %s!", still, 2497 mon_nam(shkp), value, currency(value)); 2498 else 2499 You("%sowe %s %ld %s for %s!", still, 2500 mon_nam(shkp), value, currency(value), 2501 obj->quan > 1L ? "them" : "it"); 2502 } 2503 } else { 2504 ESHK(shkp)->robbed += value; 2505 2506 if(!silent) { 2507 if(cansee(shkp->mx, shkp->my)) { 2508 Norep("%s booms: \"%s, you are a thief!\"", 2509 Monnam(shkp), plname); 2510 } else Norep("You hear a scream, \"Thief!\""); 2511 } 2512 hot_pursuit(shkp); 2513 (void) angry_guards(FALSE); 2514 } 2515 return(value); 2516} 2517 2518/* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */ 2519static char sell_response = 'a'; 2520static int sell_how = SELL_NORMAL; 2521/* can't just use sell_response='y' for auto_credit because the 'a' response 2522 shouldn't carry over from ordinary selling to credit selling */ 2523static boolean auto_credit = FALSE; 2524 2525void 2526sellobj_state(deliberate) 2527int deliberate; 2528{ 2529 /* If we're deliberately dropping something, there's no automatic 2530 response to the shopkeeper's "want to sell" query; however, if we 2531 accidentally drop anything, the shk will buy it/them without asking. 2532 This retains the old pre-query risk that slippery fingers while in 2533 shops entailed: you drop it, you've lost it. 2534 */ 2535 sell_response = (deliberate != SELL_NORMAL) ? '\0' : 'a'; 2536 sell_how = deliberate; 2537 auto_credit = FALSE; 2538} 2539 2540void 2541sellobj(obj, x, y) 2542register struct obj *obj; 2543xchar x, y; 2544{ 2545 register struct monst *shkp; 2546 register struct eshk *eshkp; 2547 long ltmp = 0L, cltmp = 0L, gltmp = 0L, offer; 2548 boolean saleitem, cgold = FALSE, container = Has_contents(obj); 2549 boolean isgold = (obj->oclass == COIN_CLASS); 2550 boolean only_partially_your_contents = FALSE; 2551 2552 if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || 2553 !inhishop(shkp)) return; 2554 if(!costly_spot(x, y)) return; 2555 if(!*u.ushops) return; 2556 2557 if(obj->unpaid && !container && !isgold) { 2558 sub_one_frombill(obj, shkp); 2559 return; 2560 } 2561 if(container) { 2562 /* find the price of content before subfrombill */ 2563 cltmp += contained_cost(obj, shkp, cltmp, TRUE, FALSE); 2564 /* find the value of contained gold */ 2565 gltmp += contained_gold(obj); 2566 cgold = (gltmp > 0L); 2567 } 2568 2569 saleitem = saleable(shkp, obj); 2570 if(!isgold && !obj->unpaid && saleitem) 2571 ltmp = set_cost(obj, shkp); 2572 2573 offer = ltmp + cltmp; 2574 2575 /* get one case out of the way: nothing to sell, and no gold */ 2576 if(!isgold && 2577 ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) { 2578 register boolean unpaid = (obj->unpaid || 2579 (container && count_unpaid(obj->cobj))); 2580 2581 if(container) { 2582 dropped_container(obj, shkp, FALSE); 2583 if(!obj->unpaid && !saleitem) 2584 obj->no_charge = 1; 2585 if(obj->unpaid || count_unpaid(obj->cobj)) 2586 subfrombill(obj, shkp); 2587 } else obj->no_charge = 1; 2588 2589 if(!unpaid && (sell_how != SELL_DONTSELL)) 2590 pline("%s seems uninterested.", Monnam(shkp)); 2591 return; 2592 } 2593 2594 /* you dropped something of your own - probably want to sell it */ 2595 rouse_shk(shkp, TRUE); /* wake up sleeping or paralyzed shk */ 2596 eshkp = ESHK(shkp); 2597 2598 if (ANGRY(shkp)) { /* they become shop-objects, no pay */ 2599 pline("Thank you, scum!"); 2600 subfrombill(obj, shkp); 2601 return; 2602 } 2603 2604 if(eshkp->robbed) { /* shkp is not angry? */ 2605 if(isgold) offer = obj->quan; 2606 else if(cgold) offer += cgold; 2607 if((eshkp->robbed -= offer < 0L)) 2608 eshkp->robbed = 0L; 2609 if(offer) verbalize( 2610 "Thank you for your contribution to restock this recently plundered shop."); 2611 subfrombill(obj, shkp); 2612 return; 2613 } 2614 2615 if(isgold || cgold) { 2616 if(!cgold) gltmp = obj->quan; 2617 2618 if(eshkp->debit >= gltmp) { 2619 if(eshkp->loan) { /* you carry shop's gold */ 2620 if(eshkp->loan >= gltmp) 2621 eshkp->loan -= gltmp; 2622 else eshkp->loan = 0L; 2623 } 2624 eshkp->debit -= gltmp; 2625 Your("debt is %spaid off.", 2626 eshkp->debit ? "partially " : ""); 2627 } else { 2628 long delta = gltmp - eshkp->debit; 2629 2630 eshkp->credit += delta; 2631 if(eshkp->debit) { 2632 eshkp->debit = 0L; 2633 eshkp->loan = 0L; 2634 Your("debt is paid off."); 2635 } 2636 pline("%ld %s %s added to your credit.", 2637 delta, currency(delta), delta > 1L ? "are" : "is"); 2638 } 2639 if(offer) goto move_on; 2640 else { 2641 if(!isgold) { 2642 if (container) 2643 dropped_container(obj, shkp, FALSE); 2644 if (!obj->unpaid && !saleitem) obj->no_charge = 1; 2645 subfrombill(obj, shkp); 2646 } 2647 return; 2648 } 2649 } 2650move_on: 2651 if((!saleitem && !(container && cltmp > 0L)) 2652 || eshkp->billct == BILLSZ 2653 || obj->oclass == BALL_CLASS 2654 || obj->oclass == CHAIN_CLASS || offer == 0L 2655 || (obj->oclass == FOOD_CLASS && obj->oeaten) 2656 || (Is_candle(obj) && 2657 obj->age < 20L * (long)objects[obj->otyp].oc_cost)) { 2658 pline("%s seems uninterested%s.", Monnam(shkp), 2659 cgold ? " in the rest" : ""); 2660 if (container) 2661 dropped_container(obj, shkp, FALSE); 2662 obj->no_charge = 1; 2663 return; 2664 } 2665 2666#ifndef GOLDOBJ 2667 if(!shkp->mgold) { 2668#else 2669 if(!money_cnt(shkp->minvent)) { 2670#endif 2671 char c, qbuf[BUFSZ]; 2672 long tmpcr = ((offer * 9L) / 10L) + (offer <= 1L); 2673 2674 if (sell_how == SELL_NORMAL || auto_credit) { 2675 c = sell_response = 'y'; 2676 } else if (sell_response != 'n') { 2677 pline("%s cannot pay you at present.", Monnam(shkp)); 2678 Sprintf(qbuf, 2679 "Will you accept %ld %s in credit for %s?", 2680 tmpcr, currency(tmpcr), doname(obj)); 2681 /* won't accept 'a' response here */ 2682 /* KLY - 3/2000 yes, we will, it's a damn nuisance 2683 to have to constantly hit 'y' to sell for credit */ 2684 c = ynaq(qbuf); 2685 if (c == 'a') { 2686 c = 'y'; 2687 auto_credit = TRUE; 2688 } 2689 } else /* previously specified "quit" */ 2690 c = 'n'; 2691 2692 if (c == 'y') { 2693 shk_names_obj(shkp, obj, (sell_how != SELL_NORMAL) ? 2694 "traded %s for %ld zorkmid%s in %scredit." : 2695 "relinquish %s and acquire %ld zorkmid%s in %scredit.", 2696 tmpcr, 2697 (eshkp->credit > 0L) ? "additional " : ""); 2698 eshkp->credit += tmpcr; 2699 subfrombill(obj, shkp); 2700 } else { 2701 if (c == 'q') sell_response = 'n'; 2702 if (container) 2703 dropped_container(obj, shkp, FALSE); 2704 if (!obj->unpaid) obj->no_charge = 1; 2705 subfrombill(obj, shkp); 2706 } 2707 } else { 2708 char qbuf[BUFSZ]; 2709#ifndef GOLDOBJ 2710 boolean short_funds = (offer > shkp->mgold); 2711 if (short_funds) offer = shkp->mgold; 2712#else 2713 long shkmoney = money_cnt(shkp->minvent); 2714 boolean short_funds = (offer > shkmoney); 2715 if (short_funds) offer = shkmoney; 2716#endif 2717 if (!sell_response) { 2718 only_partially_your_contents = 2719 (contained_cost(obj, shkp, 0L, FALSE, FALSE) != 2720 contained_cost(obj, shkp, 0L, FALSE, TRUE)); 2721 Sprintf(qbuf, 2722 "%s offers%s %ld gold piece%s for%s %s %s. Sell %s?", 2723 Monnam(shkp), short_funds ? " only" : "", 2724 offer, plur(offer), 2725 (!ltmp && cltmp && only_partially_your_contents) ? 2726 " your items in" : (!ltmp && cltmp) ? " the contents of" : "", 2727 obj->unpaid ? "the" : "your", cxname(obj), 2728 (obj->quan == 1L && 2729 !(!ltmp && cltmp && only_partially_your_contents)) ? 2730 "it" : "them"); 2731 } else qbuf[0] = '\0'; /* just to pacify lint */ 2732 2733 switch (sell_response ? sell_response : ynaq(qbuf)) { 2734 case 'q': sell_response = 'n'; 2735 case 'n': if (container) 2736 dropped_container(obj, shkp, FALSE); 2737 if (!obj->unpaid) obj->no_charge = 1; 2738 subfrombill(obj, shkp); 2739 break; 2740 case 'a': sell_response = 'y'; 2741 case 'y': if (container) 2742 dropped_container(obj, shkp, TRUE); 2743 if (!obj->unpaid && !saleitem) obj->no_charge = 1; 2744 subfrombill(obj, shkp); 2745 pay(-offer, shkp); 2746 shk_names_obj(shkp, obj, (sell_how != SELL_NORMAL) ? 2747 (!ltmp && cltmp && only_partially_your_contents) ? 2748 "sold some items inside %s for %ld gold pieces%s.%s" : 2749 "sold %s for %ld gold piece%s.%s" : 2750 "relinquish %s and receive %ld gold piece%s in compensation.%s", 2751 offer, ""); 2752 break; 2753 default: impossible("invalid sell response"); 2754 } 2755 } 2756} 2757 2758int 2759doinvbill(mode) 2760int mode; /* 0: deliver count 1: paged */ 2761{ 2762#ifdef __SASC 2763 void sasc_bug(struct obj *, unsigned); 2764#endif 2765 struct monst *shkp; 2766 struct eshk *eshkp; 2767 struct bill_x *bp, *end_bp; 2768 struct obj *obj; 2769 long totused; 2770 char *buf_p; 2771 winid datawin; 2772 2773 shkp = shop_keeper(*u.ushops); 2774 if (!shkp || !inhishop(shkp)) { 2775 if (mode != 0) impossible("doinvbill: no shopkeeper?"); 2776 return 0; 2777 } 2778 eshkp = ESHK(shkp); 2779 2780 if (mode == 0) { 2781 /* count expended items, so that the `I' command can decide 2782 whether to include 'x' in its prompt string */ 2783 int cnt = !eshkp->debit ? 0 : 1; 2784 2785 for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct]; 2786 bp < end_bp; bp++) 2787 if (bp->useup || 2788 ((obj = bp_to_obj(bp)) != 0 && obj->quan < bp->bquan)) 2789 cnt++; 2790 return cnt; 2791 } 2792 2793 datawin = create_nhwindow(NHW_MENU); 2794 putstr(datawin, 0, "Unpaid articles already used up:"); 2795 putstr(datawin, 0, ""); 2796 2797 totused = 0L; 2798 for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct]; 2799 bp < end_bp; bp++) { 2800 obj = bp_to_obj(bp); 2801 if(!obj) { 2802 impossible("Bad shopkeeper administration."); 2803 goto quit; 2804 } 2805 if(bp->useup || bp->bquan > obj->quan) { 2806 long oquan, uquan, thisused; 2807 unsigned save_unpaid; 2808 2809 save_unpaid = obj->unpaid; 2810 oquan = obj->quan; 2811 uquan = (bp->useup ? bp->bquan : bp->bquan - oquan); 2812 thisused = bp->price * uquan; 2813 totused += thisused; 2814 obj->unpaid = 0; /* ditto */ 2815 /* Why 'x'? To match `I x', more or less. */ 2816 buf_p = xprname(obj, (char *)0, 'x', FALSE, thisused, uquan); 2817#ifdef __SASC 2818 /* SAS/C 6.2 can't cope for some reason */ 2819 sasc_bug(obj,save_unpaid); 2820#else 2821 obj->unpaid = save_unpaid; 2822#endif 2823 putstr(datawin, 0, buf_p); 2824 } 2825 } 2826 if (eshkp->debit) { 2827 /* additional shop debt which has no itemization available */ 2828 if (totused) putstr(datawin, 0, ""); 2829 totused += eshkp->debit; 2830 buf_p = xprname((struct obj *)0, 2831 "usage charges and/or other fees", 2832 GOLD_SYM, FALSE, eshkp->debit, 0L); 2833 putstr(datawin, 0, buf_p); 2834 } 2835 buf_p = xprname((struct obj *)0, "Total:", '*', FALSE, totused, 0L); 2836 putstr(datawin, 0, ""); 2837 putstr(datawin, 0, buf_p); 2838 display_nhwindow(datawin, FALSE); 2839 quit: 2840 destroy_nhwindow(datawin); 2841 return(0); 2842} 2843 2844#define HUNGRY 2 2845 2846STATIC_OVL long 2847getprice(obj, shk_buying) 2848register struct obj *obj; 2849boolean shk_buying; 2850{ 2851 register long tmp = (long) objects[obj->otyp].oc_cost; 2852 2853 if (obj->oartifact) { 2854 tmp = arti_cost(obj); 2855 if (shk_buying) tmp /= 4; 2856 } 2857 switch(obj->oclass) { 2858 case FOOD_CLASS: 2859 /* simpler hunger check, (2-4)*cost */ 2860 if (u.uhs >= HUNGRY && !shk_buying) tmp *= (long) u.uhs; 2861 if (obj->oeaten) tmp = 0L; 2862 break; 2863 case WAND_CLASS: 2864 if (obj->spe == -1) tmp = 0L; 2865 break; 2866 case POTION_CLASS: 2867 if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed) 2868 tmp = 0L; 2869 break; 2870 case ARMOR_CLASS: 2871 case WEAPON_CLASS: 2872 if (obj->spe > 0) tmp += 10L * (long) obj->spe; 2873 break; 2874 case TOOL_CLASS: 2875 if (Is_candle(obj) && 2876 obj->age < 20L * (long)objects[obj->otyp].oc_cost) 2877 tmp /= 2L; 2878 break; 2879 } 2880 return tmp; 2881} 2882 2883/* shk catches thrown pick-axe */ 2884struct monst * 2885shkcatch(obj, x, y) 2886register struct obj *obj; 2887register xchar x, y; 2888{ 2889 register struct monst *shkp; 2890 2891 if (!(shkp = shop_keeper(inside_shop(x, y))) || 2892 !inhishop(shkp)) return(0); 2893 2894 if (shkp->mcanmove && !shkp->msleeping && 2895 (*u.ushops != ESHK(shkp)->shoproom || !inside_shop(u.ux, u.uy)) && 2896 dist2(shkp->mx, shkp->my, x, y) < 3 && 2897 /* if it is the shk's pos, you hit and anger him */ 2898 (shkp->mx != x || shkp->my != y)) { 2899 if (mnearto(shkp, x, y, TRUE)) 2900 verbalize("Out of my way, scum!"); 2901 if (cansee(x, y)) { 2902 pline("%s nimbly%s catches %s.", 2903 Monnam(shkp), 2904 (x == shkp->mx && y == shkp->my) ? "" : " reaches over and", 2905 the(xname(obj))); 2906 if (!canspotmon(shkp)) 2907 map_invisible(x, y); 2908 delay_output(); 2909 mark_synch(); 2910 } 2911 subfrombill(obj, shkp); 2912 (void) mpickobj(shkp, obj); 2913 return shkp; 2914 } 2915 return (struct monst *)0; 2916} 2917 2918void 2919add_damage(x, y, cost) 2920register xchar x, y; 2921long cost; 2922{ 2923 struct damage *tmp_dam; 2924 char *shops; 2925 2926 if (IS_DOOR(levl[x][y].typ)) { 2927 struct monst *mtmp; 2928 2929 /* Don't schedule for repair unless it's a real shop entrance */ 2930 for (shops = in_rooms(x, y, SHOPBASE); *shops; shops++) 2931 if ((mtmp = shop_keeper(*shops)) != 0 && 2932 x == ESHK(mtmp)->shd.x && y == ESHK(mtmp)->shd.y) 2933 break; 2934 if (!*shops) return; 2935 } 2936 for (tmp_dam = level.damagelist; tmp_dam; tmp_dam = tmp_dam->next) 2937 if (tmp_dam->place.x == x && tmp_dam->place.y == y) { 2938 tmp_dam->cost += cost; 2939 return; 2940 } 2941 tmp_dam = (struct damage *)alloc((unsigned)sizeof(struct damage)); 2942 tmp_dam->when = monstermoves; 2943 tmp_dam->place.x = x; 2944 tmp_dam->place.y = y; 2945 tmp_dam->cost = cost; 2946 tmp_dam->typ = levl[x][y].typ; 2947 tmp_dam->next = level.damagelist; 2948 level.damagelist = tmp_dam; 2949 /* If player saw damage, display as a wall forever */ 2950 if (cansee(x, y)) 2951 levl[x][y].seenv = SVALL; 2952} 2953 2954#endif /*OVLB*/ 2955#ifdef OVL0 2956 2957/* 2958 * Do something about damage. Either (!croaked) try to repair it, or 2959 * (croaked) just discard damage structs for non-shared locations, since 2960 * they'll never get repaired. Assume that shared locations will get 2961 * repaired eventually by the other shopkeeper(s). This might be an erroneous 2962 * assumption (they might all be dead too), but we have no reasonable way of 2963 * telling that. 2964 */ 2965STATIC_OVL 2966void 2967remove_damage(shkp, croaked) 2968register struct monst *shkp; 2969register boolean croaked; 2970{ 2971 register struct damage *tmp_dam, *tmp2_dam; 2972 register boolean did_repair = FALSE, saw_door = FALSE; 2973 register boolean saw_floor = FALSE, stop_picking = FALSE; 2974 register boolean saw_untrap = FALSE; 2975 uchar saw_walls = 0; 2976 2977 tmp_dam = level.damagelist; 2978 tmp2_dam = 0; 2979 while (tmp_dam) { 2980 register xchar x = tmp_dam->place.x, y = tmp_dam->place.y; 2981 char shops[5]; 2982 int disposition; 2983 2984 disposition = 0; 2985 Strcpy(shops, in_rooms(x, y, SHOPBASE)); 2986 if (index(shops, ESHK(shkp)->shoproom)) { 2987 if (croaked) 2988 disposition = (shops[1])? 0 : 1; 2989 else if (stop_picking) 2990 disposition = repair_damage(shkp, tmp_dam, FALSE); 2991 else { 2992 /* Defer the stop_occupation() until after repair msgs */ 2993 if (closed_door(x, y)) 2994 stop_picking = picking_at(x, y); 2995 disposition = repair_damage(shkp, tmp_dam, FALSE); 2996 if (!disposition) 2997 stop_picking = FALSE; 2998 } 2999 } 3000 3001 if (!disposition) { 3002 tmp2_dam = tmp_dam; 3003 tmp_dam = tmp_dam->next; 3004 continue; 3005 } 3006 3007 if (disposition > 1) { 3008 did_repair = TRUE; 3009 if (cansee(x, y)) { 3010 if (IS_WALL(levl[x][y].typ)) 3011 saw_walls++; 3012 else if (IS_DOOR(levl[x][y].typ)) 3013 saw_door = TRUE; 3014 else if (disposition == 3) /* untrapped */ 3015 saw_untrap = TRUE; 3016 else 3017 saw_floor = TRUE; 3018 } 3019 } 3020 3021 tmp_dam = tmp_dam->next; 3022 if (!tmp2_dam) { 3023 free((genericptr_t)level.damagelist); 3024 level.damagelist = tmp_dam; 3025 } else { 3026 free((genericptr_t)tmp2_dam->next); 3027 tmp2_dam->next = tmp_dam; 3028 } 3029 } 3030 if (!did_repair) 3031 return; 3032 if (saw_walls) { 3033 pline("Suddenly, %s section%s of wall close%s up!", 3034 (saw_walls == 1) ? "a" : (saw_walls <= 3) ? 3035 "some" : "several", 3036 (saw_walls == 1) ? "" : "s", (saw_walls == 1) ? "s" : ""); 3037 if (saw_door) 3038 pline_The("shop door reappears!"); 3039 if (saw_floor) 3040 pline_The("floor is repaired!"); 3041 } else { 3042 if (saw_door) 3043 pline("Suddenly, the shop door reappears!"); 3044 else if (saw_floor) 3045 pline("Suddenly, the floor damage is gone!"); 3046 else if (saw_untrap) 3047 pline("Suddenly, the trap is removed from the floor!"); 3048 else if (inside_shop(u.ux, u.uy) == ESHK(shkp)->shoproom) 3049 You_feel("more claustrophobic than before."); 3050 else if (flags.soundok && !rn2(10)) 3051 Norep("The dungeon acoustics noticeably change."); 3052 } 3053 if (stop_picking) 3054 stop_occupation(); 3055} 3056 3057/* 3058 * 0: repair postponed, 1: silent repair (no messages), 2: normal repair 3059 * 3: untrap 3060 */ 3061int 3062repair_damage(shkp, tmp_dam, catchup) 3063register struct monst *shkp; 3064register struct damage *tmp_dam; 3065boolean catchup; /* restoring a level */ 3066{ 3067 register xchar x, y, i; 3068 xchar litter[9]; 3069 register struct monst *mtmp; 3070 register struct obj *otmp; 3071 register struct trap *ttmp; 3072 3073 if ((monstermoves - tmp_dam->when) < REPAIR_DELAY) 3074 return(0); 3075 if (shkp->msleeping || !shkp->mcanmove || ESHK(shkp)->following) 3076 return(0); 3077 x = tmp_dam->place.x; 3078 y = tmp_dam->place.y; 3079 if (!IS_ROOM(tmp_dam->typ)) { 3080 if (x == u.ux && y == u.uy) 3081 if (!Passes_walls) 3082 return(0); 3083 if (x == shkp->mx && y == shkp->my) 3084 return(0); 3085 if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data))) 3086 return(0); 3087 } 3088 if ((ttmp = t_at(x, y)) != 0) { 3089 if (x == u.ux && y == u.uy) 3090 if (!Passes_walls) 3091 return(0); 3092 if (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP) { 3093 /* convert to an object */ 3094 otmp = mksobj((ttmp->ttyp == LANDMINE) ? LAND_MINE : 3095 BEARTRAP, TRUE, FALSE); 3096 otmp->quan= 1; 3097 otmp->owt = weight(otmp); 3098 (void) mpickobj(shkp, otmp); 3099 } 3100 deltrap(ttmp); 3101 if(IS_DOOR(tmp_dam->typ)) { 3102 levl[x][y].doormask = D_CLOSED; /* arbitrary */ 3103 block_point(x, y); 3104 } else if (IS_WALL(tmp_dam->typ)) { 3105 levl[x][y].typ = tmp_dam->typ; 3106 block_point(x, y); 3107 } 3108 newsym(x, y); 3109 return(3); 3110 } 3111 if (IS_ROOM(tmp_dam->typ)) { 3112 /* No messages, because player already filled trap door */ 3113 return(1); 3114 } 3115 if ((tmp_dam->typ == levl[x][y].typ) && 3116 (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN))) 3117 /* No messages if player already replaced shop door */ 3118 return(1); 3119 levl[x][y].typ = tmp_dam->typ; 3120 (void) memset((genericptr_t)litter, 0, sizeof(litter)); 3121 if ((otmp = level.objects[x][y]) != 0) { 3122 /* Scatter objects haphazardly into the shop */ 3123#define NEED_UPDATE 1 3124#define OPEN 2 3125#define INSHOP 4 3126#define horiz(i) ((i%3)-1) 3127#define vert(i) ((i/3)-1) 3128 for (i = 0; i < 9; i++) { 3129 if ((i == 4) || (!ZAP_POS(levl[x+horiz(i)][y+vert(i)].typ))) 3130 continue; 3131 litter[i] = OPEN; 3132 if (inside_shop(x+horiz(i), 3133 y+vert(i)) == ESHK(shkp)->shoproom) 3134 litter[i] |= INSHOP; 3135 } 3136 if (Punished && !u.uswallow && 3137 ((uchain->ox == x && uchain->oy == y) || 3138 (uball->ox == x && uball->oy == y))) { 3139 /* 3140 * Either the ball or chain is in the repair location. 3141 * 3142 * Take the easy way out and put ball&chain under hero. 3143 */ 3144 verbalize("Get your junk out of my wall!"); 3145 unplacebc(); /* pick 'em up */ 3146 placebc(); /* put 'em down */ 3147 } 3148 while ((otmp = level.objects[x][y]) != 0) 3149 /* Don't mess w/ boulders -- just merge into wall */ 3150 if ((otmp->otyp == BOULDER) || (otmp->otyp == ROCK)) { 3151 obj_extract_self(otmp); 3152 obfree(otmp, (struct obj *)0); 3153 } else { 3154 while (!(litter[i = rn2(9)] & INSHOP)); 3155 remove_object(otmp); 3156 place_object(otmp, x+horiz(i), y+vert(i)); 3157 litter[i] |= NEED_UPDATE; 3158 } 3159 } 3160 if (catchup) return 1; /* repair occurred while off level */ 3161 3162 block_point(x, y); 3163 if(IS_DOOR(tmp_dam->typ)) { 3164 levl[x][y].doormask = D_CLOSED; /* arbitrary */ 3165 newsym(x, y); 3166 } else { 3167 /* don't set doormask - it is (hopefully) the same as it was */ 3168 /* if not, perhaps save it with the damage array... */ 3169 3170 if (IS_WALL(tmp_dam->typ) && cansee(x, y)) { 3171 /* Player sees actual repair process, so they KNOW it's a wall */ 3172 levl[x][y].seenv = SVALL; 3173 newsym(x, y); 3174 } 3175 /* Mark this wall as "repaired". There currently is no code */ 3176 /* to do anything about repaired walls, so don't do it. */ 3177 } 3178 for (i = 0; i < 9; i++) 3179 if (litter[i] & NEED_UPDATE) 3180 newsym(x+horiz(i), y+vert(i)); 3181 return(2); 3182#undef NEED_UPDATE 3183#undef OPEN 3184#undef INSHOP 3185#undef vert 3186#undef horiz 3187} 3188#endif /*OVL0*/ 3189#ifdef OVL3 3190/* 3191 * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died 3192 */ 3193int 3194shk_move(shkp) 3195register struct monst *shkp; 3196{ 3197 register xchar gx,gy,omx,omy; 3198 register int udist; 3199 register schar appr; 3200 register struct eshk *eshkp = ESHK(shkp); 3201 int z; 3202 boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv; 3203 3204 omx = shkp->mx; 3205 omy = shkp->my; 3206 3207 if (inhishop(shkp)) 3208 remove_damage(shkp, FALSE); 3209 3210 if((udist = distu(omx,omy)) < 3 && 3211 (shkp->data != &mons[PM_GRID_BUG] || (omx==u.ux || omy==u.uy))) { 3212 if(ANGRY(shkp) || 3213 (Conflict && !resist(shkp, RING_CLASS, 0, 0))) { 3214 if(Displaced) 3215 Your("displaced image doesn't fool %s!", 3216 mon_nam(shkp)); 3217 (void) mattacku(shkp); 3218 return(0); 3219 } 3220 if(eshkp->following) { 3221 if(strncmp(eshkp->customer, plname, PL_NSIZ)) { 3222 verbalize("%s, %s! I was looking for %s.", 3223 Hello(shkp), plname, eshkp->customer); 3224 eshkp->following = 0; 3225 return(0); 3226 } 3227 if(moves > followmsg+4) { 3228 verbalize("%s, %s! Didn't you forget to pay?", 3229 Hello(shkp), plname); 3230 followmsg = moves; 3231 if (!rn2(9)) { 3232 pline("%s doesn't like customers who don't pay.", 3233 Monnam(shkp)); 3234 rile_shk(shkp); 3235 } 3236 } 3237 if(udist < 2) 3238 return(0); 3239 } 3240 } 3241 3242 appr = 1; 3243 gx = eshkp->shk.x; 3244 gy = eshkp->shk.y; 3245 satdoor = (gx == omx && gy == omy); 3246 if(eshkp->following || ((z = holetime()) >= 0 && z*z <= udist)){ 3247 /* [This distance check used to apply regardless of 3248 whether the shk was following, but that resulted in 3249 m_move() sometimes taking the shk out of the shop if 3250 the player had fenced him in with boulders or traps. 3251 Such voluntary abandonment left unpaid objects in 3252 invent, triggering billing impossibilities on the 3253 next level once the character fell through the hole.] */ 3254 if (udist > 4 && eshkp->following) 3255 return(-1); /* leave it to m_move */ 3256 gx = u.ux; 3257 gy = u.uy; 3258 } else if(ANGRY(shkp)) { 3259 /* Move towards the hero if the shopkeeper can see him. */ 3260 if(shkp->mcansee && m_canseeu(shkp)) { 3261 gx = u.ux; 3262 gy = u.uy; 3263 } 3264 avoid = FALSE; 3265 } else { 3266#define GDIST(x,y) (dist2(x,y,gx,gy)) 3267 if (Invis 3268#ifdef STEED 3269 || u.usteed 3270#endif 3271 ) { 3272 avoid = FALSE; 3273 } else { 3274 uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y); 3275 if(uondoor) { 3276 badinv = (carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK) || 3277 (Fast && (sobj_at(PICK_AXE, u.ux, u.uy) || 3278 sobj_at(DWARVISH_MATTOCK, u.ux, u.uy)))); 3279 if(satdoor && badinv) 3280 return(0); 3281 avoid = !badinv; 3282 } else { 3283 avoid = (*u.ushops && distu(gx,gy) > 8); 3284 badinv = FALSE; 3285 } 3286 3287 if(((!eshkp->robbed && !eshkp->billct && !eshkp->debit) 3288 || avoid) && GDIST(omx,omy) < 3) { 3289 if (!badinv && !onlineu(omx,omy)) 3290 return(0); 3291 if(satdoor) 3292 appr = gx = gy = 0; 3293 } 3294 } 3295 } 3296 3297 z = move_special(shkp,inhishop(shkp),appr,uondoor,avoid,omx,omy,gx,gy); 3298 if (z > 0) after_shk_move(shkp); 3299 3300 return z; 3301} 3302 3303/* called after shopkeeper moves, in case the move causes re-entry into shop */ 3304void 3305after_shk_move(shkp) 3306struct monst *shkp; 3307{ 3308 struct eshk *eshkp = ESHK(shkp); 3309 3310 if (eshkp->bill_p == (struct bill_x *) -1000 && inhishop(shkp)) { 3311 /* reset bill_p, need to re-calc player's occupancy too */ 3312 eshkp->bill_p = &eshkp->bill[0]; 3313 check_special_room(FALSE); 3314 } 3315} 3316 3317#endif /*OVL3*/ 3318#ifdef OVLB 3319 3320/* for use in levl_follower (mondata.c) */ 3321boolean 3322is_fshk(mtmp) 3323register struct monst *mtmp; 3324{ 3325 return((boolean)(mtmp->isshk && ESHK(mtmp)->following)); 3326} 3327 3328/* You are digging in the shop. */ 3329void 3330shopdig(fall) 3331register int fall; 3332{ 3333 register struct monst *shkp = shop_keeper(*u.ushops); 3334 int lang; 3335 const char *grabs = "grabs"; 3336 3337 if(!shkp) return; 3338 3339 /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */ 3340 lang = 0; 3341 if (shkp->msleeping || !shkp->mcanmove || is_silent(shkp->data)) 3342 ; /* lang stays 0 */ 3343 else if (shkp->data->msound <= MS_ANIMAL) 3344 lang = 1; 3345 else if (shkp->data->msound >= MS_HUMANOID) 3346 lang = 2; 3347 3348 if(!inhishop(shkp)) { 3349 if (Role_if(PM_KNIGHT)) { 3350 You_feel("like a common thief."); 3351 adjalign(-sgn(u.ualign.type)); 3352 } 3353 return; 3354 } 3355 3356 if(!fall) { 3357 if (lang == 2) { 3358 if(u.utraptype == TT_PIT) 3359 verbalize( 3360 "Be careful, %s, or you might fall through the floor.", 3361 flags.female ? "madam" : "sir"); 3362 else 3363 verbalize("%s, do not damage the floor here!", 3364 flags.female ? "Madam" : "Sir"); 3365 } 3366 if (Role_if(PM_KNIGHT)) { 3367 You_feel("like a common thief."); 3368 adjalign(-sgn(u.ualign.type)); 3369 } 3370 } else if(!um_dist(shkp->mx, shkp->my, 5) && 3371 !shkp->msleeping && shkp->mcanmove && 3372 (ESHK(shkp)->billct || ESHK(shkp)->debit)) { 3373 register struct obj *obj, *obj2; 3374 if (nolimbs(shkp->data)) { 3375 grabs = "knocks off"; 3376#if 0 3377 /* This is what should happen, but for balance 3378 * reasons, it isn't currently. 3379 */ 3380 if (lang == 2) 3381 pline("%s curses %s inability to grab your backpack!", 3382 shkname(shkp), mhim(shkp)); 3383 rile_shk(shkp); 3384 return; 3385#endif 3386 } 3387 if (distu(shkp->mx, shkp->my) > 2) { 3388 mnexto(shkp); 3389 /* for some reason the shopkeeper can't come next to you */ 3390 if (distu(shkp->mx, shkp->my) > 2) { 3391 if (lang == 2) 3392 pline("%s curses you in anger and frustration!", 3393 shkname(shkp)); 3394 rile_shk(shkp); 3395 return; 3396 } else 3397 pline("%s %s, and %s your backpack!", 3398 shkname(shkp), 3399 makeplural(locomotion(shkp->data,"leap")), grabs); 3400 } else 3401 pline("%s %s your backpack!", shkname(shkp), grabs); 3402 3403 for(obj = invent; obj; obj = obj2) { 3404 obj2 = obj->nobj; 3405 if ((obj->owornmask & ~(W_SWAPWEP|W_QUIVER)) != 0 || 3406 (obj == uswapwep && u.twoweap) || 3407 (obj->otyp == LEASH && obj->leashmon)) continue; 3408 if (obj == current_wand) continue; 3409 setnotworn(obj); 3410 freeinv(obj); 3411 subfrombill(obj, shkp); 3412 (void) add_to_minv(shkp, obj); /* may free obj */ 3413 } 3414 } 3415} 3416 3417#ifdef KOPS 3418STATIC_OVL void 3419makekops(mm) 3420coord *mm; 3421{ 3422 static const short k_mndx[4] = { 3423 PM_KEYSTONE_KOP, PM_KOP_SERGEANT, PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN 3424 }; 3425 int k_cnt[4], cnt, mndx, k; 3426 3427 k_cnt[0] = cnt = abs(depth(&u.uz)) + rnd(5); 3428 k_cnt[1] = (cnt / 3) + 1; /* at least one sarge */ 3429 k_cnt[2] = (cnt / 6); /* maybe a lieutenant */ 3430 k_cnt[3] = (cnt / 9); /* and maybe a kaptain */ 3431 3432 for (k = 0; k < 4; k++) { 3433 if ((cnt = k_cnt[k]) == 0) break; 3434 mndx = k_mndx[k]; 3435 if (mvitals[mndx].mvflags & G_GONE) continue; 3436 3437 while (cnt--) 3438 if (enexto(mm, mm->x, mm->y, &mons[mndx])) 3439 (void) makemon(&mons[mndx], mm->x, mm->y, NO_MM_FLAGS); 3440 } 3441} 3442#endif /* KOPS */ 3443 3444void 3445pay_for_damage(dmgstr, cant_mollify) 3446const char *dmgstr; 3447boolean cant_mollify; 3448{ 3449 register struct monst *shkp = (struct monst *)0; 3450 char shops_affected[5]; 3451 register boolean uinshp = (*u.ushops != '\0'); 3452 char qbuf[80]; 3453 register xchar x, y; 3454 boolean dugwall = !strcmp(dmgstr, "dig into") || /* wand */ 3455 !strcmp(dmgstr, "damage"); /* pick-axe */ 3456 struct damage *tmp_dam, *appear_here = 0; 3457 /* any number >= (80*80)+(24*24) would do, actually */ 3458 long cost_of_damage = 0L; 3459 unsigned int nearest_shk = 7000, nearest_damage = 7000; 3460 int picks = 0; 3461 3462 for (tmp_dam = level.damagelist; 3463 (tmp_dam && (tmp_dam->when == monstermoves)); 3464 tmp_dam = tmp_dam->next) { 3465 char *shp; 3466 3467 if (!tmp_dam->cost) 3468 continue; 3469 cost_of_damage += tmp_dam->cost; 3470 Strcpy(shops_affected, 3471 in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE)); 3472 for (shp = shops_affected; *shp; shp++) { 3473 struct monst *tmp_shk; 3474 unsigned int shk_distance; 3475 3476 if (!(tmp_shk = shop_keeper(*shp))) 3477 continue; 3478 if (tmp_shk == shkp) { 3479 unsigned int damage_distance = 3480 distu(tmp_dam->place.x, tmp_dam->place.y); 3481 3482 if (damage_distance < nearest_damage) { 3483 nearest_damage = damage_distance; 3484 appear_here = tmp_dam; 3485 } 3486 continue; 3487 } 3488 if (!inhishop(tmp_shk)) 3489 continue; 3490 shk_distance = distu(tmp_shk->mx, tmp_shk->my); 3491 if (shk_distance > nearest_shk) 3492 continue; 3493 if ((shk_distance == nearest_shk) && picks) { 3494 if (rn2(++picks)) 3495 continue; 3496 } else 3497 picks = 1; 3498 shkp = tmp_shk; 3499 nearest_shk = shk_distance; 3500 appear_here = tmp_dam; 3501 nearest_damage = distu(tmp_dam->place.x, tmp_dam->place.y); 3502 } 3503 } 3504 3505 if (!cost_of_damage || !shkp) 3506 return; 3507 3508 x = appear_here->place.x; 3509 y = appear_here->place.y; 3510 3511 /* not the best introduction to the shk... */ 3512 (void) strncpy(ESHK(shkp)->customer,plname,PL_NSIZ); 3513 3514 /* if the shk is already on the war path, be sure it's all out */ 3515 if(ANGRY(shkp) || ESHK(shkp)->following) { 3516 hot_pursuit(shkp); 3517 return; 3518 } 3519 3520 /* if the shk is not in their shop.. */ 3521 if(!*in_rooms(shkp->mx,shkp->my,SHOPBASE)) { 3522 if(!cansee(shkp->mx, shkp->my)) 3523 return; 3524 goto getcad; 3525 } 3526 3527 if(uinshp) { 3528 if(um_dist(shkp->mx, shkp->my, 1) && 3529 !um_dist(shkp->mx, shkp->my, 3)) { 3530 pline("%s leaps towards you!", shkname(shkp)); 3531 mnexto(shkp); 3532 } 3533 if(um_dist(shkp->mx, shkp->my, 1)) goto getcad; 3534 } else { 3535 /* 3536 * Make shkp show up at the door. Effect: If there is a monster 3537 * in the doorway, have the hero hear the shopkeeper yell a bit, 3538 * pause, then have the shopkeeper appear at the door, having 3539 * yanked the hapless critter out of the way. 3540 */ 3541 if (MON_AT(x, y)) { 3542 if(flags.soundok) { 3543 You_hear("an angry voice:"); 3544 verbalize("Out of my way, scum!"); 3545 wait_synch(); 3546#if defined(UNIX) || defined(VMS) 3547# if defined(SYSV) || defined(ULTRIX) || defined(VMS) 3548 (void) 3549# endif 3550 sleep(1); 3551#endif 3552 } 3553 } 3554 (void) mnearto(shkp, x, y, TRUE); 3555 } 3556 3557 if((um_dist(x, y, 1) && !uinshp) || cant_mollify || 3558#ifndef GOLDOBJ 3559 (u.ugold + ESHK(shkp)->credit) < cost_of_damage 3560#else 3561 (money_cnt(invent) + ESHK(shkp)->credit) < cost_of_damage 3562#endif 3563 || !rn2(50)) { 3564 if(um_dist(x, y, 1) && !uinshp) { 3565 pline("%s shouts:", shkname(shkp)); 3566 verbalize("Who dared %s my %s?", dmgstr, 3567 dugwall ? "shop" : "door"); 3568 } else { 3569getcad: 3570 verbalize("How dare you %s my %s?", dmgstr, 3571 dugwall ? "shop" : "door"); 3572 } 3573 hot_pursuit(shkp); 3574 return; 3575 } 3576 3577 if (Invis) Your("invisibility does not fool %s!", shkname(shkp)); 3578 Sprintf(qbuf,"\"Cad! You did %ld %s worth of damage!\" Pay? ", 3579 cost_of_damage, currency(cost_of_damage)); 3580 if(yn(qbuf) != 'n') { 3581 cost_of_damage = check_credit(cost_of_damage, shkp); 3582#ifndef GOLDOBJ 3583 u.ugold -= cost_of_damage; 3584 shkp->mgold += cost_of_damage; 3585#else 3586 money2mon(shkp, cost_of_damage); 3587#endif 3588 flags.botl = 1; 3589 pline("Mollified, %s accepts your restitution.", 3590 shkname(shkp)); 3591 /* move shk back to his home loc */ 3592 home_shk(shkp, FALSE); 3593 pacify_shk(shkp); 3594 } else { 3595 verbalize("Oh, yes! You'll pay!"); 3596 hot_pursuit(shkp); 3597 adjalign(-sgn(u.ualign.type)); 3598 } 3599} 3600#endif /*OVLB*/ 3601#ifdef OVL0 3602/* called in dokick.c when we kick an object that might be in a store */ 3603boolean 3604costly_spot(x, y) 3605register xchar x, y; 3606{ 3607 register struct monst *shkp; 3608 3609 if (!level.flags.has_shop) return FALSE; 3610 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)); 3611 if(!shkp || !inhishop(shkp)) return(FALSE); 3612 3613 return((boolean)(inside_shop(x, y) && 3614 !(x == ESHK(shkp)->shk.x && 3615 y == ESHK(shkp)->shk.y))); 3616} 3617#endif /*OVL0*/ 3618#ifdef OVLB 3619 3620/* called by dotalk(sounds.c) when #chatting; returns obj if location 3621 contains shop goods and shopkeeper is willing & able to speak */ 3622struct obj * 3623shop_object(x, y) 3624register xchar x, y; 3625{ 3626 register struct obj *otmp; 3627 register struct monst *shkp; 3628 3629 if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp)) 3630 return(struct obj *)0; 3631 3632 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) 3633 if (otmp->oclass != COIN_CLASS) 3634 break; 3635 /* note: otmp might have ->no_charge set, but that's ok */ 3636 return (otmp && costly_spot(x, y) && NOTANGRY(shkp) 3637 && shkp->mcanmove && !shkp->msleeping) 3638 ? otmp : (struct obj *)0; 3639} 3640 3641/* give price quotes for all objects linked to this one (ie, on this spot) */ 3642void 3643price_quote(first_obj) 3644register struct obj *first_obj; 3645{ 3646 register struct obj *otmp; 3647 char buf[BUFSZ], price[40]; 3648 long cost; 3649 int cnt = 0; 3650 winid tmpwin; 3651 struct monst *shkp = shop_keeper(inside_shop(u.ux, u.uy)); 3652 3653 tmpwin = create_nhwindow(NHW_MENU); 3654 putstr(tmpwin, 0, "Fine goods for sale:"); 3655 putstr(tmpwin, 0, ""); 3656 for (otmp = first_obj; otmp; otmp = otmp->nexthere) { 3657 if (otmp->oclass == COIN_CLASS) continue; 3658 cost = (otmp->no_charge || otmp == uball || otmp == uchain) ? 0L : 3659 get_cost(otmp, (struct monst *)0); 3660 if (Has_contents(otmp)) 3661 cost += contained_cost(otmp, shkp, 0L, FALSE, FALSE); 3662 if (!cost) { 3663 Strcpy(price, "no charge"); 3664 } else { 3665 Sprintf(price, "%ld %s%s", cost, currency(cost), 3666 otmp->quan > 1L ? " each" : ""); 3667 } 3668 Sprintf(buf, "%s, %s", doname(otmp), price); 3669 putstr(tmpwin, 0, buf), cnt++; 3670 } 3671 if (cnt > 1) { 3672 display_nhwindow(tmpwin, TRUE); 3673 } else if (cnt == 1) { 3674 if (first_obj->no_charge || first_obj == uball || first_obj == uchain){ 3675 pline("%s!", buf); /* buf still contains the string */ 3676 } else { 3677 /* print cost in slightly different format, so can't reuse buf */ 3678 cost = get_cost(first_obj, (struct monst *)0); 3679 if (Has_contents(first_obj)) 3680 cost += contained_cost(first_obj, shkp, 0L, FALSE, FALSE); 3681 pline("%s, price %ld %s%s%s", doname(first_obj), 3682 cost, currency(cost), first_obj->quan > 1L ? " each" : "", 3683 shk_embellish(first_obj, cost)); 3684 } 3685 } 3686 destroy_nhwindow(tmpwin); 3687} 3688#endif /*OVLB*/ 3689#ifdef OVL3 3690 3691STATIC_OVL const char * 3692shk_embellish(itm, cost) 3693register struct obj *itm; 3694long cost; 3695{ 3696 if (!rn2(3)) { 3697 register int o, choice = rn2(5); 3698 if (choice == 0) choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3); 3699 switch (choice) { 3700 case 4: 3701 if (cost < 10L) break; else o = itm->oclass; 3702 if (o == FOOD_CLASS) return ", gourmets' delight!"; 3703 if (objects[itm->otyp].oc_name_known 3704 ? objects[itm->otyp].oc_magic 3705 : (o == AMULET_CLASS || o == RING_CLASS || 3706 o == WAND_CLASS || o == POTION_CLASS || 3707 o == SCROLL_CLASS || o == SPBOOK_CLASS)) 3708 return ", painstakingly developed!"; 3709 return ", superb craftsmanship!"; 3710 case 3: return ", finest quality."; 3711 case 2: return ", an excellent choice."; 3712 case 1: return ", a real bargain."; 3713 default: break; 3714 } 3715 } else if (itm->oartifact) { 3716 return ", one of a kind!"; 3717 } 3718 return "."; 3719} 3720#endif /*OVL3*/ 3721#ifdef OVLB 3722 3723/* First 4 supplied by Ronen and Tamar, remainder by development team */ 3724const char *Izchak_speaks[]={ 3725 "%s says: 'These shopping malls give me a headache.'", 3726 "%s says: 'Slow down. Think clearly.'", 3727 "%s says: 'You need to take things one at a time.'", 3728 "%s says: 'I don't like poofy coffee... give me Columbian Supremo.'", 3729 "%s says that getting the devteam's agreement on anything is difficult.", 3730 "%s says that he has noticed those who serve their deity will prosper.", 3731 "%s says: 'Don't try to steal from me - I have friends in high places!'", 3732 "%s says: 'You may well need something from this shop in the future.'", 3733 "%s comments about the Valley of the Dead as being a gateway." 3734}; 3735 3736void 3737shk_chat(shkp) 3738struct monst *shkp; 3739{ 3740 struct eshk *eshk; 3741#ifdef GOLDOBJ 3742 long shkmoney; 3743#endif 3744 if (!shkp->isshk) { 3745 /* The monster type is shopkeeper, but this monster is 3746 not actually a shk, which could happen if someone 3747 wishes for a shopkeeper statue and then animates it. 3748 (Note: shkname() would be "" in a case like this.) */ 3749 pline("%s asks whether you've seen any untended shops recently.", 3750 Monnam(shkp)); 3751 /* [Perhaps we ought to check whether this conversation 3752 is taking place inside an untended shop, but a shopless 3753 shk can probably be expected to be rather disoriented.] */ 3754 return; 3755 } 3756 3757 eshk = ESHK(shkp); 3758 if (ANGRY(shkp)) 3759 pline("%s mentions how much %s dislikes %s customers.", 3760 shkname(shkp), mhe(shkp), 3761 eshk->robbed ? "non-paying" : "rude"); 3762 else if (eshk->following) { 3763 if (strncmp(eshk->customer, plname, PL_NSIZ)) { 3764 verbalize("%s %s! I was looking for %s.", 3765 Hello(shkp), plname, eshk->customer); 3766 eshk->following = 0; 3767 } else { 3768 verbalize("%s %s! Didn't you forget to pay?", 3769 Hello(shkp), plname); 3770 } 3771 } else if (eshk->billct) { 3772 register long total = addupbill(shkp) + eshk->debit; 3773 pline("%s says that your bill comes to %ld %s.", 3774 shkname(shkp), total, currency(total)); 3775 } else if (eshk->debit) 3776 pline("%s reminds you that you owe %s %ld %s.", 3777 shkname(shkp), mhim(shkp), 3778 eshk->debit, currency(eshk->debit)); 3779 else if (eshk->credit) 3780 pline("%s encourages you to use your %ld %s of credit.", 3781 shkname(shkp), eshk->credit, currency(eshk->credit)); 3782 else if (eshk->robbed) 3783 pline("%s complains about a recent robbery.", shkname(shkp)); 3784#ifndef GOLDOBJ 3785 else if (shkp->mgold < 50) 3786#else 3787 else if ((shkmoney = money_cnt(shkp->minvent)) < 50) 3788#endif 3789 pline("%s complains that business is bad.", shkname(shkp)); 3790#ifndef GOLDOBJ 3791 else if (shkp->mgold > 4000) 3792#else 3793 else if (shkmoney > 4000) 3794#endif 3795 pline("%s says that business is good.", shkname(shkp)); 3796 else if (strcmp(shkname(shkp), "Izchak") == 0) 3797 pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))],shkname(shkp)); 3798 else 3799 pline("%s talks about the problem of shoplifters.",shkname(shkp)); 3800} 3801 3802#ifdef KOPS 3803STATIC_OVL void 3804kops_gone(silent) 3805register boolean silent; 3806{ 3807 register int cnt = 0; 3808 register struct monst *mtmp, *mtmp2; 3809 3810 for (mtmp = fmon; mtmp; mtmp = mtmp2) { 3811 mtmp2 = mtmp->nmon; 3812 if (mtmp->data->mlet == S_KOP) { 3813 if (canspotmon(mtmp)) cnt++; 3814 mongone(mtmp); 3815 } 3816 } 3817 if (cnt && !silent) 3818 pline_The("Kop%s (disappointed) vanish%s into thin air.", 3819 plur(cnt), cnt == 1 ? "es" : ""); 3820} 3821#endif /* KOPS */ 3822 3823#endif /*OVLB*/ 3824#ifdef OVL3 3825 3826STATIC_OVL long 3827cost_per_charge(shkp, otmp, altusage) 3828struct monst *shkp; 3829struct obj *otmp; 3830boolean altusage; /* some items have an "alternate" use with different cost */ 3831{ 3832 long tmp = 0L; 3833 3834 if(!shkp || !inhishop(shkp)) return(0L); /* insurance */ 3835 tmp = get_cost(otmp, shkp); 3836 3837 /* The idea is to make the exhaustive use of */ 3838 /* an unpaid item more expensive than buying */ 3839 /* it outright. */ 3840 if(otmp->otyp == MAGIC_LAMP) { /* 1 */ 3841 /* normal use (ie, as light source) of a magic lamp never 3842 degrades its value, but not charging anything would make 3843 identifcation too easy; charge an amount comparable to 3844 what is charged for an ordinary lamp (don't bother with 3845 angry shk surchage) */ 3846 if (!altusage) tmp = (long) objects[OIL_LAMP].oc_cost; 3847 else tmp += tmp / 3L; /* djinni is being released */ 3848 } else if(otmp->otyp == MAGIC_MARKER) { /* 70 - 100 */ 3849 /* no way to determine in advance */ 3850 /* how many charges will be wasted. */ 3851 /* so, arbitrarily, one half of the */ 3852 /* price per use. */ 3853 tmp /= 2L; 3854 } else if(otmp->otyp == BAG_OF_TRICKS || /* 1 - 20 */ 3855 otmp->otyp == HORN_OF_PLENTY) { 3856 tmp /= 5L; 3857 } else if(otmp->otyp == CRYSTAL_BALL || /* 1 - 5 */ 3858 otmp->otyp == OIL_LAMP || /* 1 - 10 */ 3859 otmp->otyp == BRASS_LANTERN || 3860 (otmp->otyp >= MAGIC_FLUTE && 3861 otmp->otyp <= DRUM_OF_EARTHQUAKE) || /* 5 - 9 */ 3862 otmp->oclass == WAND_CLASS) { /* 3 - 11 */ 3863 if (otmp->spe > 1) tmp /= 4L; 3864 } else if (otmp->oclass == SPBOOK_CLASS) { 3865 tmp -= tmp / 5L; 3866 } else if (otmp->otyp == CAN_OF_GREASE || 3867 otmp->otyp == TINNING_KIT 3868#ifdef TOURIST 3869 || otmp->otyp == EXPENSIVE_CAMERA 3870#endif 3871 ) { 3872 tmp /= 10L; 3873 } else if (otmp->otyp == POT_OIL) { 3874 tmp /= 5L; 3875 } 3876 return(tmp); 3877} 3878#endif /*OVL3*/ 3879#ifdef OVLB 3880 3881/* Charge the player for partial use of an unpaid object. 3882 * 3883 * Note that bill_dummy_object() should be used instead 3884 * when an object is completely used. 3885 */ 3886void 3887check_unpaid_usage(otmp, altusage) 3888struct obj *otmp; 3889boolean altusage; 3890{ 3891 struct monst *shkp; 3892 const char *fmt, *arg1, *arg2; 3893 long tmp; 3894 3895 if (!otmp->unpaid || !*u.ushops || 3896 (otmp->spe <= 0 && objects[otmp->otyp].oc_charged)) 3897 return; 3898 if (!(shkp = shop_keeper(*u.ushops)) || !inhishop(shkp)) 3899 return; 3900 if ((tmp = cost_per_charge(shkp, otmp, altusage)) == 0L) 3901 return; 3902 3903 arg1 = arg2 = ""; 3904 if (otmp->oclass == SPBOOK_CLASS) { 3905 fmt = "%sYou owe%s %ld %s."; 3906 arg1 = rn2(2) ? "This is no free library, cad! " : ""; 3907 arg2 = ESHK(shkp)->debit > 0L ? " an additional" : ""; 3908 } else if (otmp->otyp == POT_OIL) { 3909 fmt = "%s%sThat will cost you %ld %s (Yendorian Fuel Tax)."; 3910 } else { 3911 fmt = "%s%sUsage fee, %ld %s."; 3912 if (!rn2(3)) arg1 = "Hey! "; 3913 if (!rn2(3)) arg2 = "Ahem. "; 3914 } 3915 3916 if (shkp->mcanmove || !shkp->msleeping) 3917 verbalize(fmt, arg1, arg2, tmp, currency(tmp)); 3918 ESHK(shkp)->debit += tmp; 3919 exercise(A_WIS, TRUE); /* you just got info */ 3920} 3921 3922/* for using charges of unpaid objects "used in the normal manner" */ 3923void 3924check_unpaid(otmp) 3925struct obj *otmp; 3926{ 3927 check_unpaid_usage(otmp, FALSE); /* normal item use */ 3928} 3929 3930void 3931costly_gold(x, y, amount) 3932register xchar x, y; 3933register long amount; 3934{ 3935 register long delta; 3936 register struct monst *shkp; 3937 register struct eshk *eshkp; 3938 3939 if(!costly_spot(x, y)) return; 3940 /* shkp now guaranteed to exist by costly_spot() */ 3941 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)); 3942 3943 eshkp = ESHK(shkp); 3944 if(eshkp->credit >= amount) { 3945 if(eshkp->credit > amount) 3946 Your("credit is reduced by %ld %s.", 3947 amount, currency(amount)); 3948 else Your("credit is erased."); 3949 eshkp->credit -= amount; 3950 } else { 3951 delta = amount - eshkp->credit; 3952 if(eshkp->credit) 3953 Your("credit is erased."); 3954 if(eshkp->debit) 3955 Your("debt increases by %ld %s.", 3956 delta, currency(delta)); 3957 else You("owe %s %ld %s.", 3958 shkname(shkp), delta, currency(delta)); 3959 eshkp->debit += delta; 3960 eshkp->loan += delta; 3961 eshkp->credit = 0L; 3962 } 3963} 3964 3965/* used in domove to block diagonal shop-exit */ 3966/* x,y should always be a door */ 3967boolean 3968block_door(x,y) 3969register xchar x, y; 3970{ 3971 register int roomno = *in_rooms(x, y, SHOPBASE); 3972 register struct monst *shkp; 3973 3974 if(roomno < 0 || !IS_SHOP(roomno)) return(FALSE); 3975 if(!IS_DOOR(levl[x][y].typ)) return(FALSE); 3976 if(roomno != *u.ushops) return(FALSE); 3977 3978 if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp)) 3979 return(FALSE); 3980 3981 if(shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y 3982 /* Actually, the shk should be made to block _any_ 3983 * door, including a door the player digs, if the 3984 * shk is within a 'jumping' distance. 3985 */ 3986 && ESHK(shkp)->shd.x == x && ESHK(shkp)->shd.y == y 3987 && shkp->mcanmove && !shkp->msleeping 3988 && (ESHK(shkp)->debit || ESHK(shkp)->billct || 3989 ESHK(shkp)->robbed)) { 3990 pline("%s%s blocks your way!", shkname(shkp), 3991 Invis ? " senses your motion and" : ""); 3992 return(TRUE); 3993 } 3994 return(FALSE); 3995} 3996 3997/* used in domove to block diagonal shop-entry */ 3998/* u.ux, u.uy should always be a door */ 3999boolean 4000block_entry(x,y) 4001register xchar x, y; 4002{ 4003 register xchar sx, sy; 4004 register int roomno; 4005 register struct monst *shkp; 4006 4007 if(!(IS_DOOR(levl[u.ux][u.uy].typ) && 4008 levl[u.ux][u.uy].doormask == D_BROKEN)) return(FALSE); 4009 4010 roomno = *in_rooms(x, y, SHOPBASE); 4011 if(roomno < 0 || !IS_SHOP(roomno)) return(FALSE); 4012 if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp)) 4013 return(FALSE); 4014 4015 if(ESHK(shkp)->shd.x != u.ux || ESHK(shkp)->shd.y != u.uy) 4016 return(FALSE); 4017 4018 sx = ESHK(shkp)->shk.x; 4019 sy = ESHK(shkp)->shk.y; 4020 4021 if(shkp->mx == sx && shkp->my == sy 4022 && shkp->mcanmove && !shkp->msleeping 4023 && (x == sx-1 || x == sx+1 || y == sy-1 || y == sy+1) 4024 && (Invis || carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK) 4025#ifdef STEED 4026 || u.usteed 4027#endif 4028 )) { 4029 pline("%s%s blocks your way!", shkname(shkp), 4030 Invis ? " senses your motion and" : ""); 4031 return(TRUE); 4032 } 4033 return(FALSE); 4034} 4035 4036#endif /* OVLB */ 4037#ifdef OVL2 4038 4039char * 4040shk_your(buf, obj) 4041char *buf; 4042struct obj *obj; 4043{ 4044 if (!shk_owns(buf, obj) && !mon_owns(buf, obj)) 4045 Strcpy(buf, carried(obj) ? "your" : "the"); 4046 return buf; 4047} 4048 4049char * 4050Shk_Your(buf, obj) 4051char *buf; 4052struct obj *obj; 4053{ 4054 (void) shk_your(buf, obj); 4055 *buf = highc(*buf); 4056 return buf; 4057} 4058 4059STATIC_OVL char * 4060shk_owns(buf, obj) 4061char *buf; 4062struct obj *obj; 4063{ 4064 struct monst *shkp; 4065 xchar x, y; 4066 4067 if (get_obj_location(obj, &x, &y, 0) && 4068 (obj->unpaid || 4069 (obj->where==OBJ_FLOOR && !obj->no_charge && costly_spot(x,y)))) { 4070 shkp = shop_keeper(inside_shop(x, y)); 4071 return strcpy(buf, shkp ? s_suffix(shkname(shkp)) : "the"); 4072 } 4073 return (char *)0; 4074} 4075 4076STATIC_OVL char * 4077mon_owns(buf, obj) 4078char *buf; 4079struct obj *obj; 4080{ 4081 if (obj->where == OBJ_MINVENT) 4082 return strcpy(buf, s_suffix(mon_nam(obj->ocarry))); 4083 return (char *)0; 4084} 4085 4086#endif /* OVL2 */ 4087#ifdef OVLB 4088 4089#ifdef __SASC 4090void 4091sasc_bug(struct obj *op, unsigned x){ 4092 op->unpaid=x; 4093} 4094#endif 4095 4096#endif /* OVLB */ 4097 4098/*shk.c*/ 4099