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