Add key rebinding
[aNetHack.git] / src / shk.c
bloba914a56d7159cd6beb77a593049cca35da51a010
1 /* NetHack 3.6 shk.c $NHDT-Date: 1464138042 2016/05/25 01:00:42 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.132 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack 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 tmp_dam->when = monstermoves;
3311 tmp_dam->place.x = x;
3312 tmp_dam->place.y = y;
3313 tmp_dam->cost = cost;
3314 tmp_dam->typ = levl[x][y].typ;
3315 tmp_dam->next = level.damagelist;
3316 level.damagelist = tmp_dam;
3317 /* If player saw damage, display as a wall forever */
3318 if (cansee(x, y))
3319 levl[x][y].seenv = SVALL;
3323 * Do something about damage. Either (!croaked) try to repair it, or
3324 * (croaked) just discard damage structs for non-shared locations, since
3325 * they'll never get repaired. Assume that shared locations will get
3326 * repaired eventually by the other shopkeeper(s). This might be an erroneous
3327 * assumption (they might all be dead too), but we have no reasonable way of
3328 * telling that.
3330 STATIC_OVL
3331 void
3332 remove_damage(shkp, croaked)
3333 struct monst *shkp;
3334 boolean croaked;
3336 struct damage *tmp_dam, *tmp2_dam;
3337 boolean did_repair = FALSE, saw_door = FALSE, saw_floor = FALSE,
3338 stop_picking = FALSE, doorway_trap = FALSE;
3339 int saw_walls = 0, saw_untrap = 0;
3340 char trapmsg[BUFSZ];
3342 tmp_dam = level.damagelist;
3343 tmp2_dam = 0;
3344 while (tmp_dam) {
3345 register xchar x = tmp_dam->place.x, y = tmp_dam->place.y;
3346 char shops[5];
3347 int disposition;
3348 unsigned old_doormask = 0;
3350 disposition = 0;
3351 Strcpy(shops, in_rooms(x, y, SHOPBASE));
3352 if (index(shops, ESHK(shkp)->shoproom)) {
3353 if (IS_DOOR(levl[x][y].typ))
3354 old_doormask = levl[x][y].doormask;
3356 if (croaked)
3357 disposition = (shops[1]) ? 0 : 1;
3358 else if (stop_picking)
3359 disposition = repair_damage(shkp, tmp_dam, FALSE);
3360 else {
3361 /* Defer the stop_occupation() until after repair msgs */
3362 if (closed_door(x, y))
3363 stop_picking = picking_at(x, y);
3364 disposition = repair_damage(shkp, tmp_dam, FALSE);
3365 if (!disposition)
3366 stop_picking = FALSE;
3370 if (!disposition) {
3371 tmp2_dam = tmp_dam;
3372 tmp_dam = tmp_dam->next;
3373 continue;
3376 if (disposition > 1) {
3377 did_repair = TRUE;
3378 if (cansee(x, y)) {
3379 if (IS_WALL(levl[x][y].typ)) {
3380 saw_walls++;
3381 } else if (IS_DOOR(levl[x][y].typ)
3382 /* an existing door here implies trap removal */
3383 && !(old_doormask & (D_ISOPEN | D_CLOSED))) {
3384 saw_door = TRUE;
3385 } else if (disposition == 3) { /* untrapped */
3386 saw_untrap++;
3387 if (IS_DOOR(levl[x][y].typ))
3388 doorway_trap = TRUE;
3389 } else {
3390 saw_floor = TRUE;
3395 tmp_dam = tmp_dam->next;
3396 if (!tmp2_dam) {
3397 free((genericptr_t) level.damagelist);
3398 level.damagelist = tmp_dam;
3399 } else {
3400 free((genericptr_t) tmp2_dam->next);
3401 tmp2_dam->next = tmp_dam;
3404 if (!did_repair)
3405 return;
3407 if (saw_untrap) {
3408 Sprintf(trapmsg, "%s trap%s",
3409 (saw_untrap > 3) ? "several" : (saw_untrap > 1) ? "some"
3410 : "a",
3411 plur(saw_untrap));
3412 Sprintf(eos(trapmsg), " %s", vtense(trapmsg, "are"));
3413 Sprintf(eos(trapmsg), " removed from the %s",
3414 (doorway_trap && saw_untrap == 1) ? "doorway" : "floor");
3415 } else
3416 trapmsg[0] = '\0'; /* not just lint suppression... */
3418 if (saw_walls) {
3419 char wallbuf[BUFSZ];
3421 Sprintf(wallbuf, "section%s", plur(saw_walls));
3422 pline("Suddenly, %s %s of wall %s up!",
3423 (saw_walls == 1) ? "a" : (saw_walls <= 3) ? "some" : "several",
3424 wallbuf, vtense(wallbuf, "close"));
3426 if (saw_door)
3427 pline_The("shop door reappears!");
3428 if (saw_floor)
3429 pline_The("floor is repaired!");
3430 if (saw_untrap)
3431 pline("%s!", upstart(trapmsg));
3432 } else {
3433 if (saw_door || saw_floor || saw_untrap)
3434 pline("Suddenly, %s%s%s%s%s!",
3435 saw_door ? "the shop door reappears" : "",
3436 (saw_door && saw_floor) ? " and " : "",
3437 saw_floor ? "the floor damage is gone" : "",
3438 ((saw_door || saw_floor) && *trapmsg) ? " and " : "",
3439 trapmsg);
3440 else if (inside_shop(u.ux, u.uy) == ESHK(shkp)->shoproom)
3441 You_feel("more claustrophobic than before.");
3442 else if (!Deaf && !rn2(10))
3443 Norep("The dungeon acoustics noticeably change.");
3445 if (stop_picking)
3446 stop_occupation();
3450 * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
3451 * 3: untrap
3454 repair_damage(shkp, tmp_dam, catchup)
3455 register struct monst *shkp;
3456 register struct damage *tmp_dam;
3457 boolean catchup; /* restoring a level */
3459 register xchar x, y, i;
3460 xchar litter[9];
3461 register struct monst *mtmp;
3462 register struct obj *otmp;
3463 register struct trap *ttmp;
3465 if ((monstermoves - tmp_dam->when) < REPAIR_DELAY)
3466 return 0;
3467 if (shkp->msleeping || !shkp->mcanmove || ESHK(shkp)->following)
3468 return 0;
3469 x = tmp_dam->place.x;
3470 y = tmp_dam->place.y;
3471 if (!IS_ROOM(tmp_dam->typ)) {
3472 if (x == u.ux && y == u.uy)
3473 if (!Passes_walls)
3474 return 0;
3475 if (x == shkp->mx && y == shkp->my)
3476 return 0;
3477 if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data)))
3478 return 0;
3480 if ((ttmp = t_at(x, y)) != 0) {
3481 if (x == u.ux && y == u.uy)
3482 if (!Passes_walls)
3483 return 0;
3484 if (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP) {
3485 /* convert to an object */
3486 otmp = mksobj((ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP,
3487 TRUE, FALSE);
3488 otmp->quan = 1L;
3489 otmp->owt = weight(otmp);
3490 (void) mpickobj(shkp, otmp);
3492 deltrap(ttmp);
3493 if (IS_DOOR(tmp_dam->typ) && !(levl[x][y].doormask & D_ISOPEN)) {
3494 levl[x][y].doormask = D_CLOSED;
3495 block_point(x, y);
3496 } else if (IS_WALL(tmp_dam->typ)) {
3497 levl[x][y].typ = tmp_dam->typ;
3498 block_point(x, y);
3500 newsym(x, y);
3501 return 3;
3503 if (IS_ROOM(tmp_dam->typ)) {
3504 /* No messages, because player already filled trap door */
3505 return 1;
3507 if ((tmp_dam->typ == levl[x][y].typ)
3508 && (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN)))
3509 /* No messages if player already replaced shop door */
3510 return 1;
3511 levl[x][y].typ = tmp_dam->typ;
3512 (void) memset((genericptr_t) litter, 0, sizeof(litter));
3513 if ((otmp = level.objects[x][y]) != 0) {
3514 /* Scatter objects haphazardly into the shop */
3515 #define NEED_UPDATE 1
3516 #define OPEN 2
3517 #define INSHOP 4
3518 #define horiz(i) ((i % 3) - 1)
3519 #define vert(i) ((i / 3) - 1)
3520 for (i = 0; i < 9; i++) {
3521 if ((i == 4) || (!ZAP_POS(levl[x + horiz(i)][y + vert(i)].typ)))
3522 continue;
3523 litter[i] = OPEN;
3524 if (inside_shop(x + horiz(i), y + vert(i))
3525 == ESHK(shkp)->shoproom)
3526 litter[i] |= INSHOP;
3528 if (Punished && !u.uswallow
3529 && ((uchain->ox == x && uchain->oy == y)
3530 || (uball->ox == x && uball->oy == y))) {
3532 * Either the ball or chain is in the repair location.
3534 * Take the easy way out and put ball&chain under hero.
3536 if (!Deaf && !muteshk(shkp))
3537 verbalize("Get your junk out of my wall!");
3538 unplacebc(); /* pick 'em up */
3539 placebc(); /* put 'em down */
3541 while ((otmp = level.objects[x][y]) != 0)
3542 /* Don't mess w/ boulders -- just merge into wall */
3543 if ((otmp->otyp == BOULDER) || (otmp->otyp == ROCK)) {
3544 obj_extract_self(otmp);
3545 obfree(otmp, (struct obj *) 0);
3546 } else {
3547 while (!(litter[i = rn2(9)] & INSHOP))
3549 remove_object(otmp);
3550 place_object(otmp, x + horiz(i), y + vert(i));
3551 litter[i] |= NEED_UPDATE;
3554 if (catchup)
3555 return 1; /* repair occurred while off level */
3557 block_point(x, y);
3558 if (IS_DOOR(tmp_dam->typ)) {
3559 levl[x][y].doormask = D_CLOSED; /* arbitrary */
3560 newsym(x, y);
3561 } else {
3562 /* don't set doormask - it is (hopefully) the same as it was
3563 if not, perhaps save it with the damage array... */
3565 if (IS_WALL(tmp_dam->typ) && cansee(x, y)) {
3566 /* Player sees actual repair process, so they KNOW it's a wall */
3567 levl[x][y].seenv = SVALL;
3568 newsym(x, y);
3570 /* Mark this wall as "repaired". There currently is no code
3571 to do anything about repaired walls, so don't do it. */
3573 for (i = 0; i < 9; i++)
3574 if (litter[i] & NEED_UPDATE)
3575 newsym(x + horiz(i), y + vert(i));
3576 return 2;
3577 #undef NEED_UPDATE
3578 #undef OPEN
3579 #undef INSHOP
3580 #undef vert
3581 #undef horiz
3585 * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
3588 shk_move(shkp)
3589 register struct monst *shkp;
3591 register xchar gx, gy, omx, omy;
3592 register int udist;
3593 register schar appr;
3594 register struct eshk *eshkp = ESHK(shkp);
3595 int z;
3596 boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv;
3598 omx = shkp->mx;
3599 omy = shkp->my;
3601 if (inhishop(shkp))
3602 remove_damage(shkp, FALSE);
3604 if ((udist = distu(omx, omy)) < 3 && (shkp->data != &mons[PM_GRID_BUG]
3605 || (omx == u.ux || omy == u.uy))) {
3606 if (ANGRY(shkp) || (Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
3607 if (Displaced)
3608 Your("displaced image doesn't fool %s!", shkname(shkp));
3609 (void) mattacku(shkp);
3610 return 0;
3612 if (eshkp->following) {
3613 if (strncmp(eshkp->customer, plname, PL_NSIZ)) {
3614 if (!Deaf && !muteshk(shkp))
3615 verbalize("%s, %s! I was looking for %s.", Hello(shkp),
3616 plname, eshkp->customer);
3617 eshkp->following = 0;
3618 return 0;
3620 if (moves > followmsg + 4) {
3621 if (!Deaf && !muteshk(shkp))
3622 verbalize("%s, %s! Didn't you forget to pay?",
3623 Hello(shkp), plname);
3624 else
3625 pline("%s holds out %s upturned %s.",
3626 Shknam(shkp),
3627 mhis(shkp),
3628 mbodypart(shkp, HAND));
3629 followmsg = moves;
3630 if (!rn2(9)) {
3631 pline("%s doesn't like customers who don't pay.",
3632 Shknam(shkp));
3633 rile_shk(shkp);
3636 if (udist < 2)
3637 return 0;
3641 appr = 1;
3642 gx = eshkp->shk.x;
3643 gy = eshkp->shk.y;
3644 satdoor = (gx == omx && gy == omy);
3645 if (eshkp->following || ((z = holetime()) >= 0 && z * z <= udist)) {
3646 /* [This distance check used to apply regardless of
3647 whether the shk was following, but that resulted in
3648 m_move() sometimes taking the shk out of the shop if
3649 the player had fenced him in with boulders or traps.
3650 Such voluntary abandonment left unpaid objects in
3651 invent, triggering billing impossibilities on the
3652 next level once the character fell through the hole.] */
3653 if (udist > 4 && eshkp->following && !eshkp->billct)
3654 return -1; /* leave it to m_move */
3655 gx = u.ux;
3656 gy = u.uy;
3657 } else if (ANGRY(shkp)) {
3658 /* Move towards the hero if the shopkeeper can see him. */
3659 if (shkp->mcansee && m_canseeu(shkp)) {
3660 gx = u.ux;
3661 gy = u.uy;
3663 avoid = FALSE;
3664 } else {
3665 #define GDIST(x, y) (dist2(x, y, gx, gy))
3666 if (Invis || u.usteed) {
3667 avoid = FALSE;
3668 } else {
3669 uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y);
3670 if (uondoor) {
3671 badinv =
3672 (carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
3673 || (Fast && (sobj_at(PICK_AXE, u.ux, u.uy)
3674 || sobj_at(DWARVISH_MATTOCK, u.ux, u.uy))));
3675 if (satdoor && badinv)
3676 return 0;
3677 avoid = !badinv;
3678 } else {
3679 avoid = (*u.ushops && distu(gx, gy) > 8);
3680 badinv = FALSE;
3683 if (((!eshkp->robbed && !eshkp->billct && !eshkp->debit) || avoid)
3684 && GDIST(omx, omy) < 3) {
3685 if (!badinv && !onlineu(omx, omy))
3686 return 0;
3687 if (satdoor)
3688 appr = gx = gy = 0;
3693 z = move_special(shkp, inhishop(shkp), appr, uondoor, avoid, omx, omy, gx,
3694 gy);
3695 if (z > 0)
3696 after_shk_move(shkp);
3698 return z;
3701 /* called after shopkeeper moves, in case themove causes re-entry into shop */
3702 void
3703 after_shk_move(shkp)
3704 struct monst *shkp;
3706 struct eshk *eshkp = ESHK(shkp);
3708 if (eshkp->bill_p == (struct bill_x *) -1000 && inhishop(shkp)) {
3709 /* reset bill_p, need to re-calc player's occupancy too */
3710 eshkp->bill_p = &eshkp->bill[0];
3711 check_special_room(FALSE);
3715 /* for use in levl_follower (mondata.c) */
3716 boolean
3717 is_fshk(mtmp)
3718 register struct monst *mtmp;
3720 return (boolean) (mtmp->isshk && ESHK(mtmp)->following);
3723 /* You are digging in the shop. */
3724 void
3725 shopdig(fall)
3726 register int fall;
3728 register struct monst *shkp = shop_keeper(*u.ushops);
3729 int lang;
3730 const char *grabs = "grabs";
3732 if (!shkp)
3733 return;
3735 /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */
3736 lang = 0;
3737 if (shkp->msleeping || !shkp->mcanmove || is_silent(shkp->data))
3738 ; /* lang stays 0 */
3739 else if (shkp->data->msound <= MS_ANIMAL)
3740 lang = 1;
3741 else if (shkp->data->msound >= MS_HUMANOID)
3742 lang = 2;
3744 if (!inhishop(shkp)) {
3745 if (Role_if(PM_KNIGHT)) {
3746 You_feel("like a common thief.");
3747 adjalign(-sgn(u.ualign.type));
3749 return;
3752 if (!fall) {
3753 if (lang == 2) {
3754 if (!Deaf && !muteshk(shkp)) {
3755 if (u.utraptype == TT_PIT)
3756 verbalize(
3757 "Be careful, %s, or you might fall through the floor.",
3758 flags.female ? "madam" : "sir");
3759 else
3760 verbalize("%s, do not damage the floor here!",
3761 flags.female ? "Madam" : "Sir");
3764 if (Role_if(PM_KNIGHT)) {
3765 You_feel("like a common thief.");
3766 adjalign(-sgn(u.ualign.type));
3768 } else if (!um_dist(shkp->mx, shkp->my, 5)
3769 && !shkp->msleeping && shkp->mcanmove
3770 && (ESHK(shkp)->billct || ESHK(shkp)->debit)) {
3771 register struct obj *obj, *obj2;
3773 if (nolimbs(shkp->data)) {
3774 grabs = "knocks off";
3775 #if 0
3776 /* This is what should happen, but for balance
3777 * reasons, it isn't currently.
3779 if (lang == 2)
3780 pline("%s curses %s inability to grab your backpack!",
3781 shkname(shkp), mhim(shkp));
3782 rile_shk(shkp);
3783 return;
3784 #endif
3786 if (distu(shkp->mx, shkp->my) > 2) {
3787 mnexto(shkp);
3788 /* for some reason the shopkeeper can't come next to you */
3789 if (distu(shkp->mx, shkp->my) > 2) {
3790 if (lang == 2)
3791 pline("%s curses you in anger and frustration!",
3792 shkname(shkp));
3793 else if (lang == 1)
3794 growl(shkp);
3795 rile_shk(shkp);
3796 return;
3797 } else
3798 pline("%s %s, and %s your backpack!", shkname(shkp),
3799 makeplural(locomotion(shkp->data, "leap")), grabs);
3800 } else
3801 pline("%s %s your backpack!", shkname(shkp), grabs);
3803 for (obj = invent; obj; obj = obj2) {
3804 obj2 = obj->nobj;
3805 if ((obj->owornmask & ~(W_SWAPWEP | W_QUIVER)) != 0
3806 || (obj == uswapwep && u.twoweap)
3807 || (obj->otyp == LEASH && obj->leashmon))
3808 continue;
3809 if (obj == current_wand)
3810 continue;
3811 setnotworn(obj);
3812 freeinv(obj);
3813 subfrombill(obj, shkp);
3814 (void) add_to_minv(shkp, obj); /* may free obj */
3819 STATIC_OVL void
3820 makekops(mm)
3821 coord *mm;
3823 static const short k_mndx[4] = { PM_KEYSTONE_KOP, PM_KOP_SERGEANT,
3824 PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN };
3825 int k_cnt[4], cnt, mndx, k;
3827 k_cnt[0] = cnt = abs(depth(&u.uz)) + rnd(5);
3828 k_cnt[1] = (cnt / 3) + 1; /* at least one sarge */
3829 k_cnt[2] = (cnt / 6); /* maybe a lieutenant */
3830 k_cnt[3] = (cnt / 9); /* and maybe a kaptain */
3832 for (k = 0; k < 4; k++) {
3833 if ((cnt = k_cnt[k]) == 0)
3834 break;
3835 mndx = k_mndx[k];
3836 if (mvitals[mndx].mvflags & G_GONE)
3837 continue;
3839 while (cnt--)
3840 if (enexto(mm, mm->x, mm->y, &mons[mndx]))
3841 (void) makemon(&mons[mndx], mm->x, mm->y, NO_MM_FLAGS);
3845 void
3846 pay_for_damage(dmgstr, cant_mollify)
3847 const char *dmgstr;
3848 boolean cant_mollify;
3850 register struct monst *shkp = (struct monst *) 0;
3851 char shops_affected[5];
3852 register boolean uinshp = (*u.ushops != '\0');
3853 char qbuf[80];
3854 register xchar x, y;
3855 boolean dugwall = (!strcmp(dmgstr, "dig into") /* wand */
3856 || !strcmp(dmgstr, "damage")); /* pick-axe */
3857 boolean animal, pursue;
3858 struct damage *tmp_dam, *appear_here = 0;
3859 /* any number >= (80*80)+(24*24) would do, actually */
3860 long cost_of_damage = 0L;
3861 unsigned int nearest_shk = 7000, nearest_damage = 7000;
3862 int picks = 0;
3864 for (tmp_dam = level.damagelist;
3865 (tmp_dam && (tmp_dam->when == monstermoves));
3866 tmp_dam = tmp_dam->next) {
3867 char *shp;
3869 if (!tmp_dam->cost)
3870 continue;
3871 cost_of_damage += tmp_dam->cost;
3872 Strcpy(shops_affected,
3873 in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
3874 for (shp = shops_affected; *shp; shp++) {
3875 struct monst *tmp_shk;
3876 unsigned int shk_distance;
3878 if (!(tmp_shk = shop_keeper(*shp)))
3879 continue;
3880 if (tmp_shk == shkp) {
3881 unsigned int damage_distance =
3882 distu(tmp_dam->place.x, tmp_dam->place.y);
3884 if (damage_distance < nearest_damage) {
3885 nearest_damage = damage_distance;
3886 appear_here = tmp_dam;
3888 continue;
3890 if (!inhishop(tmp_shk))
3891 continue;
3892 shk_distance = distu(tmp_shk->mx, tmp_shk->my);
3893 if (shk_distance > nearest_shk)
3894 continue;
3895 if ((shk_distance == nearest_shk) && picks) {
3896 if (rn2(++picks))
3897 continue;
3898 } else
3899 picks = 1;
3900 shkp = tmp_shk;
3901 nearest_shk = shk_distance;
3902 appear_here = tmp_dam;
3903 nearest_damage = distu(tmp_dam->place.x, tmp_dam->place.y);
3907 if (!cost_of_damage || !shkp)
3908 return;
3910 animal = (shkp->data->msound <= MS_ANIMAL);
3911 pursue = FALSE;
3912 x = appear_here->place.x;
3913 y = appear_here->place.y;
3915 /* not the best introduction to the shk... */
3916 (void) strncpy(ESHK(shkp)->customer, plname, PL_NSIZ);
3918 /* if the shk is already on the war path, be sure it's all out */
3919 if (ANGRY(shkp) || ESHK(shkp)->following) {
3920 hot_pursuit(shkp);
3921 return;
3924 /* if the shk is not in their shop.. */
3925 if (!*in_rooms(shkp->mx, shkp->my, SHOPBASE)) {
3926 if (!cansee(shkp->mx, shkp->my))
3927 return;
3928 pursue = TRUE;
3929 goto getcad;
3932 if (uinshp) {
3933 if (um_dist(shkp->mx, shkp->my, 1)
3934 && !um_dist(shkp->mx, shkp->my, 3)) {
3935 pline("%s leaps towards you!", shkname(shkp));
3936 mnexto(shkp);
3938 pursue = um_dist(shkp->mx, shkp->my, 1);
3939 if (pursue)
3940 goto getcad;
3941 } else {
3943 * Make shkp show up at the door. Effect: If there is a monster
3944 * in the doorway, have the hero hear the shopkeeper yell a bit,
3945 * pause, then have the shopkeeper appear at the door, having
3946 * yanked the hapless critter out of the way.
3948 if (MON_AT(x, y)) {
3949 if (!animal) {
3950 if (!Deaf && !muteshk(shkp)) {
3951 You_hear("an angry voice:");
3952 verbalize("Out of my way, scum!");
3954 wait_synch();
3955 #if defined(UNIX) || defined(VMS)
3956 #if defined(SYSV) || defined(ULTRIX) || defined(VMS)
3957 (void)
3958 #endif
3959 sleep(1);
3960 #endif
3961 } else {
3962 growl(shkp);
3965 (void) mnearto(shkp, x, y, TRUE);
3968 if ((um_dist(x, y, 1) && !uinshp) || cant_mollify
3969 || (money_cnt(invent) + ESHK(shkp)->credit) < cost_of_damage
3970 || !rn2(50)) {
3971 getcad:
3972 if (muteshk(shkp)) {
3973 if (animal && shkp->mcanmove && !shkp->msleeping)
3974 yelp(shkp);
3975 } else if (pursue || uinshp || !um_dist(x, y, 1)) {
3976 if (!Deaf)
3977 verbalize("How dare you %s my %s?", dmgstr,
3978 dugwall ? "shop" : "door");
3979 else
3980 pline("%s is %s that you decided to %s %s %s!",
3981 Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
3982 dmgstr, mhis(shkp), dugwall ? "shop" : "door");
3983 } else {
3984 if (!Deaf) {
3985 pline("%s shouts:", shkname(shkp));
3986 verbalize("Who dared %s my %s?", dmgstr,
3987 dugwall ? "shop" : "door");
3988 } else {
3989 pline("%s is %s that someone decided to %s %s %s!",
3990 Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
3991 dmgstr, mhis(shkp), dugwall ? "shop" : "door");
3994 hot_pursuit(shkp);
3995 return;
3998 if (Invis)
3999 Your("invisibility does not fool %s!", shkname(shkp));
4000 Sprintf(qbuf, "%sYou did %ld %s worth of damage!%s Pay?",
4001 !animal ? cad(TRUE) : "", cost_of_damage,
4002 currency(cost_of_damage), !animal ? "\"" : "");
4003 if (yn(qbuf) != 'n') {
4004 cost_of_damage = check_credit(cost_of_damage, shkp);
4005 money2mon(shkp, cost_of_damage);
4006 context.botl = 1;
4007 pline("Mollified, %s accepts your restitution.", shkname(shkp));
4008 /* move shk back to his home loc */
4009 home_shk(shkp, FALSE);
4010 pacify_shk(shkp);
4011 } else {
4012 if (!animal) {
4013 if (!Deaf && !muteshk(shkp))
4014 verbalize("Oh, yes! You'll pay!");
4015 else
4016 pline("%s lunges %s %s toward your %s!",
4017 Shknam(shkp),
4018 mhis(shkp),
4019 mbodypart(shkp, HAND),
4020 body_part(NECK));
4021 } else
4022 growl(shkp);
4023 hot_pursuit(shkp);
4024 adjalign(-sgn(u.ualign.type));
4028 /* called in dokick.c when we kick an object that might be in a store */
4029 boolean
4030 costly_spot(x, y)
4031 register xchar x, y;
4033 struct monst *shkp;
4034 struct eshk *eshkp;
4036 if (!level.flags.has_shop)
4037 return FALSE;
4038 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
4039 if (!shkp || !inhishop(shkp))
4040 return FALSE;
4041 eshkp = ESHK(shkp);
4042 return (boolean) (inside_shop(x, y)
4043 && !(x == eshkp->shk.x && y == eshkp->shk.y));
4046 /* called by dotalk(sounds.c) when #chatting; returns obj if location
4047 contains shop goods and shopkeeper is willing & able to speak */
4048 struct obj *
4049 shop_object(x, y)
4050 register xchar x, y;
4052 register struct obj *otmp;
4053 register struct monst *shkp;
4055 if (!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
4056 return (struct obj *) 0;
4058 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
4059 if (otmp->oclass != COIN_CLASS)
4060 break;
4061 /* note: otmp might have ->no_charge set, but that's ok */
4062 return (otmp && costly_spot(x, y)
4063 && NOTANGRY(shkp) && shkp->mcanmove && !shkp->msleeping)
4064 ? otmp
4065 : (struct obj *) 0;
4068 /* give price quotes for all objects linked to this one (ie, on this spot) */
4069 void
4070 price_quote(first_obj)
4071 register struct obj *first_obj;
4073 register struct obj *otmp;
4074 char buf[BUFSZ], price[40];
4075 long cost = 0L;
4076 int cnt = 0;
4077 boolean contentsonly = FALSE;
4078 winid tmpwin;
4079 struct monst *shkp = shop_keeper(inside_shop(u.ux, u.uy));
4081 tmpwin = create_nhwindow(NHW_MENU);
4082 putstr(tmpwin, 0, "Fine goods for sale:");
4083 putstr(tmpwin, 0, "");
4084 for (otmp = first_obj; otmp; otmp = otmp->nexthere) {
4085 if (otmp->oclass == COIN_CLASS)
4086 continue;
4087 cost = (otmp->no_charge || otmp == uball || otmp == uchain)
4088 ? 0L
4089 : get_cost(otmp, (struct monst *) 0);
4090 contentsonly = !cost;
4091 if (Has_contents(otmp))
4092 cost += contained_cost(otmp, shkp, 0L, FALSE, FALSE);
4093 if (!cost) {
4094 Strcpy(price, "no charge");
4095 contentsonly = FALSE;
4096 } else {
4097 Sprintf(price, "%ld %s%s", cost, currency(cost),
4098 (otmp->quan) > 1L ? " each" : "");
4100 Sprintf(buf, "%s%s, %s", contentsonly ? the_contents_of : "",
4101 doname(otmp), price);
4102 putstr(tmpwin, 0, buf), cnt++;
4104 if (cnt > 1) {
4105 display_nhwindow(tmpwin, TRUE);
4106 } else if (cnt == 1) {
4107 if (!cost) {
4108 /* "<doname(obj)>, no charge" */
4109 pline("%s!", upstart(buf)); /* buf still contains the string */
4110 } else {
4111 /* print cost in slightly different format, so can't reuse buf;
4112 cost and contentsonly are already set up */
4113 Sprintf(buf, "%s%s", contentsonly ? the_contents_of : "",
4114 doname(first_obj));
4115 pline("%s, price %ld %s%s%s", upstart(buf), cost, currency(cost),
4116 (first_obj->quan > 1L) ? " each" : "",
4117 contentsonly ? "." : shk_embellish(first_obj, cost));
4120 destroy_nhwindow(tmpwin);
4123 STATIC_OVL const char *
4124 shk_embellish(itm, cost)
4125 register struct obj *itm;
4126 long cost;
4128 if (!rn2(3)) {
4129 register int o, choice = rn2(5);
4131 if (choice == 0)
4132 choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
4133 switch (choice) {
4134 case 4:
4135 if (cost < 10L)
4136 break;
4137 else
4138 o = itm->oclass;
4139 if (o == FOOD_CLASS)
4140 return ", gourmets' delight!";
4141 if (objects[itm->otyp].oc_name_known
4142 ? objects[itm->otyp].oc_magic
4143 : (o == AMULET_CLASS || o == RING_CLASS || o == WAND_CLASS
4144 || o == POTION_CLASS || o == SCROLL_CLASS
4145 || o == SPBOOK_CLASS))
4146 return ", painstakingly developed!";
4147 return ", superb craftsmanship!";
4148 case 3:
4149 return ", finest quality.";
4150 case 2:
4151 return ", an excellent choice.";
4152 case 1:
4153 return ", a real bargain.";
4154 default:
4155 break;
4157 } else if (itm->oartifact) {
4158 return ", one of a kind!";
4160 return ".";
4163 /* First 4 supplied by Ronen and Tamar, remainder by development team */
4164 const char *Izchak_speaks[] = {
4165 "%s says: 'These shopping malls give me a headache.'",
4166 "%s says: 'Slow down. Think clearly.'",
4167 "%s says: 'You need to take things one at a time.'",
4168 "%s says: 'I don't like poofy coffee... give me Columbian Supremo.'",
4169 "%s says that getting the devteam's agreement on anything is difficult.",
4170 "%s says that he has noticed those who serve their deity will prosper.",
4171 "%s says: 'Don't try to steal from me - I have friends in high places!'",
4172 "%s says: 'You may well need something from this shop in the future.'",
4173 "%s comments about the Valley of the Dead as being a gateway."
4176 void
4177 shk_chat(shkp)
4178 struct monst *shkp;
4180 struct eshk *eshk;
4181 long shkmoney;
4183 if (!shkp->isshk) {
4184 /* The monster type is shopkeeper, but this monster is
4185 not actually a shk, which could happen if someone
4186 wishes for a shopkeeper statue and then animates it.
4187 (Note: shkname() would be "" in a case like this.) */
4188 pline("%s asks whether you've seen any untended shops recently.",
4189 Monnam(shkp));
4190 /* [Perhaps we ought to check whether this conversation
4191 is taking place inside an untended shop, but a shopless
4192 shk can probably be expected to be rather disoriented.] */
4193 return;
4196 eshk = ESHK(shkp);
4197 if (ANGRY(shkp)) {
4198 pline("%s %s how much %s dislikes %s customers.",
4199 shkname(shkp),
4200 (!Deaf && !muteshk(shkp)) ? "mentions" : "indicates",
4201 mhe(shkp), eshk->robbed ? "non-paying" : "rude");
4202 } else if (eshk->following) {
4203 if (strncmp(eshk->customer, plname, PL_NSIZ)) {
4204 if (!Deaf && !muteshk(shkp))
4205 verbalize("%s %s! I was looking for %s.",
4206 Hello(shkp), plname, eshk->customer);
4207 eshk->following = 0;
4208 } else {
4209 if (!Deaf && !muteshk(shkp))
4210 verbalize("%s %s! Didn't you forget to pay?",
4211 Hello(shkp), plname);
4212 else
4213 pline("%s taps you on the %s.",
4214 Shknam(shkp), body_part(ARM));
4216 } else if (eshk->billct) {
4217 register long total = addupbill(shkp) + eshk->debit;
4219 pline("%s %s that your bill comes to %ld %s.",
4220 shkname(shkp),
4221 (!Deaf && !muteshk(shkp)) ? "says" : "indicates",
4222 total, currency(total));
4223 } else if (eshk->debit) {
4224 pline("%s %s that you owe %s %ld %s.",
4225 shkname(shkp),
4226 (!Deaf && !muteshk(shkp)) ? "reminds you" : "indicates",
4227 mhim(shkp), eshk->debit, currency(eshk->debit));
4228 } else if (eshk->credit) {
4229 pline("%s encourages you to use your %ld %s of credit.",
4230 shkname(shkp), eshk->credit, currency(eshk->credit));
4231 } else if (eshk->robbed) {
4232 pline("%s %s about a recent robbery.",
4233 Shknam(shkp),
4234 (!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
4235 } else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
4236 pline("%s %s that business is bad.",
4237 shkname(shkp),
4238 (!Deaf && !muteshk(shkp)) ? "complains" : "indicates");
4239 } else if (shkmoney > 4000) {
4240 pline("%s %s that business is good.",
4241 shkname(shkp),
4242 (!Deaf && !muteshk(shkp)) ? "says" : "indicates");
4243 } else if (is_izchak(shkp, FALSE)) {
4244 if (!Deaf && !muteshk(shkp))
4245 pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
4246 } else {
4247 if (!Deaf && !muteshk(shkp))
4248 pline("%s talks about the problem of shoplifters.", shkname(shkp));
4252 STATIC_OVL void
4253 kops_gone(silent)
4254 boolean silent;
4256 register int cnt = 0;
4257 register struct monst *mtmp, *mtmp2;
4259 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
4260 mtmp2 = mtmp->nmon;
4261 if (mtmp->data->mlet == S_KOP) {
4262 if (canspotmon(mtmp))
4263 cnt++;
4264 mongone(mtmp);
4267 if (cnt && !silent)
4268 pline_The("Kop%s (disappointed) vanish%s into thin air.",
4269 plur(cnt), (cnt == 1) ? "es" : "");
4272 STATIC_OVL long
4273 cost_per_charge(shkp, otmp, altusage)
4274 struct monst *shkp;
4275 struct obj *otmp;
4276 boolean altusage; /* some items have an "alternate" use with different cost */
4278 long tmp = 0L;
4280 if (!shkp || !inhishop(shkp))
4281 return 0L; /* insurance */
4282 tmp = get_cost(otmp, shkp);
4284 /* The idea is to make the exhaustive use of an unpaid item
4285 * more expensive than buying it outright.
4287 if (otmp->otyp == MAGIC_LAMP) { /* 1 */
4288 /* normal use (ie, as light source) of a magic lamp never
4289 degrades its value, but not charging anything would make
4290 identification too easy; charge an amount comparable to
4291 what is charged for an ordinary lamp (don't bother with
4292 angry shk surcharge) */
4293 if (!altusage)
4294 tmp = (long) objects[OIL_LAMP].oc_cost;
4295 else
4296 tmp += tmp / 3L; /* djinni is being released */
4297 } else if (otmp->otyp == MAGIC_MARKER) { /* 70 - 100 */
4298 /* No way to determine in advance how many charges will be
4299 * wasted. So, arbitrarily, one half of the price per use.
4301 tmp /= 2L;
4302 } else if (otmp->otyp == BAG_OF_TRICKS /* 1 - 20 */
4303 || otmp->otyp == HORN_OF_PLENTY) {
4304 /* altusage: emptying of all the contents at once */
4305 if (!altusage)
4306 tmp /= 5L;
4307 } else if (otmp->otyp == CRYSTAL_BALL /* 1 - 5 */
4308 || otmp->otyp == OIL_LAMP /* 1 - 10 */
4309 || otmp->otyp == BRASS_LANTERN
4310 || (otmp->otyp >= MAGIC_FLUTE
4311 && otmp->otyp <= DRUM_OF_EARTHQUAKE) /* 5 - 9 */
4312 || otmp->oclass == WAND_CLASS) { /* 3 - 11 */
4313 if (otmp->spe > 1)
4314 tmp /= 4L;
4315 } else if (otmp->oclass == SPBOOK_CLASS) {
4316 tmp -= tmp / 5L;
4317 } else if (otmp->otyp == CAN_OF_GREASE || otmp->otyp == TINNING_KIT
4318 || otmp->otyp == EXPENSIVE_CAMERA) {
4319 tmp /= 10L;
4320 } else if (otmp->otyp == POT_OIL) {
4321 tmp /= 5L;
4323 return tmp;
4326 /* Charge the player for partial use of an unpaid object.
4328 * Note that bill_dummy_object() should be used instead
4329 * when an object is completely used.
4331 void
4332 check_unpaid_usage(otmp, altusage)
4333 struct obj *otmp;
4334 boolean altusage;
4336 struct monst *shkp;
4337 const char *fmt, *arg1, *arg2;
4338 char buf[BUFSZ];
4339 long tmp;
4341 if (!otmp->unpaid || !*u.ushops
4342 || (otmp->spe <= 0 && objects[otmp->otyp].oc_charged))
4343 return;
4344 if (!(shkp = shop_keeper(*u.ushops)) || !inhishop(shkp))
4345 return;
4346 if ((tmp = cost_per_charge(shkp, otmp, altusage)) == 0L)
4347 return;
4349 arg1 = arg2 = "";
4350 if (otmp->oclass == SPBOOK_CLASS) {
4351 fmt = "%sYou owe%s %ld %s.";
4352 Sprintf(buf, "This is no free library, %s! ", cad(FALSE));
4353 arg1 = rn2(2) ? buf : "";
4354 arg2 = ESHK(shkp)->debit > 0L ? " an additional" : "";
4355 } else if (otmp->otyp == POT_OIL) {
4356 fmt = "%s%sThat will cost you %ld %s (Yendorian Fuel Tax).";
4357 } else if (altusage && (otmp->otyp == BAG_OF_TRICKS
4358 || otmp->otyp == HORN_OF_PLENTY)) {
4359 fmt = "%s%sEmptying that will cost you %ld %s.";
4360 if (!rn2(3))
4361 arg1 = "Whoa! ";
4362 if (!rn2(3))
4363 arg1 = "Watch it! ";
4364 } else {
4365 fmt = "%s%sUsage fee, %ld %s.";
4366 if (!rn2(3))
4367 arg1 = "Hey! ";
4368 if (!rn2(3))
4369 arg2 = "Ahem. ";
4372 if (!Deaf && !muteshk(shkp)) {
4373 verbalize(fmt, arg1, arg2, tmp, currency(tmp));
4374 exercise(A_WIS, TRUE); /* you just got info */
4376 ESHK(shkp)->debit += tmp;
4379 /* for using charges of unpaid objects "used in the normal manner" */
4380 void
4381 check_unpaid(otmp)
4382 struct obj *otmp;
4384 check_unpaid_usage(otmp, FALSE); /* normal item use */
4387 void
4388 costly_gold(x, y, amount)
4389 register xchar x, y;
4390 register long amount;
4392 register long delta;
4393 register struct monst *shkp;
4394 register struct eshk *eshkp;
4396 if (!costly_spot(x, y))
4397 return;
4398 /* shkp now guaranteed to exist by costly_spot() */
4399 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
4401 eshkp = ESHK(shkp);
4402 if (eshkp->credit >= amount) {
4403 if (eshkp->credit > amount)
4404 Your("credit is reduced by %ld %s.", amount, currency(amount));
4405 else
4406 Your("credit is erased.");
4407 eshkp->credit -= amount;
4408 } else {
4409 delta = amount - eshkp->credit;
4410 if (eshkp->credit)
4411 Your("credit is erased.");
4412 if (eshkp->debit)
4413 Your("debt increases by %ld %s.", delta, currency(delta));
4414 else
4415 You("owe %s %ld %s.", shkname(shkp), delta, currency(delta));
4416 eshkp->debit += delta;
4417 eshkp->loan += delta;
4418 eshkp->credit = 0L;
4422 /* used in domove to block diagonal shop-exit */
4423 /* x,y should always be a door */
4424 boolean
4425 block_door(x, y)
4426 register xchar x, y;
4428 register int roomno = *in_rooms(x, y, SHOPBASE);
4429 register struct monst *shkp;
4431 if (roomno < 0 || !IS_SHOP(roomno))
4432 return FALSE;
4433 if (!IS_DOOR(levl[x][y].typ))
4434 return FALSE;
4435 if (roomno != *u.ushops)
4436 return FALSE;
4438 if (!(shkp = shop_keeper((char) roomno)) || !inhishop(shkp))
4439 return FALSE;
4441 if (shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y
4442 /* Actually, the shk should be made to block _any_
4443 * door, including a door the player digs, if the
4444 * shk is within a 'jumping' distance.
4446 && ESHK(shkp)->shd.x == x
4447 && ESHK(shkp)->shd.y == y
4448 && shkp->mcanmove && !shkp->msleeping
4449 && (ESHK(shkp)->debit || ESHK(shkp)->billct || ESHK(shkp)->robbed)) {
4450 pline("%s%s blocks your way!", shkname(shkp),
4451 Invis ? " senses your motion and" : "");
4452 return TRUE;
4454 return FALSE;
4457 /* used in domove to block diagonal shop-entry;
4458 u.ux, u.uy should always be a door */
4459 boolean
4460 block_entry(x, y)
4461 register xchar x, y;
4463 register xchar sx, sy;
4464 register int roomno;
4465 register struct monst *shkp;
4467 if (!(IS_DOOR(levl[u.ux][u.uy].typ)
4468 && levl[u.ux][u.uy].doormask == D_BROKEN))
4469 return FALSE;
4471 roomno = *in_rooms(x, y, SHOPBASE);
4472 if (roomno < 0 || !IS_SHOP(roomno))
4473 return FALSE;
4474 if (!(shkp = shop_keeper((char) roomno)) || !inhishop(shkp))
4475 return FALSE;
4477 if (ESHK(shkp)->shd.x != u.ux || ESHK(shkp)->shd.y != u.uy)
4478 return FALSE;
4480 sx = ESHK(shkp)->shk.x;
4481 sy = ESHK(shkp)->shk.y;
4483 if (shkp->mx == sx && shkp->my == sy && shkp->mcanmove && !shkp->msleeping
4484 && (x == sx - 1 || x == sx + 1 || y == sy - 1 || y == sy + 1)
4485 && (Invis || carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
4486 || u.usteed)) {
4487 pline("%s%s blocks your way!", shkname(shkp),
4488 Invis ? " senses your motion and" : "");
4489 return TRUE;
4491 return FALSE;
4494 /* "your " or "Foobar's " (note the trailing space) */
4495 char *
4496 shk_your(buf, obj)
4497 char *buf;
4498 struct obj *obj;
4500 if (!shk_owns(buf, obj) && !mon_owns(buf, obj))
4501 Strcpy(buf, the_your[carried(obj) ? 1 : 0]);
4502 return strcat(buf, " ");
4505 char *
4506 Shk_Your(buf, obj)
4507 char *buf;
4508 struct obj *obj;
4510 (void) shk_your(buf, obj);
4511 *buf = highc(*buf);
4512 return buf;
4515 STATIC_OVL char *
4516 shk_owns(buf, obj)
4517 char *buf;
4518 struct obj *obj;
4520 struct monst *shkp;
4521 xchar x, y;
4523 if (get_obj_location(obj, &x, &y, 0)
4524 && (obj->unpaid || (obj->where == OBJ_FLOOR && !obj->no_charge
4525 && costly_spot(x, y)))) {
4526 shkp = shop_keeper(inside_shop(x, y));
4527 return strcpy(buf, shkp ? s_suffix(shkname(shkp)) : the_your[0]);
4529 return (char *) 0;
4532 STATIC_OVL char *
4533 mon_owns(buf, obj)
4534 char *buf;
4535 struct obj *obj;
4537 if (obj->where == OBJ_MINVENT)
4538 return strcpy(buf, s_suffix(y_monnam(obj->ocarry)));
4539 return (char *) 0;
4542 STATIC_OVL const char *
4543 cad(altusage)
4544 boolean altusage; /* used as a verbalized exclamation: \"Cad! ...\" */
4546 const char *res = 0;
4548 switch (is_demon(youmonst.data) ? 3 : poly_gender()) {
4549 case 0:
4550 res = "cad";
4551 break;
4552 case 1:
4553 res = "minx";
4554 break;
4555 case 2:
4556 res = "beast";
4557 break;
4558 case 3:
4559 res = "fiend";
4560 break;
4561 default:
4562 impossible("cad: unknown gender");
4563 res = "thing";
4564 break;
4566 if (altusage) {
4567 char *cadbuf = mon_nam(&youmonst); /* snag an output buffer */
4569 /* alternate usage adds a leading double quote and trailing
4570 exclamation point plus sentence separating spaces */
4571 Sprintf(cadbuf, "\"%s! ", res);
4572 cadbuf[1] = highc(cadbuf[1]);
4573 res = cadbuf;
4575 return res;
4578 #ifdef __SASC
4579 void
4580 sasc_bug(struct obj *op, unsigned x)
4582 op->unpaid = x;
4584 #endif
4586 /*shk.c*/