Difference between revisions of "Source:NetHack 3.0.0/shk.c"
Jump to navigation
Jump to search
Kernigh bot (talk | contribs) m (NetHack 3.0.0/shk.c moved to Source:NetHack 3.0.0/shk.c: Robot: moved page) |
m (Undo revision 49431 by 69.31.241.242 (talk)) |
(One intermediate revision by one other user not shown) | |
(No difference)
|
Latest revision as of 15:29, 31 May 2010
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
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
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. }