hack.shk.c 27 KB

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