NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / src / shk.c
blob48db58b21d8300213260f60a9101ee5630ca1197
1 /* aNetHack 0.0.1 shk.c $ANH-Date: 1464138042 2016/05/25 01:00:42 $ $ANH-Branch: master $:$ANH-Revision: 1.132 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* aNetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 #define PAY_SOME 2
8 #define PAY_BUY 1
9 #define PAY_CANT 0 /* too poor */
10 #define PAY_SKIP (-1)
11 #define PAY_BROKE (-2)
13 STATIC_DCL void FDECL(makekops, (coord *));
14 STATIC_DCL void FDECL(call_kops, (struct monst *, BOOLEAN_P));
15 STATIC_DCL void FDECL(kops_gone, (BOOLEAN_P));
17 #define NOTANGRY(mon) ((mon)->mpeaceful)
18 #define ANGRY(mon) (!NOTANGRY(mon))
19 #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
21 #define muteshk(shkp) \
22 ((shkp)->msleeping || !(shkp)->mcanmove \
23 || (shkp)->data->msound <= MS_ANIMAL)
25 extern const struct shclass shtypes[]; /* defined in shknam.c */
27 STATIC_VAR NEARDATA long int followmsg; /* last time of follow message */
28 STATIC_VAR const char and_its_contents[] = " and its contents";
29 STATIC_VAR const char the_contents_of[] = "the contents of ";
31 STATIC_DCL void FDECL(append_honorific, (char *));
32 STATIC_DCL void FDECL(setpaid, (struct monst *));
33 STATIC_DCL long FDECL(addupbill, (struct monst *));
34 STATIC_DCL void FDECL(pacify_shk, (struct monst *));
35 STATIC_DCL struct bill_x *FDECL(onbill, (struct obj *, struct monst *,
36 BOOLEAN_P));
37 STATIC_DCL struct monst *FDECL(next_shkp, (struct monst *, BOOLEAN_P));
38 STATIC_DCL long FDECL(shop_debt, (struct eshk *));
39 STATIC_DCL char *FDECL(shk_owns, (char *, struct obj *));
40 STATIC_DCL char *FDECL(mon_owns, (char *, struct obj *));
41 STATIC_DCL void FDECL(clear_unpaid_obj, (struct monst *, struct obj *));
42 STATIC_DCL void FDECL(clear_unpaid, (struct monst *, struct obj *));
43 STATIC_DCL long FDECL(check_credit, (long, struct monst *));
44 STATIC_DCL void FDECL(pay, (long, struct monst *));
45 STATIC_DCL long FDECL(get_cost, (struct obj *, struct monst *));
46 STATIC_DCL long FDECL(set_cost, (struct obj *, struct monst *));
47 STATIC_DCL const char *FDECL(shk_embellish, (struct obj *, long));
48 STATIC_DCL long FDECL(cost_per_charge, (struct monst *, struct obj *,
49 BOOLEAN_P));
50 STATIC_DCL long FDECL(cheapest_item, (struct monst *));
51 STATIC_DCL int FDECL(dopayobj, (struct monst *, struct bill_x *,
52 struct obj **, int, BOOLEAN_P));
53 STATIC_DCL long FDECL(stolen_container, (struct obj *, struct monst *,
54 long, BOOLEAN_P));
55 STATIC_DCL long FDECL(getprice, (struct obj *, BOOLEAN_P));
56 STATIC_DCL void FDECL(shk_names_obj, (struct monst *, struct obj *,
57 const char *, long, const char *));
58 STATIC_DCL struct obj *FDECL(bp_to_obj, (struct bill_x *));
59 STATIC_DCL boolean FDECL(inherits, (struct monst *, int, int));
60 STATIC_DCL void FDECL(set_repo_loc, (struct monst *));
61 STATIC_DCL boolean NDECL(angry_shk_exists);
62 STATIC_DCL void FDECL(rile_shk, (struct monst *));
63 STATIC_DCL void FDECL(rouse_shk, (struct monst *, BOOLEAN_P));
64 STATIC_DCL void FDECL(remove_damage, (struct monst *, BOOLEAN_P));
65 STATIC_DCL void FDECL(sub_one_frombill, (struct obj *, struct monst *));
66 STATIC_DCL void FDECL(add_one_tobill, (struct obj *, BOOLEAN_P,
67 struct monst *));
68 STATIC_DCL void FDECL(dropped_container, (struct obj *, struct monst *,
69 BOOLEAN_P));
70 STATIC_DCL void FDECL(add_to_billobjs, (struct obj *));
71 STATIC_DCL void FDECL(bill_box_content, (struct obj *, BOOLEAN_P, BOOLEAN_P,
72 struct monst *));
73 STATIC_DCL boolean FDECL(rob_shop, (struct monst *));
74 STATIC_DCL void FDECL(deserted_shop, (char *));
75 STATIC_DCL boolean FDECL(special_stock, (struct obj *, struct monst *,
76 BOOLEAN_P));
77 STATIC_DCL const char *FDECL(cad, (BOOLEAN_P));
80 invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
81 obj->quan <= bp->bquan
84 static const char *angrytexts[] = { "quite upset", "ticked off", "furious" };
87 * Transfer money from inventory to monster when paying
88 * shopkeepers, priests, oracle, succubus, and other demons.
89 * Simple with only gold coins.
90 * This routine will handle money changing when multiple
91 * coin types is implemented, only appropriate
92 * monsters will pay change. (Peaceful shopkeepers, priests
93 * and the oracle try to maintain goodwill while selling
94 * their wares or services. Angry monsters and all demons
95 * will keep anything they get their hands on.
96 * Returns the amount actually paid, so we can know
97 * if the monster kept the change.
99 long
100 money2mon(mon, amount)
101 struct monst *mon;
102 long amount;
104 struct obj *ygold = findgold(invent);
106 if (amount <= 0) {
107 impossible("%s payment in money2mon!", amount ? "negative" : "zero");
108 return 0L;
110 if (!ygold || ygold->quan < amount) {
111 impossible("Paying without %s money?", ygold ? "enough" : "");
112 return 0L;
115 if (ygold->quan > amount)
116 ygold = splitobj(ygold, amount);
117 else if (ygold->owornmask)
118 remove_worn_item(ygold, FALSE); /* quiver */
119 freeinv(ygold);
120 add_to_minv(mon, ygold);
121 context.botl = 1;
122 return amount;
126 * Transfer money from monster to inventory.
127 * Used when the shopkeeper pay for items, and when
128 * the priest gives you money for an ale.
130 void
131 money2u(mon, amount)
132 struct monst *mon;
133 long amount;
135 struct obj *mongold = findgold(mon->minvent);
137 if (amount <= 0) {
138 impossible("%s payment in money2u!", amount ? "negative" : "zero");
139 return;
141 if (!mongold || mongold->quan < amount) {
142 impossible("%s paying without %s money?", a_monnam(mon),
143 mongold ? "enough" : "");
144 return;
147 if (mongold->quan > amount)
148 mongold = splitobj(mongold, amount);
149 obj_extract_self(mongold);
151 if (!merge_choice(invent, mongold) && inv_cnt(FALSE) >= 52) {
152 You("have no room for the money!");
153 dropy(mongold);
154 } else {
155 addinv(mongold);
156 context.botl = 1;
160 STATIC_OVL struct monst *
161 next_shkp(shkp, withbill)
162 register struct monst *shkp;
163 register boolean withbill;
165 for (; shkp; shkp = shkp->nmon) {
166 if (DEADMONSTER(shkp))
167 continue;
168 if (shkp->isshk && (ESHK(shkp)->billct || !withbill))
169 break;
172 if (shkp) {
173 if (NOTANGRY(shkp)) {
174 if (ESHK(shkp)->surcharge)
175 pacify_shk(shkp);
176 } else {
177 if (!ESHK(shkp)->surcharge)
178 rile_shk(shkp);
181 return shkp;
184 /* called in mon.c */
185 void
186 shkgone(mtmp)
187 struct monst *mtmp;
189 struct eshk *eshk = ESHK(mtmp);
190 struct mkroom *sroom = &rooms[eshk->shoproom - ROOMOFFSET];
191 struct obj *otmp;
192 char *p;
193 int sx, sy;
195 /* [BUG: some of this should be done on the shop level */
196 /* even when the shk dies on a different level.] */
197 if (on_level(&eshk->shoplevel, &u.uz)) {
198 remove_damage(mtmp, TRUE);
199 sroom->resident = (struct monst *) 0;
200 if (!search_special(ANY_SHOP))
201 level.flags.has_shop = 0;
203 /* items on shop floor revert to ordinary objects */
204 for (sx = sroom->lx; sx <= sroom->hx; sx++)
205 for (sy = sroom->ly; sy <= sroom->hy; sy++)
206 for (otmp = level.objects[sx][sy]; otmp;
207 otmp = otmp->nexthere)
208 otmp->no_charge = 0;
210 /* Make sure bill is set only when the
211 dead shk is the resident shk. */
212 if ((p = index(u.ushops, eshk->shoproom)) != 0) {
213 setpaid(mtmp);
214 eshk->bill_p = (struct bill_x *) 0;
215 /* remove eshk->shoproom from u.ushops */
216 do {
217 *p = *(p + 1);
218 } while (*++p);
223 void
224 set_residency(shkp, zero_out)
225 register struct monst *shkp;
226 register boolean zero_out;
228 if (on_level(&(ESHK(shkp)->shoplevel), &u.uz))
229 rooms[ESHK(shkp)->shoproom - ROOMOFFSET].resident =
230 (zero_out) ? (struct monst *) 0 : shkp;
233 void
234 replshk(mtmp, mtmp2)
235 register struct monst *mtmp, *mtmp2;
237 rooms[ESHK(mtmp2)->shoproom - ROOMOFFSET].resident = mtmp2;
238 if (inhishop(mtmp) && *u.ushops == ESHK(mtmp)->shoproom) {
239 ESHK(mtmp2)->bill_p = &(ESHK(mtmp2)->bill[0]);
243 /* do shopkeeper specific structure munging -dlc */
244 void
245 restshk(shkp, ghostly)
246 struct monst *shkp;
247 boolean ghostly;
249 if (u.uz.dlevel) {
250 struct eshk *eshkp = ESHK(shkp);
252 if (eshkp->bill_p != (struct bill_x *) -1000)
253 eshkp->bill_p = &eshkp->bill[0];
254 /* shoplevel can change as dungeons move around */
255 /* savebones guarantees that non-homed shk's will be gone */
256 if (ghostly) {
257 assign_level(&eshkp->shoplevel, &u.uz);
258 if (ANGRY(shkp) && strncmpi(eshkp->customer, plname, PL_NSIZ))
259 pacify_shk(shkp);
264 /* Clear the unpaid bit on a single object and its contents. */
265 STATIC_OVL void
266 clear_unpaid_obj(shkp, otmp)
267 struct monst *shkp;
268 struct obj *otmp;
270 if (Has_contents(otmp))
271 clear_unpaid(shkp, otmp->cobj);
272 if (onbill(otmp, shkp, TRUE))
273 otmp->unpaid = 0;
276 /* Clear the unpaid bit on all of the objects in the list. */
277 STATIC_OVL void
278 clear_unpaid(shkp, list)
279 struct monst *shkp;
280 struct obj *list;
282 while (list) {
283 clear_unpaid_obj(shkp, list);
284 list = list->nobj;
288 /* either you paid or left the shop or the shopkeeper died */
289 STATIC_OVL void
290 setpaid(shkp)
291 register struct monst *shkp;
293 register struct obj *obj;
294 register struct monst *mtmp;
296 clear_unpaid(shkp, invent);
297 clear_unpaid(shkp, fobj);
298 clear_unpaid(shkp, level.buriedobjlist);
299 if (thrownobj)
300 clear_unpaid_obj(shkp, thrownobj);
301 if (kickedobj)
302 clear_unpaid_obj(shkp, kickedobj);
303 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
304 clear_unpaid(shkp, mtmp->minvent);
305 for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon)
306 clear_unpaid(shkp, mtmp->minvent);
308 while ((obj = billobjs) != 0) {
309 obj_extract_self(obj);
310 dealloc_obj(obj);
312 if (shkp) {
313 ESHK(shkp)->billct = 0;
314 ESHK(shkp)->credit = 0L;
315 ESHK(shkp)->debit = 0L;
316 ESHK(shkp)->loan = 0L;
320 STATIC_OVL long
321 addupbill(shkp)
322 register struct monst *shkp;
324 register int ct = ESHK(shkp)->billct;
325 register struct bill_x *bp = ESHK(shkp)->bill_p;
326 register long total = 0L;
328 while (ct--) {
329 total += bp->price * bp->bquan;
330 bp++;
332 return total;
335 STATIC_OVL void
336 call_kops(shkp, nearshop)
337 register struct monst *shkp;
338 register boolean nearshop;
340 /* Keystone Kops srt@ucla */
341 register boolean nokops;
343 if (!shkp)
344 return;
346 if (!Deaf)
347 pline("An alarm sounds!");
349 nokops = ((mvitals[PM_KEYSTONE_KOP].mvflags & G_GONE)
350 && (mvitals[PM_KOP_SERGEANT].mvflags & G_GONE)
351 && (mvitals[PM_KOP_LIEUTENANT].mvflags & G_GONE)
352 && (mvitals[PM_KOP_KAPTAIN].mvflags & G_GONE));
354 if (!angry_guards(!!Deaf) && nokops) {
355 if (flags.verbose && !Deaf)
356 pline("But no one seems to respond to it.");
357 return;
360 if (nokops)
361 return;
364 coord mm;
366 if (nearshop) {
367 /* Create swarm around you, if you merely "stepped out" */
368 if (flags.verbose)
369 pline_The("Keystone Kops appear!");
370 mm.x = u.ux;
371 mm.y = u.uy;
372 makekops(&mm);
373 return;
375 if (flags.verbose)
376 pline_The("Keystone Kops are after you!");
377 /* Create swarm near down staircase (hinders return to level) */
378 mm.x = xdnstair;
379 mm.y = ydnstair;
380 makekops(&mm);
381 /* Create swarm near shopkeeper (hinders return to shop) */
382 mm.x = shkp->mx;
383 mm.y = shkp->my;
384 makekops(&mm);
388 /* x,y is strictly inside shop */
389 char
390 inside_shop(x, y)
391 register xchar x, y;
393 register char rno;
395 rno = levl[x][y].roomno;
396 if ((rno < ROOMOFFSET) || levl[x][y].edge || !IS_SHOP(rno - ROOMOFFSET))
397 rno = NO_ROOM;
398 return rno;
401 void
402 u_left_shop(leavestring, newlev)
403 char *leavestring;
404 boolean newlev;
406 struct monst *shkp;
407 struct eshk *eshkp;
410 * IF player
411 * ((didn't leave outright) AND
412 * ((he is now strictly-inside the shop) OR
413 * (he wasn't strictly-inside last turn anyway)))
414 * THEN (there's nothing to do, so just return)
416 if (!*leavestring && (!levl[u.ux][u.uy].edge || levl[u.ux0][u.uy0].edge))
417 return;
419 shkp = shop_keeper(*u.ushops0);
420 if (!shkp || !inhishop(shkp))
421 return; /* shk died, teleported, changed levels... */
423 eshkp = ESHK(shkp);
424 if (!eshkp->billct && !eshkp->debit) /* bill is settled */
425 return;
427 if (!*leavestring && !muteshk(shkp)) {
429 * Player just stepped onto shop-boundary (known from above logic).
430 * Try to intimidate him into paying his bill
432 if (!Deaf && !muteshk(shkp))
433 verbalize(NOTANGRY(shkp) ? "%s! Please pay before leaving."
434 : "%s! Don't you leave without paying!",
435 plname);
436 else
437 pline("%s %s that you need to pay before leaving%s",
438 Shknam(shkp),
439 NOTANGRY(shkp) ? "points out" : "makes it clear",
440 NOTANGRY(shkp) ? "." : "!");
441 return;
444 if (rob_shop(shkp)) {
445 call_kops(shkp, (!newlev && levl[u.ux0][u.uy0].edge));
449 /* robbery from outside the shop via telekinesis or grappling hook */
450 void
451 remote_burglary(x, y)
452 xchar x, y;
454 struct monst *shkp;
455 struct eshk *eshkp;
457 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
458 if (!shkp || !inhishop(shkp))
459 return; /* shk died, teleported, changed levels... */
461 eshkp = ESHK(shkp);
462 if (!eshkp->billct && !eshkp->debit) /* bill is settled */
463 return;
465 if (rob_shop(shkp)) {
466 /*[might want to set 2nd arg based on distance from shop doorway]*/
467 call_kops(shkp, FALSE);
471 /* shop merchandise has been taken; pay for it with any credit available;
472 return false if the debt is fully covered by credit, true otherwise */
473 STATIC_OVL boolean
474 rob_shop(shkp)
475 struct monst *shkp;
477 struct eshk *eshkp;
478 long total;
480 eshkp = ESHK(shkp);
481 rouse_shk(shkp, TRUE);
482 total = (addupbill(shkp) + eshkp->debit);
483 if (eshkp->credit >= total) {
484 Your("credit of %ld %s is used to cover your shopping bill.",
485 eshkp->credit, currency(eshkp->credit));
486 total = 0L; /* credit gets cleared by setpaid() */
487 } else {
488 You("escaped the shop without paying!");
489 total -= eshkp->credit;
491 setpaid(shkp);
492 if (!total)
493 return FALSE;
495 /* by this point, we know an actual robbery has taken place */
496 eshkp->robbed += total;
497 You("stole %ld %s worth of merchandise.", total, currency(total));
498 if (!Role_if(PM_ROGUE)) /* stealing is unlawful */
499 adjalign(-sgn(u.ualign.type));
501 hot_pursuit(shkp);
502 return TRUE;
505 /* give a message when entering an untended shop (caller has verified that) */
506 STATIC_OVL void
507 deserted_shop(enterstring)
508 /*const*/ char *enterstring;
510 struct monst *mtmp;
511 struct mkroom *r = &rooms[(int) *enterstring - ROOMOFFSET];
512 int x, y, m = 0, n = 0;
514 for (x = r->lx; x <= r->hx; ++x)
515 for (y = r->ly; y <= r->hy; ++y) {
516 if (x == u.ux && y == u.uy)
517 continue;
518 if ((mtmp = m_at(x, y)) != 0) {
519 ++n;
520 if (sensemon(mtmp) || ((mtmp->m_ap_type == M_AP_NOTHING
521 || mtmp->m_ap_type == M_AP_MONSTER)
522 && canseemon(mtmp)))
523 ++m;
527 if (Blind && !(Blind_telepat || Detect_monsters))
528 ++n; /* force feedback to be less specific */
530 pline("This shop %s %s.", (m < n) ? "seems to be" : "is",
531 !n ? "deserted" : "untended");
534 void
535 u_entered_shop(enterstring)
536 char *enterstring;
538 register int rt;
539 register struct monst *shkp;
540 register struct eshk *eshkp;
541 static char empty_shops[5];
543 if (!*enterstring)
544 return;
546 if (!(shkp = shop_keeper(*enterstring))) {
547 if (!index(empty_shops, *enterstring)
548 && in_rooms(u.ux, u.uy, SHOPBASE)
549 != in_rooms(u.ux0, u.uy0, SHOPBASE))
550 deserted_shop(enterstring);
551 Strcpy(empty_shops, u.ushops);
552 u.ushops[0] = '\0';
553 return;
556 eshkp = ESHK(shkp);
558 if (!inhishop(shkp)) {
559 /* dump core when referenced */
560 eshkp->bill_p = (struct bill_x *) -1000;
561 if (!index(empty_shops, *enterstring))
562 deserted_shop(enterstring);
563 Strcpy(empty_shops, u.ushops);
564 u.ushops[0] = '\0';
565 return;
568 eshkp->bill_p = &(eshkp->bill[0]);
570 if ((!eshkp->visitct || *eshkp->customer)
571 && strncmpi(eshkp->customer, plname, PL_NSIZ)) {
572 /* You seem to be new here */
573 eshkp->visitct = 0;
574 eshkp->following = 0;
575 (void) strncpy(eshkp->customer, plname, PL_NSIZ);
576 pacify_shk(shkp);
579 if (muteshk(shkp) || eshkp->following)
580 return; /* no dialog */
582 if (Invis) {
583 pline("%s senses your presence.", shkname(shkp));
584 if (!Deaf && !muteshk(shkp))
585 verbalize("Invisible customers are not welcome!");
586 else
587 pline("%s stands firm as if %s knows you are there.",
588 Shknam(shkp), mhe(shkp));
589 return;
592 rt = rooms[*enterstring - ROOMOFFSET].rtype;
594 if (ANGRY(shkp)) {
595 if (!Deaf && !muteshk(shkp))
596 verbalize("So, %s, you dare return to %s %s?!", plname,
597 s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
598 else
599 pline("%s seems %s over your return to %s %s!",
600 Shknam(shkp),
601 angrytexts[rn2(SIZE(angrytexts))],
602 mhis(shkp),
603 shtypes[rt - SHOPBASE].name);
604 } else if (eshkp->robbed) {
605 if (!Deaf)
606 pline("%s mutters imprecations against shoplifters.",
607 shkname(shkp));
608 else
609 pline("%s is combing through %s inventory list.",
610 Shknam(shkp),
611 mhis(shkp));
612 } else {
613 if (!Deaf && !muteshk(shkp))
614 verbalize("%s, %s! Welcome%s to %s %s!", Hello(shkp), plname,
615 eshkp->visitct++ ? " again" : "",
616 s_suffix(shkname(shkp)), shtypes[rt - SHOPBASE].name);
617 else
618 You("enter %s %s%s!",
619 s_suffix(shkname(shkp)),
620 shtypes[rt - SHOPBASE].name,
621 eshkp->visitct++ ? " again" : "");
623 /* can't do anything about blocking if teleported in */
624 if (!inside_shop(u.ux, u.uy)) {
625 boolean should_block;
626 int cnt;
627 const char *tool;
628 struct obj *pick = carrying(PICK_AXE),
629 *mattock = carrying(DWARVISH_MATTOCK);
631 if (pick || mattock) {
632 cnt = 1; /* so far */
633 if (pick && mattock) { /* carrying both types */
634 tool = "digging tool";
635 cnt = 2; /* `more than 1' is all that matters */
636 } else if (pick) {
637 tool = "pick-axe";
638 /* hack: `pick' already points somewhere into inventory */
639 while ((pick = pick->nobj) != 0)
640 if (pick->otyp == PICK_AXE)
641 ++cnt;
642 } else { /* assert(mattock != 0) */
643 tool = "mattock";
644 while ((mattock = mattock->nobj) != 0)
645 if (mattock->otyp == DWARVISH_MATTOCK)
646 ++cnt;
647 /* [ALI] Shopkeeper identifies mattock(s) */
648 if (!Blind)
649 makeknown(DWARVISH_MATTOCK);
651 if (!Deaf && !muteshk(shkp))
652 verbalize(NOTANGRY(shkp)
653 ? "Will you please leave your %s%s outside?"
654 : "Leave the %s%s outside.",
655 tool, plur(cnt));
656 else
657 pline("%s %s to let you in with your %s%s.",
658 Shknam(shkp),
659 NOTANGRY(shkp) ? "is hesitant" : "refuses",
660 tool, plur(cnt));
661 should_block = TRUE;
662 } else if (u.usteed) {
663 if (!Deaf && !muteshk(shkp))
664 verbalize(NOTANGRY(shkp) ? "Will you please leave %s outside?"
665 : "Leave %s outside.",
666 y_monnam(u.usteed));
667 else
668 pline("%s %s to let you in while you're riding %s.",
669 Shknam(shkp),
670 NOTANGRY(shkp) ? "doesn't want" : "refuses",
671 y_monnam(u.usteed));
672 should_block = TRUE;
673 } else {
674 should_block =
675 (Fast && (sobj_at(PICK_AXE, u.ux, u.uy)
676 || sobj_at(DWARVISH_MATTOCK, u.ux, u.uy)));
678 if (should_block)
679 (void) dochug(shkp); /* shk gets extra move */
681 return;
684 /* called when removing a pick-axe or mattock from a container */
685 void
686 pick_pick(obj)
687 struct obj *obj;
689 struct monst *shkp;
691 if (obj->unpaid || !is_pick(obj))
692 return;
693 shkp = shop_keeper(*u.ushops);
694 if (shkp && inhishop(shkp)) {
695 static NEARDATA long pickmovetime = 0L;
697 /* if you bring a sack of N picks into a shop to sell,
698 don't repeat this N times when they're taken out */
699 if (moves != pickmovetime) {
700 if (!Deaf && !muteshk(shkp))
701 verbalize("You sneaky %s! Get out of here with that pick!",
702 cad(FALSE));
703 else
704 pline("%s %s your pick!",
705 Shknam(shkp),
706 haseyes(shkp->data) ? "glares at"
707 : "is dismayed because of");
709 pickmovetime = moves;
714 Decide whether two unpaid items are mergable; caller is responsible for
715 making sure they're unpaid and the same type of object; we check the price
716 quoted by the shopkeeper and also that they both belong to the same shk.
718 boolean
719 same_price(obj1, obj2)
720 struct obj *obj1, *obj2;
722 register struct monst *shkp1, *shkp2;
723 struct bill_x *bp1 = 0, *bp2 = 0;
724 boolean are_mergable = FALSE;
726 /* look up the first object by finding shk whose bill it's on */
727 for (shkp1 = next_shkp(fmon, TRUE); shkp1;
728 shkp1 = next_shkp(shkp1->nmon, TRUE))
729 if ((bp1 = onbill(obj1, shkp1, TRUE)) != 0)
730 break;
731 /* second object is probably owned by same shk; if not, look harder */
732 if (shkp1 && (bp2 = onbill(obj2, shkp1, TRUE)) != 0) {
733 shkp2 = shkp1;
734 } else {
735 for (shkp2 = next_shkp(fmon, TRUE); shkp2;
736 shkp2 = next_shkp(shkp2->nmon, TRUE))
737 if ((bp2 = onbill(obj2, shkp2, TRUE)) != 0)
738 break;
741 if (!bp1 || !bp2)
742 impossible("same_price: object wasn't on any bill!");
743 else
744 are_mergable = (shkp1 == shkp2 && bp1->price == bp2->price);
745 return are_mergable;
749 * Figure out how much is owed to a given shopkeeper.
750 * At present, we ignore any amount robbed from the shop, to avoid
751 * turning the `$' command into a way to discover that the current
752 * level is bones data which has a shk on the warpath.
754 STATIC_OVL long
755 shop_debt(eshkp)
756 struct eshk *eshkp;
758 struct bill_x *bp;
759 int ct;
760 long debt = eshkp->debit;
762 for (bp = eshkp->bill_p, ct = eshkp->billct; ct > 0; bp++, ct--)
763 debt += bp->price * bp->bquan;
764 return debt;
767 /* called in response to the `$' command */
768 void
769 shopper_financial_report()
771 struct monst *shkp, *this_shkp = shop_keeper(inside_shop(u.ux, u.uy));
772 struct eshk *eshkp;
773 long amt;
774 int pass;
776 eshkp = this_shkp ? ESHK(this_shkp) : 0;
777 if (eshkp && !(eshkp->credit || shop_debt(eshkp))) {
778 You("have no credit or debt in here.");
779 this_shkp = 0; /* skip first pass */
782 /* pass 0: report for the shop we're currently in, if any;
783 pass 1: report for all other shops on this level. */
784 for (pass = this_shkp ? 0 : 1; pass <= 1; pass++)
785 for (shkp = next_shkp(fmon, FALSE); shkp;
786 shkp = next_shkp(shkp->nmon, FALSE)) {
787 if ((shkp != this_shkp) ^ pass)
788 continue;
789 eshkp = ESHK(shkp);
790 if ((amt = eshkp->credit) != 0)
791 You("have %ld %s credit at %s %s.", amt, currency(amt),
792 s_suffix(shkname(shkp)),
793 shtypes[eshkp->shoptype - SHOPBASE].name);
794 else if (shkp == this_shkp)
795 You("have no credit in here.");
796 if ((amt = shop_debt(eshkp)) != 0)
797 You("owe %s %ld %s.", shkname(shkp), amt, currency(amt));
798 else if (shkp == this_shkp)
799 You("don't owe any money here.");
804 inhishop(mtmp)
805 register struct monst *mtmp;
807 struct eshk *eshkp = ESHK(mtmp);
809 return (index(in_rooms(mtmp->mx, mtmp->my, SHOPBASE), eshkp->shoproom)
810 && on_level(&eshkp->shoplevel, &u.uz));
813 struct monst *
814 shop_keeper(rmno)
815 char rmno;
817 struct monst *shkp;
819 shkp = (rmno >= ROOMOFFSET) ? rooms[rmno - ROOMOFFSET].resident : 0;
820 if (shkp) {
821 if (has_eshk(shkp)) {
822 if (NOTANGRY(shkp)) {
823 if (ESHK(shkp)->surcharge)
824 pacify_shk(shkp);
825 } else {
826 if (!ESHK(shkp)->surcharge)
827 rile_shk(shkp);
829 } else {
830 /* would have segfaulted on ESHK dereference previously */
831 impossible("%s? (rmno=%d, rtype=%d, mnum=%d, \"%s\")",
832 shkp->isshk ? "shopkeeper career change"
833 : "shop resident not shopkeeper",
834 (int) rmno,
835 (int) rooms[rmno - ROOMOFFSET].rtype,
836 shkp->mnum,
837 /* [real shopkeeper name is kept in ESHK, not MNAME] */
838 has_mname(shkp) ? MNAME(shkp) : "anonymous");
839 /* not sure if this is appropriate, because it does nothing to
840 correct the underlying rooms[].resident issue but... */
841 return (struct monst *) 0;
844 return shkp;
847 boolean
848 tended_shop(sroom)
849 struct mkroom *sroom;
851 struct monst *mtmp = sroom->resident;
853 return !mtmp ? FALSE : (boolean) inhishop(mtmp);
856 STATIC_OVL struct bill_x *
857 onbill(obj, shkp, silent)
858 struct obj *obj;
859 struct monst *shkp;
860 boolean silent;
862 if (shkp) {
863 register struct bill_x *bp = ESHK(shkp)->bill_p;
864 register int ct = ESHK(shkp)->billct;
866 while (--ct >= 0)
867 if (bp->bo_id == obj->o_id) {
868 if (!obj->unpaid)
869 pline("onbill: paid obj on bill?");
870 return bp;
871 } else
872 bp++;
874 if (obj->unpaid && !silent)
875 pline("onbill: unpaid obj not on bill?");
876 return (struct bill_x *) 0;
879 /* check whether an object or any of its contents belongs to a shop */
880 boolean
881 is_unpaid(obj)
882 struct obj *obj;
884 return (boolean) (obj->unpaid
885 || (Has_contents(obj) && count_unpaid(obj->cobj)));
888 /* Delete the contents of the given object. */
889 void
890 delete_contents(obj)
891 register struct obj *obj;
893 register struct obj *curr;
895 while ((curr = obj->cobj) != 0) {
896 obj_extract_self(curr);
897 obfree(curr, (struct obj *) 0);
901 /* called with two args on merge */
902 void
903 obfree(obj, merge)
904 register struct obj *obj, *merge;
906 register struct bill_x *bp;
907 register struct bill_x *bpm;
908 register struct monst *shkp;
910 if (obj->otyp == LEASH && obj->leashmon)
911 o_unleash(obj);
912 if (obj->oclass == FOOD_CLASS)
913 food_disappears(obj);
914 if (obj->oclass == SPBOOK_CLASS)
915 book_disappears(obj);
916 if (Has_contents(obj))
917 delete_contents(obj);
919 shkp = 0;
920 if (obj->unpaid) {
921 /* look for a shopkeeper who owns this object */
922 for (shkp = next_shkp(fmon, TRUE); shkp;
923 shkp = next_shkp(shkp->nmon, TRUE))
924 if (onbill(obj, shkp, TRUE))
925 break;
927 /* sanity check, more or less */
928 if (!shkp)
929 shkp = shop_keeper(*u.ushops);
931 * Note: `shkp = shop_keeper(*u.ushops)' used to be
932 * unconditional. But obfree() is used all over
933 * the place, so making its behavior be dependent
934 * upon player location doesn't make much sense.
937 if ((bp = onbill(obj, shkp, FALSE)) != 0) {
938 if (!merge) {
939 bp->useup = 1;
940 obj->unpaid = 0; /* only for doinvbill */
941 add_to_billobjs(obj);
942 return;
944 bpm = onbill(merge, shkp, FALSE);
945 if (!bpm) {
946 /* this used to be a rename */
947 impossible("obfree: not on bill??");
948 return;
949 } else {
950 /* this was a merger */
951 bpm->bquan += bp->bquan;
952 ESHK(shkp)->billct--;
953 #ifdef DUMB
955 /* DRS/NS 2.2.6 messes up -- Peter Kendell */
956 int indx = ESHK(shkp)->billct;
958 *bp = ESHK(shkp)->bill_p[indx];
960 #else
961 *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
962 #endif
965 if (obj->owornmask) {
966 impossible("obfree: deleting worn obj (%d: %ld)", obj->otyp,
967 obj->owornmask);
968 /* unfortunately at this point we don't know whether worn mask
969 applied to hero or a monster or perhaps something bogus, so
970 can't call remove_worn_item() to get <X>_off() side-effects */
971 setnotworn(obj);
973 dealloc_obj(obj);
976 STATIC_OVL long
977 check_credit(tmp, shkp)
978 long tmp;
979 register struct monst *shkp;
981 long credit = ESHK(shkp)->credit;
983 if (credit == 0L) {
984 ; /* nothing to do; just 'return tmp;' */
985 } else if (credit >= tmp) {
986 pline_The("price is deducted from your credit.");
987 ESHK(shkp)->credit -= tmp;
988 tmp = 0L;
989 } else {
990 pline_The("price is partially covered by your credit.");
991 ESHK(shkp)->credit = 0L;
992 tmp -= credit;
994 return tmp;
997 STATIC_OVL void
998 pay(tmp, shkp)
999 long tmp;
1000 register struct monst *shkp;
1002 long robbed = ESHK(shkp)->robbed;
1003 long balance = ((tmp <= 0L) ? tmp : check_credit(tmp, shkp));
1005 if (balance > 0)
1006 money2mon(shkp, balance);
1007 else if (balance < 0)
1008 money2u(shkp, -balance);
1009 context.botl = 1;
1010 if (robbed) {
1011 robbed -= tmp;
1012 if (robbed < 0)
1013 robbed = 0L;
1014 ESHK(shkp)->robbed = robbed;
1018 /* return shkp to home position */
1019 void
1020 home_shk(shkp, killkops)
1021 register struct monst *shkp;
1022 register boolean killkops;
1024 register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y;
1026 (void) mnearto(shkp, x, y, TRUE);
1027 level.flags.has_shop = 1;
1028 if (killkops) {
1029 kops_gone(TRUE);
1030 pacify_guards();
1032 after_shk_move(shkp);
1035 STATIC_OVL boolean
1036 angry_shk_exists()
1038 register struct monst *shkp;
1040 for (shkp = next_shkp(fmon, FALSE); shkp;
1041 shkp = next_shkp(shkp->nmon, FALSE))
1042 if (ANGRY(shkp))
1043 return TRUE;
1044 return FALSE;
1047 /* remove previously applied surcharge from all billed items */
1048 STATIC_OVL void
1049 pacify_shk(shkp)
1050 register struct monst *shkp;
1052 NOTANGRY(shkp) = TRUE; /* make peaceful */
1053 if (ESHK(shkp)->surcharge) {
1054 register struct bill_x *bp = ESHK(shkp)->bill_p;
1055 register int ct = ESHK(shkp)->billct;
1057 ESHK(shkp)->surcharge = FALSE;
1058 while (ct-- > 0) {
1059 register long reduction = (bp->price + 3L) / 4L;
1060 bp->price -= reduction; /* undo 33% increase */
1061 bp++;
1066 /* add aggravation surcharge to all billed items */
1067 STATIC_OVL void
1068 rile_shk(shkp)
1069 register struct monst *shkp;
1071 NOTANGRY(shkp) = FALSE; /* make angry */
1072 if (!ESHK(shkp)->surcharge) {
1073 register struct bill_x *bp = ESHK(shkp)->bill_p;
1074 register int ct = ESHK(shkp)->billct;
1076 ESHK(shkp)->surcharge = TRUE;
1077 while (ct-- > 0) {
1078 register long surcharge = (bp->price + 2L) / 3L;
1079 bp->price += surcharge;
1080 bp++;
1085 /* wakeup and/or unparalyze shopkeeper */
1086 STATIC_OVL void
1087 rouse_shk(shkp, verbosely)
1088 struct monst *shkp;
1089 boolean verbosely;
1091 if (!shkp->mcanmove || shkp->msleeping) {
1092 /* greed induced recovery... */
1093 if (verbosely && canspotmon(shkp))
1094 pline("%s %s.", Shknam(shkp),
1095 shkp->msleeping ? "wakes up" : "can move again");
1096 shkp->msleeping = 0;
1097 shkp->mfrozen = 0;
1098 shkp->mcanmove = 1;
1102 void
1103 make_happy_shk(shkp, silentkops)
1104 register struct monst *shkp;
1105 register boolean silentkops;
1107 boolean wasmad = ANGRY(shkp);
1108 struct eshk *eshkp = ESHK(shkp);
1110 pacify_shk(shkp);
1111 eshkp->following = 0;
1112 eshkp->robbed = 0L;
1113 if (!Role_if(PM_ROGUE))
1114 adjalign(sgn(u.ualign.type));
1115 if (!inhishop(shkp)) {
1116 char shk_nam[BUFSZ];
1117 boolean vanished = canseemon(shkp);
1119 Strcpy(shk_nam, shkname(shkp));
1120 if (on_level(&eshkp->shoplevel, &u.uz)) {
1121 home_shk(shkp, FALSE);
1122 /* didn't disappear if shk can still be seen */
1123 if (canseemon(shkp))
1124 vanished = FALSE;
1125 } else {
1126 /* if sensed, does disappear regardless whether seen */
1127 if (sensemon(shkp))
1128 vanished = TRUE;
1129 /* can't act as porter for the Amulet, even if shk
1130 happens to be going farther down rather than up */
1131 mdrop_special_objs(shkp);
1132 /* arrive near shop's door */
1133 migrate_to_level(shkp, ledger_no(&eshkp->shoplevel),
1134 MIGR_APPROX_XY, &eshkp->shd);
1135 /* dismiss kops on that level when shk arrives */
1136 eshkp->dismiss_kops = TRUE;
1138 if (vanished)
1139 pline("Satisfied, %s suddenly disappears!", shk_nam);
1140 } else if (wasmad)
1141 pline("%s calms down.", Shknam(shkp));
1143 make_happy_shoppers(silentkops);
1146 /* called by make_happy_shk() and also by losedogs() for migrating shk */
1147 void
1148 make_happy_shoppers(silentkops)
1149 boolean silentkops;
1151 if (!angry_shk_exists()) {
1152 kops_gone(silentkops);
1153 pacify_guards();
1157 void
1158 hot_pursuit(shkp)
1159 register struct monst *shkp;
1161 if (!shkp->isshk)
1162 return;
1164 rile_shk(shkp);
1165 (void) strncpy(ESHK(shkp)->customer, plname, PL_NSIZ);
1166 ESHK(shkp)->following = 1;
1169 /* Used when the shkp is teleported or falls (ox == 0) out of his shop, or
1170 when the player is not on a costly_spot and he damages something inside
1171 the shop. These conditions must be checked by the calling function. */
1172 /*ARGSUSED*/
1173 void
1174 make_angry_shk(shkp, ox, oy)
1175 struct monst *shkp;
1176 xchar ox UNUSED; /* <ox,oy> predate 'noit_Monnam()', let alone Shknam() */
1177 xchar oy UNUSED;
1179 struct eshk *eshkp = ESHK(shkp);
1181 /* all pending shop transactions are now "past due" */
1182 if (eshkp->billct || eshkp->debit || eshkp->loan || eshkp->credit) {
1183 eshkp->robbed += (addupbill(shkp) + eshkp->debit + eshkp->loan);
1184 eshkp->robbed -= eshkp->credit;
1185 if (eshkp->robbed < 0L)
1186 eshkp->robbed = 0L;
1187 /* billct, debit, loan, and credit will be cleared by setpaid */
1188 setpaid(shkp);
1191 pline("%s %s!", Shknam(shkp), !ANGRY(shkp) ? "gets angry" : "is furious");
1192 hot_pursuit(shkp);
1195 STATIC_VAR const char
1196 no_money[] = "Moreover, you%s have no money.",
1197 not_enough_money[] = "Besides, you don't have enough to interest %s.";
1199 /* delivers the cheapest item on the list */
1200 STATIC_OVL long
1201 cheapest_item(shkp)
1202 register struct monst *shkp;
1204 register int ct = ESHK(shkp)->billct;
1205 register struct bill_x *bp = ESHK(shkp)->bill_p;
1206 register long gmin = (bp->price * bp->bquan);
1208 while (ct--) {
1209 if (bp->price * bp->bquan < gmin)
1210 gmin = bp->price * bp->bquan;
1211 bp++;
1213 return gmin;
1217 dopay()
1219 register struct eshk *eshkp;
1220 register struct monst *shkp;
1221 struct monst *nxtm, *resident;
1222 long ltmp;
1223 long umoney;
1224 int pass, tmp, sk = 0, seensk = 0;
1225 boolean paid = FALSE, stashed_gold = (hidden_gold() > 0L);
1227 multi = 0;
1229 /* Find how many shk's there are, how many are in
1230 * sight, and are you in a shop room with one.
1232 nxtm = resident = 0;
1233 for (shkp = next_shkp(fmon, FALSE); shkp;
1234 shkp = next_shkp(shkp->nmon, FALSE)) {
1235 sk++;
1236 if (ANGRY(shkp) && distu(shkp->mx, shkp->my) <= 2)
1237 nxtm = shkp;
1238 if (canspotmon(shkp))
1239 seensk++;
1240 if (inhishop(shkp) && (*u.ushops == ESHK(shkp)->shoproom))
1241 resident = shkp;
1244 if (nxtm) { /* Player should always appease an */
1245 shkp = nxtm; /* irate shk standing next to them. */
1246 goto proceed;
1249 if ((!sk && (!Blind || Blind_telepat)) || (!Blind && !seensk)) {
1250 There("appears to be no shopkeeper here to receive your payment.");
1251 return 0;
1254 if (!seensk) {
1255 You_cant("see...");
1256 return 0;
1259 /* The usual case. Allow paying at a distance when
1260 * inside a tended shop. Should we change that?
1262 if (sk == 1 && resident) {
1263 shkp = resident;
1264 goto proceed;
1267 if (seensk == 1) {
1268 for (shkp = next_shkp(fmon, FALSE); shkp;
1269 shkp = next_shkp(shkp->nmon, FALSE))
1270 if (canspotmon(shkp))
1271 break;
1272 if (shkp != resident && distu(shkp->mx, shkp->my) > 2) {
1273 pline("%s is not near enough to receive your payment.",
1274 Shknam(shkp));
1275 return 0;
1277 } else {
1278 struct monst *mtmp;
1279 coord cc;
1280 int cx, cy;
1282 pline("Pay whom?");
1283 cc.x = u.ux;
1284 cc.y = u.uy;
1285 if (getpos(&cc, TRUE, "the creature you want to pay") < 0)
1286 return 0; /* player pressed ESC */
1287 cx = cc.x;
1288 cy = cc.y;
1289 if (cx < 0) {
1290 pline("Try again...");
1291 return 0;
1293 if (u.ux == cx && u.uy == cy) {
1294 You("are generous to yourself.");
1295 return 0;
1297 mtmp = m_at(cx, cy);
1298 if (!cansee(cx, cy) && (!mtmp || !canspotmon(mtmp))) {
1299 You("can't %s anyone there.", !Blind ? "see" : "sense");
1300 return 0;
1302 if (!mtmp) {
1303 There("is no one there to receive your payment.");
1304 return 0;
1306 if (!mtmp->isshk) {
1307 pline("%s is not interested in your payment.", Monnam(mtmp));
1308 return 0;
1310 if (mtmp != resident && distu(mtmp->mx, mtmp->my) > 2) {
1311 pline("%s is too far to receive your payment.", Shknam(mtmp));
1312 return 0;
1314 shkp = mtmp;
1317 if (!shkp) {
1318 debugpline0("dopay: null shkp.");
1319 return 0;
1321 proceed:
1322 eshkp = ESHK(shkp);
1323 ltmp = eshkp->robbed;
1325 /* wake sleeping shk when someone who owes money offers payment */
1326 if (ltmp || eshkp->billct || eshkp->debit)
1327 rouse_shk(shkp, TRUE);
1329 if (!shkp->mcanmove || shkp->msleeping) { /* still asleep/paralyzed */
1330 pline("%s %s.", Shknam(shkp),
1331 rn2(2) ? "seems to be napping" : "doesn't respond");
1332 return 0;
1335 if (shkp != resident && NOTANGRY(shkp)) {
1336 umoney = money_cnt(invent);
1337 if (!ltmp)
1338 You("do not owe %s anything.", shkname(shkp));
1339 else if (!umoney) {
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 if (umoney > ltmp) {
1345 You("give %s the %ld gold piece%s %s asked for.",
1346 shkname(shkp), ltmp, plur(ltmp), mhe(shkp));
1347 pay(ltmp, shkp);
1348 } else {
1349 You("give %s all your%s gold.", shkname(shkp),
1350 stashed_gold ? " openly kept" : "");
1351 pay(umoney, shkp);
1352 if (stashed_gold)
1353 pline("But you have hidden gold!");
1355 if ((umoney < ltmp / 2L) || (umoney < ltmp && stashed_gold))
1356 pline("Unfortunately, %s doesn't look satisfied.", mhe(shkp));
1357 else
1358 make_happy_shk(shkp, FALSE);
1360 return 1;
1363 /* ltmp is still eshkp->robbed here */
1364 if (!eshkp->billct && !eshkp->debit) {
1365 umoney = money_cnt(invent);
1366 if (!ltmp && NOTANGRY(shkp)) {
1367 You("do not owe %s anything.", shkname(shkp));
1368 if (!umoney)
1369 pline(no_money, stashed_gold ? " seem to" : "");
1370 } else if (ltmp) {
1371 pline("%s is after blood, not money!", shkname(shkp));
1372 if (umoney < ltmp / 2L || (umoney < ltmp && stashed_gold)) {
1373 if (!umoney)
1374 pline(no_money, stashed_gold ? " seem to" : "");
1375 else
1376 pline(not_enough_money, mhim(shkp));
1377 return 1;
1379 pline("But since %s shop has been robbed recently,", mhis(shkp));
1380 pline("you %scompensate %s for %s losses.",
1381 (umoney < ltmp) ? "partially " : "", shkname(shkp),
1382 mhis(shkp));
1383 pay(umoney < ltmp ? umoney : ltmp, shkp);
1384 make_happy_shk(shkp, FALSE);
1385 } else {
1386 /* shopkeeper is angry, but has not been robbed --
1387 * door broken, attacked, etc. */
1388 pline("%s is after your hide, not your money!", Shknam(shkp));
1389 if (umoney < 1000L) {
1390 if (!umoney)
1391 pline(no_money, stashed_gold ? " seem to" : "");
1392 else
1393 pline(not_enough_money, mhim(shkp));
1394 return 1;
1396 You("try to appease %s by giving %s 1000 gold pieces.",
1397 x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE), mhim(shkp));
1398 pay(1000L, shkp);
1399 if (strncmp(eshkp->customer, plname, PL_NSIZ) || rn2(3))
1400 make_happy_shk(shkp, FALSE);
1401 else
1402 pline("But %s is as angry as ever.", shkname(shkp));
1404 return 1;
1406 if (shkp != resident) {
1407 impossible("dopay: not to shopkeeper?");
1408 if (resident)
1409 setpaid(resident);
1410 return 0;
1412 /* pay debt, if any, first */
1413 if (eshkp->debit) {
1414 long dtmp = eshkp->debit;
1415 long loan = eshkp->loan;
1416 char sbuf[BUFSZ];
1418 umoney = money_cnt(invent);
1419 Sprintf(sbuf, "You owe %s %ld %s ", shkname(shkp), dtmp,
1420 currency(dtmp));
1421 if (loan) {
1422 if (loan == dtmp)
1423 Strcat(sbuf, "you picked up in the store.");
1424 else
1425 Strcat(sbuf,
1426 "for gold picked up and the use of merchandise.");
1427 } else
1428 Strcat(sbuf, "for the use of merchandise.");
1429 pline1(sbuf);
1430 if (umoney + eshkp->credit < dtmp) {
1431 pline("But you don't%s have enough gold%s.",
1432 stashed_gold ? " seem to" : "",
1433 eshkp->credit ? " or credit" : "");
1434 return 1;
1435 } else {
1436 if (eshkp->credit >= dtmp) {
1437 eshkp->credit -= dtmp;
1438 eshkp->debit = 0L;
1439 eshkp->loan = 0L;
1440 Your("debt is covered by your credit.");
1441 } else if (!eshkp->credit) {
1442 money2mon(shkp, dtmp);
1443 eshkp->debit = 0L;
1444 eshkp->loan = 0L;
1445 You("pay that debt.");
1446 context.botl = 1;
1447 } else {
1448 dtmp -= eshkp->credit;
1449 eshkp->credit = 0L;
1450 money2mon(shkp, dtmp);
1451 eshkp->debit = 0L;
1452 eshkp->loan = 0L;
1453 pline("That debt is partially offset by your credit.");
1454 You("pay the remainder.");
1455 context.botl = 1;
1457 paid = TRUE;
1460 /* now check items on bill */
1461 if (eshkp->billct) {
1462 register boolean itemize;
1463 int iprompt;
1465 umoney = money_cnt(invent);
1466 if (!umoney && !eshkp->credit) {
1467 You("%shave no money or credit%s.",
1468 stashed_gold ? "seem to " : "", paid ? " left" : "");
1469 return 0;
1471 if ((umoney + eshkp->credit) < cheapest_item(shkp)) {
1472 You("don't have enough money to buy%s the item%s you picked.",
1473 eshkp->billct > 1 ? " any of" : "", plur(eshkp->billct));
1474 if (stashed_gold)
1475 pline("Maybe you have some gold stashed away?");
1476 return 0;
1479 /* this isn't quite right; it itemizes without asking if the
1480 * single item on the bill is partly used up and partly unpaid */
1481 iprompt = (eshkp->billct > 1 ? ynq("Itemized billing?") : 'y');
1482 itemize = (iprompt == 'y');
1483 if (iprompt == 'q')
1484 goto thanks;
1486 for (pass = 0; pass <= 1; pass++) {
1487 tmp = 0;
1488 while (tmp < eshkp->billct) {
1489 struct obj *otmp;
1490 register struct bill_x *bp = &(eshkp->bill_p[tmp]);
1492 /* find the object on one of the lists */
1493 if ((otmp = bp_to_obj(bp)) != 0) {
1494 /* if completely used up, object quantity is stale;
1495 restoring it to its original value here avoids
1496 making the partly-used-up code more complicated */
1497 if (bp->useup)
1498 otmp->quan = bp->bquan;
1499 } else {
1500 impossible("Shopkeeper administration out of order.");
1501 setpaid(shkp); /* be nice to the player */
1502 return 1;
1504 if (pass == bp->useup && otmp->quan == bp->bquan) {
1505 /* pay for used-up items on first pass and others
1506 * on second, so player will be stuck in the store
1507 * less often; things which are partly used up
1508 * are processed on both passes */
1509 tmp++;
1510 } else {
1511 switch (dopayobj(shkp, bp, &otmp, pass, itemize)) {
1512 case PAY_CANT:
1513 return 1; /*break*/
1514 case PAY_BROKE:
1515 paid = TRUE;
1516 goto thanks; /*break*/
1517 case PAY_SKIP:
1518 tmp++;
1519 continue; /*break*/
1520 case PAY_SOME:
1521 paid = TRUE;
1522 if (itemize)
1523 bot();
1524 continue; /*break*/
1525 case PAY_BUY:
1526 paid = TRUE;
1527 break;
1529 if (itemize)
1530 bot();
1531 *bp = eshkp->bill_p[--eshkp->billct];
1535 thanks:
1536 if (!itemize)
1537 update_inventory(); /* Done in dopayobj() if itemize. */
1539 if (!ANGRY(shkp) && paid) {
1540 if (!Deaf && !muteshk(shkp))
1541 verbalize("Thank you for shopping in %s %s!", s_suffix(shkname(shkp)),
1542 shtypes[eshkp->shoptype - SHOPBASE].name);
1543 else
1544 pline("%s nods appreciatively at you for shopping in %s %s!",
1545 Shknam(shkp),
1546 mhis(shkp),
1547 shtypes[eshkp->shoptype - SHOPBASE].name);
1549 return 1;
1552 /* return 2 if used-up portion paid
1553 * 1 if paid successfully
1554 * 0 if not enough money
1555 * -1 if skip this object
1556 * -2 if no money/credit left
1558 STATIC_OVL int
1559 dopayobj(shkp, bp, obj_p, which, itemize)
1560 register struct monst *shkp;
1561 register struct bill_x *bp;
1562 struct obj **obj_p;
1563 int which; /* 0 => used-up item, 1 => other (unpaid or lost) */
1564 boolean itemize;
1566 register struct obj *obj = *obj_p;
1567 long ltmp, quan, save_quan;
1568 long umoney = money_cnt(invent);
1569 int buy;
1570 boolean stashed_gold = (hidden_gold() > 0L), consumed = (which == 0);
1572 if (!obj->unpaid && !bp->useup) {
1573 impossible("Paid object on bill??");
1574 return PAY_BUY;
1576 if (itemize && umoney + ESHK(shkp)->credit == 0L) {
1577 You("%shave no money or credit left.",
1578 stashed_gold ? "seem to " : "");
1579 return PAY_BROKE;
1581 /* we may need to temporarily adjust the object, if part of the
1582 original quantity has been used up but part remains unpaid */
1583 save_quan = obj->quan;
1584 if (consumed) {
1585 /* either completely used up (simple), or split needed */
1586 quan = bp->bquan;
1587 if (quan > obj->quan) /* difference is amount used up */
1588 quan -= obj->quan;
1589 } else {
1590 /* dealing with ordinary unpaid item */
1591 quan = obj->quan;
1593 obj->quan = quan; /* to be used by doname() */
1594 obj->unpaid = 0; /* ditto */
1595 iflags.suppress_price++; /* affects containers */
1596 ltmp = bp->price * quan;
1597 buy = PAY_BUY; /* flag; if changed then return early */
1599 if (itemize) {
1600 char qbuf[BUFSZ], qsfx[BUFSZ];
1602 Sprintf(qsfx, " for %ld %s. Pay?", ltmp, currency(ltmp));
1603 (void) safe_qbuf(qbuf, (char *) 0, qsfx, obj,
1604 (quan == 1L) ? Doname2 : doname, ansimpleoname,
1605 (quan == 1L) ? "that" : "those");
1606 if (yn(qbuf) == 'n') {
1607 buy = PAY_SKIP; /* don't want to buy */
1608 } else if (quan < bp->bquan && !consumed) { /* partly used goods */
1609 obj->quan = bp->bquan - save_quan; /* used up amount */
1610 if (!Deaf && !muteshk(shkp)) {
1611 verbalize("%s for the other %s before buying %s.",
1612 ANGRY(shkp) ? "Pay" : "Please pay",
1613 simpleonames(obj), /* short name suffices */
1614 save_quan > 1L ? "these" : "this one");
1615 } else {
1616 pline("%s %s%s your bill for the other %s first.",
1617 Shknam(shkp),
1618 ANGRY(shkp) ? "angrily " : "",
1619 nolimbs(shkp->data) ? "motions to" : "points out",
1620 simpleonames(obj));
1622 buy = PAY_SKIP; /* shk won't sell */
1625 if (buy == PAY_BUY && umoney + ESHK(shkp)->credit < ltmp) {
1626 You("don't%s have gold%s enough to pay for %s.",
1627 stashed_gold ? " seem to" : "",
1628 (ESHK(shkp)->credit > 0L) ? " or credit" : "",
1629 thesimpleoname(obj));
1630 buy = itemize ? PAY_SKIP : PAY_CANT;
1633 if (buy != PAY_BUY) {
1634 /* restore unpaid object to original state */
1635 obj->quan = save_quan;
1636 obj->unpaid = 1;
1637 iflags.suppress_price--;
1638 return buy;
1641 pay(ltmp, shkp);
1642 shk_names_obj(shkp, obj,
1643 consumed ? "paid for %s at a cost of %ld gold piece%s.%s"
1644 : "bought %s for %ld gold piece%s.%s",
1645 ltmp, "");
1646 obj->quan = save_quan; /* restore original count */
1647 /* quan => amount just bought, save_quan => remaining unpaid count */
1648 if (consumed) {
1649 if (quan != bp->bquan) {
1650 /* eliminate used-up portion; remainder is still unpaid */
1651 bp->bquan = obj->quan;
1652 obj->unpaid = 1;
1653 bp->useup = 0;
1654 buy = PAY_SOME;
1655 } else { /* completely used-up, so get rid of it */
1656 obj_extract_self(obj);
1657 /* assert( obj == *obj_p ); */
1658 dealloc_obj(obj);
1659 *obj_p = 0; /* destroy pointer to freed object */
1661 } else if (itemize)
1662 update_inventory(); /* Done just once in dopay() if !itemize. */
1663 iflags.suppress_price--;
1664 return buy;
1667 static struct repo { /* repossession context */
1668 struct monst *shopkeeper;
1669 coord location;
1670 } repo;
1672 /* routine called after dying (or quitting) */
1673 boolean
1674 paybill(croaked)
1675 int croaked; /* -1: escaped dungeon; 0: quit; 1: died */
1677 struct monst *mtmp, *mtmp2, *firstshk, *resident, *creditor, *hostile,
1678 *localshk;
1679 struct eshk *eshkp;
1680 boolean taken = FALSE, local;
1681 int numsk = 0;
1683 /* if we escaped from the dungeon, shopkeepers can't reach us;
1684 shops don't occur on level 1, but this could happen if hero
1685 level teleports out of the dungeon and manages not to die */
1686 if (croaked < 0)
1687 return FALSE;
1688 /* [should probably also return false when dead hero has been
1689 petrified since shk shouldn't be able to grab inventory
1690 which has been shut inside a statue] */
1692 /* this is where inventory will end up if any shk takes it */
1693 repo.location.x = repo.location.y = 0;
1694 repo.shopkeeper = 0;
1697 * Scan all shopkeepers on the level, to prioritize them:
1698 * 1) keeper of shop hero is inside and who is owed money,
1699 * 2) keeper of shop hero is inside who isn't owed any money,
1700 * 3) other shk who is owed money, 4) other shk who is angry,
1701 * 5) any shk local to this level, and if none is found,
1702 * 6) first shk on monster list (last resort; unlikely, since
1703 * any nonlocal shk will probably be in the owed category
1704 * and almost certainly be in the angry category).
1706 resident = creditor = hostile = localshk = (struct monst *) 0;
1707 for (mtmp = next_shkp(fmon, FALSE); mtmp;
1708 mtmp = next_shkp(mtmp2, FALSE)) {
1709 mtmp2 = mtmp->nmon;
1710 eshkp = ESHK(mtmp);
1711 local = on_level(&eshkp->shoplevel, &u.uz);
1712 if (local && index(u.ushops, eshkp->shoproom)) {
1713 /* inside this shk's shop [there might be more than one
1714 resident shk if hero is standing in a breech of a shared
1715 wall, so give priority to one who's also owed money] */
1716 if (!resident || eshkp->billct || eshkp->debit || eshkp->robbed)
1717 resident = mtmp;
1718 } else if (eshkp->billct || eshkp->debit || eshkp->robbed) {
1719 /* owe this shopkeeper money (might also owe others) */
1720 if (!creditor)
1721 creditor = mtmp;
1722 } else if (eshkp->following || ANGRY(mtmp)) {
1723 /* this shopkeeper is antagonistic (others might be too) */
1724 if (!hostile)
1725 hostile = mtmp;
1726 } else if (local) {
1727 /* this shopkeeper's shop is on current level */
1728 if (!localshk)
1729 localshk = mtmp;
1733 /* give highest priority shopkeeper first crack */
1734 firstshk = resident ? resident
1735 : creditor ? creditor
1736 : hostile ? hostile
1737 : localshk;
1738 if (firstshk) {
1739 numsk++;
1740 taken = inherits(firstshk, numsk, croaked);
1743 /* now handle the rest */
1744 for (mtmp = next_shkp(fmon, FALSE); mtmp;
1745 mtmp = next_shkp(mtmp2, FALSE)) {
1746 mtmp2 = mtmp->nmon;
1747 eshkp = ESHK(mtmp);
1748 local = on_level(&eshkp->shoplevel, &u.uz);
1749 if (mtmp != firstshk) {
1750 numsk++;
1751 taken |= inherits(mtmp, numsk, croaked);
1753 /* for bones: we don't want a shopless shk around */
1754 if (!local)
1755 mongone(mtmp);
1757 return taken;
1760 STATIC_OVL boolean
1761 inherits(shkp, numsk, croaked)
1762 struct monst *shkp;
1763 int numsk;
1764 int croaked;
1766 long loss = 0L;
1767 long umoney;
1768 struct eshk *eshkp = ESHK(shkp);
1769 boolean take = FALSE, taken = FALSE;
1770 unsigned save_minvis = shkp->minvis;
1771 int roomno = *u.ushops;
1772 char takes[BUFSZ];
1774 shkp->minvis = 0;
1775 /* The simplifying principle is that first-come
1776 already took everything you had. */
1777 if (numsk > 1) {
1778 if (cansee(shkp->mx, shkp->my) && croaked) {
1779 takes[0] = '\0';
1780 if (has_head(shkp->data) && !rn2(2))
1781 Sprintf(takes, ", shakes %s %s,", mhis(shkp),
1782 mbodypart(shkp, HEAD));
1783 pline("%s %slooks at your corpse%s and %s.", Shknam(shkp),
1784 (!shkp->mcanmove || shkp->msleeping) ? "wakes up, " : "",
1785 takes, !inhishop(shkp) ? "disappears" : "sighs");
1787 rouse_shk(shkp, FALSE); /* wake shk for bones */
1788 taken = (roomno == eshkp->shoproom);
1789 goto skip;
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) && !eshkp->billct
1795 && !eshkp->robbed && !eshkp->debit && NOTANGRY(shkp)
1796 && !eshkp->following && u.ugrave_arise < LOW_PM) {
1797 taken = (invent != 0);
1798 if (taken)
1799 pline("%s gratefully inherits all your possessions.",
1800 shkname(shkp));
1801 set_repo_loc(shkp);
1802 goto clear;
1805 if (eshkp->billct || eshkp->debit || eshkp->robbed) {
1806 if (roomno == eshkp->shoproom && inhishop(shkp))
1807 loss = addupbill(shkp) + eshkp->debit;
1808 if (loss < eshkp->robbed)
1809 loss = eshkp->robbed;
1810 take = TRUE;
1813 if (eshkp->following || ANGRY(shkp) || take) {
1814 if (!invent)
1815 goto skip;
1816 umoney = money_cnt(invent);
1817 takes[0] = '\0';
1818 if (!shkp->mcanmove || shkp->msleeping)
1819 Strcat(takes, "wakes up and ");
1820 if (distu(shkp->mx, shkp->my) > 2)
1821 Strcat(takes, "comes and ");
1822 Strcat(takes, "takes");
1824 if (loss > umoney || !loss || roomno == eshkp->shoproom) {
1825 eshkp->robbed -= umoney;
1826 if (eshkp->robbed < 0L)
1827 eshkp->robbed = 0L;
1828 if (umoney > 0)
1829 money2mon(shkp, umoney);
1830 context.botl = 1;
1831 pline("%s %s all your possessions.", shkname(shkp), takes);
1832 taken = TRUE;
1833 /* where to put player's invent (after disclosure) */
1834 set_repo_loc(shkp);
1835 } else {
1836 money2mon(shkp, loss);
1837 context.botl = 1;
1838 pline("%s %s the %ld %s %sowed %s.", Shknam(shkp),
1839 takes, loss, currency(loss),
1840 strncmp(eshkp->customer, plname, PL_NSIZ) ? "" : "you ",
1841 mhim(shkp));
1842 /* shopkeeper has now been paid in full */
1843 pacify_shk(shkp);
1844 eshkp->following = 0;
1845 eshkp->robbed = 0L;
1847 skip:
1848 /* in case we create bones */
1849 rouse_shk(shkp, FALSE); /* wake up */
1850 if (!inhishop(shkp))
1851 home_shk(shkp, FALSE);
1853 clear:
1854 shkp->minvis = save_minvis;
1855 setpaid(shkp);
1856 return taken;
1859 STATIC_OVL void
1860 set_repo_loc(shkp)
1861 struct monst *shkp;
1863 register xchar ox, oy;
1864 struct eshk *eshkp = ESHK(shkp);
1866 /* if you're not in this shk's shop room, or if you're in its doorway
1867 or entry spot, then your gear gets dumped all the way inside */
1868 if (*u.ushops != eshkp->shoproom || IS_DOOR(levl[u.ux][u.uy].typ)
1869 || (u.ux == eshkp->shk.x && u.uy == eshkp->shk.y)) {
1870 /* shk.x,shk.y is the position immediately in
1871 * front of the door -- move in one more space
1873 ox = eshkp->shk.x;
1874 oy = eshkp->shk.y;
1875 ox += sgn(ox - eshkp->shd.x);
1876 oy += sgn(oy - eshkp->shd.y);
1877 } else { /* already inside this shk's shop */
1878 ox = u.ux;
1879 oy = u.uy;
1881 /* finish_paybill will deposit invent here */
1882 repo.location.x = ox;
1883 repo.location.y = oy;
1884 repo.shopkeeper = shkp;
1887 /* called at game exit, after inventory disclosure but before making bones */
1888 void
1889 finish_paybill()
1891 struct monst *shkp = repo.shopkeeper;
1892 int ox = repo.location.x, oy = repo.location.y;
1894 #if 0 /* don't bother */
1895 if (ox == 0 && oy == 0)
1896 impossible("finish_paybill: no location");
1897 #endif
1898 /* normally done by savebones(), but that's too late in this case */
1899 unleash_all();
1900 /* if hero has any gold left, take it into shopkeeper's possession */
1901 if (shkp) {
1902 long umoney = money_cnt(invent);
1904 if (umoney)
1905 money2mon(shkp, umoney);
1907 /* transfer rest of the character's inventory to the shop floor */
1908 drop_upon_death((struct monst *) 0, (struct obj *) 0, ox, oy);
1911 /* find obj on one of the lists */
1912 STATIC_OVL struct obj *
1913 bp_to_obj(bp)
1914 register struct bill_x *bp;
1916 register struct obj *obj;
1917 register unsigned int id = bp->bo_id;
1919 if (bp->useup)
1920 obj = o_on(id, billobjs);
1921 else
1922 obj = find_oid(id);
1923 return obj;
1927 * Look for o_id on all lists but billobj. Return obj or NULL if not found.
1928 * Its OK for restore_timers() to call this function, there should not
1929 * be any timeouts on the billobjs chain.
1931 struct obj *
1932 find_oid(id)
1933 unsigned id;
1935 struct obj *obj;
1936 struct monst *mon, *mmtmp[3];
1937 int i;
1939 /* first check various obj lists directly */
1940 if ((obj = o_on(id, invent)) != 0)
1941 return obj;
1942 if ((obj = o_on(id, fobj)) != 0)
1943 return obj;
1944 if ((obj = o_on(id, level.buriedobjlist)) != 0)
1945 return obj;
1946 if ((obj = o_on(id, migrating_objs)) != 0)
1947 return obj;
1949 /* not found yet; check inventory for members of various monst lists */
1950 mmtmp[0] = fmon;
1951 mmtmp[1] = migrating_mons;
1952 mmtmp[2] = mydogs; /* for use during level changes */
1953 for (i = 0; i < 3; i++)
1954 for (mon = mmtmp[i]; mon; mon = mon->nmon)
1955 if ((obj = o_on(id, mon->minvent)) != 0)
1956 return obj;
1958 /* not found at all */
1959 return (struct obj *) 0;
1962 /* Returns the price of an arbitrary item in the shop.
1963 Returns 0 if the item doesn't belong to a shopkeeper. */
1964 long
1965 get_cost_of_shop_item(obj)
1966 register struct obj *obj;
1968 struct monst *shkp;
1969 xchar x, y;
1970 long cost = 0L;
1972 if (*u.ushops
1973 && obj->oclass != COIN_CLASS
1974 && obj != uball && obj != uchain
1975 && get_obj_location(obj, &x, &y, 0)
1976 && (obj->unpaid
1977 || (obj->where == OBJ_FLOOR
1978 && !obj->no_charge && costly_spot(x, y)))
1979 && (shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0
1980 && inhishop(shkp)) {
1981 cost = obj->quan * get_cost(obj, shkp);
1982 if (Has_contents(obj))
1983 cost += contained_cost(obj, shkp, 0L, FALSE, FALSE);
1985 return cost;
1988 /* calculate the value that the shk will charge for [one of] an object */
1989 STATIC_OVL long
1990 get_cost(obj, shkp)
1991 register struct obj *obj;
1992 register struct monst *shkp; /* if angry, impose a surcharge */
1994 long tmp = getprice(obj, FALSE),
1995 /* used to perform a single calculation even when multiple
1996 adjustments (unID'd, dunce/tourist, charisma) are made */
1997 multiplier = 1L, divisor = 1L;
1999 if (!tmp)
2000 tmp = 5L;
2001 /* shopkeeper may notice if the player isn't very knowledgeable -
2002 especially when gem prices are concerned */
2003 if (!obj->dknown || !objects[obj->otyp].oc_name_known) {
2004 if (obj->oclass == GEM_CLASS
2005 && objects[obj->otyp].oc_material == GLASS) {
2006 int i;
2007 /* get a value that's 'random' from game to game, but the
2008 same within the same game */
2009 boolean pseudorand =
2010 (((int) ubirthday % obj->otyp) >= obj->otyp / 2);
2012 /* all gems are priced high - real or not */
2013 switch (obj->otyp - LAST_GEM) {
2014 case 1: /* white */
2015 i = pseudorand ? DIAMOND : OPAL;
2016 break;
2017 case 2: /* blue */
2018 i = pseudorand ? SAPPHIRE : AQUAMARINE;
2019 break;
2020 case 3: /* red */
2021 i = pseudorand ? RUBY : JASPER;
2022 break;
2023 case 4: /* yellowish brown */
2024 i = pseudorand ? AMBER : TOPAZ;
2025 break;
2026 case 5: /* orange */
2027 i = pseudorand ? JACINTH : AGATE;
2028 break;
2029 case 6: /* yellow */
2030 i = pseudorand ? CITRINE : CHRYSOBERYL;
2031 break;
2032 case 7: /* black */
2033 i = pseudorand ? BLACK_OPAL : JET;
2034 break;
2035 case 8: /* green */
2036 i = pseudorand ? EMERALD : JADE;
2037 break;
2038 case 9: /* violet */
2039 i = pseudorand ? AMETHYST : FLUORITE;
2040 break;
2041 default:
2042 impossible("bad glass gem %d?", obj->otyp);
2043 i = STRANGE_OBJECT;
2044 break;
2046 tmp = (long) objects[i].oc_cost;
2047 } else if (!(obj->o_id % 4)) {
2048 /* unid'd, arbitrarily impose surcharge: tmp *= 4/3 */
2049 multiplier *= 4L;
2050 divisor *= 3L;
2053 if (uarmh && uarmh->otyp == DUNCE_CAP)
2054 multiplier *= 4L, divisor *= 3L;
2055 else if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV / 2))
2056 || (uarmu && !uarm && !uarmc)) /* touristy shirt visible */
2057 multiplier *= 4L, divisor *= 3L;
2059 if (ACURR(A_CHA) > 18)
2060 divisor *= 2L;
2061 else if (ACURR(A_CHA) == 18)
2062 multiplier *= 2L, divisor *= 3L;
2063 else if (ACURR(A_CHA) >= 16)
2064 multiplier *= 3L, divisor *= 4L;
2065 else if (ACURR(A_CHA) <= 5)
2066 multiplier *= 2L;
2067 else if (ACURR(A_CHA) <= 7)
2068 multiplier *= 3L, divisor *= 2L;
2069 else if (ACURR(A_CHA) <= 10)
2070 multiplier *= 4L, divisor *= 3L;
2072 /* tmp = (tmp * multiplier) / divisor [with roundoff tweak] */
2073 tmp *= multiplier;
2074 if (divisor > 1L) {
2075 /* tmp = (((tmp * 10) / divisor) + 5) / 10 */
2076 tmp *= 10L;
2077 tmp /= divisor;
2078 tmp += 5L;
2079 tmp /= 10L;
2082 if (tmp <= 0L)
2083 tmp = 1L;
2084 /* the artifact prices in artilist[] are also used as a score bonus;
2085 inflate their shop price here without affecting score calculation */
2086 if (obj->oartifact)
2087 tmp *= 4L;
2089 /* anger surcharge should match rile_shk's, so we do it separately
2090 from the multiplier/divisor calculation */
2091 if (shkp && ESHK(shkp)->surcharge)
2092 tmp += (tmp + 2L) / 3L;
2093 return tmp;
2096 /* returns the price of a container's content. the price
2097 * of the "top" container is added in the calling functions.
2098 * a different price quoted for selling as vs. buying.
2100 long
2101 contained_cost(obj, shkp, price, usell, unpaid_only)
2102 struct obj *obj;
2103 struct monst *shkp;
2104 long price;
2105 boolean usell;
2106 boolean unpaid_only;
2108 register struct obj *otmp;
2110 /* price of contained objects; "top" container handled by caller */
2111 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2112 if (otmp->oclass == COIN_CLASS)
2113 continue;
2115 if (usell) {
2116 if (saleable(shkp, otmp) && !otmp->unpaid
2117 && otmp->oclass != BALL_CLASS
2118 && !(otmp->oclass == FOOD_CLASS && otmp->oeaten)
2119 && !(Is_candle(otmp)
2120 && otmp->age < 20L * (long) objects[otmp->otyp].oc_cost))
2121 price += set_cost(otmp, shkp);
2122 } else if (!otmp->no_charge && (otmp->unpaid || !unpaid_only)) {
2123 price += get_cost(otmp, shkp) * otmp->quan;
2126 if (Has_contents(otmp))
2127 price = contained_cost(otmp, shkp, price, usell, unpaid_only);
2130 return price;
2133 /* count amount of gold inside container 'obj' and any nested containers */
2134 long
2135 contained_gold(obj)
2136 struct obj *obj;
2138 register struct obj *otmp;
2139 register long value = 0L;
2141 /* accumulate contained gold */
2142 for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
2143 if (otmp->oclass == COIN_CLASS)
2144 value += otmp->quan;
2145 else if (Has_contents(otmp))
2146 value += contained_gold(otmp);
2148 return value;
2151 STATIC_OVL void
2152 dropped_container(obj, shkp, sale)
2153 register struct obj *obj;
2154 register struct monst *shkp;
2155 register boolean sale;
2157 register struct obj *otmp;
2159 /* the "top" container is treated in the calling fn */
2160 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2161 if (otmp->oclass == COIN_CLASS)
2162 continue;
2164 if (!otmp->unpaid && !(sale && saleable(shkp, otmp)))
2165 otmp->no_charge = 1;
2167 if (Has_contents(otmp))
2168 dropped_container(otmp, shkp, sale);
2172 void
2173 picked_container(obj)
2174 register struct obj *obj;
2176 register struct obj *otmp;
2178 /* the "top" container is treated in the calling fn */
2179 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2180 if (otmp->oclass == COIN_CLASS)
2181 continue;
2183 if (otmp->no_charge)
2184 otmp->no_charge = 0;
2186 if (Has_contents(otmp))
2187 picked_container(otmp);
2191 STATIC_OVL boolean
2192 special_stock(obj, shkp, quietly)
2193 struct obj *obj;
2194 struct monst *shkp;
2195 boolean quietly;
2197 /* for unique situations */
2198 if (ESHK(shkp)->shoptype == CANDLESHOP
2199 && obj->otyp == CANDELABRUM_OF_INVOCATION) {
2200 if (!quietly) {
2201 if (is_izchak(shkp, TRUE) && !u.uevent.invoked) {
2202 if (Deaf || muteshk(shkp)) {
2203 pline("%s seems %s that you want to sell that.",
2204 Shknam(shkp),
2205 (obj->spe < 7) ? "horrified" : "concerned");
2206 } else {
2207 verbalize("No thanks, I'd hang onto that if I were you.");
2208 if (obj->spe < 7)
2209 verbalize(
2210 "You'll need %d%s candle%s to go along with it.",
2211 (7 - obj->spe), (obj->spe > 0) ? " more" : "",
2212 plur(7 - obj->spe));
2213 /* [what if hero is already carrying enough candles?
2214 should Izchak explain how to attach them instead?] */
2216 } else {
2217 if (!Deaf && !muteshk(shkp))
2218 verbalize("I won't stock that. Take it out of here!");
2219 else
2220 pline("%s shakes %s %s in refusal.",
2221 Shknam(shkp),
2222 mhis(shkp),
2223 mbodypart(shkp, HEAD));
2226 return TRUE;
2228 return FALSE;
2231 /* calculate how much the shk will pay when buying [all of] an object */
2232 STATIC_OVL long
2233 set_cost(obj, shkp)
2234 register struct obj *obj;
2235 register struct monst *shkp;
2237 long tmp = getprice(obj, TRUE) * obj->quan, multiplier = 1L, divisor = 1L;
2239 if (uarmh && uarmh->otyp == DUNCE_CAP)
2240 divisor *= 3L;
2241 else if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV / 2))
2242 || (uarmu && !uarm && !uarmc)) /* touristy shirt visible */
2243 divisor *= 3L;
2244 else
2245 divisor *= 2L;
2247 /* shopkeeper may notice if the player isn't very knowledgeable -
2248 especially when gem prices are concerned */
2249 if (!obj->dknown || !objects[obj->otyp].oc_name_known) {
2250 if (obj->oclass == GEM_CLASS) {
2251 /* different shop keepers give different prices */
2252 if (objects[obj->otyp].oc_material == GEMSTONE
2253 || objects[obj->otyp].oc_material == GLASS) {
2254 tmp = (obj->otyp % (6 - shkp->m_id % 3));
2255 tmp = (tmp + 3) * obj->quan;
2257 } else if (tmp > 1L && !(shkp->m_id % 4))
2258 multiplier *= 3L, divisor *= 4L;
2261 if (tmp >= 1L) {
2262 /* [see get_cost()] */
2263 tmp *= multiplier;
2264 if (divisor > 1L) {
2265 tmp *= 10L;
2266 tmp /= divisor;
2267 tmp += 5L;
2268 tmp /= 10L;
2270 /* avoid adjusting nonzero to zero */
2271 if (tmp < 1L)
2272 tmp = 1L;
2275 /* (no adjustment for angry shk here) */
2276 return tmp;
2279 /* called when an item's value has been enhanced; if it happens to be
2280 on any shop bill, update that bill to reflect the new higher price
2281 [if the new price drops for some reason, keep the old one in place] */
2282 void
2283 alter_cost(obj, amt)
2284 struct obj *obj;
2285 long amt; /* if 0, use regular shop pricing, otherwise force amount;
2286 if negative, use abs(amt) even if it's less than old cost */
2288 struct bill_x *bp = 0;
2289 struct monst *shkp;
2290 long new_price;
2292 for (shkp = next_shkp(fmon, TRUE); shkp; shkp = next_shkp(shkp, TRUE))
2293 if ((bp = onbill(obj, shkp, TRUE)) != 0) {
2294 new_price = !amt ? get_cost(obj, shkp) : (amt < 0L) ? -amt : amt;
2295 if (new_price > bp->price || amt < 0L) {
2296 bp->price = new_price;
2297 update_inventory();
2299 break; /* done */
2301 return;
2304 /* called from doinv(invent.c) for inventory of unpaid objects */
2305 long
2306 unpaid_cost(unp_obj, include_contents)
2307 struct obj *unp_obj; /* known to be unpaid or contain unpaid */
2308 boolean include_contents;
2310 struct bill_x *bp = (struct bill_x *) 0;
2311 struct monst *shkp;
2312 long amt = 0L;
2313 xchar ox, oy;
2315 if (!get_obj_location(unp_obj, &ox, &oy, BURIED_TOO | CONTAINED_TOO))
2316 ox = u.ux, oy = u.uy; /* (shouldn't happen) */
2317 if ((shkp = shop_keeper(*in_rooms(ox, oy, SHOPBASE))) != 0) {
2318 bp = onbill(unp_obj, shkp, TRUE);
2319 } else {
2320 /* didn't find shk? try searching bills */
2321 for (shkp = next_shkp(fmon, TRUE); shkp;
2322 shkp = next_shkp(shkp->nmon, TRUE))
2323 if ((bp = onbill(unp_obj, shkp, TRUE)) != 0)
2324 break;
2327 /* onbill() gave no message if unexpected problem occurred */
2328 if (!shkp || (unp_obj->unpaid && !bp)) {
2329 impossible("unpaid_cost: object wasn't on any bill.");
2330 } else {
2331 if (bp)
2332 amt = unp_obj->quan * bp->price;
2333 if (include_contents && Has_contents(unp_obj))
2334 amt = contained_cost(unp_obj, shkp, amt, FALSE, TRUE);
2336 return amt;
2339 STATIC_OVL void
2340 add_one_tobill(obj, dummy, shkp)
2341 struct obj *obj;
2342 boolean dummy;
2343 struct monst *shkp;
2345 struct eshk *eshkp;
2346 struct bill_x *bp;
2347 int bct;
2349 if (!billable(&shkp, obj, *u.ushops, TRUE))
2350 return;
2351 eshkp = ESHK(shkp);
2353 if (eshkp->billct == BILLSZ) {
2354 You("got that for free!");
2355 return;
2358 bct = eshkp->billct;
2359 bp = &(eshkp->bill_p[bct]);
2360 bp->bo_id = obj->o_id;
2361 bp->bquan = obj->quan;
2362 if (dummy) { /* a dummy object must be inserted into */
2363 bp->useup = 1; /* the billobjs chain here. crucial for */
2364 add_to_billobjs(obj); /* eating floorfood in shop. see eat.c */
2365 } else
2366 bp->useup = 0;
2367 bp->price = get_cost(obj, shkp);
2368 eshkp->billct++;
2369 obj->unpaid = 1;
2372 STATIC_OVL void
2373 add_to_billobjs(obj)
2374 struct obj *obj;
2376 if (obj->where != OBJ_FREE)
2377 panic("add_to_billobjs: obj not free");
2378 if (obj->timed)
2379 obj_stop_timers(obj);
2381 obj->nobj = billobjs;
2382 billobjs = obj;
2383 obj->where = OBJ_ONBILL;
2386 /* recursive billing of objects within containers. */
2387 STATIC_OVL void
2388 bill_box_content(obj, ininv, dummy, shkp)
2389 register struct obj *obj;
2390 register boolean ininv, dummy;
2391 register struct monst *shkp;
2393 register struct obj *otmp;
2395 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2396 if (otmp->oclass == COIN_CLASS)
2397 continue;
2399 /* the "top" box is added in addtobill() */
2400 if (!otmp->no_charge)
2401 add_one_tobill(otmp, dummy, shkp);
2402 if (Has_contents(otmp))
2403 bill_box_content(otmp, ininv, dummy, shkp);
2407 /* shopkeeper tells you what you bought or sold, sometimes partly IDing it */
2408 STATIC_OVL void
2409 shk_names_obj(shkp, obj, fmt, amt, arg)
2410 struct monst *shkp;
2411 struct obj *obj;
2412 const char *fmt; /* "%s %ld %s %s", doname(obj), amt, plur(amt), arg */
2413 long amt;
2414 const char *arg;
2416 char *obj_name, fmtbuf[BUFSZ];
2417 boolean was_unknown = !obj->dknown;
2419 obj->dknown = TRUE;
2420 /* Use real name for ordinary weapons/armor, and spell-less
2421 * scrolls/books (that is, blank and mail), but only if the
2422 * object is within the shk's area of interest/expertise.
2424 if (!objects[obj->otyp].oc_magic && saleable(shkp, obj)
2425 && (obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS
2426 || obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS
2427 || obj->otyp == MIRROR)) {
2428 was_unknown |= !objects[obj->otyp].oc_name_known;
2429 makeknown(obj->otyp);
2431 obj_name = doname(obj);
2432 /* Use an alternate message when extra information is being provided */
2433 if (was_unknown) {
2434 Sprintf(fmtbuf, "%%s; you %s", fmt);
2435 obj_name[0] = highc(obj_name[0]);
2436 pline(fmtbuf, obj_name, (obj->quan > 1L) ? "them" : "it", amt,
2437 plur(amt), arg);
2438 } else {
2439 You(fmt, obj_name, amt, plur(amt), arg);
2443 /* decide whether a shopkeeper thinks an item belongs to her */
2444 boolean
2445 billable(shkpp, obj, roomno, reset_nocharge)
2446 struct monst **shkpp; /* in: non-null if shk has been validated; out: shk */
2447 struct obj *obj;
2448 char roomno;
2449 boolean reset_nocharge;
2451 struct monst *shkp = *shkpp;
2453 /* if caller hasn't supplied a shopkeeper, look one up now */
2454 if (!shkp) {
2455 if (!roomno)
2456 return FALSE;
2457 shkp = shop_keeper(roomno);
2458 if (!shkp || !inhishop(shkp))
2459 return FALSE;
2460 *shkpp = shkp;
2462 /* perhaps we threw it away earlier */
2463 if (onbill(obj, shkp, FALSE)
2464 || (obj->oclass == FOOD_CLASS && obj->oeaten))
2465 return FALSE;
2466 /* outer container might be marked no_charge but still have contents
2467 which should be charged for; clear no_charge when picking things up */
2468 if (obj->no_charge) {
2469 if (!Has_contents(obj) || (contained_gold(obj) == 0L
2470 && contained_cost(obj, shkp, 0L, FALSE,
2471 !reset_nocharge) == 0L))
2472 shkp = 0; /* not billable */
2473 if (reset_nocharge && !shkp && obj->oclass != COIN_CLASS) {
2474 obj->no_charge = 0;
2475 if (Has_contents(obj))
2476 picked_container(obj); /* clear no_charge */
2479 return shkp ? TRUE : FALSE;
2482 void
2483 addtobill(obj, ininv, dummy, silent)
2484 struct obj *obj;
2485 boolean ininv, dummy, silent;
2487 struct monst *shkp = 0;
2488 long ltmp, cltmp, gltmp;
2489 int contentscount;
2490 boolean container;
2492 if (!billable(&shkp, obj, *u.ushops, TRUE))
2493 return;
2495 if (obj->oclass == COIN_CLASS) {
2496 costly_gold(obj->ox, obj->oy, obj->quan);
2497 return;
2498 } else if (ESHK(shkp)->billct == BILLSZ) {
2499 if (!silent)
2500 You("got that for free!");
2501 return;
2504 ltmp = cltmp = gltmp = 0L;
2505 container = Has_contents(obj);
2507 if (!obj->no_charge)
2508 ltmp = get_cost(obj, shkp);
2510 if (obj->no_charge && !container) {
2511 obj->no_charge = 0;
2512 return;
2515 if (container) {
2516 cltmp = contained_cost(obj, shkp, cltmp, FALSE, FALSE);
2517 gltmp = contained_gold(obj);
2519 if (ltmp)
2520 add_one_tobill(obj, dummy, shkp);
2521 if (cltmp)
2522 bill_box_content(obj, ininv, dummy, shkp);
2523 picked_container(obj); /* reset contained obj->no_charge */
2525 ltmp += cltmp;
2527 if (gltmp) {
2528 costly_gold(obj->ox, obj->oy, gltmp);
2529 if (!ltmp)
2530 return;
2533 if (obj->no_charge)
2534 obj->no_charge = 0;
2535 contentscount = count_unpaid(obj->cobj);
2536 } else { /* !container */
2537 add_one_tobill(obj, dummy, shkp);
2538 contentscount = 0;
2541 if (!Deaf && !muteshk(shkp) && !silent) {
2542 char buf[BUFSZ];
2544 if (!ltmp) {
2545 pline("%s has no interest in %s.", Shknam(shkp), the(xname(obj)));
2546 return;
2548 if (!ininv) {
2549 pline("%s will cost you %ld %s%s.", The(xname(obj)), ltmp,
2550 currency(ltmp), (obj->quan > 1L) ? " each" : "");
2551 } else {
2552 long save_quan = obj->quan;
2554 Strcpy(buf, "\"For you, ");
2555 if (ANGRY(shkp)) {
2556 Strcat(buf, "scum;");
2557 } else {
2558 append_honorific(buf);
2559 Strcat(buf, "; only");
2561 obj->quan = 1L; /* fool xname() into giving singular */
2562 pline("%s %ld %s %s %s%s.\"", buf, ltmp, currency(ltmp),
2563 (save_quan > 1L) ? "per"
2564 : (contentscount && !obj->unpaid)
2565 ? "for the contents of this"
2566 : "for this",
2567 xname(obj),
2568 (contentscount && obj->unpaid) ? and_its_contents : "");
2569 obj->quan = save_quan;
2571 } else if (!silent) {
2572 if (ltmp)
2573 pline_The("list price of %s%s%s is %ld %s%s.",
2574 (contentscount && !obj->unpaid) ? the_contents_of : "",
2575 the(xname(obj)),
2576 (contentscount && obj->unpaid) ? and_its_contents : "",
2577 ltmp, currency(ltmp), (obj->quan > 1L) ? " each" : "");
2578 else
2579 pline("%s does not notice.", Shknam(shkp));
2583 void
2584 append_honorific(buf)
2585 char *buf;
2587 /* (chooses among [0]..[3] normally; [1]..[4] after the
2588 Wizard has been killed or invocation ritual performed) */
2589 static const char *const honored[] = { "good", "honored", "most gracious",
2590 "esteemed",
2591 "most renowned and sacred" };
2592 Strcat(buf, honored[rn2(SIZE(honored) - 1) + u.uevent.udemigod]);
2593 if (is_vampire(youmonst.data))
2594 Strcat(buf, (flags.female) ? " dark lady" : " dark lord");
2595 else if (is_elf(youmonst.data))
2596 Strcat(buf, (flags.female) ? " hiril" : " hir");
2597 else
2598 Strcat(buf, !is_human(youmonst.data) ? " creature" : (flags.female)
2599 ? " lady"
2600 : " sir");
2603 void
2604 splitbill(obj, otmp)
2605 register struct obj *obj, *otmp;
2607 /* otmp has been split off from obj */
2608 register struct bill_x *bp;
2609 register long tmp;
2610 register struct monst *shkp = shop_keeper(*u.ushops);
2612 if (!shkp || !inhishop(shkp)) {
2613 impossible("splitbill: no resident shopkeeper??");
2614 return;
2616 bp = onbill(obj, shkp, FALSE);
2617 if (!bp) {
2618 impossible("splitbill: not on bill?");
2619 return;
2621 if (bp->bquan < otmp->quan) {
2622 impossible("Negative quantity on bill??");
2624 if (bp->bquan == otmp->quan) {
2625 impossible("Zero quantity on bill??");
2627 bp->bquan -= otmp->quan;
2629 if (ESHK(shkp)->billct == BILLSZ)
2630 otmp->unpaid = 0;
2631 else {
2632 tmp = bp->price;
2633 bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
2634 bp->bo_id = otmp->o_id;
2635 bp->bquan = otmp->quan;
2636 bp->useup = 0;
2637 bp->price = tmp;
2638 ESHK(shkp)->billct++;
2642 STATIC_OVL void
2643 sub_one_frombill(obj, shkp)
2644 register struct obj *obj;
2645 register struct monst *shkp;
2647 register struct bill_x *bp;
2649 if ((bp = onbill(obj, shkp, FALSE)) != 0) {
2650 register struct obj *otmp;
2652 obj->unpaid = 0;
2653 if (bp->bquan > obj->quan) {
2654 otmp = newobj();
2655 *otmp = *obj;
2656 otmp->oextra = (struct oextra *) 0;
2657 bp->bo_id = otmp->o_id = context.ident++;
2658 otmp->where = OBJ_FREE;
2659 otmp->quan = (bp->bquan -= obj->quan);
2660 otmp->owt = 0; /* superfluous */
2661 bp->useup = 1;
2662 add_to_billobjs(otmp);
2663 return;
2665 ESHK(shkp)->billct--;
2666 #ifdef DUMB
2668 /* DRS/NS 2.2.6 messes up -- Peter Kendell */
2669 int indx = ESHK(shkp)->billct;
2671 *bp = ESHK(shkp)->bill_p[indx];
2673 #else
2674 *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
2675 #endif
2676 return;
2677 } else if (obj->unpaid) {
2678 impossible("sub_one_frombill: unpaid object not on bill");
2679 obj->unpaid = 0;
2683 /* recursive check of unpaid objects within nested containers. */
2684 void
2685 subfrombill(obj, shkp)
2686 register struct obj *obj;
2687 register struct monst *shkp;
2689 register struct obj *otmp;
2691 sub_one_frombill(obj, shkp);
2693 if (Has_contents(obj))
2694 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2695 if (otmp->oclass == COIN_CLASS)
2696 continue;
2698 if (Has_contents(otmp))
2699 subfrombill(otmp, shkp);
2700 else
2701 sub_one_frombill(otmp, shkp);
2705 STATIC_OVL long
2706 stolen_container(obj, shkp, price, ininv)
2707 struct obj *obj;
2708 struct monst *shkp;
2709 long price;
2710 boolean ininv;
2712 struct obj *otmp;
2713 struct bill_x *bp;
2714 long billamt;
2716 /* the price of contained objects; caller handles top container */
2717 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2718 if (otmp->oclass == COIN_CLASS)
2719 continue;
2720 billamt = 0L;
2721 if (!billable(&shkp, otmp, ESHK(shkp)->shoproom, TRUE)) {
2722 /* billable() returns false for objects already on bill */
2723 if ((bp = onbill(otmp, shkp, FALSE)) == 0)
2724 continue;
2725 /* this assumes that we're being called by stolen_value()
2726 (or by a recursive call to self on behalf of it) where
2727 the cost of this object is about to be added to shop
2728 debt in place of having it remain on the current bill */
2729 billamt = bp->bquan * bp->price;
2730 sub_one_frombill(otmp, shkp); /* avoid double billing */
2733 if (billamt)
2734 price += billamt;
2735 else if (ininv ? otmp->unpaid : !otmp->no_charge)
2736 price += otmp->quan * get_cost(otmp, shkp);
2738 if (Has_contents(otmp))
2739 price = stolen_container(otmp, shkp, price, ininv);
2742 return price;
2745 long
2746 stolen_value(obj, x, y, peaceful, silent)
2747 struct obj *obj;
2748 xchar x, y;
2749 boolean peaceful, silent;
2751 long value = 0L, gvalue = 0L, billamt = 0L;
2752 char roomno = *in_rooms(x, y, SHOPBASE);
2753 struct bill_x *bp;
2754 struct monst *shkp = 0;
2756 if (!billable(&shkp, obj, roomno, FALSE)) {
2757 /* things already on the bill yield a not-billable result, so
2758 we need to check bill before deciding that shk doesn't care */
2759 if ((bp = onbill(obj, shkp, FALSE)) == 0)
2760 return 0L;
2761 /* shk does care; take obj off bill to avoid double billing */
2762 billamt = bp->bquan * bp->price;
2763 sub_one_frombill(obj, shkp);
2766 if (obj->oclass == COIN_CLASS) {
2767 gvalue += obj->quan;
2768 } else {
2769 if (billamt)
2770 value += billamt;
2771 else if (!obj->no_charge)
2772 value += obj->quan * get_cost(obj, shkp);
2774 if (Has_contents(obj)) {
2775 boolean ininv =
2776 (obj->where == OBJ_INVENT || obj->where == OBJ_FREE);
2778 value += stolen_container(obj, shkp, 0L, ininv);
2779 if (!ininv)
2780 gvalue += contained_gold(obj);
2784 if (gvalue + value == 0L)
2785 return 0L;
2787 value += gvalue;
2789 if (peaceful) {
2790 boolean credit_use = !!ESHK(shkp)->credit;
2791 value = check_credit(value, shkp);
2792 /* 'peaceful' affects general treatment, but doesn't affect
2793 * the fact that other code expects that all charges after the
2794 * shopkeeper is angry are included in robbed, not debit */
2795 if (ANGRY(shkp))
2796 ESHK(shkp)->robbed += value;
2797 else
2798 ESHK(shkp)->debit += value;
2800 if (!silent) {
2801 const char *still = "";
2803 if (credit_use) {
2804 if (ESHK(shkp)->credit) {
2805 You("have %ld %s credit remaining.", ESHK(shkp)->credit,
2806 currency(ESHK(shkp)->credit));
2807 return value;
2808 } else if (!value) {
2809 You("have no credit remaining.");
2810 return 0;
2812 still = "still ";
2814 if (obj->oclass == COIN_CLASS)
2815 You("%sowe %s %ld %s!", still, shkname(shkp), value,
2816 currency(value));
2817 else
2818 You("%sowe %s %ld %s for %s!", still, shkname(shkp),
2819 value, currency(value), (obj->quan > 1L) ? "them" : "it");
2821 } else {
2822 ESHK(shkp)->robbed += value;
2824 if (!silent) {
2825 if (canseemon(shkp)) {
2826 Norep("%s booms: \"%s, you are a thief!\"",
2827 Shknam(shkp), plname);
2828 } else
2829 Norep("You hear a scream, \"Thief!\"");
2831 hot_pursuit(shkp);
2832 (void) angry_guards(FALSE);
2834 return value;
2837 /* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */
2838 static char sell_response = 'a';
2839 static int sell_how = SELL_NORMAL;
2840 /* can't just use sell_response='y' for auto_credit because the 'a' response
2841 shouldn't carry over from ordinary selling to credit selling */
2842 static boolean auto_credit = FALSE;
2844 void
2845 sellobj_state(deliberate)
2846 int deliberate;
2848 /* If we're deliberately dropping something, there's no automatic
2849 response to the shopkeeper's "want to sell" query; however, if we
2850 accidentally drop anything, the shk will buy it/them without asking.
2851 This retains the old pre-query risk that slippery fingers while in
2852 shops entailed: you drop it, you've lost it.
2854 sell_response = (deliberate != SELL_NORMAL) ? '\0' : 'a';
2855 sell_how = deliberate;
2856 auto_credit = FALSE;
2859 void
2860 sellobj(obj, x, y)
2861 register struct obj *obj;
2862 xchar x, y;
2864 register struct monst *shkp;
2865 register struct eshk *eshkp;
2866 long ltmp = 0L, cltmp = 0L, gltmp = 0L, offer, shkmoney;
2867 boolean saleitem, cgold = FALSE, container = Has_contents(obj);
2868 boolean isgold = (obj->oclass == COIN_CLASS);
2869 boolean only_partially_your_contents = FALSE;
2871 if (!*u.ushops) /* do cheapest exclusion test first */
2872 return;
2873 if (!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
2874 return;
2875 if (!costly_spot(x, y))
2876 return;
2878 if (obj->unpaid && !container && !isgold) {
2879 sub_one_frombill(obj, shkp);
2880 return;
2882 if (container) {
2883 /* find the price of content before subfrombill */
2884 cltmp = contained_cost(obj, shkp, cltmp, TRUE, FALSE);
2885 /* find the value of contained gold */
2886 gltmp += contained_gold(obj);
2887 cgold = (gltmp > 0L);
2890 saleitem = saleable(shkp, obj);
2891 if (!isgold && !obj->unpaid && saleitem)
2892 ltmp = set_cost(obj, shkp);
2894 offer = ltmp + cltmp;
2896 /* get one case out of the way: nothing to sell, and no gold */
2897 if (!(isgold || cgold)
2898 && ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) {
2899 boolean unpaid = is_unpaid(obj);
2901 if (container) {
2902 dropped_container(obj, shkp, FALSE);
2903 if (!obj->unpaid)
2904 obj->no_charge = 1;
2905 if (unpaid)
2906 subfrombill(obj, shkp);
2907 } else
2908 obj->no_charge = 1;
2910 if (!unpaid && (sell_how != SELL_DONTSELL)
2911 && !special_stock(obj, shkp, FALSE))
2912 pline("%s seems uninterested.", Shknam(shkp));
2913 return;
2916 /* you dropped something of your own - probably want to sell it */
2917 rouse_shk(shkp, TRUE); /* wake up sleeping or paralyzed shk */
2918 eshkp = ESHK(shkp);
2920 if (ANGRY(shkp)) { /* they become shop-objects, no pay */
2921 if (!Deaf && !muteshk(shkp))
2922 verbalize("Thank you, scum!");
2923 else
2924 pline("%s smirks with satisfaction.", Shknam(shkp));
2925 subfrombill(obj, shkp);
2926 return;
2929 if (eshkp->robbed) { /* shkp is not angry? */
2930 if (isgold)
2931 offer = obj->quan;
2932 else if (cgold)
2933 offer += cgold;
2934 if ((eshkp->robbed -= offer < 0L))
2935 eshkp->robbed = 0L;
2936 if (offer && !Deaf && !muteshk(shkp))
2937 verbalize(
2938 "Thank you for your contribution to restock this recently plundered shop.");
2939 subfrombill(obj, shkp);
2940 return;
2943 if (isgold || cgold) {
2944 if (!cgold)
2945 gltmp = obj->quan;
2947 if (eshkp->debit >= gltmp) {
2948 if (eshkp->loan) { /* you carry shop's gold */
2949 if (eshkp->loan >= gltmp)
2950 eshkp->loan -= gltmp;
2951 else
2952 eshkp->loan = 0L;
2954 eshkp->debit -= gltmp;
2955 Your("debt is %spaid off.", eshkp->debit ? "partially " : "");
2956 } else {
2957 long delta = gltmp - eshkp->debit;
2959 eshkp->credit += delta;
2960 if (eshkp->debit) {
2961 eshkp->debit = 0L;
2962 eshkp->loan = 0L;
2963 Your("debt is paid off.");
2965 if (eshkp->credit == delta)
2966 You("have established %ld %s credit.", delta,
2967 currency(delta));
2968 else
2969 pline("%ld %s added to your credit; total is now %ld %s.",
2970 delta, currency(delta), eshkp->credit,
2971 currency(eshkp->credit));
2974 if (!offer || sell_how == SELL_DONTSELL) {
2975 if (!isgold) {
2976 if (container)
2977 dropped_container(obj, shkp, FALSE);
2978 if (!obj->unpaid)
2979 obj->no_charge = 1;
2980 subfrombill(obj, shkp);
2982 return;
2986 if ((!saleitem && !(container && cltmp > 0L)) || eshkp->billct == BILLSZ
2987 || obj->oclass == BALL_CLASS || obj->oclass == CHAIN_CLASS
2988 || offer == 0L || (obj->oclass == FOOD_CLASS && obj->oeaten)
2989 || (Is_candle(obj)
2990 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)) {
2991 pline("%s seems uninterested%s.", Shknam(shkp),
2992 cgold ? " in the rest" : "");
2993 if (container)
2994 dropped_container(obj, shkp, FALSE);
2995 obj->no_charge = 1;
2996 return;
2999 shkmoney = money_cnt(shkp->minvent);
3000 if (!shkmoney) {
3001 char c, qbuf[BUFSZ];
3002 long tmpcr = ((offer * 9L) / 10L) + (offer <= 1L);
3004 if (sell_how == SELL_NORMAL || auto_credit) {
3005 c = sell_response = 'y';
3006 } else if (sell_response != 'n') {
3007 pline("%s cannot pay you at present.", shkname(shkp));
3008 Sprintf(qbuf, "Will you accept %ld %s in credit for ", tmpcr,
3009 currency(tmpcr));
3010 c = ynaq(safe_qbuf(qbuf, qbuf, "?", obj, doname, thesimpleoname,
3011 (obj->quan == 1L) ? "that" : "those"));
3012 if (c == 'a') {
3013 c = 'y';
3014 auto_credit = TRUE;
3016 } else /* previously specified "quit" */
3017 c = 'n';
3019 if (c == 'y') {
3020 shk_names_obj(
3021 shkp, obj,
3022 (sell_how != SELL_NORMAL)
3023 ? "traded %s for %ld zorkmid%s in %scredit."
3024 : "relinquish %s and acquire %ld zorkmid%s in %scredit.",
3025 tmpcr, (eshkp->credit > 0L) ? "additional " : "");
3026 eshkp->credit += tmpcr;
3027 subfrombill(obj, shkp);
3028 } else {
3029 if (c == 'q')
3030 sell_response = 'n';
3031 if (container)
3032 dropped_container(obj, shkp, FALSE);
3033 if (!obj->unpaid)
3034 obj->no_charge = 1;
3035 subfrombill(obj, shkp);
3037 } else {
3038 char qbuf[BUFSZ], qsfx[BUFSZ];
3039 boolean short_funds = (offer > shkmoney), one;
3041 if (short_funds)
3042 offer = shkmoney;
3043 if (!sell_response) {
3044 long yourc = 0L, shksc;
3046 if (container) {
3047 /* number of items owned by shk */
3048 shksc = count_contents(obj, TRUE, TRUE, FALSE);
3049 /* number of items owned by you (total - shksc) */
3050 yourc = count_contents(obj, TRUE, TRUE, TRUE) - shksc;
3051 only_partially_your_contents = shksc && yourc;
3054 "<shk> offers * for ..." query formatting.
3055 Normal item(s):
3056 "... your <object>. Sell it?"
3057 "... your <objects>. Sell them?"
3058 A container is either owned by the hero, or already
3059 owned by the shk (!ltmp), or the shk isn't interested
3060 in buying it (also !ltmp). It's either empty (!cltmp)
3061 or it has contents owned by the hero or it has some
3062 contents owned by the hero and others by the shk.
3063 (The case where it has contents already entirely owned
3064 by the shk is treated the same was if it were empty
3065 since the hero isn't selling any of those contents.)
3066 Your container:
3067 "... your <empty bag>. Sell it?"
3068 "... your <bag> and its contents. Sell them?"
3069 "... your <bag> and item inside. Sell them?"
3070 "... your <bag> and items inside. Sell them?"
3071 Shk's container:
3072 "... your item in the <bag>. Sell it?"
3073 "... your items in the <bag>. Sell them?"
3075 Sprintf(qbuf, "%s offers%s %ld gold piece%s for %s%s ",
3076 shkname(shkp), short_funds ? " only" : "", offer,
3077 plur(offer),
3078 (cltmp && !ltmp)
3079 ? ((yourc == 1L) ? "your item in " : "your items in ")
3080 : "",
3081 obj->unpaid ? "the" : "your");
3082 one = obj->unpaid ? (yourc == 1L) : (obj->quan == 1L && !cltmp);
3083 Sprintf(qsfx, "%s. Sell %s?",
3084 (cltmp && ltmp)
3085 ? (only_partially_your_contents
3086 ? ((yourc == 1L) ? " and item inside"
3087 : " and items inside")
3088 : and_its_contents)
3089 : "",
3090 one ? "it" : "them");
3091 (void) safe_qbuf(qbuf, qbuf, qsfx, obj, xname, simpleonames,
3092 one ? "that" : "those");
3093 } else
3094 qbuf[0] = '\0'; /* just to pacify lint */
3096 switch (sell_response ? sell_response : ynaq(qbuf)) {
3097 case 'q':
3098 sell_response = 'n';
3099 case 'n':
3100 if (container)
3101 dropped_container(obj, shkp, FALSE);
3102 if (!obj->unpaid)
3103 obj->no_charge = 1;
3104 subfrombill(obj, shkp);
3105 break;
3106 case 'a':
3107 sell_response = 'y';
3108 case 'y':
3109 if (container)
3110 dropped_container(obj, shkp, TRUE);
3111 if (!obj->unpaid && !saleitem)
3112 obj->no_charge = 1;
3113 subfrombill(obj, shkp);
3114 pay(-offer, shkp);
3115 shk_names_obj(shkp, obj,
3116 (sell_how != SELL_NORMAL)
3117 ? ((!ltmp && cltmp && only_partially_your_contents)
3118 ? "sold some items inside %s for %ld gold piece%s.%s"
3119 : "sold %s for %ld gold piece%s.%s")
3120 : "relinquish %s and receive %ld gold piece%s in compensation.%s",
3121 offer, "");
3122 break;
3123 default:
3124 impossible("invalid sell response");
3130 doinvbill(mode)
3131 int mode; /* 0: deliver count 1: paged */
3133 #ifdef __SASC
3134 void sasc_bug(struct obj *, unsigned);
3135 #endif
3136 struct monst *shkp;
3137 struct eshk *eshkp;
3138 struct bill_x *bp, *end_bp;
3139 struct obj *obj;
3140 long totused;
3141 char *buf_p;
3142 winid datawin;
3144 shkp = shop_keeper(*u.ushops);
3145 if (!shkp || !inhishop(shkp)) {
3146 if (mode != 0)
3147 impossible("doinvbill: no shopkeeper?");
3148 return 0;
3150 eshkp = ESHK(shkp);
3152 if (mode == 0) {
3153 /* count expended items, so that the `I' command can decide
3154 whether to include 'x' in its prompt string */
3155 int cnt = !eshkp->debit ? 0 : 1;
3157 for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct];
3158 bp < end_bp; bp++)
3159 if (bp->useup
3160 || ((obj = bp_to_obj(bp)) != 0 && obj->quan < bp->bquan))
3161 cnt++;
3162 return cnt;
3165 datawin = create_nhwindow(NHW_MENU);
3166 putstr(datawin, 0, "Unpaid articles already used up:");
3167 putstr(datawin, 0, "");
3169 totused = 0L;
3170 for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct];
3171 bp < end_bp; bp++) {
3172 obj = bp_to_obj(bp);
3173 if (!obj) {
3174 impossible("Bad shopkeeper administration.");
3175 goto quit;
3177 if (bp->useup || bp->bquan > obj->quan) {
3178 long oquan, uquan, thisused;
3180 oquan = obj->quan;
3181 uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
3182 thisused = bp->price * uquan;
3183 totused += thisused;
3184 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3185 /* Why 'x'? To match `I x', more or less. */
3186 buf_p = xprname(obj, (char *) 0, 'x', FALSE, thisused, uquan);
3187 iflags.suppress_price--;
3188 putstr(datawin, 0, buf_p);
3191 if (eshkp->debit) {
3192 /* additional shop debt which has no itemization available */
3193 if (totused)
3194 putstr(datawin, 0, "");
3195 totused += eshkp->debit;
3196 buf_p = xprname((struct obj *) 0, "usage charges and/or other fees",
3197 GOLD_SYM, FALSE, eshkp->debit, 0L);
3198 putstr(datawin, 0, buf_p);
3200 buf_p = xprname((struct obj *) 0, "Total:", '*', FALSE, totused, 0L);
3201 putstr(datawin, 0, "");
3202 putstr(datawin, 0, buf_p);
3203 display_nhwindow(datawin, FALSE);
3204 quit:
3205 destroy_nhwindow(datawin);
3206 return 0;
3209 STATIC_OVL long
3210 getprice(obj, shk_buying)
3211 register struct obj *obj;
3212 boolean shk_buying;
3214 register long tmp = (long) objects[obj->otyp].oc_cost;
3216 if (obj->oartifact) {
3217 tmp = arti_cost(obj);
3218 if (shk_buying)
3219 tmp /= 4;
3221 switch (obj->oclass) {
3222 case FOOD_CLASS:
3223 /* simpler hunger check, (2-4)*cost */
3224 if (u.uhs >= HUNGRY && !shk_buying)
3225 tmp *= (long) u.uhs;
3226 if (obj->oeaten)
3227 tmp = 0L;
3228 break;
3229 case WAND_CLASS:
3230 if (obj->spe == -1)
3231 tmp = 0L;
3232 break;
3233 case POTION_CLASS:
3234 if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
3235 tmp = 0L;
3236 break;
3237 case ARMOR_CLASS:
3238 case WEAPON_CLASS:
3239 if (obj->spe > 0)
3240 tmp += 10L * (long) obj->spe;
3241 break;
3242 case TOOL_CLASS:
3243 if (Is_candle(obj)
3244 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
3245 tmp /= 2L;
3246 break;
3248 return tmp;
3251 /* shk catches thrown pick-axe */
3252 struct monst *
3253 shkcatch(obj, x, y)
3254 register struct obj *obj;
3255 register xchar x, y;
3257 register struct monst *shkp;
3259 if (!(shkp = shop_keeper(inside_shop(x, y))) || !inhishop(shkp))
3260 return 0;
3262 if (shkp->mcanmove && !shkp->msleeping
3263 && (*u.ushops != ESHK(shkp)->shoproom || !inside_shop(u.ux, u.uy))
3264 && dist2(shkp->mx, shkp->my, x, y) < 3
3265 /* if it is the shk's pos, you hit and anger him */
3266 && (shkp->mx != x || shkp->my != y)) {
3267 if (mnearto(shkp, x, y, TRUE) && !Deaf && !muteshk(shkp))
3268 verbalize("Out of my way, scum!");
3269 if (cansee(x, y)) {
3270 pline("%s nimbly%s catches %s.", Shknam(shkp),
3271 (x == shkp->mx && y == shkp->my) ? "" : " reaches over and",
3272 the(xname(obj)));
3273 if (!canspotmon(shkp))
3274 map_invisible(x, y);
3275 delay_output();
3276 mark_synch();
3278 subfrombill(obj, shkp);
3279 (void) mpickobj(shkp, obj);
3280 return shkp;
3282 return (struct monst *) 0;
3285 void
3286 add_damage(x, y, cost)
3287 register xchar x, y;
3288 long cost;
3290 struct damage *tmp_dam;
3291 char *shops;
3293 if (IS_DOOR(levl[x][y].typ)) {
3294 struct monst *mtmp;
3296 /* Don't schedule for repair unless it's a real shop entrance */
3297 for (shops = in_rooms(x, y, SHOPBASE); *shops; shops++)
3298 if ((mtmp = shop_keeper(*shops)) != 0 && x == ESHK(mtmp)->shd.x
3299 && y == ESHK(mtmp)->shd.y)
3300 break;
3301 if (!*shops)
3302 return;
3304 for (tmp_dam = level.damagelist; tmp_dam; tmp_dam = tmp_dam->next)
3305 if (tmp_dam->place.x == x && tmp_dam->place.y == y) {
3306 tmp_dam->cost += cost;
3307 return;
3309 tmp_dam = (struct damage *) alloc((unsigned) sizeof(struct damage));
3310 (void) memset((genericptr_t)tmp_dam, 0, sizeof(struct damage));
3311 tmp_dam->when = monstermoves;
3312 tmp_dam->place.x = x;
3313 tmp_dam->place.y = y;
3314 tmp_dam->cost = cost;
3315 tmp_dam->typ = levl[x][y].typ;
3316 tmp_dam->next = level.damagelist;
3317 level.damagelist = tmp_dam;
3318 /* If player saw damage, display as a wall forever */
3319 if (cansee(x, y))
3320 levl[x][y].seenv = SVALL;
3324 * Do something about damage. Either (!croaked) try to repair it, or
3325 * (croaked) just discard damage structs for non-shared locations, since
3326 * they'll never get repaired. Assume that shared locations will get
3327 * repaired eventually by the other shopkeeper(s). This might be an erroneous
3328 * assumption (they might all be dead too), but we have no reasonable way of
3329 * telling that.
3331 STATIC_OVL
3332 void
3333 remove_damage(shkp, croaked)
3334 struct monst *shkp;
3335 boolean croaked;
3337 struct damage *tmp_dam, *tmp2_dam;
3338 boolean did_repair = FALSE, saw_door = FALSE, saw_floor = FALSE,
3339 stop_picking = FALSE, doorway_trap = FALSE;
3340 int saw_walls = 0, saw_untrap = 0;
3341 char trapmsg[BUFSZ];
3343 tmp_dam = level.damagelist;
3344 tmp2_dam = 0;
3345 while (tmp_dam) {
3346 register xchar x = tmp_dam->place.x, y = tmp_dam->place.y;
3347 char shops[5];
3348 int disposition;
3349 unsigned old_doormask = 0;
3351 disposition = 0;
3352 Strcpy(shops, in_rooms(x, y, SHOPBASE));
3353 if (index(shops, ESHK(shkp)->shoproom)) {
3354 if (IS_DOOR(levl[x][y].typ))
3355 old_doormask = levl[x][y].doormask;
3357 if (croaked)
3358 disposition = (shops[1]) ? 0 : 1;
3359 else if (stop_picking)
3360 disposition = repair_damage(shkp, tmp_dam, FALSE);
3361 else {
3362 /* Defer the stop_occupation() until after repair msgs */
3363 if (closed_door(x, y))
3364 stop_picking = picking_at(x, y);
3365 disposition = repair_damage(shkp, tmp_dam, FALSE);
3366 if (!disposition)
3367 stop_picking = FALSE;
3371 if (!disposition) {
3372 tmp2_dam = tmp_dam;
3373 tmp_dam = tmp_dam->next;
3374 continue;
3377 if (disposition > 1) {
3378 did_repair = TRUE;
3379 if (cansee(x, y)) {
3380 if (IS_WALL(levl[x][y].typ)) {
3381 saw_walls++;
3382 } else if (IS_DOOR(levl[x][y].typ)
3383 /* an existing door here implies trap removal */
3384 && !(old_doormask & (D_ISOPEN | D_CLOSED))) {
3385 saw_door = TRUE;
3386 } else if (disposition == 3) { /* untrapped */
3387 saw_untrap++;
3388 if (IS_DOOR(levl[x][y].typ))
3389 doorway_trap = TRUE;
3390 } else {
3391 saw_floor = TRUE;
3396 tmp_dam = tmp_dam->next;
3397 if (!tmp2_dam) {
3398 free((genericptr_t) level.damagelist);
3399 level.damagelist = tmp_dam;
3400 } else {
3401 free((genericptr_t) tmp2_dam->next);
3402 tmp2_dam->next = tmp_dam;
3405 if (!did_repair)
3406 return;
3408 if (saw_untrap) {
3409 Sprintf(trapmsg, "%s trap%s",
3410 (saw_untrap > 3) ? "several" : (saw_untrap > 1) ? "some"
3411 : "a",
3412 plur(saw_untrap));
3413 Sprintf(eos(trapmsg), " %s", vtense(trapmsg, "are"));
3414 Sprintf(eos(trapmsg), " removed from the %s",
3415 (doorway_trap && saw_untrap == 1) ? "doorway" : "floor");
3416 } else
3417 trapmsg[0] = '\0'; /* not just lint suppression... */
3419 if (saw_walls) {
3420 char wallbuf[BUFSZ];
3422 Sprintf(wallbuf, "section%s", plur(saw_walls));
3423 pline("Suddenly, %s %s of wall %s up!",
3424 (saw_walls == 1) ? "a" : (saw_walls <= 3) ? "some" : "several",
3425 wallbuf, vtense(wallbuf, "close"));
3427 if (saw_door)
3428 pline_The("shop door reappears!");
3429 if (saw_floor)
3430 pline_The("floor is repaired!");
3431 if (saw_untrap)
3432 pline("%s!", upstart(trapmsg));
3433 } else {
3434 if (saw_door || saw_floor || saw_untrap)
3435 pline("Suddenly, %s%s%s%s%s!",
3436 saw_door ? "the shop door reappears" : "",
3437 (saw_door && saw_floor) ? " and " : "",
3438 saw_floor ? "the floor damage is gone" : "",
3439 ((saw_door || saw_floor) && *trapmsg) ? " and " : "",
3440 trapmsg);
3441 else if (inside_shop(u.ux, u.uy) == ESHK(shkp)->shoproom)
3442 You_feel("more claustrophobic than before.");
3443 else if (!Deaf && !rn2(10))
3444 Norep("The dungeon acoustics noticeably change.");
3446 if (stop_picking)
3447 stop_occupation();
3451 * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
3452 * 3: untrap
3455 repair_damage(shkp, tmp_dam, catchup)
3456 register struct monst *shkp;
3457 register struct damage *tmp_dam;
3458 boolean catchup; /* restoring a level */
3460 register xchar x, y, i;
3461 xchar litter[9];
3462 register struct monst *mtmp;
3463 register struct obj *otmp;
3464 register struct trap *ttmp;
3466 if ((monstermoves - tmp_dam->when) < REPAIR_DELAY)
3467 return 0;
3468 if (shkp->msleeping || !shkp->mcanmove || ESHK(shkp)->following)
3469 return 0;
3470 x = tmp_dam->place.x;
3471 y = tmp_dam->place.y;
3472 if (!IS_ROOM(tmp_dam->typ)) {
3473 if (x == u.ux && y == u.uy)
3474 if (!Passes_walls)
3475 return 0;
3476 if (x == shkp->mx && y == shkp->my)
3477 return 0;
3478 if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data)))
3479 return 0;
3481 if ((ttmp = t_at(x, y)) != 0) {
3482 if (x == u.ux && y == u.uy)
3483 if (!Passes_walls)
3484 return 0;
3485 if (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP) {
3486 /* convert to an object */
3487 otmp = mksobj((ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP,
3488 TRUE, FALSE);
3489 otmp->quan = 1L;
3490 otmp->owt = weight(otmp);
3491 (void) mpickobj(shkp, otmp);
3493 deltrap(ttmp);
3494 if (IS_DOOR(tmp_dam->typ) && !(levl[x][y].doormask & D_ISOPEN)) {
3495 levl[x][y].doormask = D_CLOSED;
3496 block_point(x, y);
3497 } else if (IS_WALL(tmp_dam->typ)) {
3498 levl[x][y].typ = tmp_dam->typ;
3499 block_point(x, y);
3501 newsym(x, y);
3502 return 3;
3504 if (IS_ROOM(tmp_dam->typ)) {
3505 /* No messages, because player already filled trap door */
3506 return 1;
3508 if ((tmp_dam->typ == levl[x][y].typ)
3509 && (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN)))
3510 /* No messages if player already replaced shop door */
3511 return 1;
3512 levl[x][y].typ = tmp_dam->typ;
3513 (void) memset((genericptr_t) litter, 0, sizeof(litter));
3514 if ((otmp = level.objects[x][y]) != 0) {
3515 /* Scatter objects haphazardly into the shop */
3516 #define NEED_UPDATE 1
3517 #define OPEN 2
3518 #define INSHOP 4
3519 #define horiz(i) ((i % 3) - 1)
3520 #define vert(i) ((i / 3) - 1)
3521 for (i = 0; i < 9; i++) {
3522 if ((i == 4) || (!ZAP_POS(levl[x + horiz(i)][y + vert(i)].typ)))
3523 continue;
3524 litter[i] = OPEN;
3525 if (inside_shop(x + horiz(i), y + vert(i))
3526 == ESHK(shkp)->shoproom)
3527 litter[i] |= INSHOP;
3529 if (Punished && !u.uswallow
3530 && ((uchain->ox == x && uchain->oy == y)
3531 || (uball->ox == x && uball->oy == y))) {
3533 * Either the ball or chain is in the repair location.
3535 * Take the easy way out and put ball&chain under hero.
3537 if (!Deaf && !muteshk(shkp))
3538 verbalize("Get your junk out of my wall!");
3539 unplacebc(); /* pick 'em up */
3540 placebc(); /* put 'em down */
3542 while ((otmp = level.objects[x][y]) != 0)
3543 /* Don't mess w/ boulders -- just merge into wall */
3544 if ((otmp->otyp == BOULDER) || (otmp->otyp == ROCK)) {
3545 obj_extract_self(otmp);
3546 obfree(otmp, (struct obj *) 0);
3547 } else {
3548 while (!(litter[i = rn2(9)] & INSHOP))
3550 remove_object(otmp);
3551 place_object(otmp, x + horiz(i), y + vert(i));
3552 litter[i] |= NEED_UPDATE;
3555 if (catchup)
3556 return 1; /* repair occurred while off level */
3558 block_point(x, y);
3559 if (IS_DOOR(tmp_dam->typ)) {
3560 levl[x][y].doormask = D_CLOSED; /* arbitrary */
3561 newsym(x, y);
3562 } else {
3563 /* don't set doormask - it is (hopefully) the same as it was
3564 if not, perhaps save it with the damage array... */
3566 if (IS_WALL(tmp_dam->typ) && cansee(x, y)) {
3567 /* Player sees actual repair process, so they KNOW it's a wall */
3568 levl[x][y].seenv = SVALL;
3569 newsym(x, y);
3571 /* Mark this wall as "repaired". There currently is no code
3572 to do anything about repaired walls, so don't do it. */
3574 for (i = 0; i < 9; i++)
3575 if (litter[i] & NEED_UPDATE)
3576 newsym(x + horiz(i), y + vert(i));
3577 return 2;
3578 #undef NEED_UPDATE
3579 #undef OPEN
3580 #undef INSHOP
3581 #undef vert
3582 #undef horiz
3586 * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
3589 shk_move(shkp)
3590 register struct monst *shkp;
3592 register xchar gx, gy, omx, omy;
3593 register int udist;
3594 register schar appr;
3595 register struct eshk *eshkp = ESHK(shkp);
3596 int z;
3597 boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv;
3599 omx = shkp->mx;
3600 omy = shkp->my;
3602 if (inhishop(shkp))
3603 remove_damage(shkp, FALSE);
3605 if ((udist = distu(omx, omy)) < 3 && (shkp->data != &mons[PM_GRID_BUG]
3606 || (omx == u.ux || omy == u.uy))) {
3607 if (ANGRY(shkp) || (Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
3608 if (Displaced)
3609 Your("displaced image doesn't fool %s!", shkname(shkp));
3610 (void) mattacku(shkp);
3611 return 0;
3613 if (eshkp->following) {
3614 if (strncmp(eshkp->customer, plname, PL_NSIZ)) {
3615 if (!Deaf && !muteshk(shkp))
3616 verbalize("%s, %s! I was looking for %s.", Hello(shkp),
3617 plname, eshkp->customer);
3618 eshkp->following = 0;
3619 return 0;
3621 if (moves > followmsg + 4) {
3622 if (!Deaf && !muteshk(shkp))
3623 verbalize("%s, %s! Didn't you forget to pay?",
3624 Hello(shkp), plname);
3625 else
3626 pline("%s holds out %s upturned %s.",
3627 Shknam(shkp),
3628 mhis(shkp),
3629 mbodypart(shkp, HAND));
3630 followmsg = moves;
3631 if (!rn2(9)) {
3632 pline("%s doesn't like customers who don't pay.",
3633 Shknam(shkp));
3634 rile_shk(shkp);
3637 if (udist < 2)
3638 return 0;
3642 appr = 1;
3643 gx = eshkp->shk.x;
3644 gy = eshkp->shk.y;
3645 satdoor = (gx == omx && gy == omy);
3646 if (eshkp->following || ((z = holetime()) >= 0 && z * z <= udist)) {
3647 /* [This distance check used to apply regardless of
3648 whether the shk was following, but that resulted in
3649 m_move() sometimes taking the shk out of the shop if
3650 the player had fenced him in with boulders or traps.
3651 Such voluntary abandonment left unpaid objects in
3652 invent, triggering billing impossibilities on the
3653 next level once the character fell through the hole.] */
3654 if (udist > 4 && eshkp->following && !eshkp->billct)
3655 return -1; /* leave it to m_move */
3656 gx = u.ux;
3657 gy = u.uy;
3658 } else if (ANGRY(shkp)) {
3659 /* Move towards the hero if the shopkeeper can see him. */
3660 if (shkp->mcansee && m_canseeu(shkp)) {
3661 gx = u.ux;
3662 gy = u.uy;
3664 avoid = FALSE;
3665 } else {
3666 #define GDIST(x, y) (dist2(x, y, gx, gy))
3667 if (Invis || u.usteed) {
3668 avoid = FALSE;
3669 } else {
3670 uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y);
3671 if (uondoor) {
3672 badinv =
3673 (carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
3674 || (Fast && (sobj_at(PICK_AXE, u.ux, u.uy)
3675 || sobj_at(DWARVISH_MATTOCK, u.ux, u.uy))));
3676 if (satdoor && badinv)
3677 return 0;
3678 avoid = !badinv;
3679 } else {
3680 avoid = (*u.ushops && distu(gx, gy) > 8);
3681 badinv = FALSE;
3684 if (((!eshkp->robbed && !eshkp->billct && !eshkp->debit) || avoid)
3685 && GDIST(omx, omy) < 3) {
3686 if (!badinv && !onlineu(omx, omy))
3687 return 0;
3688 if (satdoor)
3689 appr = gx = gy = 0;
3694 z = move_special(shkp, inhishop(shkp), appr, uondoor, avoid, omx, omy, gx,
3695 gy);
3696 if (z > 0)
3697 after_shk_move(shkp);
3699 return z;
3702 /* called after shopkeeper moves, in case themove causes re-entry into shop */
3703 void
3704 after_shk_move(shkp)
3705 struct monst *shkp;
3707 struct eshk *eshkp = ESHK(shkp);
3709 if (eshkp->bill_p == (struct bill_x *) -1000 && inhishop(shkp)) {
3710 /* reset bill_p, need to re-calc player's occupancy too */
3711 eshkp->bill_p = &eshkp->bill[0];
3712 check_special_room(FALSE);
3716 /* for use in levl_follower (mondata.c) */
3717 boolean
3718 is_fshk(mtmp)
3719 register struct monst *mtmp;
3721 return (boolean) (mtmp->isshk && ESHK(mtmp)->following);
3724 /* You are digging in the shop. */
3725 void
3726 shopdig(fall)
3727 register int fall;
3729 register struct monst *shkp = shop_keeper(*u.ushops);
3730 int lang;
3731 const char *grabs = "grabs";
3733 if (!shkp)
3734 return;
3736 /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */
3737 lang = 0;
3738 if (shkp->msleeping || !shkp->mcanmove || is_silent(shkp->data))
3739 ; /* lang stays 0 */
3740 else if (shkp->data->msound <= MS_ANIMAL)
3741 lang = 1;
3742 else if (shkp->data->msound >= MS_HUMANOID)
3743 lang = 2;
3745 if (!inhishop(shkp)) {
3746 if (Role_if(PM_KNIGHT)) {
3747 You_feel("like a common thief.");
3748 adjalign(-sgn(u.ualign.type));
3750 return;
3753 if (!fall) {
3754 if (lang == 2) {
3755 if (!Deaf && !muteshk(shkp)) {
3756 if (u.utraptype == TT_PIT)
3757 verbalize(
3758 "Be careful, %s, or you might fall through the floor.",
3759 flags.female ? "madam" : "sir");
3760 else
3761 verbalize("%s, do not damage the floor here!",
3762 flags.female ? "Madam" : "Sir");
3765 if (Role_if(PM_KNIGHT)) {
3766 You_feel("like a common thief.");
3767 adjalign(-sgn(u.ualign.type));
3769 } else if (!um_dist(shkp->mx, shkp->my, 5)
3770 && !shkp->msleeping && shkp->mcanmove
3771 && (ESHK(shkp)->billct || ESHK(shkp)->debit)) {
3772 register struct obj *obj, *obj2;
3774 if (nolimbs(shkp->data)) {
3775 grabs = "knocks off";
3776 #if 0
3777 /* This is what should happen, but for balance
3778 * reasons, it isn't currently.
3780 if (lang == 2)
3781 pline("%s curses %s inability to grab your backpack!",
3782 shkname(shkp), mhim(shkp));
3783 rile_shk(shkp);
3784 return;
3785 #endif
3787 if (distu(shkp->mx, shkp->my) > 2) {
3788 mnexto(shkp);
3789 /* for some reason the shopkeeper can't come next to you */
3790 if (distu(shkp->mx, shkp->my) > 2) {
3791 if (lang == 2)
3792 pline("%s curses you in anger and frustration!",
3793 shkname(shkp));
3794 else if (lang == 1)
3795 growl(shkp);
3796 rile_shk(shkp);
3797 return;
3798 } else
3799 pline("%s %s, and %s your backpack!", shkname(shkp),
3800 makeplural(locomotion(shkp->data, "leap")), grabs);
3801 } else
3802 pline("%s %s your backpack!", shkname(shkp), grabs);
3804 for (obj = invent; obj; obj = obj2) {
3805 obj2 = obj->nobj;
3806 if ((obj->owornmask & ~(W_SWAPWEP | W_QUIVER)) != 0
3807 || (obj == uswapwep && u.twoweap)
3808 || (obj->otyp == LEASH && obj->leashmon))
3809 continue;
3810 if (obj == current_wand)
3811 continue;
3812 setnotworn(obj);
3813 freeinv(obj);
3814 subfrombill(obj, shkp);
3815 (void) add_to_minv(shkp, obj); /* may free obj */
3820 STATIC_OVL void
3821 makekops(mm)
3822 coord *mm;
3824 static const short k_mndx[4] = { PM_KEYSTONE_KOP, PM_KOP_SERGEANT,
3825 PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN };
3826 int k_cnt[4], cnt, mndx, k;
3828 k_cnt[0] = cnt = abs(depth(&u.uz)) + rnd(5);
3829 k_cnt[1] = (cnt / 3) + 1; /* at least one sarge */
3830 k_cnt[2] = (cnt / 6); /* maybe a lieutenant */
3831 k_cnt[3] = (cnt / 9); /* and maybe a kaptain */
3833 for (k = 0; k < 4; k++) {
3834 if ((cnt = k_cnt[k]) == 0)
3835 break;
3836 mndx = k_mndx[k];
3837 if (mvitals[mndx].mvflags & G_GONE)
3838 continue;
3840 while (cnt--)
3841 if (enexto(mm, mm->x, mm->y, &mons[mndx]))
3842 (void) makemon(&mons[mndx], mm->x, mm->y, NO_MM_FLAGS);
3846 void
3847 pay_for_damage(dmgstr, cant_mollify)
3848 const char *dmgstr;
3849 boolean cant_mollify;
3851 register struct monst *shkp = (struct monst *) 0;
3852 char shops_affected[5];
3853 register boolean uinshp = (*u.ushops != '\0');
3854 char qbuf[80];
3855 register xchar x, y;
3856 boolean dugwall = (!strcmp(dmgstr, "dig into") /* wand */
3857 || !strcmp(dmgstr, "damage")); /* pick-axe */
3858 boolean animal, pursue;
3859 struct damage *tmp_dam, *appear_here = 0;
3860 /* any number >= (80*80)+(24*24) would do, actually */
3861 long cost_of_damage = 0L;
3862 unsigned int nearest_shk = 7000, nearest_damage = 7000;
3863 int picks = 0;
3865 for (tmp_dam = level.damagelist;
3866 (tmp_dam && (tmp_dam->when == monstermoves));
3867 tmp_dam = tmp_dam->next) {
3868 char *shp;
3870 if (!tmp_dam->cost)
3871 continue;
3872 cost_of_damage += tmp_dam->cost;
3873 Strcpy(shops_affected,
3874 in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
3875 for (shp = shops_affected; *shp; shp++) {
3876 struct monst *tmp_shk;
3877 unsigned int shk_distance;
3879 if (!(tmp_shk = shop_keeper(*shp)))
3880 continue;
3881 if (tmp_shk == shkp) {
3882 unsigned int damage_distance =
3883 distu(tmp_dam->place.x, tmp_dam->place.y);
3885 if (damage_distance < nearest_damage) {
3886 nearest_damage = damage_distance;
3887 appear_here = tmp_dam;
3889 continue;
3891 if (!inhishop(tmp_shk))
3892 continue;
3893 shk_distance = distu(tmp_shk->mx, tmp_shk->my);
3894 if (shk_distance > nearest_shk)
3895 continue;
3896 if ((shk_distance == nearest_shk) && picks) {
3897 if (rn2(++picks))
3898 continue;
3899 } else
3900 picks = 1;
3901 shkp = tmp_shk;
3902 nearest_shk = shk_distance;
3903 appear_here = tmp_dam;
3904 nearest_damage = distu(tmp_dam->place.x, tmp_dam->place.y);
3908 if (!cost_of_damage || !shkp)
3909 return;
3911 animal = (shkp->data->msound <= MS_ANIMAL);
3912 pursue = FALSE;
3913 x = appear_here->place.x;
3914 y = appear_here->place.y;
3916 /* not the best introduction to the shk... */
3917 (void) strncpy(ESHK(shkp)->customer, plname, PL_NSIZ);
3919 /* if the shk is already on the war path, be sure it's all out */
3920 if (ANGRY(shkp) || ESHK(shkp)->following) {
3921 hot_pursuit(shkp);
3922 return;
3925 /* if the shk is not in their shop.. */
3926 if (!*in_rooms(shkp->mx, shkp->my, SHOPBASE)) {
3927 if (!cansee(shkp->mx, shkp->my))
3928 return;
3929 pursue = TRUE;
3930 goto getcad;
3933 if (uinshp) {
3934 if (um_dist(shkp->mx, shkp->my, 1)
3935 && !um_dist(shkp->mx, shkp->my, 3)) {
3936 pline("%s leaps towards you!", shkname(shkp));
3937 mnexto(shkp);
3939 pursue = um_dist(shkp->mx, shkp->my, 1);
3940 if (pursue)
3941 goto getcad;
3942 } else {
3944 * Make shkp show up at the door. Effect: If there is a monster
3945 * in the doorway, have the hero hear the shopkeeper yell a bit,
3946 * pause, then have the shopkeeper appear at the door, having
3947 * yanked the hapless critter out of the way.
3949 if (MON_AT(x, y)) {
3950 if (!animal) {
3951 if (!Deaf && !muteshk(shkp)) {
3952 You_hear("an angry voice:");
3953 verbalize("Out of my way, scum!");
3955 wait_synch();
3956 #if defined(UNIX) || defined(VMS)
3957 #if defined(SYSV) || defined(ULTRIX) || defined(VMS)
3958 (void)
3959 #endif
3960 sleep(1);
3961 #endif
3962 } else {
3963 growl(shkp);
3966 (void) mnearto(shkp, x, y, TRUE);
3969 if ((um_dist(x, y, 1) && !uinshp) || cant_mollify
3970 || (money_cnt(invent) + ESHK(shkp)->credit) < cost_of_damage
3971 || !rn2(50)) {
3972 getcad:
3973 if (muteshk(shkp)) {
3974 if (animal && shkp->mcanmove && !shkp->msleeping)
3975 yelp(shkp);
3976 } else if (pursue || uinshp || !um_dist(x, y, 1)) {
3977 if (!Deaf)
3978 verbalize("How dare you %s my %s?", dmgstr,
3979 dugwall ? "shop" : "door");
3980 else
3981 pline("%s is %s that you decided to %s %s %s!",
3982 Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
3983 dmgstr, mhis(shkp), dugwall ? "shop" : "door");
3984 } else {
3985 if (!Deaf) {
3986 pline("%s shouts:", shkname(shkp));
3987 verbalize("Who dared %s my %s?", dmgstr,
3988 dugwall ? "shop" : "door");
3989 } else {
3990 pline("%s is %s that someone decided to %s %s %s!",
3991 Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
3992 dmgstr, mhis(shkp), dugwall ? "shop" : "door");
3995 hot_pursuit(shkp);
3996 return;
3999 if (Invis)
4000 Your("invisibility does not fool %s!", shkname(shkp));
4001 Sprintf(qbuf, "%sYou did %ld %s worth of damage!%s Pay?",
4002 !animal ? cad(TRUE) : "", cost_of_damage,
4003 currency(cost_of_damage), !animal ? "\"" : "");
4004 if (yn(qbuf) != 'n') {
4005 cost_of_damage = check_credit(cost_of_damage, shkp);
4006 money2mon(shkp, cost_of_damage);
4007 context.botl = 1;
4008 pline("Mollified, %s accepts your restitution.", shkname(shkp));
4009 /* move shk back to his home loc */
4010 home_shk(shkp, FALSE);
4011 pacify_shk(shkp);
4012 } else {
4013 if (!animal) {
4014 if (!Deaf && !muteshk(shkp))
4015 verbalize("Oh, yes! You'll pay!");
4016 else
4017 pline("%s lunges %s %s toward your %s!",
4018 Shknam(shkp),
4019 mhis(shkp),
4020 mbodypart(shkp, HAND),
4021 body_part(NECK));
4022 } else
4023 growl(shkp);
4024 hot_pursuit(shkp);
4025 adjalign(-sgn(u.ualign.type));
4029 /* called in dokick.c when we kick an object that might be in a store */
4030 boolean
4031 costly_spot(x, y)
4032 register xchar x, y;
4034 struct monst *shkp;
4035 struct eshk *eshkp;
4037 if (!level.flags.has_shop)
4038 return FALSE;
4039 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
4040 if (!shkp || !inhishop(shkp))
4041 return FALSE;
4042 eshkp = ESHK(shkp);
4043 return (boolean) (inside_shop(x, y)
4044 && !(x == eshkp->shk.x && y == eshkp->shk.y));
4047 /* called by dotalk(sounds.c) when #chatting; returns obj if location
4048 contains shop goods and shopkeeper is willing & able to speak */
4049 struct obj *
4050 shop_object(x, y)
4051 register xchar x, y;
4053 register struct obj *otmp;
4054 register struct monst *shkp;
4056 if (!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
4057 return (struct obj *) 0;
4059 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
4060 if (otmp->oclass != COIN_CLASS)
4061 break;
4062 /* note: otmp might have ->no_charge set, but that's ok */
4063 return (otmp && costly_spot(x, y)
4064 && NOTANGRY(shkp) && shkp->mcanmove && !shkp->msleeping)
4065 ? otmp
4066 : (struct obj *) 0;
4069 /* give price quotes for all objects linked to this one (ie, on this spot) */
4070 void
4071 price_quote(first_obj)
4072 register struct obj *first_obj;
4074 register struct obj *otmp;
4075 char buf[BUFSZ], price[40];
4076 long cost = 0L;
4077 int cnt = 0;
4078 boolean contentsonly = FALSE;
4079 winid tmpwin;
4080 struct monst *shkp = shop_keeper(inside_shop(u.ux, u.uy));
4082 tmpwin = create_nhwindow(NHW_MENU);
4083 putstr(tmpwin, 0, "Fine goods for sale:");
4084 putstr(tmpwin, 0, "");
4085 for (otmp = first_obj; otmp; otmp = otmp->nexthere) {
4086 if (otmp->oclass == COIN_CLASS)
4087 continue;
4088 cost = (otmp->no_charge || otmp == uball || otmp == uchain)
4089 ? 0L
4090 : get_cost(otmp, (struct monst *) 0);
4091 contentsonly = !cost;
4092 if (Has_contents(otmp))
4093 cost += contained_cost(otmp, shkp, 0L, FALSE, FALSE);
4094 if (!cost) {
4095 Strcpy(price, "no charge");
4096 contentsonly = FALSE;
4097 } else {
4098 Sprintf(price, "%ld %s%s", cost, currency(cost),
4099 (otmp->quan) > 1L ? " each" : "");
4101 Sprintf(buf, "%s%s, %s", contentsonly ? the_contents_of : "",
4102 doname(otmp), price);
4103 putstr(tmpwin, 0, buf), cnt++;
4105 if (cnt > 1) {
4106 display_nhwindow(tmpwin, TRUE);
4107 } else if (cnt == 1) {
4108 if (!cost) {
4109 /* "<doname(obj)>, no charge" */
4110 pline("%s!", upstart(buf)); /* buf still contains the string */
4111 } else {
4112 /* print cost in slightly different format, so can't reuse buf;
4113 cost and contentsonly are already set up */
4114 Sprintf(buf, "%s%s", contentsonly ? the_contents_of : "",
4115 doname(first_obj));
4116 pline("%s, price %ld %s%s%s", upstart(buf), cost, currency(cost),
4117 (first_obj->quan > 1L) ? " each" : "",
4118 contentsonly ? "." : shk_embellish(first_obj, cost));
4121 destroy_nhwindow(tmpwin);
4124 STATIC_OVL const char *
4125 shk_embellish(itm, cost)
4126 register struct obj *itm;
4127 long cost;
4129 if (!rn2(3)) {
4130 register int o, choice = rn2(5);
4132 if (choice == 0)
4133 choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
4134 switch (choice) {
4135 case 4:
4136 if (cost < 10L)
4137 break;
4138 else
4139 o = itm->oclass;
4140 if (o == FOOD_CLASS)
4141 return ", gourmets' delight!";
4142 if (objects[itm->otyp].oc_name_known
4143 ? objects[itm->otyp].oc_magic
4144 : (o == AMULET_CLASS || o == RING_CLASS || o == WAND_CLASS
4145 || o == POTION_CLASS || o == SCROLL_CLASS
4146 || o == SPBOOK_CLASS))
4147 return ", painstakingly developed!";
4148 return ", superb craftsmanship!";
4149 case 3:
4150 return ", finest quality.";
4151 case 2:
4152 return ", an excellent choice.";
4153 case 1:
4154 return ", a real bargain.";
4155 default:
4156 break;
4158 } else if (itm->oartifact) {
4159 return ", one of a kind!";
4161 return ".";
4164 /* First 4 supplied by Ronen and Tamar, remainder by development team */
4165 const char *Izchak_speaks[] = {
4166 "%s says: 'These shopping malls give me a headache.'",
4167 "%s says: 'Slow down. Think clearly.'",
4168 "%s says: 'You need to take things one at a time.'",
4169 "%s says: 'I don't like poofy coffee... give me Columbian Supremo.'",
4170 "%s says that getting the devteam's agreement on anything is difficult.",
4171 "%s says that he has noticed those who serve their deity will prosper.",
4172 "%s says: 'Don't try to steal from me - I have friends in high places!'",
4173 "%s says: 'You may well need something from this shop in the future.'",
4174 "%s comments about the Valley of the Dead as being a gateway."
4177 void
4178 shk_chat(shkp)
4179 struct monst *shkp;
4181 struct eshk *eshk;
4182 long shkmoney;
4184 if (!shkp->isshk) {
4185 /* The monster type is shopkeeper, but this monster is
4186 not actually a shk, which could happen if someone
4187 wishes for a shopkeeper statue and then animates it.
4188 (Note: shkname() would be "" in a case like this.) */
4189 pline("%s asks whether you've seen any untended shops recently.",
4190 Monnam(shkp));
4191 /* [Perhaps we ought to check whether this conversation
4192 is taking place inside an untended shop, but a shopless
4193 shk can probably be expected to be rather disoriented.] */
4194 return;
4197 eshk = ESHK(shkp);
4198 if (ANGRY(shkp)) {
4199 pline("%s %s how much %s dislikes %s customers.",
4200 shkname(shkp),
4201 (!Deaf && !muteshk(shkp)) ? "mentions" : "indicates",
4202 mhe(shkp), eshk->robbed ? "non-paying" : "rude");
4203 } else if (eshk->following) {
4204 if (strncmp(eshk->customer, plname, PL_NSIZ)) {
4205 if (!Deaf && !muteshk(shkp))
4206 verbalize("%s %s! I was looking for %s.",
4207 Hello(shkp), plname, eshk->customer);
4208 eshk->following = 0;
4209 } else {
4210 if (!Deaf && !muteshk(shkp))
4211 verbalize("%s %s! Didn't you forget to pay?",
4212 Hello(shkp), plname);
4213 else
4214 pline("%s taps you on the %s.",
4215 Shknam(shkp), body_part(ARM));
4217 } else if (eshk->billct) {
4218 register long total = addupbill(shkp) + eshk->debit;
4220 pline("%s %s that your bill comes to %ld %s.",
4221 shkname(shkp),
4222 (!Deaf && !muteshk(shkp)) ? "says" : "indicates",
4223 total, currency(total));
4224 } else if (eshk->debit) {
4225 pline("%s %s that you owe %s %ld %s.",
4226 shkname(shkp),
4227 (!Deaf && !muteshk(shkp)) ? "reminds you" : "indicates",
4228 mhim(shkp), eshk->debit, currency(eshk->debit));
4229 } else if (eshk->credit) {
4230 pline("%s encourages you to use your %ld %s of credit.",
4231 shkname(shkp), eshk->credit, currency(eshk->credit));
4232 } else if (eshk->robbed) {
4233 pline("%s %s about a recent robbery.",
4234 Shknam(shkp),
4235 (!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
4236 } else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
4237 pline("%s %s that business is bad.",
4238 shkname(shkp),
4239 (!Deaf && !muteshk(shkp)) ? "complains" : "indicates");
4240 } else if (shkmoney > 4000) {
4241 pline("%s %s that business is good.",
4242 shkname(shkp),
4243 (!Deaf && !muteshk(shkp)) ? "says" : "indicates");
4244 } else if (is_izchak(shkp, FALSE)) {
4245 if (!Deaf && !muteshk(shkp))
4246 pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
4247 } else {
4248 if (!Deaf && !muteshk(shkp))
4249 pline("%s talks about the problem of shoplifters.", shkname(shkp));
4253 STATIC_OVL void
4254 kops_gone(silent)
4255 boolean silent;
4257 register int cnt = 0;
4258 register struct monst *mtmp, *mtmp2;
4260 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
4261 mtmp2 = mtmp->nmon;
4262 if (mtmp->data->mlet == S_KOP) {
4263 if (canspotmon(mtmp))
4264 cnt++;
4265 mongone(mtmp);
4268 if (cnt && !silent)
4269 pline_The("Kop%s (disappointed) vanish%s into thin air.",
4270 plur(cnt), (cnt == 1) ? "es" : "");
4273 STATIC_OVL long
4274 cost_per_charge(shkp, otmp, altusage)
4275 struct monst *shkp;
4276 struct obj *otmp;
4277 boolean altusage; /* some items have an "alternate" use with different cost */
4279 long tmp = 0L;
4281 if (!shkp || !inhishop(shkp))
4282 return 0L; /* insurance */
4283 tmp = get_cost(otmp, shkp);
4285 /* The idea is to make the exhaustive use of an unpaid item
4286 * more expensive than buying it outright.
4288 if (otmp->otyp == MAGIC_LAMP) { /* 1 */
4289 /* normal use (ie, as light source) of a magic lamp never
4290 degrades its value, but not charging anything would make
4291 identification too easy; charge an amount comparable to
4292 what is charged for an ordinary lamp (don't bother with
4293 angry shk surcharge) */
4294 if (!altusage)
4295 tmp = (long) objects[OIL_LAMP].oc_cost;
4296 else
4297 tmp += tmp / 3L; /* djinni is being released */
4298 } else if (otmp->otyp == MAGIC_MARKER) { /* 70 - 100 */
4299 /* No way to determine in advance how many charges will be
4300 * wasted. So, arbitrarily, one half of the price per use.
4302 tmp /= 2L;
4303 } else if (otmp->otyp == BAG_OF_TRICKS /* 1 - 20 */
4304 || otmp->otyp == HORN_OF_PLENTY) {
4305 /* altusage: emptying of all the contents at once */
4306 if (!altusage)
4307 tmp /= 5L;
4308 } else if (otmp->otyp == CRYSTAL_BALL /* 1 - 5 */
4309 || otmp->otyp == OIL_LAMP /* 1 - 10 */
4310 || otmp->otyp == BRASS_LANTERN
4311 || (otmp->otyp >= MAGIC_FLUTE
4312 && otmp->otyp <= DRUM_OF_EARTHQUAKE) /* 5 - 9 */
4313 || otmp->oclass == WAND_CLASS) { /* 3 - 11 */
4314 if (otmp->spe > 1)
4315 tmp /= 4L;
4316 } else if (otmp->oclass == SPBOOK_CLASS) {
4317 tmp -= tmp / 5L;
4318 } else if (otmp->otyp == CAN_OF_GREASE || otmp->otyp == TINNING_KIT
4319 || otmp->otyp == EXPENSIVE_CAMERA) {
4320 tmp /= 10L;
4321 } else if (otmp->otyp == POT_OIL) {
4322 tmp /= 5L;
4324 return tmp;
4327 /* Charge the player for partial use of an unpaid object.
4329 * Note that bill_dummy_object() should be used instead
4330 * when an object is completely used.
4332 void
4333 check_unpaid_usage(otmp, altusage)
4334 struct obj *otmp;
4335 boolean altusage;
4337 struct monst *shkp;
4338 const char *fmt, *arg1, *arg2;
4339 char buf[BUFSZ];
4340 long tmp;
4342 if (!otmp->unpaid || !*u.ushops
4343 || (otmp->spe <= 0 && objects[otmp->otyp].oc_charged))
4344 return;
4345 if (!(shkp = shop_keeper(*u.ushops)) || !inhishop(shkp))
4346 return;
4347 if ((tmp = cost_per_charge(shkp, otmp, altusage)) == 0L)
4348 return;
4350 arg1 = arg2 = "";
4351 if (otmp->oclass == SPBOOK_CLASS) {
4352 fmt = "%sYou owe%s %ld %s.";
4353 Sprintf(buf, "This is no free library, %s! ", cad(FALSE));
4354 arg1 = rn2(2) ? buf : "";
4355 arg2 = ESHK(shkp)->debit > 0L ? " an additional" : "";
4356 } else if (otmp->otyp == POT_OIL) {
4357 fmt = "%s%sThat will cost you %ld %s (Yendorian Fuel Tax).";
4358 } else if (altusage && (otmp->otyp == BAG_OF_TRICKS
4359 || otmp->otyp == HORN_OF_PLENTY)) {
4360 fmt = "%s%sEmptying that will cost you %ld %s.";
4361 if (!rn2(3))
4362 arg1 = "Whoa! ";
4363 if (!rn2(3))
4364 arg1 = "Watch it! ";
4365 } else {
4366 fmt = "%s%sUsage fee, %ld %s.";
4367 if (!rn2(3))
4368 arg1 = "Hey! ";
4369 if (!rn2(3))
4370 arg2 = "Ahem. ";
4373 if (!Deaf && !muteshk(shkp)) {
4374 verbalize(fmt, arg1, arg2, tmp, currency(tmp));
4375 exercise(A_WIS, TRUE); /* you just got info */
4377 ESHK(shkp)->debit += tmp;
4380 /* for using charges of unpaid objects "used in the normal manner" */
4381 void
4382 check_unpaid(otmp)
4383 struct obj *otmp;
4385 check_unpaid_usage(otmp, FALSE); /* normal item use */
4388 void
4389 costly_gold(x, y, amount)
4390 register xchar x, y;
4391 register long amount;
4393 register long delta;
4394 register struct monst *shkp;
4395 register struct eshk *eshkp;
4397 if (!costly_spot(x, y))
4398 return;
4399 /* shkp now guaranteed to exist by costly_spot() */
4400 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
4402 eshkp = ESHK(shkp);
4403 if (eshkp->credit >= amount) {
4404 if (eshkp->credit > amount)
4405 Your("credit is reduced by %ld %s.", amount, currency(amount));
4406 else
4407 Your("credit is erased.");
4408 eshkp->credit -= amount;
4409 } else {
4410 delta = amount - eshkp->credit;
4411 if (eshkp->credit)
4412 Your("credit is erased.");
4413 if (eshkp->debit)
4414 Your("debt increases by %ld %s.", delta, currency(delta));
4415 else
4416 You("owe %s %ld %s.", shkname(shkp), delta, currency(delta));
4417 eshkp->debit += delta;
4418 eshkp->loan += delta;
4419 eshkp->credit = 0L;
4423 /* used in domove to block diagonal shop-exit */
4424 /* x,y should always be a door */
4425 boolean
4426 block_door(x, y)
4427 register xchar x, y;
4429 register int roomno = *in_rooms(x, y, SHOPBASE);
4430 register struct monst *shkp;
4432 if (roomno < 0 || !IS_SHOP(roomno))
4433 return FALSE;
4434 if (!IS_DOOR(levl[x][y].typ))
4435 return FALSE;
4436 if (roomno != *u.ushops)
4437 return FALSE;
4439 if (!(shkp = shop_keeper((char) roomno)) || !inhishop(shkp))
4440 return FALSE;
4442 if (shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y
4443 /* Actually, the shk should be made to block _any_
4444 * door, including a door the player digs, if the
4445 * shk is within a 'jumping' distance.
4447 && ESHK(shkp)->shd.x == x
4448 && ESHK(shkp)->shd.y == y
4449 && shkp->mcanmove && !shkp->msleeping
4450 && (ESHK(shkp)->debit || ESHK(shkp)->billct || ESHK(shkp)->robbed)) {
4451 pline("%s%s blocks your way!", shkname(shkp),
4452 Invis ? " senses your motion and" : "");
4453 return TRUE;
4455 return FALSE;
4458 /* used in domove to block diagonal shop-entry;
4459 u.ux, u.uy should always be a door */
4460 boolean
4461 block_entry(x, y)
4462 register xchar x, y;
4464 register xchar sx, sy;
4465 register int roomno;
4466 register struct monst *shkp;
4468 if (!(IS_DOOR(levl[u.ux][u.uy].typ)
4469 && levl[u.ux][u.uy].doormask == D_BROKEN))
4470 return FALSE;
4472 roomno = *in_rooms(x, y, SHOPBASE);
4473 if (roomno < 0 || !IS_SHOP(roomno))
4474 return FALSE;
4475 if (!(shkp = shop_keeper((char) roomno)) || !inhishop(shkp))
4476 return FALSE;
4478 if (ESHK(shkp)->shd.x != u.ux || ESHK(shkp)->shd.y != u.uy)
4479 return FALSE;
4481 sx = ESHK(shkp)->shk.x;
4482 sy = ESHK(shkp)->shk.y;
4484 if (shkp->mx == sx && shkp->my == sy && shkp->mcanmove && !shkp->msleeping
4485 && (x == sx - 1 || x == sx + 1 || y == sy - 1 || y == sy + 1)
4486 && (Invis || carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
4487 || u.usteed)) {
4488 pline("%s%s blocks your way!", shkname(shkp),
4489 Invis ? " senses your motion and" : "");
4490 return TRUE;
4492 return FALSE;
4495 /* "your " or "Foobar's " (note the trailing space) */
4496 char *
4497 shk_your(buf, obj)
4498 char *buf;
4499 struct obj *obj;
4501 if (!shk_owns(buf, obj) && !mon_owns(buf, obj))
4502 Strcpy(buf, the_your[carried(obj) ? 1 : 0]);
4503 return strcat(buf, " ");
4506 char *
4507 Shk_Your(buf, obj)
4508 char *buf;
4509 struct obj *obj;
4511 (void) shk_your(buf, obj);
4512 *buf = highc(*buf);
4513 return buf;
4516 STATIC_OVL char *
4517 shk_owns(buf, obj)
4518 char *buf;
4519 struct obj *obj;
4521 struct monst *shkp;
4522 xchar x, y;
4524 if (get_obj_location(obj, &x, &y, 0)
4525 && (obj->unpaid || (obj->where == OBJ_FLOOR && !obj->no_charge
4526 && costly_spot(x, y)))) {
4527 shkp = shop_keeper(inside_shop(x, y));
4528 return strcpy(buf, shkp ? s_suffix(shkname(shkp)) : the_your[0]);
4530 return (char *) 0;
4533 STATIC_OVL char *
4534 mon_owns(buf, obj)
4535 char *buf;
4536 struct obj *obj;
4538 if (obj->where == OBJ_MINVENT)
4539 return strcpy(buf, s_suffix(y_monnam(obj->ocarry)));
4540 return (char *) 0;
4543 STATIC_OVL const char *
4544 cad(altusage)
4545 boolean altusage; /* used as a verbalized exclamation: \"Cad! ...\" */
4547 const char *res = 0;
4549 switch (is_demon(youmonst.data) ? 3 : poly_gender()) {
4550 case 0:
4551 res = "cad";
4552 break;
4553 case 1:
4554 res = "minx";
4555 break;
4556 case 2:
4557 res = "beast";
4558 break;
4559 case 3:
4560 res = "fiend";
4561 break;
4562 default:
4563 impossible("cad: unknown gender");
4564 res = "thing";
4565 break;
4567 if (altusage) {
4568 char *cadbuf = mon_nam(&youmonst); /* snag an output buffer */
4570 /* alternate usage adds a leading double quote and trailing
4571 exclamation point plus sentence separating spaces */
4572 Sprintf(cadbuf, "\"%s! ", res);
4573 cadbuf[1] = highc(cadbuf[1]);
4574 res = cadbuf;
4576 return res;
4579 #ifdef __SASC
4580 void
4581 sasc_bug(struct obj *op, unsigned x)
4583 op->unpaid = x;
4585 #endif
4587 /*shk.c*/