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