abstract
| - Below is the full text to shk.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0 89/02/10 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. /* block some unused #defines to avoid overloading some cpp's */ 6. #define MONATTK_H 7. #include "hack.h" 8. 9. #include "eshk.h" 10. 11. #ifdef KOPS 12. static int makekops(); 13. static void kops_gone(); 14. #endif /* KOPS */ 15. 16. #define NOTANGRY(mon) mon->mpeaceful 17. #define ANGRY(mon) !NOTANGRY(mon) 18. 19. /* Descriptor of current shopkeeper. Note that the bill need not be 20. per-shopkeeper, since it is valid only when in a shop. */ 21. static struct monst *shopkeeper = 0; 22. static struct bill_x *bill; 23. static int shlevel = 0; /* level of this shopkeeper */ 24. /* struct obj *billobjs; /* objects on bill with bp->useup */ 25. /* only accessed here and by save & restore */ 26. static long int total; /* filled by addupbill() */ 27. static long int followmsg; /* last time of follow message */ 28. static void setpaid(), findshk P((int)); 29. static int dopayobj P((struct bill_x *)), getprice P((struct obj *)); 30. static struct obj *bp_to_obj P((struct bill_x *)); 31. 32. /* 33. invariants: obj->unpaid iff onbill(obj) [unless bp->useup] 34. obj->quan <= bp->bquan 35. */ 36. 37. char * 38. shkname(mtmp) /* called in do_name.c */ 39. register struct monst *mtmp; 40. { 41. return(ESHK(mtmp)->shknam); 42. } 43. 44. void 45. shkdead(mtmp) /* called in mon.c */ 46. register struct monst *mtmp; 47. { 48. register struct eshk *eshk = ESHK(mtmp); 49. 50. if(eshk->shoplevel == dlevel) 51. rooms[eshk->shoproom].rtype = OROOM; 52. if(mtmp == shopkeeper) { 53. setpaid(); 54. shopkeeper = 0; 55. bill = (struct bill_x *) -1000; /* dump core when referenced */ 56. } 57. } 58. 59. void 60. replshk(mtmp,mtmp2) 61. register struct monst *mtmp, *mtmp2; 62. { 63. if(mtmp == shopkeeper) { 64. shopkeeper = mtmp2; 65. bill = &(ESHK(shopkeeper)->bill[0]); 66. } 67. } 68. 69. static void 70. setpaid(){ /* caller has checked that shopkeeper exists */ 71. /* either we paid or left the shop or he just died */ 72. register struct obj *obj; 73. register struct monst *mtmp; 74. for(obj = invent; obj; obj = obj->nobj) 75. obj->unpaid = 0; 76. for(obj = fobj; obj; obj = obj->nobj) 77. obj->unpaid = 0; 78. for(obj = fcobj; obj; obj = obj->nobj) 79. obj->unpaid = 0; 80. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 81. for(obj = mtmp->minvent; obj; obj = obj->nobj) 82. obj->unpaid = 0; 83. for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon) 84. for(obj = mtmp->minvent; obj; obj = obj->nobj) 85. obj->unpaid = 0; 86. while(obj = billobjs){ 87. billobjs = obj->nobj; 88. free((genericptr_t) obj); 89. } 90. if(shopkeeper) { 91. ESHK(shopkeeper)->billct = 0; 92. ESHK(shopkeeper)->credit = 0L; 93. ESHK(shopkeeper)->debit = 0L; 94. } 95. } 96. 97. static void 98. addupbill(){ /* delivers result in total */ 99. /* caller has checked that shopkeeper exists */ 100. register int ct = ESHK(shopkeeper)->billct; 101. register struct bill_x *bp = bill; 102. total = 0; 103. while(ct--){ 104. total += bp->price * bp->bquan; 105. bp++; 106. } 107. } 108. 109. int 110. inshop() { 111. register int roomno = inroom(u.ux,u.uy); 112. 113. /* Did we just leave a shop? */ 114. if(u.uinshop && 115. (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) { 116. 117. /* This is part of the bugfix for shopkeepers not having their 118. * bill paid. As reported by ab@unido -dgk 119. * I made this standard due to the KOPS code below. -mrs 120. */ 121. if(shopkeeper) { 122. if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->debit) { 123. if(inroom(shopkeeper->mx, shopkeeper->my) 124. == u.uinshop - 1) /* ab@unido */ 125. You("escaped the shop without paying!"); 126. addupbill(); 127. total += ESHK(shopkeeper)->debit; 128. You("stole %ld zorkmids worth of merchandise.", 129. total); 130. ESHK(shopkeeper)->robbed += total; 131. ESHK(shopkeeper)->credit = 0L; 132. ESHK(shopkeeper)->debit = 0L; 133. if (pl_character[0] != 'R') /* stealing is unlawful */ 134. adjalign(-sgn(u.ualigntyp)); 135. setpaid(); 136. if((rooms[ESHK(shopkeeper)->shoproom].rtype == SHOPBASE) 137. == (rn2(3) == 0)) 138. ESHK(shopkeeper)->following = 1; 139. #ifdef KOPS 140. { /* Keystone Kops srt@ucla */ 141. coord mm; 142. 143. if (flags.soundok) 144. pline("An alarm sounds throughout the dungeon!"); 145. if(flags.verbose) { 146. if((mons[PM_KEYSTONE_KOP].geno & G_GENOD) && 147. (mons[PM_KOP_SERGEANT].geno & G_GENOD) && 148. (mons[PM_KOP_LIEUTENANT].geno & G_GENOD) && 149. (mons[PM_KOP_KAPTAIN].geno & G_GENOD)) { 150. if (flags.soundok) 151. pline("But no one seems to respond to it."); 152. } else 153. pline("The Keystone Kops are after you!"); 154. } 155. /* Create a swarm near the staircase */ 156. mm.x = xdnstair; 157. mm.y = ydnstair; 158. (void) makekops(&mm); 159. /* Create a swarm near the shopkeeper */ 160. mm.x = shopkeeper->mx; 161. mm.y = shopkeeper->my; 162. (void) makekops(&mm); 163. } 164. #endif 165. } 166. shopkeeper = 0; 167. shlevel = 0; 168. } 169. u.uinshop = 0; 170. } 171. 172. /* Did we just enter a zoo of some kind? */ 173. /* This counts everything except shops and vaults 174. -- vault.c insists that a vault remain a VAULT */ 175. if(roomno >= 0) { 176. register int rt = rooms[roomno].rtype; 177. register struct monst *mtmp; 178. 179. switch (rt) { 180. case ZOO: 181. pline("Welcome to David's treasure zoo!"); 182. break; 183. case SWAMP: 184. pline("It looks rather muddy down here."); 185. break; 186. #ifdef THRONES 187. case COURT: 188. You("enter an opulent throne room!"); 189. break; 190. #endif 191. case MORGUE: 192. if(midnight()) 193. pline("Run away! Run away!"); 194. else 195. You("have an uncanny feeling..."); 196. break; 197. case BEEHIVE: 198. You("enter a giant beehive!"); 199. break; 200. #ifdef ARMY 201. case BARRACKS: 202. if(!((mons[PM_SOLDIER].geno & G_GENOD) && 203. (mons[PM_SERGEANT].geno & G_GENOD) && 204. (mons[PM_LIEUTENANT].geno & G_GENOD) && 205. (mons[PM_CAPTAIN].geno & G_GENOD))) 206. You("enter a military barracks!"); 207. else You("enter an abandoned barracks."); 208. break; 209. #endif 210. #ifdef ORACLE 211. case DELPHI: 212. if(!(mons[PM_ORACLE].geno & G_GENOD)) 213. pline("\"Hello, %s, welcome to Delphi!\"", plname); 214. break; 215. #endif 216. default: 217. rt = 0; 218. } 219. 220. if(rt != 0) { 221. rooms[roomno].rtype = OROOM; 222. if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO) 223. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 224. /* was if(rt != ZOO || !rn2(3)) -- why should ZOO 225. be different from COURT or MORGUE? */ 226. if(!Stealth && !rn2(3)) 227. mtmp->msleep = 0; 228. } 229. } 230. #if defined(ALTARS) && defined(THEOLOGY) 231. if(roomno >= 0 && rooms[roomno].rtype == TEMPLE) { 232. intemple(); 233. } 234. #endif 235. /* Did we just enter a shop? */ 236. if(roomno >= 0 && rooms[roomno].rtype >= SHOPBASE) { 237. register int rt = rooms[roomno].rtype; 238. 239. if(shlevel != dlevel || !shopkeeper 240. || ESHK(shopkeeper)->shoproom != roomno) 241. findshk(roomno); 242. if(!shopkeeper) { 243. rooms[roomno].rtype = OROOM; 244. u.uinshop = 0; 245. } else if(!u.uinshop){ 246. if(!ESHK(shopkeeper)->visitct || 247. strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)) { 248. /* He seems to be new here */ 249. ESHK(shopkeeper)->visitct = 0; 250. ESHK(shopkeeper)->following = 0; 251. (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ); 252. NOTANGRY(shopkeeper) = 1; 253. } 254. if(!ESHK(shopkeeper)->following && inhishop(shopkeeper)) { 255. if(ANGRY(shopkeeper)) 256. pline("\"So, %s, you dare return to %s's %s?!\"", 257. plname, 258. shkname(shopkeeper), 259. shtypes[rt - SHOPBASE].name); 260. else 261. if(ESHK(shopkeeper)->robbed) 262. pline("\"Beware, %s! I am upset about missing stock!\"", 263. plname); 264. else 265. pline("\"Hello, %s! Welcome%s to %s's %s!\"", 266. plname, 267. ESHK(shopkeeper)->visitct++ ? " again" : "", 268. shkname(shopkeeper), 269. shtypes[rt - SHOPBASE].name); 270. if(carrying(PICK_AXE) != (struct obj *)0) { 271. pline(NOTANGRY(shopkeeper) ? 272. "\"Will you please leave your pick-axe outside?\"" : 273. "\"Leave the pick-axe outside.\""); 274. if(dochug(shopkeeper)) { 275. u.uinshop = 0; /* he died moving */ 276. return(0); 277. } 278. } 279. } 280. u.uinshop = (unsigned int)(roomno + 1); 281. } 282. } 283. return (int)u.uinshop; 284. } 285. 286. int 287. inhishop(mtmp) 288. register struct monst *mtmp; 289. { 290. return((ESHK(mtmp)->shoproom == inroom(mtmp->mx, mtmp->my) && 291. ESHK(mtmp)->shoplevel == dlevel)); 292. } 293. 294. static void 295. findshk(roomno) 296. register int roomno; 297. { 298. register struct monst *mtmp; 299. 300. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 301. if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno 302. && ESHK(mtmp)->shoplevel == dlevel) { 303. shopkeeper = mtmp; 304. bill = &(ESHK(shopkeeper)->bill[0]); 305. shlevel = dlevel; 306. if(ANGRY(shopkeeper) && 307. strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ)) 308. NOTANGRY(shopkeeper) = 1; 309. /* billobjs = 0; -- this is wrong if we save in a shop */ 310. /* (and it is harmless to have too many things in billobjs) */ 311. return; 312. } 313. shopkeeper = 0; 314. shlevel = 0; 315. bill = (struct bill_x *) -1000; /* dump core when referenced */ 316. } 317. 318. static struct bill_x * 319. onbill(obj) 320. register struct obj *obj; 321. { 322. register struct bill_x *bp; 323. if(!shopkeeper) return (struct bill_x *)0; 324. for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++) 325. if(bp->bo_id == obj->o_id) { 326. if(!obj->unpaid) pline("onbill: paid obj on bill?"); 327. return(bp); 328. } 329. if(obj->unpaid) pline("onbill: unpaid obj not on bill?"); 330. return (struct bill_x *)0; 331. } 332. 333. /* called with two args on merge */ 334. void 335. obfree(obj, merge) 336. register struct obj *obj, *merge; 337. { 338. register struct bill_x *bp = onbill(obj); 339. register struct bill_x *bpm; 340. if(bp) { 341. if(!merge){ 342. bp->useup = 1; 343. obj->unpaid = 0; /* only for doinvbill */ 344. obj->nobj = billobjs; 345. billobjs = obj; 346. return; 347. } 348. bpm = onbill(merge); 349. if(!bpm){ 350. /* this used to be a rename */ 351. impossible("obfree: not on bill??"); 352. return; 353. } else { 354. /* this was a merger */ 355. bpm->bquan += bp->bquan; 356. ESHK(shopkeeper)->billct--; 357. *bp = bill[ESHK(shopkeeper)->billct]; 358. } 359. } 360. free((genericptr_t) obj); 361. } 362. 363. static long 364. check_credit(tmp, shkp) 365. long tmp; 366. register struct monst *shkp; 367. { 368. long credit = ESHK(shkp)->credit; 369. 370. if(credit == 0L) return(tmp); 371. if(credit >= tmp) { 372. pline("The price is deducted from your credit."); 373. ESHK(shkp)->credit -=tmp; 374. tmp = 0L; 375. } else { 376. pline("The price is partially covered by your credit."); 377. ESHK(shkp)->credit = 0L; 378. tmp -= credit; 379. } 380. return(tmp); 381. } 382. 383. static void 384. pay(tmp,shkp) 385. long tmp; 386. register struct monst *shkp; 387. { 388. long robbed = ESHK(shkp)->robbed; 389. long balance = ((tmp <= 0) ? tmp : check_credit(tmp, shkp)); 390. 391. u.ugold -= balance; 392. shkp->mgold += balance; 393. flags.botl = 1; 394. if(robbed) { 395. robbed -= tmp; 396. if(robbed < 0) robbed = 0; 397. ESHK(shkp)->robbed = robbed; 398. } 399. } 400. 401. /* return shkp to home position */ 402. void 403. home_shk(shkp) 404. register struct monst *shkp; 405. { 406. register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y; 407. if(levl[x][y].mmask) 408. mnearto(m_at(x,y), x, y, FALSE); 409. levl[shkp->mx][shkp->my].mmask = 0; 410. shkp->mx = x; 411. shkp->my = y; 412. levl[shkp->mx][shkp->my].mmask = 1; 413. unpmon(shkp); 414. } 415. 416. void 417. make_happy_shk(shkp) 418. struct monst *shkp; 419. { 420. register boolean wasmad = ANGRY(shkp); 421. 422. NOTANGRY(shkp) = 1; 423. ESHK(shkp)->following = 0; 424. ESHK(shkp)->robbed = 0; 425. if (pl_character[0] != 'R') 426. adjalign(sgn(u.ualigntyp)); 427. if(!inhishop(shkp)) { 428. pline("Satisfied, %s suddenly disappears!", mon_nam(shkp)); 429. if(ESHK(shkp)->shoplevel == dlevel) 430. home_shk(shkp); 431. else 432. fall_down(shkp, ESHK(shkp)->shoplevel); 433. } else if(wasmad) 434. pline("%s calms down.", Monnam(shkp)); 435. #ifdef KOPS 436. kops_gone(); 437. #endif 438. } 439. 440. static const char no_money[] = "Moreover, you have no money."; 441. 442. int 443. dopay() 444. { 445. long ltmp; 446. register struct bill_x *bp; 447. register struct monst *shkp; 448. int pass, tmp; 449. 450. multi = 0; 451. (void) inshop(); 452. for(shkp = fmon; shkp; shkp = shkp->nmon) 453. if(shkp->isshk && dist(shkp->mx,shkp->my) < 3) 454. break; 455. if(!shkp && u.uinshop && inhishop(shopkeeper)) 456. shkp = shopkeeper; 457. 458. if(!shkp) { 459. pline("There is nobody here to receive your payment."); 460. return(0); 461. } 462. ltmp = ESHK(shkp)->robbed; 463. if(shkp != shopkeeper && NOTANGRY(shkp)) { 464. if(!ltmp) 465. You("do not owe %s anything.", mon_nam(shkp)); 466. else if(!u.ugold) 467. You("have no money."); 468. else { 469. long ugold = u.ugold; 470. 471. if(ugold > ltmp) { 472. You("give %s the %ld gold pieces %s asked for.", 473. mon_nam(shkp), ltmp, 474. ESHK(shkp)->ismale ? "he" : "she"); 475. pay(ltmp, shkp); 476. } else { 477. You("give %s all your gold.", mon_nam(shkp)); 478. pay(u.ugold, shkp); 479. } 480. if(ugold < ltmp/2) 481. pline("Unfortunately, %s doesn't look satisfied.", 482. ESHK(shkp)->ismale ? "he" : "she"); 483. else 484. make_happy_shk(shkp); 485. } 486. return(1); 487. } 488. 489. /* ltmp is still ESHK(shkp)->robbed here */ 490. if(!ESHK(shkp)->billct) { 491. if(!ltmp && NOTANGRY(shkp)) { 492. You("do not owe %s anything.", mon_nam(shkp)); 493. if(!u.ugold) pline(no_money); 494. } else if(ltmp) { 495. pline("%s is after blood, not money!", mon_nam(shkp)); 496. if(u.ugold < ltmp/2) { 497. if(!u.ugold) pline(no_money); 498. else pline("Besides, you don't have enough to interest %s.", 499. ESHK(shkp)->ismale ? "him" : "her"); 500. return(1); 501. } 502. pline("But since %s shop has been robbed recently,", 503. ESHK(shkp)->ismale ? "his" : "her"); 504. pline("you %scompensate %s for %s losses.", 505. (u.ugold < ltmp) ? "partially " : "", 506. mon_nam(shkp), 507. ESHK(shkp)->ismale ? "his" : "her"); 508. pay(u.ugold < ltmp ? u.ugold : ltmp, shkp); 509. make_happy_shk(shkp); 510. } else { 511. /* shopkeeper is angry, but has not been robbed -- 512. * door broken, attacked, etc. */ 513. pline("%s is after your hide, not your money!", 514. mon_nam(shkp)); 515. if(u.ugold < 1000) { 516. if(!u.ugold) pline(no_money); 517. else 518. pline("Besides, you don't have enough to interest %s.", 519. ESHK(shkp)->ismale ? "him" : "her"); 520. return(1); 521. } 522. You("try to appease %s by giving %s 1000 gold pieces.", 523. a_monnam(shkp, "angry"), 524. ESHK(shkp)->ismale ? "him" : "her"); 525. pay(1000L,shkp); 526. if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ) 527. || rn2(3)) 528. make_happy_shk(shkp); 529. else 530. pline("But %s is as angry as ever.", Monnam(shkp)); 531. } 532. return(1); 533. } 534. if(shkp != shopkeeper) { 535. impossible("dopay: not to shopkeeper?"); 536. if(shopkeeper) setpaid(); 537. return(0); 538. } 539. /* pay debt, if any, first */ 540. if(ESHK(shopkeeper)->debit) { 541. You("owe %s %ld zorkmids for the use of merchandise.", 542. shkname(shopkeeper), ESHK(shopkeeper)->debit); 543. if(u.ugold + ESHK(shopkeeper)->credit < 544. ESHK(shopkeeper)->debit) { 545. pline("But you don't have enough gold%s.", 546. ESHK(shopkeeper)->credit ? " or credit" : ""); 547. return(1); 548. } else { 549. long dtmp = ESHK(shopkeeper)->debit; 550. 551. if(ESHK(shopkeeper)->credit >= dtmp) { 552. ESHK(shopkeeper)->credit -= dtmp; 553. ESHK(shopkeeper)->debit = 0L; 554. Your("debt is covered by your credit."); 555. } else if(!ESHK(shopkeeper)->credit) { 556. u.ugold -= dtmp; 557. shopkeeper->mgold += dtmp; 558. ESHK(shopkeeper)->debit = 0L; 559. You("pay that debt."); 560. flags.botl = 1; 561. } else { 562. dtmp -= ESHK(shopkeeper)->credit; 563. ESHK(shopkeeper)->credit = 0L; 564. u.ugold -= dtmp; 565. shopkeeper->mgold += dtmp; 566. ESHK(shopkeeper)->debit = 0L; 567. pline("That debt is partially offset by your credit."); 568. You("pay the remainder."); 569. flags.botl = 1; 570. } 571. } 572. } 573. for(pass = 0; pass <= 1; pass++) { 574. tmp = 0; 575. while(tmp < ESHK(shopkeeper)->billct) { 576. bp = &bill[tmp]; 577. if(!pass && !bp->useup) { 578. tmp++; 579. continue; 580. } 581. if(!dopayobj(bp)) return(1); 582. #ifdef MSDOS 583. *bp = bill[--ESHK(shopkeeper)->billct]; 584. #else 585. bill[tmp] = bill[--ESHK(shopkeeper)->billct]; 586. #endif /* MSDOS /**/ 587. } 588. } 589. pline("\"Thank you for shopping in %s's %s!\"", 590. shkname(shopkeeper), 591. shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - SHOPBASE].name); 592. NOTANGRY(shopkeeper) = 1; 593. return(1); 594. } 595. 596. /* return 1 if paid successfully */ 597. /* 0 if not enough money */ 598. /* -1 if object could not be found (but was paid) */ 599. static int 600. dopayobj(bp) 601. register struct bill_x *bp; 602. { 603. register struct obj *obj; 604. long ltmp; 605. 606. /* find the object on one of the lists */ 607. obj = bp_to_obj(bp); 608. 609. if(!obj) { 610. impossible("Shopkeeper administration out of order."); 611. setpaid(); /* be nice to the player */ 612. return(0); 613. } 614. 615. if(!obj->unpaid && !bp->useup){ 616. impossible("Paid object on bill??"); 617. return(1); 618. } 619. obj->unpaid = 0; 620. ltmp = bp->price * bp->bquan; 621. if(ANGRY(shopkeeper)) ltmp += ltmp/3; 622. if(u.ugold + ESHK(shopkeeper)->credit < ltmp){ 623. You("don't have gold%s enough to pay for %s.", 624. (ESHK(shopkeeper)->credit > 0L) ? " or credit" : "", 625. doname(obj)); 626. obj->unpaid = 1; 627. return(0); 628. } 629. pay(ltmp, shopkeeper); 630. You("bought %s for %ld gold piece%s.", 631. doname(obj), ltmp, plur(ltmp)); 632. if(bp->useup) { 633. register struct obj *otmp = billobjs; 634. if(obj == billobjs) 635. billobjs = obj->nobj; 636. else { 637. while(otmp && otmp->nobj != obj) otmp = otmp->nobj; 638. if(otmp) otmp->nobj = obj->nobj; 639. else pline("Error in shopkeeper administration."); 640. } 641. free((genericptr_t) obj); 642. } 643. return(1); 644. } 645. 646. /* routine called after dying (or quitting) with nonempty bill or upset shk */ 647. boolean 648. paybill(){ 649. register struct monst *mtmp; 650. register int loss = 0; 651. register struct obj *otmp; 652. register xchar ox, oy; 653. register boolean take = FALSE; 654. register boolean taken = FALSE; 655. 656. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 657. if(mtmp->isshk) { 658. /* for bones: we don't want a shopless shk around */ 659. if(ESHK(mtmp)->shoplevel != dlevel) mongone(mtmp); 660. else shopkeeper = mtmp; 661. } 662. 663. if(!shopkeeper) return(FALSE); 664. 665. /* get one case out of the way: you die in the shop, the */ 666. /* shopkeeper is peaceful, nothing stolen, nothing owed. */ 667. if(in_shop(u.ux,u.uy) && !IS_DOOR(levl[u.ux][u.uy].typ) && 668. !ESHK(shopkeeper)->billct && !ESHK(shopkeeper)->robbed && 669. inhishop(shopkeeper) && NOTANGRY(shopkeeper) && 670. !ESHK(shopkeeper)->following) { 671. pline("%s gratefully inherits all your possessions.", 672. Monnam(shopkeeper)); 673. goto clear; 674. } 675. 676. if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->robbed) { 677. addupbill(); 678. loss = ((total >= ESHK(shopkeeper)->robbed) ? total : 679. ESHK(shopkeeper)->robbed); 680. take = TRUE; 681. } 682. 683. if(ESHK(shopkeeper)->following || ANGRY(shopkeeper) || take) { 684. if((loss > u.ugold) || !loss) { 685. pline("%s comes and takes all your possessions.", 686. Monnam(shopkeeper)); 687. taken = TRUE; 688. shopkeeper->mgold += u.ugold; 689. u.ugold = 0; 690. /* in case bones: make it be for real... */ 691. if(!in_shop(u.ux, u.uy) || IS_DOOR(levl[u.ux][u.uy].typ)) { 692. /* shk.x,shk.y is the position immediately in 693. * front of the door -- move in one more space 694. */ 695. ox = ESHK(shopkeeper)->shk.x; 696. oy = ESHK(shopkeeper)->shk.y; 697. ox += sgn(ox - ESHK(shopkeeper)->shd.x); 698. oy += sgn(oy - ESHK(shopkeeper)->shd.y); 699. } else { 700. ox = u.ux; 701. oy = u.uy; 702. } 703. 704. if (invent) { 705. levl[ox][oy].omask = 1; 706. for(otmp = invent; otmp; otmp = otmp->nobj) { 707. otmp->ox = ox; 708. otmp->oy = oy; 709. otmp->age = 0; 710. } 711. 712. /* add to main object list at end so invent is 713. still good */ 714. if (fobj) { 715. otmp = fobj; 716. while(otmp->nobj) 717. otmp = otmp->nobj; 718. otmp->nobj = invent; 719. } else 720. fobj = invent; 721. } 722. } else { 723. u.ugold -= loss; 724. shopkeeper->mgold += loss; 725. pline("%s comes and takes %ld zorkmids %sowed %s.", 726. Monnam(shopkeeper), 727. loss, 728. strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ) ? "" : "you ", 729. ESHK(shopkeeper)->ismale ? "him" : "her"); 730. } 731. 732. /* in case we create bones */ 733. if(!inhishop(shopkeeper)) 734. home_shk(shopkeeper); 735. } 736. clear: 737. setpaid(); 738. return(taken); 739. } 740. 741. /* find obj on one of the lists */ 742. static struct obj * 743. bp_to_obj(bp) 744. register struct bill_x *bp; 745. { 746. register struct obj *obj; 747. register struct monst *mtmp; 748. register unsigned int id = bp->bo_id; 749. 750. if(bp->useup) 751. obj = o_on(id, billobjs); 752. else if(!(obj = o_on(id, invent)) && 753. !(obj = o_on(id, fobj)) && 754. !(obj = o_on(id, fcobj))) { 755. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 756. if(obj = o_on(id, mtmp->minvent)) 757. break; 758. for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon) 759. if(obj = o_on(id, mtmp->minvent)) 760. break; 761. } 762. return(obj); 763. } 764. 765. static long 766. get_cost(obj) 767. register struct obj *obj; 768. { 769. register long tmp; 770. 771. tmp = getprice(obj); 772. if (!tmp) tmp = 5; 773. if (ANGRY(shopkeeper) || 774. (pl_character[0] == 'T' && u.ulevel < (MAXULEV/2)) 775. #ifdef SHIRT 776. || (uarmu && !uarm) /* wearing just a Hawaiian shirt */ 777. #endif 778. ) 779. tmp += tmp/3; 780. if (ACURR(A_CHA) > 18) tmp /= 2; 781. else if (ACURR(A_CHA) > 17) tmp = (tmp * 2)/3; 782. else if (ACURR(A_CHA) > 15) tmp = (tmp * 3)/4; 783. else if (ACURR(A_CHA) < 11) tmp = (tmp * 4)/3; 784. else if (ACURR(A_CHA) < 8) tmp = (tmp * 3)/2; 785. else if (ACURR(A_CHA) < 6) tmp *= 2; 786. return(tmp); 787. } 788. 789. 790. /* called in hack.c when we pickup an object */ 791. void 792. addtobill(obj, ininv) 793. register struct obj *obj; 794. register boolean ininv; 795. { 796. register struct bill_x *bp; 797. char buf[40]; 798. if(!shopkeeper || !inhishop(shopkeeper)) return; 799. 800. if(!costly_spot(obj->ox,obj->oy) || /* either pickup or kick */ 801. onbill(obj) /* perhaps we threw it away earlier */ 802. ) return; 803. if(ESHK(shopkeeper)->billct == BILLSZ) { 804. You("got that for free!"); 805. return; 806. } 807. /* To recognize objects the shopkeeper is not interested in. -dgk 808. */ 809. if (obj->no_charge) { 810. obj->no_charge = 0; 811. return; 812. } 813. bp = &bill[ESHK(shopkeeper)->billct]; 814. bp->bo_id = obj->o_id; 815. bp->bquan = obj->quan; 816. bp->useup = 0; 817. bp->price = get_cost(obj); 818. Strcpy(buf, "\"For you, "); 819. if (ANGRY(shopkeeper)) Strcat(buf, "scum "); 820. else { 821. switch(rnd(4) 822. #ifdef HARD 823. + u.udemigod 824. #endif 825. ) { 826. case 1: Strcat(buf, "good"); 827. break; 828. case 2: Strcat(buf, "honored"); 829. break; 830. case 3: Strcat(buf, "most gracious"); 831. break; 832. case 4: Strcat(buf, "esteemed"); 833. break; 834. case 5: if (u.ualigntyp == U_CHAOTIC) Strcat(buf, "un"); 835. Strcat(buf, "holy"); 836. break; 837. } 838. #ifdef POLYSELF 839. if(!is_human(uasmon)) Strcat(buf, " creature"); 840. else 841. #endif 842. Strcat(buf, (flags.female) ? " lady" : " sir"); 843. } 844. obj->dknown = 1; /* after all, the shk is telling you what it is */ 845. if(ininv) { 846. obj->quan = 1; /* fool xname() into giving singular */ 847. pline("%s; only %d %s %s.\"", buf, bp->price, 848. (bp->bquan > 1) ? "per" : "for this", xname(obj)); 849. obj->quan = bp->bquan; 850. } else pline("The %s will cost you %d zorkmids%s.", 851. xname(obj), bp->price, 852. (bp->bquan > 1) ? " each" : ""); 853. ESHK(shopkeeper)->billct++; 854. obj->unpaid = 1; 855. } 856. 857. void 858. splitbill(obj, otmp) 859. register struct obj *obj, *otmp; 860. { 861. /* otmp has been split off from obj */ 862. register struct bill_x *bp; 863. register int tmp; 864. bp = onbill(obj); 865. if(!bp) { 866. impossible("splitbill: not on bill?"); 867. return; 868. } 869. if(bp->bquan < otmp->quan) { 870. impossible("Negative quantity on bill??"); 871. } 872. if(bp->bquan == otmp->quan) { 873. impossible("Zero quantity on bill??"); 874. } 875. bp->bquan -= otmp->quan; 876. 877. if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0; 878. else { 879. tmp = bp->price; 880. bp = &bill[ESHK(shopkeeper)->billct]; 881. bp->bo_id = otmp->o_id; 882. bp->bquan = otmp->quan; 883. bp->useup = 0; 884. bp->price = tmp; 885. ESHK(shopkeeper)->billct++; 886. } 887. } 888. 889. void 890. subfrombill(obj) 891. register struct obj *obj; 892. { 893. long ltmp; 894. /* register int tmp; /* use of tmp commented out below */ 895. register struct obj *otmp; 896. register struct bill_x *bp; 897. if(!costly_spot(u.ux,u.uy)) 898. return; 899. if((bp = onbill(obj)) != 0) { 900. obj->unpaid = 0; 901. if(bp->bquan > obj->quan){ 902. otmp = newobj(0); 903. *otmp = *obj; 904. bp->bo_id = otmp->o_id = flags.ident++; 905. otmp->quan = (bp->bquan -= obj->quan); 906. otmp->owt = 0; /* superfluous */ 907. otmp->onamelth = 0; 908. bp->useup = 1; 909. otmp->nobj = billobjs; 910. billobjs = otmp; 911. return; 912. } 913. ESHK(shopkeeper)->billct--; 914. *bp = bill[ESHK(shopkeeper)->billct]; 915. return; 916. } 917. if(obj->unpaid) { 918. if(inhishop(shopkeeper)) 919. pline("%s didn't notice.", Monnam(shopkeeper)); 920. obj->unpaid = 0; 921. return; /* %% */ 922. } 923. /* he dropped something of his own - probably wants to sell it */ 924. if(shopkeeper->msleep || shopkeeper->mfroz || !inhishop(shopkeeper)) 925. return; 926. ltmp = getprice(obj) * obj->quan; 927. if(ESHK(shopkeeper)->billct == BILLSZ 928. || !saleable(rooms[ESHK(shopkeeper)->shoproom].rtype-SHOPBASE, obj) 929. || otmp->olet == BALL_SYM || ltmp == 0L) { 930. pline("%s seems not interested.", Monnam(shopkeeper)); 931. obj->no_charge = 1; 932. return; 933. } 934. if (ANGRY(shopkeeper) || (pl_character[0] == 'T' && u.ulevel < (MAXULEV/2)) 935. #ifdef SHIRT 936. || (uarmu && !uarm) /* wearing just a Hawaiian shirt */ 937. #endif 938. ) { 939. ltmp /= 3; 940. NOTANGRY(shopkeeper) = 1; 941. } else ltmp /= 2; 942. if(ESHK(shopkeeper)->robbed) { 943. if((ESHK(shopkeeper)->robbed -= ltmp) < 0) 944. ESHK(shopkeeper)->robbed = 0; 945. pline("\"Thank you for your contribution to restock this recently plundered shop.\""); 946. return; 947. } 948. if(ltmp > shopkeeper->mgold) 949. ltmp = shopkeeper->mgold; 950. pay(-ltmp, shopkeeper); 951. if(!ltmp) { 952. pline("%s gladly accepts %s but cannot pay you at present.", 953. Monnam(shopkeeper), doname(obj)); 954. obj->no_charge = 1; 955. } else 956. You("sold %s for %ld gold piece%s.", doname(obj), ltmp, 957. plur(ltmp)); 958. } 959. 960. int 961. doinvbill(mode) 962. int mode; /* 0: deliver count 1: paged */ 963. { 964. register struct bill_x *bp; 965. register struct obj *obj; 966. long totused, thisused; 967. char buf[BUFSZ]; 968. 969. if(mode == 0) { 970. register int cnt = 0; 971. 972. if(shopkeeper) 973. for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) 974. if(bp->useup || 975. ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan)) 976. cnt++; 977. return(cnt); 978. } 979. 980. if(!shopkeeper) { 981. impossible("doinvbill: no shopkeeper?"); 982. return(0); 983. } 984. 985. set_pager(0); 986. if(page_line("Unpaid articles already used up:") || page_line("")) 987. goto quit; 988. 989. totused = 0; 990. for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) { 991. obj = bp_to_obj(bp); 992. if(!obj) { 993. impossible("Bad shopkeeper administration."); 994. goto quit; 995. } 996. if(bp->useup || bp->bquan > obj->quan) { 997. register int cnt, oquan, uquan; 998. 999. oquan = obj->quan; 1000. uquan = (bp->useup ? bp->bquan : bp->bquan - oquan); 1001. thisused = bp->price * uquan; 1002. totused += thisused; 1003. obj->quan = uquan; /* cheat doname */ 1004. Sprintf(buf, "x - %s", doname(obj)); 1005. obj->quan = oquan; /* restore value */ 1006. for(cnt = 0; buf[cnt]; cnt++); 1007. while(cnt < 50) 1008. buf[cnt++] = ' '; 1009. Sprintf(&buf[cnt], " %5ld zorkmids", thisused); 1010. if(page_line(buf)) 1011. goto quit; 1012. } 1013. } 1014. Sprintf(buf, "Total:%50ld zorkmids", totused); 1015. if(page_line("") || page_line(buf)) 1016. goto quit; 1017. set_pager(1); 1018. return(0); 1019. quit: 1020. set_pager(2); 1021. return(0); 1022. } 1023. 1024. #define HUNGRY 2 1025. static int 1026. getprice(obj) 1027. register struct obj *obj; 1028. { 1029. register int tmp = objects[obj->otyp].oc_cost; 1030. 1031. switch(obj->olet) { 1032. case AMULET_SYM: 1033. if(obj->otyp == AMULET_OF_YENDOR) { 1034. /* don't let the player get rich selling fakes */ 1035. tmp = (obj->spe < 0 ? 0 : 3500); 1036. } 1037. break; 1038. case FOOD_SYM: 1039. /* simpler hunger check, (2-4)*cost */ 1040. if (u.uhs >= HUNGRY) tmp *= u.uhs; 1041. break; 1042. case WAND_SYM: 1043. if (obj->spe == -1) tmp = 0; 1044. break; 1045. case POTION_SYM: 1046. if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed) 1047. tmp = 0; 1048. break; 1049. case ARMOR_SYM: 1050. if (u.uac > 0) tmp += u.uac * 2; 1051. case WEAPON_SYM: 1052. if (obj->spe > 0) tmp += 10 * obj->spe; 1053. break; 1054. case CHAIN_SYM: 1055. pline("Strange... carrying a chain?"); 1056. break; 1057. } 1058. return(tmp); 1059. } 1060. 1061. int 1062. shkcatch(obj) 1063. register struct obj *obj; 1064. { 1065. register struct monst *shkp = shopkeeper; 1066. 1067. if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep && 1068. u.dx && u.dy && 1069. inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop && 1070. shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y && 1071. u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) { 1072. pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj)); 1073. obj->nobj = shkp->minvent; 1074. shkp->minvent = obj; 1075. return(1); 1076. } 1077. return(0); 1078. } 1079. 1080. /* 1081. * shk_move: return 1: he moved 0: he didn't -1: let m_move do it -2: died 1082. */ 1083. int 1084. shk_move(shkp) 1085. register struct monst *shkp; 1086. { 1087. register xchar gx,gy,omx,omy; 1088. register int udist; 1089. register schar appr; 1090. int z; 1091. schar shkroom; 1092. boolean uondoor, satdoor, avoid, badinv; 1093. 1094. omx = shkp->mx; 1095. omy = shkp->my; 1096. 1097. if((udist = dist(omx,omy)) < 3) { 1098. if(ANGRY(shkp)) { 1099. if(Displaced) 1100. Your("displaced image doesn't fool %s!", 1101. Monnam(shkp)); 1102. (void) mattacku(shkp); 1103. return(0); 1104. } 1105. if(ESHK(shkp)->following) { 1106. if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)) { 1107. pline("\"Hello, %s! I was looking for %s.\"", 1108. plname, ESHK(shkp)->customer); 1109. ESHK(shkp)->following = 0; 1110. return(0); 1111. } 1112. if(moves > followmsg+4) { 1113. pline("\"Hello, %s! Didn't you forget to pay?\"", 1114. plname); 1115. followmsg = moves; 1116. #ifdef HARD 1117. if (!rn2(4)) { 1118. pline ("%s doesn't like customers who don't pay.", Monnam(shkp)); 1119. NOTANGRY(shkp) = 0; 1120. } 1121. #endif 1122. } 1123. if(udist < 2) 1124. return(0); 1125. } 1126. } 1127. 1128. shkroom = inroom(omx,omy); 1129. appr = 1; 1130. gx = ESHK(shkp)->shk.x; 1131. gy = ESHK(shkp)->shk.y; 1132. satdoor = (gx == omx && gy == omy); 1133. if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){ 1134. gx = u.ux; 1135. gy = u.uy; 1136. if(shkroom < 0 || shkroom != inroom(u.ux,u.uy)) 1137. if(udist > 4) 1138. return(-1); /* leave it to m_move */ 1139. } else if(ANGRY(shkp)) { 1140. long saveBlind = Blinded; 1141. struct obj *saveUblindf = ublindf; 1142. Blinded = 0; 1143. ublindf = (struct obj *)0; 1144. if(shkp->mcansee && !Invis && cansee(omx,omy)) { 1145. gx = u.ux; 1146. gy = u.uy; 1147. } 1148. Blinded = saveBlind; 1149. ublindf = saveUblindf; 1150. avoid = FALSE; 1151. } else { 1152. #define GDIST(x,y) (dist2(x,y,gx,gy)) 1153. if(Invis) 1154. avoid = FALSE; 1155. else { 1156. uondoor = (u.ux == ESHK(shkp)->shd.x && 1157. u.uy == ESHK(shkp)->shd.y); 1158. if(uondoor) { 1159. if(ESHK(shkp)->billct && inhishop(shkp)) 1160. pline(NOTANGRY(shkp) ? 1161. "\"Hello, %s! Will you please pay before leaving?\"" : 1162. "\"Hey, %s! Don't leave without paying!\"", 1163. plname); 1164. badinv = (!!carrying(PICK_AXE)); 1165. if(satdoor && badinv) 1166. return(0); 1167. avoid = !badinv; 1168. } else { 1169. avoid = (u.uinshop && dist(gx,gy) > 8); 1170. badinv = FALSE; 1171. } 1172. 1173. if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid) 1174. && GDIST(omx,omy) < 3) { 1175. if(!badinv && !online(omx,omy)) 1176. return(0); 1177. if(satdoor) 1178. appr = gx = gy = 0; 1179. } 1180. } 1181. } 1182. 1183. return(move_special(shkp,shkroom,appr,uondoor,avoid,omx,omy,gx,gy)); 1184. } 1185. 1186. int 1187. online(x,y) /* New version to speed things up. 1188. * Compiler dependant, may not always work. 1189. */ 1190. register xchar x, y; 1191. { 1192. return((x-=u.ux) == 0 || (y-=u.uy) == 0 || x == y || (x+=y) == 0); 1193. } 1194. 1195. /* Original version, just in case... 1196. *online(x,y) { 1197. * return(x==u.ux || y==u.uy || (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy)); 1198. *} 1199. */ 1200. 1201. /* for use in levl_follower (mondata.c) */ 1202. boolean 1203. is_fshk(mtmp) 1204. register struct monst *mtmp; 1205. { 1206. return(mtmp->isshk && ESHK(mtmp)->following); 1207. } 1208. 1209. /* He is digging in the shop. */ 1210. void 1211. shopdig(fall) 1212. register int fall; 1213. { 1214. if(!shopkeeper) return; 1215. if(!inhishop(shopkeeper)) { 1216. if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp)); 1217. return; 1218. } 1219. 1220. if(!fall) { 1221. if(u.utraptype == TT_PIT) 1222. pline("\"Be careful, %s, or you might fall through the floor.\"", 1223. flags.female ? "madam" : "sir"); 1224. else 1225. pline("\"%s, do not damage the floor here!\"", 1226. flags.female ? "Madam" : "Sir"); 1227. if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp)); 1228. } else if(um_dist(shopkeeper->mx, shopkeeper->my, 2)) { 1229. register struct obj *obj, *obj2; 1230. 1231. if(dist(shopkeeper->mx, shopkeeper->my) > 2) { 1232. mnexto(shopkeeper); 1233. /* for some reason he can't come next to you */ 1234. if(dist(shopkeeper->mx, shopkeeper->my) > 2) { 1235. pline("%s curses you in anger and frustration!", 1236. shkname(shopkeeper)); 1237. NOTANGRY(shopkeeper) = 0; 1238. return; 1239. } else pline("%s leaps, and grabs your backpack!", 1240. shkname(shopkeeper)); 1241. } else pline("%s grabs your backpack!", shkname(shopkeeper)); 1242. 1243. for(obj = invent; obj; obj = obj2) { 1244. obj2 = obj->nobj; 1245. if(obj->owornmask) continue; 1246. freeinv(obj); 1247. obj->nobj = shopkeeper->minvent; 1248. shopkeeper->minvent = obj; 1249. if(obj->unpaid) 1250. subfrombill(obj); 1251. } 1252. } 1253. } 1254. 1255. #ifdef KOPS 1256. static int 1257. makekops(mm) /* returns the number of (all types of) Kops made */ 1258. coord *mm; 1259. { 1260. register int cnt = dlevel + rnd(5); 1261. register int scnt = (cnt / 3) + 1; /* at least one sarge */ 1262. register int lcnt = (cnt / 6); /* maybe a lieutenant */ 1263. register int kcnt = (cnt / 9); /* and maybe a kaptain */ 1264. 1265. while(cnt--) { 1266. enexto(mm, mm->x, mm->y); 1267. (void) makemon(&mons[PM_KEYSTONE_KOP], mm->x, mm->y); 1268. } 1269. while(scnt--) { 1270. enexto(mm, mm->x, mm->y); 1271. (void) makemon(&mons[PM_KOP_SERGEANT], mm->x, mm->y); 1272. } 1273. while(lcnt--) { 1274. enexto(mm, mm->x, mm->y); 1275. (void) makemon(&mons[PM_KOP_LIEUTENANT], mm->x, mm->y); 1276. } 1277. while(kcnt--) { 1278. enexto(mm, mm->x, mm->y); 1279. (void) makemon(&mons[PM_KOP_KAPTAIN], mm->x, mm->y); 1280. } 1281. return(cnt + scnt + lcnt + kcnt); 1282. } 1283. #endif 1284. 1285. boolean 1286. in_shop(x,y) 1287. register int x, y; 1288. { 1289. register int roomno = inroom(x, y); 1290. 1291. if (roomno < 0) return(FALSE); 1292. return (IS_SHOP(rooms[roomno])); 1293. } 1294. 1295. void 1296. pay_for_door(x,y,dmgstr) 1297. register int x, y; 1298. register char *dmgstr; 1299. { 1300. register struct monst *mtmp; 1301. register int ox, oy; 1302. register int roomno = inroom(x, y); 1303. register int damage = (ACURR(A_STR) > 18) ? 400 : 20 * ACURR(A_STR); 1304. 1305. /* make sure this function is not used in the wrong place */ 1306. if(!(IS_DOOR(levl[x][y].typ) && in_shop(x, y))) return; 1307. 1308. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 1309. if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno 1310. && ESHK(mtmp)->shoplevel == dlevel) { 1311. shopkeeper = mtmp; 1312. } 1313. 1314. if(!shopkeeper) return; 1315. 1316. /* not the best introduction to the shk... */ 1317. (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ); 1318. 1319. /* if he is already on the war path, be sure it's all out */ 1320. if(ANGRY(shopkeeper) || ESHK(shopkeeper)->following) { 1321. NOTANGRY(shopkeeper) = 0; 1322. ESHK(shopkeeper)->following = 1; 1323. return; 1324. } 1325. 1326. ox = shopkeeper->mx; 1327. oy = shopkeeper->my; 1328. 1329. /* if he's not in his shop.. */ 1330. if(!in_shop(ox, oy)) return; 1331. 1332. /* if a !shopkeeper shows up at the door, move him */ 1333. if(levl[x][y].mmask && (mtmp = m_at(x, y)) != shopkeeper) { 1334. if(flags.soundok) { 1335. You("hear an angry voice: \"Out of my way, scum!\""); 1336. (void) fflush(stdout); 1337. #if defined(SYSV) || defined(ULTRIX) 1338. (void) 1339. #endif 1340. #ifdef UNIX 1341. sleep(1); 1342. #endif 1343. } 1344. mnearto(mtmp, x, y, FALSE); 1345. } 1346. 1347. /* make shk show up at the door */ 1348. levl[shopkeeper->mx][shopkeeper->my].mmask = 0; 1349. levl[x][y].mmask = 1; 1350. shopkeeper->mx = x; 1351. shopkeeper->my = y; 1352. pmon(shopkeeper); 1353. 1354. if(um_dist(x, y, 1)) goto chase; 1355. 1356. if(u.ugold < damage || !rn2(50)) { 1357. chase: 1358. if(um_dist(x, y, 1)) 1359. pline("%s shouts: \"Who dared %s my door?\"", 1360. shkname(shopkeeper), dmgstr); 1361. else pline("\"How dare you %s my door?\"", dmgstr); 1362. NOTANGRY(shopkeeper) = 0; 1363. ESHK(shopkeeper)->following = 1; 1364. return; 1365. } 1366. 1367. pline("\"Cad! You did %d zorkmids worth of damage!\" Pay? ", damage); 1368. if(yn() != 'n') { 1369. u.ugold -= damage; 1370. shopkeeper->mgold += damage; 1371. flags.botl = 1; 1372. pline("Mollified, %s accepts your restitution.", 1373. shkname(shopkeeper)); 1374. 1375. /* clear ox oy of another monster, if one got there somehow */ 1376. if(levl[ox][oy].mmask) mnearto(m_at(ox,oy),ox,oy,FALSE); 1377. 1378. /* move shk back to his orig loc */ 1379. levl[shopkeeper->mx][shopkeeper->my].mmask = 0; 1380. levl[ox][oy].mmask = 1; 1381. shopkeeper->mx = ox; 1382. shopkeeper->my = oy; 1383. unpmon(shopkeeper); 1384. NOTANGRY(shopkeeper) = 1; 1385. } 1386. else { 1387. pline("\"Oh, yes! You'll pay!\""); 1388. ESHK(shopkeeper)->following = 1; 1389. NOTANGRY(shopkeeper) = 0; 1390. adjalign(-sgn(u.ualigntyp)); 1391. } 1392. } 1393. 1394. /* called in dokick.c when we kick an object in a store */ 1395. boolean 1396. costly_spot(x, y) 1397. register int x, y; 1398. { 1399. register struct monst *shkp = shopkeeper; 1400. 1401. if(!shkp) return(FALSE); 1402. 1403. return(in_shop(x, y) && levl[x][y].typ != DOOR && 1404. !(x == ESHK(shkp)->shk.x && y == ESHK(shkp)->shk.y)); 1405. } 1406. 1407. #ifdef KOPS 1408. static void 1409. kops_gone() 1410. { 1411. register int cnt = 0; 1412. register struct monst *mtmp, *mtmp2; 1413. 1414. /* turn off automatic resurrection of kops */ 1415. allow_kops = FALSE; 1416. 1417. for(mtmp = fmon; mtmp; mtmp = mtmp2) { 1418. mtmp2 = mtmp->nmon; 1419. if(mtmp->data->mlet == S_KOP) { 1420. mongone(mtmp); 1421. cnt++; 1422. } 1423. } 1424. if(cnt) pline("The Kops (disappointed) disappear into thin air."); 1425. allow_kops = TRUE; 1426. } 1427. #endif 1428. 1429. static long 1430. cost_per_charge(otmp) 1431. register struct obj *otmp; 1432. { 1433. register long tmp = get_cost(otmp); 1434. 1435. /* The idea is to make the exhaustive use of */ 1436. /* an unpaid item more expansive than buying */ 1437. /* outright. */ 1438. if(otmp->otyp == MAGIC_LAMP) { /* 1 */ 1439. tmp += (tmp/3L); 1440. } else if(otmp->otyp == MAGIC_MARKER) { /* 70 - 100 */ 1441. /* no way to determine in advance */ 1442. /* how many charges will be wasted. */ 1443. /* so, arbitrarily, one half of the */ 1444. /* price per use. */ 1445. tmp = (tmp/2L); 1446. } else if(otmp->otyp == BAG_OF_TRICKS) { /* 1 - 20 */ 1447. tmp = (tmp/5L); 1448. } else if(otmp->otyp == CRYSTAL_BALL || /* 1 - 5 */ 1449. otmp->otyp == LAMP || /* 1-10 */ 1450. #ifdef MUSIC 1451. (otmp->otyp >= MAGIC_FLUTE && 1452. otmp->otyp <= DRUM_OF_EARTHQUAKE) || /* 5 - 9 */ 1453. #endif 1454. otmp->olet == WAND_SYM) { /* 3 - 11 */ 1455. if(otmp->spe == 1) tmp += (tmp/3L); 1456. else tmp = (tmp/4L); 1457. } 1458. else return(0L); 1459. return(tmp); 1460. } 1461. 1462. /* for using charges of unpaid objects */ 1463. void 1464. check_unpaid(otmp) 1465. register struct obj *otmp; 1466. { 1467. if(!in_shop(u.ux, u.uy)) return; 1468. 1469. if(otmp->spe <= 0) return; 1470. 1471. if(otmp->unpaid) { 1472. ESHK(shopkeeper)->debit += cost_per_charge(otmp); 1473. } 1474. }
|