About: Source:NetHack 3.4.0/shk.c   Sponge Permalink

An Entity of Type : owl:Thing, within Data Space : 134.155.108.49:8890 associated with source dataset(s)

Below is the full text to shk.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/shk.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code

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