use of #terrain while underwater
[aNetHack.git] / src / shk.c
blob3f5819cc4d3e266d357990bae690d8e4e45e3aea
1 /* NetHack 3.6 shk.c $NHDT-Date: 1457392872 2016/03/07 23:21:12 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.125 $ */
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 register char rmno;
817 struct monst *shkp =
818 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(
832 "shopkeeper career change? (rmno=%d, ROOMOFFSET=%d, mnum=%d, %s)",
833 (int)rmno, ROOMOFFSET, shkp->mnum,
834 has_mname(shkp) ? MNAME(shkp) : "anonymous"
837 /* not sure if this is appropriate, because it does nothing to
838 correct the underlying rooms[].resident issue but... */
839 return (struct monst *)0;
842 return shkp;
845 boolean
846 tended_shop(sroom)
847 struct mkroom *sroom;
849 struct monst *mtmp = sroom->resident;
851 return !mtmp ? FALSE : (boolean) inhishop(mtmp);
854 STATIC_OVL struct bill_x *
855 onbill(obj, shkp, silent)
856 struct obj *obj;
857 struct monst *shkp;
858 boolean silent;
860 if (shkp) {
861 register struct bill_x *bp = ESHK(shkp)->bill_p;
862 register int ct = ESHK(shkp)->billct;
864 while (--ct >= 0)
865 if (bp->bo_id == obj->o_id) {
866 if (!obj->unpaid)
867 pline("onbill: paid obj on bill?");
868 return bp;
869 } else
870 bp++;
872 if (obj->unpaid && !silent)
873 pline("onbill: unpaid obj not on bill?");
874 return (struct bill_x *) 0;
877 /* check whether an object or any of its contents belongs to a shop */
878 boolean
879 is_unpaid(obj)
880 struct obj *obj;
882 return (boolean) (obj->unpaid
883 || (Has_contents(obj) && count_unpaid(obj->cobj)));
886 /* Delete the contents of the given object. */
887 void
888 delete_contents(obj)
889 register struct obj *obj;
891 register struct obj *curr;
893 while ((curr = obj->cobj) != 0) {
894 obj_extract_self(curr);
895 obfree(curr, (struct obj *) 0);
899 /* called with two args on merge */
900 void
901 obfree(obj, merge)
902 register struct obj *obj, *merge;
904 register struct bill_x *bp;
905 register struct bill_x *bpm;
906 register struct monst *shkp;
908 if (obj->otyp == LEASH && obj->leashmon)
909 o_unleash(obj);
910 if (obj->oclass == FOOD_CLASS)
911 food_disappears(obj);
912 if (obj->oclass == SPBOOK_CLASS)
913 book_disappears(obj);
914 if (Has_contents(obj))
915 delete_contents(obj);
917 shkp = 0;
918 if (obj->unpaid) {
919 /* look for a shopkeeper who owns this object */
920 for (shkp = next_shkp(fmon, TRUE); shkp;
921 shkp = next_shkp(shkp->nmon, TRUE))
922 if (onbill(obj, shkp, TRUE))
923 break;
925 /* sanity check, more or less */
926 if (!shkp)
927 shkp = shop_keeper(*u.ushops);
929 * Note: `shkp = shop_keeper(*u.ushops)' used to be
930 * unconditional. But obfree() is used all over
931 * the place, so making its behavior be dependent
932 * upon player location doesn't make much sense.
935 if ((bp = onbill(obj, shkp, FALSE)) != 0) {
936 if (!merge) {
937 bp->useup = 1;
938 obj->unpaid = 0; /* only for doinvbill */
939 add_to_billobjs(obj);
940 return;
942 bpm = onbill(merge, shkp, FALSE);
943 if (!bpm) {
944 /* this used to be a rename */
945 impossible("obfree: not on bill??");
946 return;
947 } else {
948 /* this was a merger */
949 bpm->bquan += bp->bquan;
950 ESHK(shkp)->billct--;
951 #ifdef DUMB
953 /* DRS/NS 2.2.6 messes up -- Peter Kendell */
954 int indx = ESHK(shkp)->billct;
956 *bp = ESHK(shkp)->bill_p[indx];
958 #else
959 *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
960 #endif
963 if (obj->owornmask) {
964 impossible("obfree: deleting worn obj (%d: %ld)", obj->otyp,
965 obj->owornmask);
966 /* unfortunately at this point we don't know whether worn mask
967 applied to hero or a monster or perhaps something bogus, so
968 can't call remove_worn_item() to get <X>_off() side-effects */
969 setnotworn(obj);
971 dealloc_obj(obj);
974 STATIC_OVL long
975 check_credit(tmp, shkp)
976 long tmp;
977 register struct monst *shkp;
979 long credit = ESHK(shkp)->credit;
981 if (credit == 0L) {
982 ; /* nothing to do; just 'return tmp;' */
983 } else if (credit >= tmp) {
984 pline_The("price is deducted from your credit.");
985 ESHK(shkp)->credit -= tmp;
986 tmp = 0L;
987 } else {
988 pline_The("price is partially covered by your credit.");
989 ESHK(shkp)->credit = 0L;
990 tmp -= credit;
992 return tmp;
995 STATIC_OVL void
996 pay(tmp, shkp)
997 long tmp;
998 register struct monst *shkp;
1000 long robbed = ESHK(shkp)->robbed;
1001 long balance = ((tmp <= 0L) ? tmp : check_credit(tmp, shkp));
1003 if (balance > 0)
1004 money2mon(shkp, balance);
1005 else if (balance < 0)
1006 money2u(shkp, -balance);
1007 context.botl = 1;
1008 if (robbed) {
1009 robbed -= tmp;
1010 if (robbed < 0)
1011 robbed = 0L;
1012 ESHK(shkp)->robbed = robbed;
1016 /* return shkp to home position */
1017 void
1018 home_shk(shkp, killkops)
1019 register struct monst *shkp;
1020 register boolean killkops;
1022 register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y;
1024 (void) mnearto(shkp, x, y, TRUE);
1025 level.flags.has_shop = 1;
1026 if (killkops) {
1027 kops_gone(TRUE);
1028 pacify_guards();
1030 after_shk_move(shkp);
1033 STATIC_OVL boolean
1034 angry_shk_exists()
1036 register struct monst *shkp;
1038 for (shkp = next_shkp(fmon, FALSE); shkp;
1039 shkp = next_shkp(shkp->nmon, FALSE))
1040 if (ANGRY(shkp))
1041 return TRUE;
1042 return FALSE;
1045 /* remove previously applied surcharge from all billed items */
1046 STATIC_OVL void
1047 pacify_shk(shkp)
1048 register struct monst *shkp;
1050 NOTANGRY(shkp) = TRUE; /* make peaceful */
1051 if (ESHK(shkp)->surcharge) {
1052 register struct bill_x *bp = ESHK(shkp)->bill_p;
1053 register int ct = ESHK(shkp)->billct;
1055 ESHK(shkp)->surcharge = FALSE;
1056 while (ct-- > 0) {
1057 register long reduction = (bp->price + 3L) / 4L;
1058 bp->price -= reduction; /* undo 33% increase */
1059 bp++;
1064 /* add aggravation surcharge to all billed items */
1065 STATIC_OVL void
1066 rile_shk(shkp)
1067 register struct monst *shkp;
1069 NOTANGRY(shkp) = FALSE; /* make angry */
1070 if (!ESHK(shkp)->surcharge) {
1071 register struct bill_x *bp = ESHK(shkp)->bill_p;
1072 register int ct = ESHK(shkp)->billct;
1074 ESHK(shkp)->surcharge = TRUE;
1075 while (ct-- > 0) {
1076 register long surcharge = (bp->price + 2L) / 3L;
1077 bp->price += surcharge;
1078 bp++;
1083 /* wakeup and/or unparalyze shopkeeper */
1084 STATIC_OVL void
1085 rouse_shk(shkp, verbosely)
1086 struct monst *shkp;
1087 boolean verbosely;
1089 if (!shkp->mcanmove || shkp->msleeping) {
1090 /* greed induced recovery... */
1091 if (verbosely && canspotmon(shkp))
1092 pline("%s %s.", Shknam(shkp),
1093 shkp->msleeping ? "wakes up" : "can move again");
1094 shkp->msleeping = 0;
1095 shkp->mfrozen = 0;
1096 shkp->mcanmove = 1;
1100 void
1101 make_happy_shk(shkp, silentkops)
1102 register struct monst *shkp;
1103 register boolean silentkops;
1105 boolean wasmad = ANGRY(shkp);
1106 struct eshk *eshkp = ESHK(shkp);
1108 pacify_shk(shkp);
1109 eshkp->following = 0;
1110 eshkp->robbed = 0L;
1111 if (!Role_if(PM_ROGUE))
1112 adjalign(sgn(u.ualign.type));
1113 if (!inhishop(shkp)) {
1114 char shk_nam[BUFSZ];
1115 boolean vanished = canseemon(shkp);
1117 Strcpy(shk_nam, shkname(shkp));
1118 if (on_level(&eshkp->shoplevel, &u.uz)) {
1119 home_shk(shkp, FALSE);
1120 /* didn't disappear if shk can still be seen */
1121 if (canseemon(shkp))
1122 vanished = FALSE;
1123 } else {
1124 /* if sensed, does disappear regardless whether seen */
1125 if (sensemon(shkp))
1126 vanished = TRUE;
1127 /* can't act as porter for the Amulet, even if shk
1128 happens to be going farther down rather than up */
1129 mdrop_special_objs(shkp);
1130 /* arrive near shop's door */
1131 migrate_to_level(shkp, ledger_no(&eshkp->shoplevel),
1132 MIGR_APPROX_XY, &eshkp->shd);
1133 /* dismiss kops on that level when shk arrives */
1134 eshkp->dismiss_kops = TRUE;
1136 if (vanished)
1137 pline("Satisfied, %s suddenly disappears!", shk_nam);
1138 } else if (wasmad)
1139 pline("%s calms down.", Shknam(shkp));
1141 make_happy_shoppers(silentkops);
1144 /* called by make_happy_shk() and also by losedogs() for migrating shk */
1145 void
1146 make_happy_shoppers(silentkops)
1147 boolean silentkops;
1149 if (!angry_shk_exists()) {
1150 kops_gone(silentkops);
1151 pacify_guards();
1155 void
1156 hot_pursuit(shkp)
1157 register struct monst *shkp;
1159 if (!shkp->isshk)
1160 return;
1162 rile_shk(shkp);
1163 (void) strncpy(ESHK(shkp)->customer, plname, PL_NSIZ);
1164 ESHK(shkp)->following = 1;
1167 /* Used when the shkp is teleported or falls (ox == 0) out of his shop, or
1168 when the player is not on a costly_spot and he damages something inside
1169 the shop. These conditions must be checked by the calling function. */
1170 /*ARGSUSED*/
1171 void
1172 make_angry_shk(shkp, ox, oy)
1173 struct monst *shkp;
1174 xchar ox UNUSED; /* <ox,oy> predate 'noit_Monnam()', let alone Shknam() */
1175 xchar oy UNUSED;
1177 struct eshk *eshkp = ESHK(shkp);
1179 /* all pending shop transactions are now "past due" */
1180 if (eshkp->billct || eshkp->debit || eshkp->loan || eshkp->credit) {
1181 eshkp->robbed += (addupbill(shkp) + eshkp->debit + eshkp->loan);
1182 eshkp->robbed -= eshkp->credit;
1183 if (eshkp->robbed < 0L)
1184 eshkp->robbed = 0L;
1185 /* billct, debit, loan, and credit will be cleared by setpaid */
1186 setpaid(shkp);
1189 pline("%s %s!", Shknam(shkp), !ANGRY(shkp) ? "gets angry" : "is furious");
1190 hot_pursuit(shkp);
1193 STATIC_VAR const char
1194 no_money[] = "Moreover, you%s have no money.",
1195 not_enough_money[] = "Besides, you don't have enough to interest %s.";
1197 /* delivers the cheapest item on the list */
1198 STATIC_OVL long
1199 cheapest_item(shkp)
1200 register struct monst *shkp;
1202 register int ct = ESHK(shkp)->billct;
1203 register struct bill_x *bp = ESHK(shkp)->bill_p;
1204 register long gmin = (bp->price * bp->bquan);
1206 while (ct--) {
1207 if (bp->price * bp->bquan < gmin)
1208 gmin = bp->price * bp->bquan;
1209 bp++;
1211 return gmin;
1215 dopay()
1217 register struct eshk *eshkp;
1218 register struct monst *shkp;
1219 struct monst *nxtm, *resident;
1220 long ltmp;
1221 long umoney;
1222 int pass, tmp, sk = 0, seensk = 0;
1223 boolean paid = FALSE, stashed_gold = (hidden_gold() > 0L);
1225 multi = 0;
1227 /* Find how many shk's there are, how many are in
1228 * sight, and are you in a shop room with one.
1230 nxtm = resident = 0;
1231 for (shkp = next_shkp(fmon, FALSE); shkp;
1232 shkp = next_shkp(shkp->nmon, FALSE)) {
1233 sk++;
1234 if (ANGRY(shkp) && distu(shkp->mx, shkp->my) <= 2)
1235 nxtm = shkp;
1236 if (canspotmon(shkp))
1237 seensk++;
1238 if (inhishop(shkp) && (*u.ushops == ESHK(shkp)->shoproom))
1239 resident = shkp;
1242 if (nxtm) { /* Player should always appease an */
1243 shkp = nxtm; /* irate shk standing next to them. */
1244 goto proceed;
1247 if ((!sk && (!Blind || Blind_telepat)) || (!Blind && !seensk)) {
1248 There("appears to be no shopkeeper here to receive your payment.");
1249 return 0;
1252 if (!seensk) {
1253 You_cant("see...");
1254 return 0;
1257 /* The usual case. Allow paying at a distance when
1258 * inside a tended shop. Should we change that?
1260 if (sk == 1 && resident) {
1261 shkp = resident;
1262 goto proceed;
1265 if (seensk == 1) {
1266 for (shkp = next_shkp(fmon, FALSE); shkp;
1267 shkp = next_shkp(shkp->nmon, FALSE))
1268 if (canspotmon(shkp))
1269 break;
1270 if (shkp != resident && distu(shkp->mx, shkp->my) > 2) {
1271 pline("%s is not near enough to receive your payment.",
1272 Shknam(shkp));
1273 return 0;
1275 } else {
1276 struct monst *mtmp;
1277 coord cc;
1278 int cx, cy;
1280 pline("Pay whom?");
1281 cc.x = u.ux;
1282 cc.y = u.uy;
1283 if (getpos(&cc, TRUE, "the creature you want to pay") < 0)
1284 return 0; /* player pressed ESC */
1285 cx = cc.x;
1286 cy = cc.y;
1287 if (cx < 0) {
1288 pline("Try again...");
1289 return 0;
1291 if (u.ux == cx && u.uy == cy) {
1292 You("are generous to yourself.");
1293 return 0;
1295 mtmp = m_at(cx, cy);
1296 if (!cansee(cx, cy) && (!mtmp || !canspotmon(mtmp))) {
1297 You("can't %s anyone there.", !Blind ? "see" : "sense");
1298 return 0;
1300 if (!mtmp) {
1301 There("is no one there to receive your payment.");
1302 return 0;
1304 if (!mtmp->isshk) {
1305 pline("%s is not interested in your payment.", Monnam(mtmp));
1306 return 0;
1308 if (mtmp != resident && distu(mtmp->mx, mtmp->my) > 2) {
1309 pline("%s is too far to receive your payment.", Shknam(mtmp));
1310 return 0;
1312 shkp = mtmp;
1315 if (!shkp) {
1316 debugpline0("dopay: null shkp.");
1317 return 0;
1319 proceed:
1320 eshkp = ESHK(shkp);
1321 ltmp = eshkp->robbed;
1323 /* wake sleeping shk when someone who owes money offers payment */
1324 if (ltmp || eshkp->billct || eshkp->debit)
1325 rouse_shk(shkp, TRUE);
1327 if (!shkp->mcanmove || shkp->msleeping) { /* still asleep/paralyzed */
1328 pline("%s %s.", Shknam(shkp),
1329 rn2(2) ? "seems to be napping" : "doesn't respond");
1330 return 0;
1333 if (shkp != resident && NOTANGRY(shkp)) {
1334 umoney = money_cnt(invent);
1335 if (!ltmp)
1336 You("do not owe %s anything.", shkname(shkp));
1337 else if (!umoney) {
1338 You("%shave no money.", stashed_gold ? "seem to " : "");
1339 if (stashed_gold)
1340 pline("But you have some gold stashed away.");
1341 } else {
1342 if (umoney > ltmp) {
1343 You("give %s the %ld gold piece%s %s asked for.",
1344 shkname(shkp), ltmp, plur(ltmp), mhe(shkp));
1345 pay(ltmp, shkp);
1346 } else {
1347 You("give %s all your%s gold.", shkname(shkp),
1348 stashed_gold ? " openly kept" : "");
1349 pay(umoney, shkp);
1350 if (stashed_gold)
1351 pline("But you have hidden gold!");
1353 if ((umoney < ltmp / 2L) || (umoney < ltmp && stashed_gold))
1354 pline("Unfortunately, %s doesn't look satisfied.", mhe(shkp));
1355 else
1356 make_happy_shk(shkp, FALSE);
1358 return 1;
1361 /* ltmp is still eshkp->robbed here */
1362 if (!eshkp->billct && !eshkp->debit) {
1363 umoney = money_cnt(invent);
1364 if (!ltmp && NOTANGRY(shkp)) {
1365 You("do not owe %s anything.", shkname(shkp));
1366 if (!umoney)
1367 pline(no_money, stashed_gold ? " seem to" : "");
1368 } else if (ltmp) {
1369 pline("%s is after blood, not money!", shkname(shkp));
1370 if (umoney < ltmp / 2L || (umoney < ltmp && stashed_gold)) {
1371 if (!umoney)
1372 pline(no_money, stashed_gold ? " seem to" : "");
1373 else
1374 pline(not_enough_money, mhim(shkp));
1375 return 1;
1377 pline("But since %s shop has been robbed recently,", mhis(shkp));
1378 pline("you %scompensate %s for %s losses.",
1379 (umoney < ltmp) ? "partially " : "", shkname(shkp),
1380 mhis(shkp));
1381 pay(umoney < ltmp ? umoney : ltmp, shkp);
1382 make_happy_shk(shkp, FALSE);
1383 } else {
1384 /* shopkeeper is angry, but has not been robbed --
1385 * door broken, attacked, etc. */
1386 pline("%s is after your hide, not your money!", Shknam(shkp));
1387 if (umoney < 1000L) {
1388 if (!umoney)
1389 pline(no_money, stashed_gold ? " seem to" : "");
1390 else
1391 pline(not_enough_money, mhim(shkp));
1392 return 1;
1394 You("try to appease %s by giving %s 1000 gold pieces.",
1395 x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE), mhim(shkp));
1396 pay(1000L, shkp);
1397 if (strncmp(eshkp->customer, plname, PL_NSIZ) || rn2(3))
1398 make_happy_shk(shkp, FALSE);
1399 else
1400 pline("But %s is as angry as ever.", shkname(shkp));
1402 return 1;
1404 if (shkp != resident) {
1405 impossible("dopay: not to shopkeeper?");
1406 if (resident)
1407 setpaid(resident);
1408 return 0;
1410 /* pay debt, if any, first */
1411 if (eshkp->debit) {
1412 long dtmp = eshkp->debit;
1413 long loan = eshkp->loan;
1414 char sbuf[BUFSZ];
1416 umoney = money_cnt(invent);
1417 Sprintf(sbuf, "You owe %s %ld %s ", shkname(shkp), dtmp,
1418 currency(dtmp));
1419 if (loan) {
1420 if (loan == dtmp)
1421 Strcat(sbuf, "you picked up in the store.");
1422 else
1423 Strcat(sbuf,
1424 "for gold picked up and the use of merchandise.");
1425 } else
1426 Strcat(sbuf, "for the use of merchandise.");
1427 pline1(sbuf);
1428 if (umoney + eshkp->credit < dtmp) {
1429 pline("But you don't%s have enough gold%s.",
1430 stashed_gold ? " seem to" : "",
1431 eshkp->credit ? " or credit" : "");
1432 return 1;
1433 } else {
1434 if (eshkp->credit >= dtmp) {
1435 eshkp->credit -= dtmp;
1436 eshkp->debit = 0L;
1437 eshkp->loan = 0L;
1438 Your("debt is covered by your credit.");
1439 } else if (!eshkp->credit) {
1440 money2mon(shkp, dtmp);
1441 eshkp->debit = 0L;
1442 eshkp->loan = 0L;
1443 You("pay that debt.");
1444 context.botl = 1;
1445 } else {
1446 dtmp -= eshkp->credit;
1447 eshkp->credit = 0L;
1448 money2mon(shkp, dtmp);
1449 eshkp->debit = 0L;
1450 eshkp->loan = 0L;
1451 pline("That debt is partially offset by your credit.");
1452 You("pay the remainder.");
1453 context.botl = 1;
1455 paid = TRUE;
1458 /* now check items on bill */
1459 if (eshkp->billct) {
1460 register boolean itemize;
1461 int iprompt;
1463 umoney = money_cnt(invent);
1464 if (!umoney && !eshkp->credit) {
1465 You("%shave no money or credit%s.",
1466 stashed_gold ? "seem to " : "", paid ? " left" : "");
1467 return 0;
1469 if ((umoney + eshkp->credit) < cheapest_item(shkp)) {
1470 You("don't have enough money to buy%s the item%s you picked.",
1471 eshkp->billct > 1 ? " any of" : "", plur(eshkp->billct));
1472 if (stashed_gold)
1473 pline("Maybe you have some gold stashed away?");
1474 return 0;
1477 /* this isn't quite right; it itemizes without asking if the
1478 * single item on the bill is partly used up and partly unpaid */
1479 iprompt = (eshkp->billct > 1 ? ynq("Itemized billing?") : 'y');
1480 itemize = (iprompt == 'y');
1481 if (iprompt == 'q')
1482 goto thanks;
1484 for (pass = 0; pass <= 1; pass++) {
1485 tmp = 0;
1486 while (tmp < eshkp->billct) {
1487 struct obj *otmp;
1488 register struct bill_x *bp = &(eshkp->bill_p[tmp]);
1490 /* find the object on one of the lists */
1491 if ((otmp = bp_to_obj(bp)) != 0) {
1492 /* if completely used up, object quantity is stale;
1493 restoring it to its original value here avoids
1494 making the partly-used-up code more complicated */
1495 if (bp->useup)
1496 otmp->quan = bp->bquan;
1497 } else {
1498 impossible("Shopkeeper administration out of order.");
1499 setpaid(shkp); /* be nice to the player */
1500 return 1;
1502 if (pass == bp->useup && otmp->quan == bp->bquan) {
1503 /* pay for used-up items on first pass and others
1504 * on second, so player will be stuck in the store
1505 * less often; things which are partly used up
1506 * are processed on both passes */
1507 tmp++;
1508 } else {
1509 switch (dopayobj(shkp, bp, &otmp, pass, itemize)) {
1510 case PAY_CANT:
1511 return 1; /*break*/
1512 case PAY_BROKE:
1513 paid = TRUE;
1514 goto thanks; /*break*/
1515 case PAY_SKIP:
1516 tmp++;
1517 continue; /*break*/
1518 case PAY_SOME:
1519 paid = TRUE;
1520 if (itemize)
1521 bot();
1522 continue; /*break*/
1523 case PAY_BUY:
1524 paid = TRUE;
1525 break;
1527 if (itemize)
1528 bot();
1529 *bp = eshkp->bill_p[--eshkp->billct];
1533 thanks:
1534 if (!itemize)
1535 update_inventory(); /* Done in dopayobj() if itemize. */
1537 if (!ANGRY(shkp) && paid) {
1538 if (!Deaf && !muteshk(shkp))
1539 verbalize("Thank you for shopping in %s %s!", s_suffix(shkname(shkp)),
1540 shtypes[eshkp->shoptype - SHOPBASE].name);
1541 else
1542 pline("%s nods appreciatively at you for shopping in %s %s!",
1543 Shknam(shkp),
1544 mhis(shkp),
1545 shtypes[eshkp->shoptype - SHOPBASE].name);
1547 return 1;
1550 /* return 2 if used-up portion paid
1551 * 1 if paid successfully
1552 * 0 if not enough money
1553 * -1 if skip this object
1554 * -2 if no money/credit left
1556 STATIC_OVL int
1557 dopayobj(shkp, bp, obj_p, which, itemize)
1558 register struct monst *shkp;
1559 register struct bill_x *bp;
1560 struct obj **obj_p;
1561 int which; /* 0 => used-up item, 1 => other (unpaid or lost) */
1562 boolean itemize;
1564 register struct obj *obj = *obj_p;
1565 long ltmp, quan, save_quan;
1566 long umoney = money_cnt(invent);
1567 int buy;
1568 boolean stashed_gold = (hidden_gold() > 0L), consumed = (which == 0);
1570 if (!obj->unpaid && !bp->useup) {
1571 impossible("Paid object on bill??");
1572 return PAY_BUY;
1574 if (itemize && umoney + ESHK(shkp)->credit == 0L) {
1575 You("%shave no money or credit left.",
1576 stashed_gold ? "seem to " : "");
1577 return PAY_BROKE;
1579 /* we may need to temporarily adjust the object, if part of the
1580 original quantity has been used up but part remains unpaid */
1581 save_quan = obj->quan;
1582 if (consumed) {
1583 /* either completely used up (simple), or split needed */
1584 quan = bp->bquan;
1585 if (quan > obj->quan) /* difference is amount used up */
1586 quan -= obj->quan;
1587 } else {
1588 /* dealing with ordinary unpaid item */
1589 quan = obj->quan;
1591 obj->quan = quan; /* to be used by doname() */
1592 obj->unpaid = 0; /* ditto */
1593 iflags.suppress_price++; /* affects containers */
1594 ltmp = bp->price * quan;
1595 buy = PAY_BUY; /* flag; if changed then return early */
1597 if (itemize) {
1598 char qbuf[BUFSZ], qsfx[BUFSZ];
1600 Sprintf(qsfx, " for %ld %s. Pay?", ltmp, currency(ltmp));
1601 (void) safe_qbuf(qbuf, (char *) 0, qsfx, obj,
1602 (quan == 1L) ? Doname2 : doname, ansimpleoname,
1603 (quan == 1L) ? "that" : "those");
1604 if (yn(qbuf) == 'n') {
1605 buy = PAY_SKIP; /* don't want to buy */
1606 } else if (quan < bp->bquan && !consumed) { /* partly used goods */
1607 obj->quan = bp->bquan - save_quan; /* used up amount */
1608 if (!Deaf && !muteshk(shkp)) {
1609 verbalize("%s for the other %s before buying %s.",
1610 ANGRY(shkp) ? "Pay" : "Please pay",
1611 simpleonames(obj), /* short name suffices */
1612 save_quan > 1L ? "these" : "this one");
1613 } else {
1614 pline("%s %s%s your bill for the other %s first.",
1615 Shknam(shkp),
1616 ANGRY(shkp) ? "angrily " : "",
1617 nolimbs(shkp->data) ? "motions to" : "points out",
1618 simpleonames(obj));
1620 buy = PAY_SKIP; /* shk won't sell */
1623 if (buy == PAY_BUY && umoney + ESHK(shkp)->credit < ltmp) {
1624 You("don't%s have gold%s enough to pay for %s.",
1625 stashed_gold ? " seem to" : "",
1626 (ESHK(shkp)->credit > 0L) ? " or credit" : "",
1627 thesimpleoname(obj));
1628 buy = itemize ? PAY_SKIP : PAY_CANT;
1631 if (buy != PAY_BUY) {
1632 /* restore unpaid object to original state */
1633 obj->quan = save_quan;
1634 obj->unpaid = 1;
1635 iflags.suppress_price--;
1636 return buy;
1639 pay(ltmp, shkp);
1640 shk_names_obj(shkp, obj,
1641 consumed ? "paid for %s at a cost of %ld gold piece%s.%s"
1642 : "bought %s for %ld gold piece%s.%s",
1643 ltmp, "");
1644 obj->quan = save_quan; /* restore original count */
1645 /* quan => amount just bought, save_quan => remaining unpaid count */
1646 if (consumed) {
1647 if (quan != bp->bquan) {
1648 /* eliminate used-up portion; remainder is still unpaid */
1649 bp->bquan = obj->quan;
1650 obj->unpaid = 1;
1651 bp->useup = 0;
1652 buy = PAY_SOME;
1653 } else { /* completely used-up, so get rid of it */
1654 obj_extract_self(obj);
1655 /* assert( obj == *obj_p ); */
1656 dealloc_obj(obj);
1657 *obj_p = 0; /* destroy pointer to freed object */
1659 } else if (itemize)
1660 update_inventory(); /* Done just once in dopay() if !itemize. */
1661 iflags.suppress_price--;
1662 return buy;
1665 static struct repo { /* repossession context */
1666 struct monst *shopkeeper;
1667 coord location;
1668 } repo;
1670 /* routine called after dying (or quitting) */
1671 boolean
1672 paybill(croaked)
1673 int croaked; /* -1: escaped dungeon; 0: quit; 1: died */
1675 struct monst *mtmp, *mtmp2, *firstshk, *resident, *creditor, *hostile,
1676 *localshk;
1677 struct eshk *eshkp;
1678 boolean taken = FALSE, local;
1679 int numsk = 0;
1681 /* if we escaped from the dungeon, shopkeepers can't reach us;
1682 shops don't occur on level 1, but this could happen if hero
1683 level teleports out of the dungeon and manages not to die */
1684 if (croaked < 0)
1685 return FALSE;
1686 /* [should probably also return false when dead hero has been
1687 petrified since shk shouldn't be able to grab inventory
1688 which has been shut inside a statue] */
1690 /* this is where inventory will end up if any shk takes it */
1691 repo.location.x = repo.location.y = 0;
1692 repo.shopkeeper = 0;
1695 * Scan all shopkeepers on the level, to prioritize them:
1696 * 1) keeper of shop hero is inside and who is owed money,
1697 * 2) keeper of shop hero is inside who isn't owed any money,
1698 * 3) other shk who is owed money, 4) other shk who is angry,
1699 * 5) any shk local to this level, and if none is found,
1700 * 6) first shk on monster list (last resort; unlikely, since
1701 * any nonlocal shk will probably be in the owed category
1702 * and almost certainly be in the angry category).
1704 resident = creditor = hostile = localshk = (struct monst *) 0;
1705 for (mtmp = next_shkp(fmon, FALSE); mtmp;
1706 mtmp = next_shkp(mtmp2, FALSE)) {
1707 mtmp2 = mtmp->nmon;
1708 eshkp = ESHK(mtmp);
1709 local = on_level(&eshkp->shoplevel, &u.uz);
1710 if (local && index(u.ushops, eshkp->shoproom)) {
1711 /* inside this shk's shop [there might be more than one
1712 resident shk if hero is standing in a breech of a shared
1713 wall, so give priority to one who's also owed money] */
1714 if (!resident || eshkp->billct || eshkp->debit || eshkp->robbed)
1715 resident = mtmp;
1716 } else if (eshkp->billct || eshkp->debit || eshkp->robbed) {
1717 /* owe this shopkeeper money (might also owe others) */
1718 if (!creditor)
1719 creditor = mtmp;
1720 } else if (eshkp->following || ANGRY(mtmp)) {
1721 /* this shopkeeper is antagonistic (others might be too) */
1722 if (!hostile)
1723 hostile = mtmp;
1724 } else if (local) {
1725 /* this shopkeeper's shop is on current level */
1726 if (!localshk)
1727 localshk = mtmp;
1731 /* give highest priority shopkeeper first crack */
1732 firstshk = resident ? resident
1733 : creditor ? creditor
1734 : hostile ? hostile
1735 : localshk;
1736 if (firstshk) {
1737 numsk++;
1738 taken = inherits(firstshk, numsk, croaked);
1741 /* now handle the rest */
1742 for (mtmp = next_shkp(fmon, FALSE); mtmp;
1743 mtmp = next_shkp(mtmp2, FALSE)) {
1744 mtmp2 = mtmp->nmon;
1745 eshkp = ESHK(mtmp);
1746 local = on_level(&eshkp->shoplevel, &u.uz);
1747 if (mtmp != firstshk) {
1748 numsk++;
1749 taken |= inherits(mtmp, numsk, croaked);
1751 /* for bones: we don't want a shopless shk around */
1752 if (!local)
1753 mongone(mtmp);
1755 return taken;
1758 STATIC_OVL boolean
1759 inherits(shkp, numsk, croaked)
1760 struct monst *shkp;
1761 int numsk;
1762 int croaked;
1764 long loss = 0L;
1765 long umoney;
1766 struct eshk *eshkp = ESHK(shkp);
1767 boolean take = FALSE, taken = FALSE;
1768 unsigned save_minvis = shkp->minvis;
1769 int roomno = *u.ushops;
1770 char takes[BUFSZ];
1772 shkp->minvis = 0;
1773 /* The simplifying principle is that first-come
1774 already took everything you had. */
1775 if (numsk > 1) {
1776 if (cansee(shkp->mx, shkp->my) && croaked) {
1777 takes[0] = '\0';
1778 if (has_head(shkp->data) && !rn2(2))
1779 Sprintf(takes, ", shakes %s %s,", mhis(shkp),
1780 mbodypart(shkp, HEAD));
1781 pline("%s %slooks at your corpse%s and %s.", Shknam(shkp),
1782 (!shkp->mcanmove || shkp->msleeping) ? "wakes up, " : "",
1783 takes, !inhishop(shkp) ? "disappears" : "sighs");
1785 rouse_shk(shkp, FALSE); /* wake shk for bones */
1786 taken = (roomno == eshkp->shoproom);
1787 goto skip;
1790 /* get one case out of the way: you die in the shop, the */
1791 /* shopkeeper is peaceful, nothing stolen, nothing owed. */
1792 if (roomno == eshkp->shoproom && inhishop(shkp) && !eshkp->billct
1793 && !eshkp->robbed && !eshkp->debit && NOTANGRY(shkp)
1794 && !eshkp->following && u.ugrave_arise < LOW_PM) {
1795 taken = (invent != 0);
1796 if (taken)
1797 pline("%s gratefully inherits all your possessions.",
1798 shkname(shkp));
1799 set_repo_loc(shkp);
1800 goto clear;
1803 if (eshkp->billct || eshkp->debit || eshkp->robbed) {
1804 if (roomno == eshkp->shoproom && inhishop(shkp))
1805 loss = addupbill(shkp) + eshkp->debit;
1806 if (loss < eshkp->robbed)
1807 loss = eshkp->robbed;
1808 take = TRUE;
1811 if (eshkp->following || ANGRY(shkp) || take) {
1812 if (!invent)
1813 goto skip;
1814 umoney = money_cnt(invent);
1815 takes[0] = '\0';
1816 if (!shkp->mcanmove || shkp->msleeping)
1817 Strcat(takes, "wakes up and ");
1818 if (distu(shkp->mx, shkp->my) > 2)
1819 Strcat(takes, "comes and ");
1820 Strcat(takes, "takes");
1822 if (loss > umoney || !loss || roomno == eshkp->shoproom) {
1823 eshkp->robbed -= umoney;
1824 if (eshkp->robbed < 0L)
1825 eshkp->robbed = 0L;
1826 if (umoney > 0)
1827 money2mon(shkp, umoney);
1828 context.botl = 1;
1829 pline("%s %s all your possessions.", shkname(shkp), takes);
1830 taken = TRUE;
1831 /* where to put player's invent (after disclosure) */
1832 set_repo_loc(shkp);
1833 } else {
1834 money2mon(shkp, loss);
1835 context.botl = 1;
1836 pline("%s %s the %ld %s %sowed %s.", Shknam(shkp),
1837 takes, loss, currency(loss),
1838 strncmp(eshkp->customer, plname, PL_NSIZ) ? "" : "you ",
1839 mhim(shkp));
1840 /* shopkeeper has now been paid in full */
1841 pacify_shk(shkp);
1842 eshkp->following = 0;
1843 eshkp->robbed = 0L;
1845 skip:
1846 /* in case we create bones */
1847 rouse_shk(shkp, FALSE); /* wake up */
1848 if (!inhishop(shkp))
1849 home_shk(shkp, FALSE);
1851 clear:
1852 shkp->minvis = save_minvis;
1853 setpaid(shkp);
1854 return taken;
1857 STATIC_OVL void
1858 set_repo_loc(shkp)
1859 struct monst *shkp;
1861 register xchar ox, oy;
1862 struct eshk *eshkp = ESHK(shkp);
1864 /* if you're not in this shk's shop room, or if you're in its doorway
1865 or entry spot, then your gear gets dumped all the way inside */
1866 if (*u.ushops != eshkp->shoproom || IS_DOOR(levl[u.ux][u.uy].typ)
1867 || (u.ux == eshkp->shk.x && u.uy == eshkp->shk.y)) {
1868 /* shk.x,shk.y is the position immediately in
1869 * front of the door -- move in one more space
1871 ox = eshkp->shk.x;
1872 oy = eshkp->shk.y;
1873 ox += sgn(ox - eshkp->shd.x);
1874 oy += sgn(oy - eshkp->shd.y);
1875 } else { /* already inside this shk's shop */
1876 ox = u.ux;
1877 oy = u.uy;
1879 /* finish_paybill will deposit invent here */
1880 repo.location.x = ox;
1881 repo.location.y = oy;
1882 repo.shopkeeper = shkp;
1885 /* called at game exit, after inventory disclosure but before making bones */
1886 void
1887 finish_paybill()
1889 struct monst *shkp = repo.shopkeeper;
1890 int ox = repo.location.x, oy = repo.location.y;
1892 #if 0 /* don't bother */
1893 if (ox == 0 && oy == 0)
1894 impossible("finish_paybill: no location");
1895 #endif
1896 /* normally done by savebones(), but that's too late in this case */
1897 unleash_all();
1898 /* if hero has any gold left, take it into shopkeeper's possession */
1899 if (shkp) {
1900 long umoney = money_cnt(invent);
1902 if (umoney)
1903 money2mon(shkp, umoney);
1905 /* transfer rest of the character's inventory to the shop floor */
1906 drop_upon_death((struct monst *) 0, (struct obj *) 0, ox, oy);
1909 /* find obj on one of the lists */
1910 STATIC_OVL struct obj *
1911 bp_to_obj(bp)
1912 register struct bill_x *bp;
1914 register struct obj *obj;
1915 register unsigned int id = bp->bo_id;
1917 if (bp->useup)
1918 obj = o_on(id, billobjs);
1919 else
1920 obj = find_oid(id);
1921 return obj;
1925 * Look for o_id on all lists but billobj. Return obj or NULL if not found.
1926 * Its OK for restore_timers() to call this function, there should not
1927 * be any timeouts on the billobjs chain.
1929 struct obj *
1930 find_oid(id)
1931 unsigned id;
1933 struct obj *obj;
1934 struct monst *mon, *mmtmp[3];
1935 int i;
1937 /* first check various obj lists directly */
1938 if ((obj = o_on(id, invent)) != 0)
1939 return obj;
1940 if ((obj = o_on(id, fobj)) != 0)
1941 return obj;
1942 if ((obj = o_on(id, level.buriedobjlist)) != 0)
1943 return obj;
1944 if ((obj = o_on(id, migrating_objs)) != 0)
1945 return obj;
1947 /* not found yet; check inventory for members of various monst lists */
1948 mmtmp[0] = fmon;
1949 mmtmp[1] = migrating_mons;
1950 mmtmp[2] = mydogs; /* for use during level changes */
1951 for (i = 0; i < 3; i++)
1952 for (mon = mmtmp[i]; mon; mon = mon->nmon)
1953 if ((obj = o_on(id, mon->minvent)) != 0)
1954 return obj;
1956 /* not found at all */
1957 return (struct obj *) 0;
1960 /* Returns the price of an arbitrary item in the shop.
1961 Returns 0 if the item doesn't belong to a shopkeeper. */
1962 long
1963 get_cost_of_shop_item(obj)
1964 register struct obj *obj;
1966 struct monst *shkp;
1967 xchar x, y;
1968 long cost = 0L;
1970 if (*u.ushops
1971 && obj->oclass != COIN_CLASS
1972 && obj != uball && obj != uchain
1973 && get_obj_location(obj, &x, &y, 0)
1974 && (obj->unpaid
1975 || (obj->where == OBJ_FLOOR
1976 && !obj->no_charge && costly_spot(x, y)))
1977 && (shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0
1978 && inhishop(shkp)) {
1979 cost = obj->quan * get_cost(obj, shkp);
1980 if (Has_contents(obj))
1981 cost += contained_cost(obj, shkp, 0L, FALSE, FALSE);
1983 return cost;
1986 /* calculate the value that the shk will charge for [one of] an object */
1987 STATIC_OVL long
1988 get_cost(obj, shkp)
1989 register struct obj *obj;
1990 register struct monst *shkp; /* if angry, impose a surcharge */
1992 long tmp = getprice(obj, FALSE),
1993 /* used to perform a single calculation even when multiple
1994 adjustments (unID'd, dunce/tourist, charisma) are made */
1995 multiplier = 1L, divisor = 1L;
1997 if (!tmp)
1998 tmp = 5L;
1999 /* shopkeeper may notice if the player isn't very knowledgeable -
2000 especially when gem prices are concerned */
2001 if (!obj->dknown || !objects[obj->otyp].oc_name_known) {
2002 if (obj->oclass == GEM_CLASS
2003 && objects[obj->otyp].oc_material == GLASS) {
2004 int i;
2005 /* get a value that's 'random' from game to game, but the
2006 same within the same game */
2007 boolean pseudorand =
2008 (((int) ubirthday % obj->otyp) >= obj->otyp / 2);
2010 /* all gems are priced high - real or not */
2011 switch (obj->otyp - LAST_GEM) {
2012 case 1: /* white */
2013 i = pseudorand ? DIAMOND : OPAL;
2014 break;
2015 case 2: /* blue */
2016 i = pseudorand ? SAPPHIRE : AQUAMARINE;
2017 break;
2018 case 3: /* red */
2019 i = pseudorand ? RUBY : JASPER;
2020 break;
2021 case 4: /* yellowish brown */
2022 i = pseudorand ? AMBER : TOPAZ;
2023 break;
2024 case 5: /* orange */
2025 i = pseudorand ? JACINTH : AGATE;
2026 break;
2027 case 6: /* yellow */
2028 i = pseudorand ? CITRINE : CHRYSOBERYL;
2029 break;
2030 case 7: /* black */
2031 i = pseudorand ? BLACK_OPAL : JET;
2032 break;
2033 case 8: /* green */
2034 i = pseudorand ? EMERALD : JADE;
2035 break;
2036 case 9: /* violet */
2037 i = pseudorand ? AMETHYST : FLUORITE;
2038 break;
2039 default:
2040 impossible("bad glass gem %d?", obj->otyp);
2041 i = STRANGE_OBJECT;
2042 break;
2044 tmp = (long) objects[i].oc_cost;
2045 } else if (!(obj->o_id % 4)) {
2046 /* unid'd, arbitrarily impose surcharge: tmp *= 4/3 */
2047 multiplier *= 4L;
2048 divisor *= 3L;
2051 if (uarmh && uarmh->otyp == DUNCE_CAP)
2052 multiplier *= 4L, divisor *= 3L;
2053 else if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV / 2))
2054 || (uarmu && !uarm && !uarmc)) /* touristy shirt visible */
2055 multiplier *= 4L, divisor *= 3L;
2057 if (ACURR(A_CHA) > 18)
2058 divisor *= 2L;
2059 else if (ACURR(A_CHA) == 18)
2060 multiplier *= 2L, divisor *= 3L;
2061 else if (ACURR(A_CHA) >= 16)
2062 multiplier *= 3L, divisor *= 4L;
2063 else if (ACURR(A_CHA) <= 5)
2064 multiplier *= 2L;
2065 else if (ACURR(A_CHA) <= 7)
2066 multiplier *= 3L, divisor *= 2L;
2067 else if (ACURR(A_CHA) <= 10)
2068 multiplier *= 4L, divisor *= 3L;
2070 /* tmp = (tmp * multiplier) / divisor [with roundoff tweak] */
2071 tmp *= multiplier;
2072 if (divisor > 1L) {
2073 /* tmp = (((tmp * 10) / divisor) + 5) / 10 */
2074 tmp *= 10L;
2075 tmp /= divisor;
2076 tmp += 5L;
2077 tmp /= 10L;
2080 if (tmp <= 0L)
2081 tmp = 1L;
2082 /* the artifact prices in artilist[] are also used as a score bonus;
2083 inflate their shop price here without affecting score calculation */
2084 if (obj->oartifact)
2085 tmp *= 4L;
2087 /* anger surcharge should match rile_shk's, so we do it separately
2088 from the multiplier/divisor calculation */
2089 if (shkp && ESHK(shkp)->surcharge)
2090 tmp += (tmp + 2L) / 3L;
2091 return tmp;
2094 /* returns the price of a container's content. the price
2095 * of the "top" container is added in the calling functions.
2096 * a different price quoted for selling as vs. buying.
2098 long
2099 contained_cost(obj, shkp, price, usell, unpaid_only)
2100 struct obj *obj;
2101 struct monst *shkp;
2102 long price;
2103 boolean usell;
2104 boolean unpaid_only;
2106 register struct obj *otmp;
2108 /* price of contained objects; "top" container handled by caller */
2109 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2110 if (otmp->oclass == COIN_CLASS)
2111 continue;
2113 if (usell) {
2114 if (saleable(shkp, otmp) && !otmp->unpaid
2115 && otmp->oclass != BALL_CLASS
2116 && !(otmp->oclass == FOOD_CLASS && otmp->oeaten)
2117 && !(Is_candle(otmp)
2118 && otmp->age < 20L * (long) objects[otmp->otyp].oc_cost))
2119 price += set_cost(otmp, shkp);
2120 } else if (!otmp->no_charge && (otmp->unpaid || !unpaid_only)) {
2121 price += get_cost(otmp, shkp) * otmp->quan;
2124 if (Has_contents(otmp))
2125 price = contained_cost(otmp, shkp, price, usell, unpaid_only);
2128 return price;
2131 long
2132 contained_gold(obj)
2133 register struct obj *obj;
2135 register struct obj *otmp;
2136 register long value = 0L;
2138 /* accumulate contained gold */
2139 for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
2140 if (otmp->oclass == COIN_CLASS)
2141 value += otmp->quan;
2142 else if (Has_contents(otmp))
2143 value += contained_gold(otmp);
2145 return value;
2148 STATIC_OVL void
2149 dropped_container(obj, shkp, sale)
2150 register struct obj *obj;
2151 register struct monst *shkp;
2152 register boolean sale;
2154 register struct obj *otmp;
2156 /* the "top" container is treated in the calling fn */
2157 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2158 if (otmp->oclass == COIN_CLASS)
2159 continue;
2161 if (!otmp->unpaid && !(sale && saleable(shkp, otmp)))
2162 otmp->no_charge = 1;
2164 if (Has_contents(otmp))
2165 dropped_container(otmp, shkp, sale);
2169 void
2170 picked_container(obj)
2171 register struct obj *obj;
2173 register struct obj *otmp;
2175 /* the "top" container is treated in the calling fn */
2176 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2177 if (otmp->oclass == COIN_CLASS)
2178 continue;
2180 if (otmp->no_charge)
2181 otmp->no_charge = 0;
2183 if (Has_contents(otmp))
2184 picked_container(otmp);
2188 STATIC_OVL boolean
2189 special_stock(obj, shkp, quietly)
2190 struct obj *obj;
2191 struct monst *shkp;
2192 boolean quietly;
2194 /* for unique situations */
2195 if (ESHK(shkp)->shoptype == CANDLESHOP
2196 && obj->otyp == CANDELABRUM_OF_INVOCATION) {
2197 if (!quietly) {
2198 if (is_izchak(shkp, TRUE) && !u.uevent.invoked) {
2199 if (Deaf || muteshk(shkp)) {
2200 pline("%s seems %s that you want to sell that.",
2201 Shknam(shkp),
2202 (obj->spe < 7) ? "horrified" : "concerned");
2203 } else {
2204 verbalize("No thanks, I'd hang onto that if I were you.");
2205 if (obj->spe < 7)
2206 verbalize(
2207 "You'll need %d%s candle%s to go along with it.",
2208 (7 - obj->spe), (obj->spe > 0) ? " more" : "",
2209 plur(7 - obj->spe));
2210 /* [what if hero is already carrying enough candles?
2211 should Izchak explain how to attach them instead?] */
2213 } else {
2214 if (!Deaf && !muteshk(shkp))
2215 verbalize("I won't stock that. Take it out of here!");
2216 else
2217 pline("%s shakes %s %s in refusal.",
2218 Shknam(shkp),
2219 mhis(shkp),
2220 mbodypart(shkp, HEAD));
2223 return TRUE;
2225 return FALSE;
2228 /* calculate how much the shk will pay when buying [all of] an object */
2229 STATIC_OVL long
2230 set_cost(obj, shkp)
2231 register struct obj *obj;
2232 register struct monst *shkp;
2234 long tmp = getprice(obj, TRUE) * obj->quan, multiplier = 1L, divisor = 1L;
2236 if (uarmh && uarmh->otyp == DUNCE_CAP)
2237 divisor *= 3L;
2238 else if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV / 2))
2239 || (uarmu && !uarm && !uarmc)) /* touristy shirt visible */
2240 divisor *= 3L;
2241 else
2242 divisor *= 2L;
2244 /* shopkeeper may notice if the player isn't very knowledgeable -
2245 especially when gem prices are concerned */
2246 if (!obj->dknown || !objects[obj->otyp].oc_name_known) {
2247 if (obj->oclass == GEM_CLASS) {
2248 /* different shop keepers give different prices */
2249 if (objects[obj->otyp].oc_material == GEMSTONE
2250 || objects[obj->otyp].oc_material == GLASS) {
2251 tmp = (obj->otyp % (6 - shkp->m_id % 3));
2252 tmp = (tmp + 3) * obj->quan;
2254 } else if (tmp > 1L && !(shkp->m_id % 4))
2255 multiplier *= 3L, divisor *= 4L;
2258 if (tmp >= 1L) {
2259 /* [see get_cost()] */
2260 tmp *= multiplier;
2261 if (divisor > 1L) {
2262 tmp *= 10L;
2263 tmp /= divisor;
2264 tmp += 5L;
2265 tmp /= 10L;
2267 /* avoid adjusting nonzero to zero */
2268 if (tmp < 1L)
2269 tmp = 1L;
2272 /* (no adjustment for angry shk here) */
2273 return tmp;
2276 /* called when an item's value has been enhanced; if it happens to be
2277 on any shop bill, update that bill to reflect the new higher price
2278 [if the new price drops for some reason, keep the old one in place] */
2279 void
2280 alter_cost(obj, amt)
2281 struct obj *obj;
2282 long amt; /* if 0, use regular shop pricing, otherwise force amount;
2283 if negative, use abs(amt) even if it's less than old cost */
2285 struct bill_x *bp = 0;
2286 struct monst *shkp;
2287 long new_price;
2289 for (shkp = next_shkp(fmon, TRUE); shkp; shkp = next_shkp(shkp, TRUE))
2290 if ((bp = onbill(obj, shkp, TRUE)) != 0) {
2291 new_price = !amt ? get_cost(obj, shkp) : (amt < 0L) ? -amt : amt;
2292 if (new_price > bp->price || amt < 0L) {
2293 bp->price = new_price;
2294 update_inventory();
2296 break; /* done */
2298 return;
2301 /* called from doinv(invent.c) for inventory of unpaid objects */
2302 long
2303 unpaid_cost(unp_obj, include_contents)
2304 struct obj *unp_obj; /* known to be unpaid or contain unpaid */
2305 boolean include_contents;
2307 struct bill_x *bp = (struct bill_x *) 0;
2308 struct monst *shkp;
2309 long amt = 0L;
2310 xchar ox, oy;
2312 if (!get_obj_location(unp_obj, &ox, &oy, BURIED_TOO | CONTAINED_TOO))
2313 ox = u.ux, oy = u.uy; /* (shouldn't happen) */
2314 if ((shkp = shop_keeper(*in_rooms(ox, oy, SHOPBASE))) != 0) {
2315 bp = onbill(unp_obj, shkp, TRUE);
2316 } else {
2317 /* didn't find shk? try searching bills */
2318 for (shkp = next_shkp(fmon, TRUE); shkp;
2319 shkp = next_shkp(shkp->nmon, TRUE))
2320 if ((bp = onbill(unp_obj, shkp, TRUE)) != 0)
2321 break;
2324 /* onbill() gave no message if unexpected problem occurred */
2325 if (!shkp || (unp_obj->unpaid && !bp)) {
2326 impossible("unpaid_cost: object wasn't on any bill.");
2327 } else {
2328 if (bp)
2329 amt = unp_obj->quan * bp->price;
2330 if (include_contents && Has_contents(unp_obj))
2331 amt = contained_cost(unp_obj, shkp, amt, FALSE, TRUE);
2333 return amt;
2336 STATIC_OVL void
2337 add_one_tobill(obj, dummy, shkp)
2338 struct obj *obj;
2339 boolean dummy;
2340 struct monst *shkp;
2342 struct eshk *eshkp;
2343 struct bill_x *bp;
2344 int bct;
2346 if (!billable(&shkp, obj, *u.ushops, TRUE))
2347 return;
2348 eshkp = ESHK(shkp);
2350 if (eshkp->billct == BILLSZ) {
2351 You("got that for free!");
2352 return;
2355 bct = eshkp->billct;
2356 bp = &(eshkp->bill_p[bct]);
2357 bp->bo_id = obj->o_id;
2358 bp->bquan = obj->quan;
2359 if (dummy) { /* a dummy object must be inserted into */
2360 bp->useup = 1; /* the billobjs chain here. crucial for */
2361 add_to_billobjs(obj); /* eating floorfood in shop. see eat.c */
2362 } else
2363 bp->useup = 0;
2364 bp->price = get_cost(obj, shkp);
2365 eshkp->billct++;
2366 obj->unpaid = 1;
2369 STATIC_OVL void
2370 add_to_billobjs(obj)
2371 struct obj *obj;
2373 if (obj->where != OBJ_FREE)
2374 panic("add_to_billobjs: obj not free");
2375 if (obj->timed)
2376 obj_stop_timers(obj);
2378 obj->nobj = billobjs;
2379 billobjs = obj;
2380 obj->where = OBJ_ONBILL;
2383 /* recursive billing of objects within containers. */
2384 STATIC_OVL void
2385 bill_box_content(obj, ininv, dummy, shkp)
2386 register struct obj *obj;
2387 register boolean ininv, dummy;
2388 register struct monst *shkp;
2390 register struct obj *otmp;
2392 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2393 if (otmp->oclass == COIN_CLASS)
2394 continue;
2396 /* the "top" box is added in addtobill() */
2397 if (!otmp->no_charge)
2398 add_one_tobill(otmp, dummy, shkp);
2399 if (Has_contents(otmp))
2400 bill_box_content(otmp, ininv, dummy, shkp);
2404 /* shopkeeper tells you what you bought or sold, sometimes partly IDing it */
2405 STATIC_OVL void
2406 shk_names_obj(shkp, obj, fmt, amt, arg)
2407 struct monst *shkp;
2408 struct obj *obj;
2409 const char *fmt; /* "%s %ld %s %s", doname(obj), amt, plur(amt), arg */
2410 long amt;
2411 const char *arg;
2413 char *obj_name, fmtbuf[BUFSZ];
2414 boolean was_unknown = !obj->dknown;
2416 obj->dknown = TRUE;
2417 /* Use real name for ordinary weapons/armor, and spell-less
2418 * scrolls/books (that is, blank and mail), but only if the
2419 * object is within the shk's area of interest/expertise.
2421 if (!objects[obj->otyp].oc_magic && saleable(shkp, obj)
2422 && (obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS
2423 || obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS
2424 || obj->otyp == MIRROR)) {
2425 was_unknown |= !objects[obj->otyp].oc_name_known;
2426 makeknown(obj->otyp);
2428 obj_name = doname(obj);
2429 /* Use an alternate message when extra information is being provided */
2430 if (was_unknown) {
2431 Sprintf(fmtbuf, "%%s; you %s", fmt);
2432 obj_name[0] = highc(obj_name[0]);
2433 pline(fmtbuf, obj_name, (obj->quan > 1L) ? "them" : "it", amt,
2434 plur(amt), arg);
2435 } else {
2436 You(fmt, obj_name, amt, plur(amt), arg);
2440 /* decide whether a shopkeeper thinks an item belongs to her */
2441 boolean
2442 billable(shkpp, obj, roomno, reset_nocharge)
2443 struct monst **shkpp; /* in: non-null if shk has been validated; out: shk */
2444 struct obj *obj;
2445 char roomno;
2446 boolean reset_nocharge;
2448 struct monst *shkp = *shkpp;
2450 /* if caller hasn't supplied a shopkeeper, look one up now */
2451 if (!shkp) {
2452 if (!roomno)
2453 return FALSE;
2454 shkp = shop_keeper(roomno);
2455 if (!shkp || !inhishop(shkp))
2456 return FALSE;
2457 *shkpp = shkp;
2459 /* perhaps we threw it away earlier */
2460 if (onbill(obj, shkp, FALSE)
2461 || (obj->oclass == FOOD_CLASS && obj->oeaten))
2462 return FALSE;
2463 /* outer container might be marked no_charge but still have contents
2464 which should be charged for; clear no_charge when picking things up */
2465 if (obj->no_charge) {
2466 if (!Has_contents(obj) || (contained_gold(obj) == 0L
2467 && contained_cost(obj, shkp, 0L, FALSE,
2468 !reset_nocharge) == 0L))
2469 shkp = 0; /* not billable */
2470 if (reset_nocharge && !shkp && obj->oclass != COIN_CLASS) {
2471 obj->no_charge = 0;
2472 if (Has_contents(obj))
2473 picked_container(obj); /* clear no_charge */
2476 return shkp ? TRUE : FALSE;
2479 void
2480 addtobill(obj, ininv, dummy, silent)
2481 struct obj *obj;
2482 boolean ininv, dummy, silent;
2484 struct monst *shkp = 0;
2485 long ltmp, cltmp, gltmp;
2486 int contentscount;
2487 boolean container;
2489 if (!billable(&shkp, obj, *u.ushops, TRUE))
2490 return;
2492 if (obj->oclass == COIN_CLASS) {
2493 costly_gold(obj->ox, obj->oy, obj->quan);
2494 return;
2495 } else if (ESHK(shkp)->billct == BILLSZ) {
2496 if (!silent)
2497 You("got that for free!");
2498 return;
2501 ltmp = cltmp = gltmp = 0L;
2502 container = Has_contents(obj);
2504 if (!obj->no_charge)
2505 ltmp = get_cost(obj, shkp);
2507 if (obj->no_charge && !container) {
2508 obj->no_charge = 0;
2509 return;
2512 if (container) {
2513 cltmp = contained_cost(obj, shkp, cltmp, FALSE, FALSE);
2514 gltmp = contained_gold(obj);
2516 if (ltmp)
2517 add_one_tobill(obj, dummy, shkp);
2518 if (cltmp)
2519 bill_box_content(obj, ininv, dummy, shkp);
2520 picked_container(obj); /* reset contained obj->no_charge */
2522 ltmp += cltmp;
2524 if (gltmp) {
2525 costly_gold(obj->ox, obj->oy, gltmp);
2526 if (!ltmp)
2527 return;
2530 if (obj->no_charge)
2531 obj->no_charge = 0;
2532 contentscount = count_unpaid(obj->cobj);
2533 } else { /* !container */
2534 add_one_tobill(obj, dummy, shkp);
2535 contentscount = 0;
2538 if (!Deaf && !muteshk(shkp) && !silent) {
2539 char buf[BUFSZ];
2541 if (!ltmp) {
2542 pline("%s has no interest in %s.", Shknam(shkp), the(xname(obj)));
2543 return;
2545 if (!ininv) {
2546 pline("%s will cost you %ld %s%s.", The(xname(obj)), ltmp,
2547 currency(ltmp), (obj->quan > 1L) ? " each" : "");
2548 } else {
2549 long save_quan = obj->quan;
2551 Strcpy(buf, "\"For you, ");
2552 if (ANGRY(shkp)) {
2553 Strcat(buf, "scum;");
2554 } else {
2555 append_honorific(buf);
2556 Strcat(buf, "; only");
2558 obj->quan = 1L; /* fool xname() into giving singular */
2559 pline("%s %ld %s %s %s%s.\"", buf, ltmp, currency(ltmp),
2560 (save_quan > 1L) ? "per" : (contentscount && !obj->unpaid)
2561 ? "for the contents of this"
2562 : "for this",
2563 xname(obj),
2564 (contentscount && obj->unpaid) ? and_its_contents : "");
2565 obj->quan = save_quan;
2567 } else if (!silent) {
2568 if (ltmp)
2569 pline_The("list price of %s%s%s is %ld %s%s.",
2570 (contentscount && !obj->unpaid) ? the_contents_of : "",
2571 the(xname(obj)),
2572 (contentscount && obj->unpaid) ? and_its_contents : "",
2573 ltmp, currency(ltmp), (obj->quan > 1L) ? " each" : "");
2574 else
2575 pline("%s does not notice.", Shknam(shkp));
2579 void
2580 append_honorific(buf)
2581 char *buf;
2583 /* (chooses among [0]..[3] normally; [1]..[4] after the
2584 Wizard has been killed or invocation ritual performed) */
2585 static const char *const honored[] = { "good", "honored", "most gracious",
2586 "esteemed",
2587 "most renowned and sacred" };
2588 Strcat(buf, honored[rn2(SIZE(honored) - 1) + u.uevent.udemigod]);
2589 if (is_vampire(youmonst.data))
2590 Strcat(buf, (flags.female) ? " dark lady" : " dark lord");
2591 else if (is_elf(youmonst.data))
2592 Strcat(buf, (flags.female) ? " hiril" : " hir");
2593 else
2594 Strcat(buf, !is_human(youmonst.data) ? " creature" : (flags.female)
2595 ? " lady"
2596 : " sir");
2599 void
2600 splitbill(obj, otmp)
2601 register struct obj *obj, *otmp;
2603 /* otmp has been split off from obj */
2604 register struct bill_x *bp;
2605 register long tmp;
2606 register struct monst *shkp = shop_keeper(*u.ushops);
2608 if (!shkp || !inhishop(shkp)) {
2609 impossible("splitbill: no resident shopkeeper??");
2610 return;
2612 bp = onbill(obj, shkp, FALSE);
2613 if (!bp) {
2614 impossible("splitbill: not on bill?");
2615 return;
2617 if (bp->bquan < otmp->quan) {
2618 impossible("Negative quantity on bill??");
2620 if (bp->bquan == otmp->quan) {
2621 impossible("Zero quantity on bill??");
2623 bp->bquan -= otmp->quan;
2625 if (ESHK(shkp)->billct == BILLSZ)
2626 otmp->unpaid = 0;
2627 else {
2628 tmp = bp->price;
2629 bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
2630 bp->bo_id = otmp->o_id;
2631 bp->bquan = otmp->quan;
2632 bp->useup = 0;
2633 bp->price = tmp;
2634 ESHK(shkp)->billct++;
2638 STATIC_OVL void
2639 sub_one_frombill(obj, shkp)
2640 register struct obj *obj;
2641 register struct monst *shkp;
2643 register struct bill_x *bp;
2645 if ((bp = onbill(obj, shkp, FALSE)) != 0) {
2646 register struct obj *otmp;
2648 obj->unpaid = 0;
2649 if (bp->bquan > obj->quan) {
2650 otmp = newobj();
2651 *otmp = *obj;
2652 otmp->oextra = (struct oextra *) 0;
2653 bp->bo_id = otmp->o_id = context.ident++;
2654 otmp->where = OBJ_FREE;
2655 otmp->quan = (bp->bquan -= obj->quan);
2656 otmp->owt = 0; /* superfluous */
2657 bp->useup = 1;
2658 add_to_billobjs(otmp);
2659 return;
2661 ESHK(shkp)->billct--;
2662 #ifdef DUMB
2664 /* DRS/NS 2.2.6 messes up -- Peter Kendell */
2665 int indx = ESHK(shkp)->billct;
2667 *bp = ESHK(shkp)->bill_p[indx];
2669 #else
2670 *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
2671 #endif
2672 return;
2673 } else if (obj->unpaid) {
2674 impossible("sub_one_frombill: unpaid object not on bill");
2675 obj->unpaid = 0;
2679 /* recursive check of unpaid objects within nested containers. */
2680 void
2681 subfrombill(obj, shkp)
2682 register struct obj *obj;
2683 register struct monst *shkp;
2685 register struct obj *otmp;
2687 sub_one_frombill(obj, shkp);
2689 if (Has_contents(obj))
2690 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2691 if (otmp->oclass == COIN_CLASS)
2692 continue;
2694 if (Has_contents(otmp))
2695 subfrombill(otmp, shkp);
2696 else
2697 sub_one_frombill(otmp, shkp);
2701 STATIC_OVL long
2702 stolen_container(obj, shkp, price, ininv)
2703 struct obj *obj;
2704 struct monst *shkp;
2705 long price;
2706 boolean ininv;
2708 struct obj *otmp;
2709 struct bill_x *bp;
2710 long billamt;
2712 /* the price of contained objects; caller handles top container */
2713 for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2714 if (otmp->oclass == COIN_CLASS)
2715 continue;
2716 billamt = 0L;
2717 if (!billable(&shkp, otmp, ESHK(shkp)->shoproom, TRUE)) {
2718 /* billable() returns false for objects already on bill */
2719 if ((bp = onbill(otmp, shkp, FALSE)) == 0)
2720 continue;
2721 /* this assumes that we're being called by stolen_value()
2722 (or by a recursive call to self on behalf of it) where
2723 the cost of this object is about to be added to shop
2724 debt in place of having it remain on the current bill */
2725 billamt = bp->bquan * bp->price;
2726 sub_one_frombill(otmp, shkp); /* avoid double billing */
2729 if (billamt)
2730 price += billamt;
2731 else if (ininv ? otmp->unpaid : !otmp->no_charge)
2732 price += otmp->quan * get_cost(otmp, shkp);
2734 if (Has_contents(otmp))
2735 price = stolen_container(otmp, shkp, price, ininv);
2738 return price;
2741 long
2742 stolen_value(obj, x, y, peaceful, silent)
2743 struct obj *obj;
2744 xchar x, y;
2745 boolean peaceful, silent;
2747 long value = 0L, gvalue = 0L, billamt = 0L;
2748 char roomno = *in_rooms(x, y, SHOPBASE);
2749 struct bill_x *bp;
2750 struct monst *shkp = 0;
2752 if (!billable(&shkp, obj, roomno, FALSE)) {
2753 /* things already on the bill yield a not-billable result, so
2754 we need to check bill before deciding that shk doesn't care */
2755 if ((bp = onbill(obj, shkp, FALSE)) == 0)
2756 return 0L;
2757 /* shk does care; take obj off bill to avoid double billing */
2758 billamt = bp->bquan * bp->price;
2759 sub_one_frombill(obj, shkp);
2762 if (obj->oclass == COIN_CLASS) {
2763 gvalue += obj->quan;
2764 } else {
2765 if (billamt)
2766 value += billamt;
2767 else if (!obj->no_charge)
2768 value += obj->quan * get_cost(obj, shkp);
2770 if (Has_contents(obj)) {
2771 boolean ininv =
2772 (obj->where == OBJ_INVENT || obj->where == OBJ_FREE);
2774 value += stolen_container(obj, shkp, 0L, ininv);
2775 if (!ininv)
2776 gvalue += contained_gold(obj);
2780 if (gvalue + value == 0L)
2781 return 0L;
2783 value += gvalue;
2785 if (peaceful) {
2786 boolean credit_use = !!ESHK(shkp)->credit;
2787 value = check_credit(value, shkp);
2788 /* 'peaceful' affects general treatment, but doesn't affect
2789 * the fact that other code expects that all charges after the
2790 * shopkeeper is angry are included in robbed, not debit */
2791 if (ANGRY(shkp))
2792 ESHK(shkp)->robbed += value;
2793 else
2794 ESHK(shkp)->debit += value;
2796 if (!silent) {
2797 const char *still = "";
2799 if (credit_use) {
2800 if (ESHK(shkp)->credit) {
2801 You("have %ld %s credit remaining.", ESHK(shkp)->credit,
2802 currency(ESHK(shkp)->credit));
2803 return value;
2804 } else if (!value) {
2805 You("have no credit remaining.");
2806 return 0;
2808 still = "still ";
2810 if (obj->oclass == COIN_CLASS)
2811 You("%sowe %s %ld %s!", still, shkname(shkp), value,
2812 currency(value));
2813 else
2814 You("%sowe %s %ld %s for %s!", still, shkname(shkp),
2815 value, currency(value), (obj->quan > 1L) ? "them" : "it");
2817 } else {
2818 ESHK(shkp)->robbed += value;
2820 if (!silent) {
2821 if (canseemon(shkp)) {
2822 Norep("%s booms: \"%s, you are a thief!\"",
2823 Shknam(shkp), plname);
2824 } else
2825 Norep("You hear a scream, \"Thief!\"");
2827 hot_pursuit(shkp);
2828 (void) angry_guards(FALSE);
2830 return value;
2833 /* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */
2834 static char sell_response = 'a';
2835 static int sell_how = SELL_NORMAL;
2836 /* can't just use sell_response='y' for auto_credit because the 'a' response
2837 shouldn't carry over from ordinary selling to credit selling */
2838 static boolean auto_credit = FALSE;
2840 void
2841 sellobj_state(deliberate)
2842 int deliberate;
2844 /* If we're deliberately dropping something, there's no automatic
2845 response to the shopkeeper's "want to sell" query; however, if we
2846 accidentally drop anything, the shk will buy it/them without asking.
2847 This retains the old pre-query risk that slippery fingers while in
2848 shops entailed: you drop it, you've lost it.
2850 sell_response = (deliberate != SELL_NORMAL) ? '\0' : 'a';
2851 sell_how = deliberate;
2852 auto_credit = FALSE;
2855 void
2856 sellobj(obj, x, y)
2857 register struct obj *obj;
2858 xchar x, y;
2860 register struct monst *shkp;
2861 register struct eshk *eshkp;
2862 long ltmp = 0L, cltmp = 0L, gltmp = 0L, offer, shkmoney;
2863 boolean saleitem, cgold = FALSE, container = Has_contents(obj);
2864 boolean isgold = (obj->oclass == COIN_CLASS);
2865 boolean only_partially_your_contents = FALSE;
2867 if (!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
2868 return;
2869 if (!costly_spot(x, y))
2870 return;
2871 if (!*u.ushops)
2872 return;
2874 if (obj->unpaid && !container && !isgold) {
2875 sub_one_frombill(obj, shkp);
2876 return;
2878 if (container) {
2879 /* find the price of content before subfrombill */
2880 cltmp = contained_cost(obj, shkp, cltmp, TRUE, FALSE);
2881 /* find the value of contained gold */
2882 gltmp += contained_gold(obj);
2883 cgold = (gltmp > 0L);
2886 saleitem = saleable(shkp, obj);
2887 if (!isgold && !obj->unpaid && saleitem)
2888 ltmp = set_cost(obj, shkp);
2890 offer = ltmp + cltmp;
2892 /* get one case out of the way: nothing to sell, and no gold */
2893 if (!(isgold || cgold)
2894 && ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) {
2895 boolean unpaid = is_unpaid(obj);
2897 if (container) {
2898 dropped_container(obj, shkp, FALSE);
2899 if (!obj->unpaid)
2900 obj->no_charge = 1;
2901 if (unpaid)
2902 subfrombill(obj, shkp);
2903 } else
2904 obj->no_charge = 1;
2906 if (!unpaid && (sell_how != SELL_DONTSELL)
2907 && !special_stock(obj, shkp, FALSE))
2908 pline("%s seems uninterested.", Shknam(shkp));
2909 return;
2912 /* you dropped something of your own - probably want to sell it */
2913 rouse_shk(shkp, TRUE); /* wake up sleeping or paralyzed shk */
2914 eshkp = ESHK(shkp);
2916 if (ANGRY(shkp)) { /* they become shop-objects, no pay */
2917 if (!Deaf && !muteshk(shkp))
2918 verbalize("Thank you, scum!");
2919 else
2920 pline("%s smirks with satisfaction.", Shknam(shkp));
2921 subfrombill(obj, shkp);
2922 return;
2925 if (eshkp->robbed) { /* shkp is not angry? */
2926 if (isgold)
2927 offer = obj->quan;
2928 else if (cgold)
2929 offer += cgold;
2930 if ((eshkp->robbed -= offer < 0L))
2931 eshkp->robbed = 0L;
2932 if (offer && !Deaf && !muteshk(shkp))
2933 verbalize(
2934 "Thank you for your contribution to restock this recently plundered shop.");
2935 subfrombill(obj, shkp);
2936 return;
2939 if (isgold || cgold) {
2940 if (!cgold)
2941 gltmp = obj->quan;
2943 if (eshkp->debit >= gltmp) {
2944 if (eshkp->loan) { /* you carry shop's gold */
2945 if (eshkp->loan >= gltmp)
2946 eshkp->loan -= gltmp;
2947 else
2948 eshkp->loan = 0L;
2950 eshkp->debit -= gltmp;
2951 Your("debt is %spaid off.", eshkp->debit ? "partially " : "");
2952 } else {
2953 long delta = gltmp - eshkp->debit;
2955 eshkp->credit += delta;
2956 if (eshkp->debit) {
2957 eshkp->debit = 0L;
2958 eshkp->loan = 0L;
2959 Your("debt is paid off.");
2961 if (eshkp->credit == delta)
2962 You("have established %ld %s credit.", delta,
2963 currency(delta));
2964 else
2965 pline("%ld %s added to your credit; total is now %ld %s.",
2966 delta, currency(delta), eshkp->credit,
2967 currency(eshkp->credit));
2970 if (!offer || sell_how == SELL_DONTSELL) {
2971 if (!isgold) {
2972 if (container)
2973 dropped_container(obj, shkp, FALSE);
2974 if (!obj->unpaid)
2975 obj->no_charge = 1;
2976 subfrombill(obj, shkp);
2978 return;
2982 if ((!saleitem && !(container && cltmp > 0L)) || eshkp->billct == BILLSZ
2983 || obj->oclass == BALL_CLASS || obj->oclass == CHAIN_CLASS
2984 || offer == 0L || (obj->oclass == FOOD_CLASS && obj->oeaten)
2985 || (Is_candle(obj)
2986 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)) {
2987 pline("%s seems uninterested%s.", Shknam(shkp),
2988 cgold ? " in the rest" : "");
2989 if (container)
2990 dropped_container(obj, shkp, FALSE);
2991 obj->no_charge = 1;
2992 return;
2995 shkmoney = money_cnt(shkp->minvent);
2996 if (!shkmoney) {
2997 char c, qbuf[BUFSZ];
2998 long tmpcr = ((offer * 9L) / 10L) + (offer <= 1L);
3000 if (sell_how == SELL_NORMAL || auto_credit) {
3001 c = sell_response = 'y';
3002 } else if (sell_response != 'n') {
3003 pline("%s cannot pay you at present.", shkname(shkp));
3004 Sprintf(qbuf, "Will you accept %ld %s in credit for ", tmpcr,
3005 currency(tmpcr));
3006 c = ynaq(safe_qbuf(qbuf, qbuf, "?", obj, doname, thesimpleoname,
3007 (obj->quan == 1L) ? "that" : "those"));
3008 if (c == 'a') {
3009 c = 'y';
3010 auto_credit = TRUE;
3012 } else /* previously specified "quit" */
3013 c = 'n';
3015 if (c == 'y') {
3016 shk_names_obj(
3017 shkp, obj,
3018 (sell_how != SELL_NORMAL)
3019 ? "traded %s for %ld zorkmid%s in %scredit."
3020 : "relinquish %s and acquire %ld zorkmid%s in %scredit.",
3021 tmpcr, (eshkp->credit > 0L) ? "additional " : "");
3022 eshkp->credit += tmpcr;
3023 subfrombill(obj, shkp);
3024 } else {
3025 if (c == 'q')
3026 sell_response = 'n';
3027 if (container)
3028 dropped_container(obj, shkp, FALSE);
3029 if (!obj->unpaid)
3030 obj->no_charge = 1;
3031 subfrombill(obj, shkp);
3033 } else {
3034 char qbuf[BUFSZ], qsfx[BUFSZ];
3035 boolean short_funds = (offer > shkmoney), one;
3037 if (short_funds)
3038 offer = shkmoney;
3039 if (!sell_response) {
3040 long yourc = 0L, shksc;
3042 if (container) {
3043 /* number of items owned by shk */
3044 shksc = count_contents(obj, TRUE, TRUE, FALSE);
3045 /* number of items owned by you (total - shksc) */
3046 yourc = count_contents(obj, TRUE, TRUE, TRUE) - shksc;
3047 only_partially_your_contents = shksc && yourc;
3050 "<shk> offers * for ..." query formatting.
3051 Normal item(s):
3052 "... your <object>. Sell it?"
3053 "... your <objects>. Sell them?"
3054 A container is either owned by the hero, or already
3055 owned by the shk (!ltmp), or the shk isn't interested
3056 in buying it (also !ltmp). It's either empty (!cltmp)
3057 or it has contents owned by the hero or it has some
3058 contents owned by the hero and others by the shk.
3059 (The case where it has contents already entirely owned
3060 by the shk is treated the same was if it were empty
3061 since the hero isn't selling any of those contents.)
3062 Your container:
3063 "... your <empty bag>. Sell it?"
3064 "... your <bag> and its contents. Sell them?"
3065 "... your <bag> and item inside. Sell them?"
3066 "... your <bag> and items inside. Sell them?"
3067 Shk's container:
3068 "... your item in the <bag>. Sell it?"
3069 "... your items in the <bag>. Sell them?"
3071 Sprintf(qbuf, "%s offers%s %ld gold piece%s for %s%s ",
3072 shkname(shkp), short_funds ? " only" : "", offer,
3073 plur(offer),
3074 (cltmp && !ltmp)
3075 ? ((yourc == 1L) ? "your item in " : "your items in ")
3076 : "",
3077 obj->unpaid ? "the" : "your");
3078 one = obj->unpaid ? (yourc == 1L) : (obj->quan == 1L && !cltmp);
3079 Sprintf(qsfx, "%s. Sell %s?",
3080 (cltmp && ltmp)
3081 ? (only_partially_your_contents
3082 ? ((yourc == 1L) ? " and item inside"
3083 : " and items inside")
3084 : and_its_contents)
3085 : "",
3086 one ? "it" : "them");
3087 (void) safe_qbuf(qbuf, qbuf, qsfx, obj, xname, simpleonames,
3088 one ? "that" : "those");
3089 } else
3090 qbuf[0] = '\0'; /* just to pacify lint */
3092 switch (sell_response ? sell_response : ynaq(qbuf)) {
3093 case 'q':
3094 sell_response = 'n';
3095 case 'n':
3096 if (container)
3097 dropped_container(obj, shkp, FALSE);
3098 if (!obj->unpaid)
3099 obj->no_charge = 1;
3100 subfrombill(obj, shkp);
3101 break;
3102 case 'a':
3103 sell_response = 'y';
3104 case 'y':
3105 if (container)
3106 dropped_container(obj, shkp, TRUE);
3107 if (!obj->unpaid && !saleitem)
3108 obj->no_charge = 1;
3109 subfrombill(obj, shkp);
3110 pay(-offer, shkp);
3111 shk_names_obj(shkp, obj,
3112 (sell_how != SELL_NORMAL)
3113 ? ((!ltmp && cltmp && only_partially_your_contents)
3114 ? "sold some items inside %s for %ld gold piece%s.%s"
3115 : "sold %s for %ld gold piece%s.%s")
3116 : "relinquish %s and receive %ld gold piece%s in compensation.%s",
3117 offer, "");
3118 break;
3119 default:
3120 impossible("invalid sell response");
3126 doinvbill(mode)
3127 int mode; /* 0: deliver count 1: paged */
3129 #ifdef __SASC
3130 void sasc_bug(struct obj *, unsigned);
3131 #endif
3132 struct monst *shkp;
3133 struct eshk *eshkp;
3134 struct bill_x *bp, *end_bp;
3135 struct obj *obj;
3136 long totused;
3137 char *buf_p;
3138 winid datawin;
3140 shkp = shop_keeper(*u.ushops);
3141 if (!shkp || !inhishop(shkp)) {
3142 if (mode != 0)
3143 impossible("doinvbill: no shopkeeper?");
3144 return 0;
3146 eshkp = ESHK(shkp);
3148 if (mode == 0) {
3149 /* count expended items, so that the `I' command can decide
3150 whether to include 'x' in its prompt string */
3151 int cnt = !eshkp->debit ? 0 : 1;
3153 for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct];
3154 bp < end_bp; bp++)
3155 if (bp->useup
3156 || ((obj = bp_to_obj(bp)) != 0 && obj->quan < bp->bquan))
3157 cnt++;
3158 return cnt;
3161 datawin = create_nhwindow(NHW_MENU);
3162 putstr(datawin, 0, "Unpaid articles already used up:");
3163 putstr(datawin, 0, "");
3165 totused = 0L;
3166 for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct];
3167 bp < end_bp; bp++) {
3168 obj = bp_to_obj(bp);
3169 if (!obj) {
3170 impossible("Bad shopkeeper administration.");
3171 goto quit;
3173 if (bp->useup || bp->bquan > obj->quan) {
3174 long oquan, uquan, thisused;
3176 oquan = obj->quan;
3177 uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
3178 thisused = bp->price * uquan;
3179 totused += thisused;
3180 iflags.suppress_price++; /* suppress "(unpaid)" suffix */
3181 /* Why 'x'? To match `I x', more or less. */
3182 buf_p = xprname(obj, (char *) 0, 'x', FALSE, thisused, uquan);
3183 iflags.suppress_price--;
3184 putstr(datawin, 0, buf_p);
3187 if (eshkp->debit) {
3188 /* additional shop debt which has no itemization available */
3189 if (totused)
3190 putstr(datawin, 0, "");
3191 totused += eshkp->debit;
3192 buf_p = xprname((struct obj *) 0, "usage charges and/or other fees",
3193 GOLD_SYM, FALSE, eshkp->debit, 0L);
3194 putstr(datawin, 0, buf_p);
3196 buf_p = xprname((struct obj *) 0, "Total:", '*', FALSE, totused, 0L);
3197 putstr(datawin, 0, "");
3198 putstr(datawin, 0, buf_p);
3199 display_nhwindow(datawin, FALSE);
3200 quit:
3201 destroy_nhwindow(datawin);
3202 return 0;
3205 STATIC_OVL long
3206 getprice(obj, shk_buying)
3207 register struct obj *obj;
3208 boolean shk_buying;
3210 register long tmp = (long) objects[obj->otyp].oc_cost;
3212 if (obj->oartifact) {
3213 tmp = arti_cost(obj);
3214 if (shk_buying)
3215 tmp /= 4;
3217 switch (obj->oclass) {
3218 case FOOD_CLASS:
3219 /* simpler hunger check, (2-4)*cost */
3220 if (u.uhs >= HUNGRY && !shk_buying)
3221 tmp *= (long) u.uhs;
3222 if (obj->oeaten)
3223 tmp = 0L;
3224 break;
3225 case WAND_CLASS:
3226 if (obj->spe == -1)
3227 tmp = 0L;
3228 break;
3229 case POTION_CLASS:
3230 if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
3231 tmp = 0L;
3232 break;
3233 case ARMOR_CLASS:
3234 case WEAPON_CLASS:
3235 if (obj->spe > 0)
3236 tmp += 10L * (long) obj->spe;
3237 break;
3238 case TOOL_CLASS:
3239 if (Is_candle(obj)
3240 && obj->age < 20L * (long) objects[obj->otyp].oc_cost)
3241 tmp /= 2L;
3242 break;
3244 return tmp;
3247 /* shk catches thrown pick-axe */
3248 struct monst *
3249 shkcatch(obj, x, y)
3250 register struct obj *obj;
3251 register xchar x, y;
3253 register struct monst *shkp;
3255 if (!(shkp = shop_keeper(inside_shop(x, y))) || !inhishop(shkp))
3256 return 0;
3258 if (shkp->mcanmove && !shkp->msleeping
3259 && (*u.ushops != ESHK(shkp)->shoproom || !inside_shop(u.ux, u.uy))
3260 && dist2(shkp->mx, shkp->my, x, y) < 3
3261 /* if it is the shk's pos, you hit and anger him */
3262 && (shkp->mx != x || shkp->my != y)) {
3263 if (mnearto(shkp, x, y, TRUE) && !Deaf && !muteshk(shkp))
3264 verbalize("Out of my way, scum!");
3265 if (cansee(x, y)) {
3266 pline("%s nimbly%s catches %s.", Shknam(shkp),
3267 (x == shkp->mx && y == shkp->my) ? "" : " reaches over and",
3268 the(xname(obj)));
3269 if (!canspotmon(shkp))
3270 map_invisible(x, y);
3271 delay_output();
3272 mark_synch();
3274 subfrombill(obj, shkp);
3275 (void) mpickobj(shkp, obj);
3276 return shkp;
3278 return (struct monst *) 0;
3281 void
3282 add_damage(x, y, cost)
3283 register xchar x, y;
3284 long cost;
3286 struct damage *tmp_dam;
3287 char *shops;
3289 if (IS_DOOR(levl[x][y].typ)) {
3290 struct monst *mtmp;
3292 /* Don't schedule for repair unless it's a real shop entrance */
3293 for (shops = in_rooms(x, y, SHOPBASE); *shops; shops++)
3294 if ((mtmp = shop_keeper(*shops)) != 0 && x == ESHK(mtmp)->shd.x
3295 && y == ESHK(mtmp)->shd.y)
3296 break;
3297 if (!*shops)
3298 return;
3300 for (tmp_dam = level.damagelist; tmp_dam; tmp_dam = tmp_dam->next)
3301 if (tmp_dam->place.x == x && tmp_dam->place.y == y) {
3302 tmp_dam->cost += cost;
3303 return;
3305 tmp_dam = (struct damage *) alloc((unsigned) sizeof(struct damage));
3306 tmp_dam->when = monstermoves;
3307 tmp_dam->place.x = x;
3308 tmp_dam->place.y = y;
3309 tmp_dam->cost = cost;
3310 tmp_dam->typ = levl[x][y].typ;
3311 tmp_dam->next = level.damagelist;
3312 level.damagelist = tmp_dam;
3313 /* If player saw damage, display as a wall forever */
3314 if (cansee(x, y))
3315 levl[x][y].seenv = SVALL;
3319 * Do something about damage. Either (!croaked) try to repair it, or
3320 * (croaked) just discard damage structs for non-shared locations, since
3321 * they'll never get repaired. Assume that shared locations will get
3322 * repaired eventually by the other shopkeeper(s). This might be an erroneous
3323 * assumption (they might all be dead too), but we have no reasonable way of
3324 * telling that.
3326 STATIC_OVL
3327 void
3328 remove_damage(shkp, croaked)
3329 struct monst *shkp;
3330 boolean croaked;
3332 struct damage *tmp_dam, *tmp2_dam;
3333 boolean did_repair = FALSE, saw_door = FALSE, saw_floor = FALSE,
3334 stop_picking = FALSE, doorway_trap = FALSE;
3335 int saw_walls = 0, saw_untrap = 0;
3336 char trapmsg[BUFSZ];
3338 tmp_dam = level.damagelist;
3339 tmp2_dam = 0;
3340 while (tmp_dam) {
3341 register xchar x = tmp_dam->place.x, y = tmp_dam->place.y;
3342 char shops[5];
3343 int disposition;
3344 unsigned old_doormask = 0;
3346 disposition = 0;
3347 Strcpy(shops, in_rooms(x, y, SHOPBASE));
3348 if (index(shops, ESHK(shkp)->shoproom)) {
3349 if (IS_DOOR(levl[x][y].typ))
3350 old_doormask = levl[x][y].doormask;
3352 if (croaked)
3353 disposition = (shops[1]) ? 0 : 1;
3354 else if (stop_picking)
3355 disposition = repair_damage(shkp, tmp_dam, FALSE);
3356 else {
3357 /* Defer the stop_occupation() until after repair msgs */
3358 if (closed_door(x, y))
3359 stop_picking = picking_at(x, y);
3360 disposition = repair_damage(shkp, tmp_dam, FALSE);
3361 if (!disposition)
3362 stop_picking = FALSE;
3366 if (!disposition) {
3367 tmp2_dam = tmp_dam;
3368 tmp_dam = tmp_dam->next;
3369 continue;
3372 if (disposition > 1) {
3373 did_repair = TRUE;
3374 if (cansee(x, y)) {
3375 if (IS_WALL(levl[x][y].typ)) {
3376 saw_walls++;
3377 } else if (IS_DOOR(levl[x][y].typ)
3378 /* an existing door here implies trap removal */
3379 && !(old_doormask & (D_ISOPEN | D_CLOSED))) {
3380 saw_door = TRUE;
3381 } else if (disposition == 3) { /* untrapped */
3382 saw_untrap++;
3383 if (IS_DOOR(levl[x][y].typ))
3384 doorway_trap = TRUE;
3385 } else {
3386 saw_floor = TRUE;
3391 tmp_dam = tmp_dam->next;
3392 if (!tmp2_dam) {
3393 free((genericptr_t) level.damagelist);
3394 level.damagelist = tmp_dam;
3395 } else {
3396 free((genericptr_t) tmp2_dam->next);
3397 tmp2_dam->next = tmp_dam;
3400 if (!did_repair)
3401 return;
3403 if (saw_untrap) {
3404 Sprintf(trapmsg, "%s trap%s",
3405 (saw_untrap > 3) ? "several" : (saw_untrap > 1) ? "some"
3406 : "a",
3407 plur(saw_untrap));
3408 Sprintf(eos(trapmsg), " %s", vtense(trapmsg, "are"));
3409 Sprintf(eos(trapmsg), " removed from the %s",
3410 (doorway_trap && saw_untrap == 1) ? "doorway" : "floor");
3411 } else
3412 trapmsg[0] = '\0'; /* not just lint suppression... */
3414 if (saw_walls) {
3415 char wallbuf[BUFSZ];
3417 Sprintf(wallbuf, "section%s", plur(saw_walls));
3418 pline("Suddenly, %s %s of wall %s up!",
3419 (saw_walls == 1) ? "a" : (saw_walls <= 3) ? "some" : "several",
3420 wallbuf, vtense(wallbuf, "close"));
3422 if (saw_door)
3423 pline_The("shop door reappears!");
3424 if (saw_floor)
3425 pline_The("floor is repaired!");
3426 if (saw_untrap)
3427 pline("%s!", upstart(trapmsg));
3428 } else {
3429 if (saw_door || saw_floor || saw_untrap)
3430 pline("Suddenly, %s%s%s%s%s!",
3431 saw_door ? "the shop door reappears" : "",
3432 (saw_door && saw_floor) ? " and " : "",
3433 saw_floor ? "the floor damage is gone" : "",
3434 ((saw_door || saw_floor) && *trapmsg) ? " and " : "",
3435 trapmsg);
3436 else if (inside_shop(u.ux, u.uy) == ESHK(shkp)->shoproom)
3437 You_feel("more claustrophobic than before.");
3438 else if (!Deaf && !rn2(10))
3439 Norep("The dungeon acoustics noticeably change.");
3441 if (stop_picking)
3442 stop_occupation();
3446 * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
3447 * 3: untrap
3450 repair_damage(shkp, tmp_dam, catchup)
3451 register struct monst *shkp;
3452 register struct damage *tmp_dam;
3453 boolean catchup; /* restoring a level */
3455 register xchar x, y, i;
3456 xchar litter[9];
3457 register struct monst *mtmp;
3458 register struct obj *otmp;
3459 register struct trap *ttmp;
3461 if ((monstermoves - tmp_dam->when) < REPAIR_DELAY)
3462 return 0;
3463 if (shkp->msleeping || !shkp->mcanmove || ESHK(shkp)->following)
3464 return 0;
3465 x = tmp_dam->place.x;
3466 y = tmp_dam->place.y;
3467 if (!IS_ROOM(tmp_dam->typ)) {
3468 if (x == u.ux && y == u.uy)
3469 if (!Passes_walls)
3470 return 0;
3471 if (x == shkp->mx && y == shkp->my)
3472 return 0;
3473 if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data)))
3474 return 0;
3476 if ((ttmp = t_at(x, y)) != 0) {
3477 if (x == u.ux && y == u.uy)
3478 if (!Passes_walls)
3479 return 0;
3480 if (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP) {
3481 /* convert to an object */
3482 otmp = mksobj((ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP,
3483 TRUE, FALSE);
3484 otmp->quan = 1L;
3485 otmp->owt = weight(otmp);
3486 (void) mpickobj(shkp, otmp);
3488 deltrap(ttmp);
3489 if (IS_DOOR(tmp_dam->typ) && !(levl[x][y].doormask & D_ISOPEN)) {
3490 levl[x][y].doormask = D_CLOSED;
3491 block_point(x, y);
3492 } else if (IS_WALL(tmp_dam->typ)) {
3493 levl[x][y].typ = tmp_dam->typ;
3494 block_point(x, y);
3496 newsym(x, y);
3497 return 3;
3499 if (IS_ROOM(tmp_dam->typ)) {
3500 /* No messages, because player already filled trap door */
3501 return 1;
3503 if ((tmp_dam->typ == levl[x][y].typ)
3504 && (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN)))
3505 /* No messages if player already replaced shop door */
3506 return 1;
3507 levl[x][y].typ = tmp_dam->typ;
3508 (void) memset((genericptr_t) litter, 0, sizeof(litter));
3509 if ((otmp = level.objects[x][y]) != 0) {
3510 /* Scatter objects haphazardly into the shop */
3511 #define NEED_UPDATE 1
3512 #define OPEN 2
3513 #define INSHOP 4
3514 #define horiz(i) ((i % 3) - 1)
3515 #define vert(i) ((i / 3) - 1)
3516 for (i = 0; i < 9; i++) {
3517 if ((i == 4) || (!ZAP_POS(levl[x + horiz(i)][y + vert(i)].typ)))
3518 continue;
3519 litter[i] = OPEN;
3520 if (inside_shop(x + horiz(i), y + vert(i))
3521 == ESHK(shkp)->shoproom)
3522 litter[i] |= INSHOP;
3524 if (Punished && !u.uswallow
3525 && ((uchain->ox == x && uchain->oy == y)
3526 || (uball->ox == x && uball->oy == y))) {
3528 * Either the ball or chain is in the repair location.
3530 * Take the easy way out and put ball&chain under hero.
3532 if (!Deaf && !muteshk(shkp))
3533 verbalize("Get your junk out of my wall!");
3534 unplacebc(); /* pick 'em up */
3535 placebc(); /* put 'em down */
3537 while ((otmp = level.objects[x][y]) != 0)
3538 /* Don't mess w/ boulders -- just merge into wall */
3539 if ((otmp->otyp == BOULDER) || (otmp->otyp == ROCK)) {
3540 obj_extract_self(otmp);
3541 obfree(otmp, (struct obj *) 0);
3542 } else {
3543 while (!(litter[i = rn2(9)] & INSHOP))
3545 remove_object(otmp);
3546 place_object(otmp, x + horiz(i), y + vert(i));
3547 litter[i] |= NEED_UPDATE;
3550 if (catchup)
3551 return 1; /* repair occurred while off level */
3553 block_point(x, y);
3554 if (IS_DOOR(tmp_dam->typ)) {
3555 levl[x][y].doormask = D_CLOSED; /* arbitrary */
3556 newsym(x, y);
3557 } else {
3558 /* don't set doormask - it is (hopefully) the same as it was
3559 if not, perhaps save it with the damage array... */
3561 if (IS_WALL(tmp_dam->typ) && cansee(x, y)) {
3562 /* Player sees actual repair process, so they KNOW it's a wall */
3563 levl[x][y].seenv = SVALL;
3564 newsym(x, y);
3566 /* Mark this wall as "repaired". There currently is no code
3567 to do anything about repaired walls, so don't do it. */
3569 for (i = 0; i < 9; i++)
3570 if (litter[i] & NEED_UPDATE)
3571 newsym(x + horiz(i), y + vert(i));
3572 return 2;
3573 #undef NEED_UPDATE
3574 #undef OPEN
3575 #undef INSHOP
3576 #undef vert
3577 #undef horiz
3581 * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
3584 shk_move(shkp)
3585 register struct monst *shkp;
3587 register xchar gx, gy, omx, omy;
3588 register int udist;
3589 register schar appr;
3590 register struct eshk *eshkp = ESHK(shkp);
3591 int z;
3592 boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv;
3594 omx = shkp->mx;
3595 omy = shkp->my;
3597 if (inhishop(shkp))
3598 remove_damage(shkp, FALSE);
3600 if ((udist = distu(omx, omy)) < 3 && (shkp->data != &mons[PM_GRID_BUG]
3601 || (omx == u.ux || omy == u.uy))) {
3602 if (ANGRY(shkp) || (Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
3603 if (Displaced)
3604 Your("displaced image doesn't fool %s!", shkname(shkp));
3605 (void) mattacku(shkp);
3606 return 0;
3608 if (eshkp->following) {
3609 if (strncmp(eshkp->customer, plname, PL_NSIZ)) {
3610 if (!Deaf && !muteshk(shkp))
3611 verbalize("%s, %s! I was looking for %s.", Hello(shkp),
3612 plname, eshkp->customer);
3613 eshkp->following = 0;
3614 return 0;
3616 if (moves > followmsg + 4) {
3617 if (!Deaf && !muteshk(shkp))
3618 verbalize("%s, %s! Didn't you forget to pay?",
3619 Hello(shkp), plname);
3620 else
3621 pline("%s holds out %s upturned %s.",
3622 Shknam(shkp),
3623 mhis(shkp),
3624 mbodypart(shkp, HAND));
3625 followmsg = moves;
3626 if (!rn2(9)) {
3627 pline("%s doesn't like customers who don't pay.",
3628 Shknam(shkp));
3629 rile_shk(shkp);
3632 if (udist < 2)
3633 return 0;
3637 appr = 1;
3638 gx = eshkp->shk.x;
3639 gy = eshkp->shk.y;
3640 satdoor = (gx == omx && gy == omy);
3641 if (eshkp->following || ((z = holetime()) >= 0 && z * z <= udist)) {
3642 /* [This distance check used to apply regardless of
3643 whether the shk was following, but that resulted in
3644 m_move() sometimes taking the shk out of the shop if
3645 the player had fenced him in with boulders or traps.
3646 Such voluntary abandonment left unpaid objects in
3647 invent, triggering billing impossibilities on the
3648 next level once the character fell through the hole.] */
3649 if (udist > 4 && eshkp->following && !eshkp->billct)
3650 return -1; /* leave it to m_move */
3651 gx = u.ux;
3652 gy = u.uy;
3653 } else if (ANGRY(shkp)) {
3654 /* Move towards the hero if the shopkeeper can see him. */
3655 if (shkp->mcansee && m_canseeu(shkp)) {
3656 gx = u.ux;
3657 gy = u.uy;
3659 avoid = FALSE;
3660 } else {
3661 #define GDIST(x, y) (dist2(x, y, gx, gy))
3662 if (Invis || u.usteed) {
3663 avoid = FALSE;
3664 } else {
3665 uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y);
3666 if (uondoor) {
3667 badinv =
3668 (carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
3669 || (Fast && (sobj_at(PICK_AXE, u.ux, u.uy)
3670 || sobj_at(DWARVISH_MATTOCK, u.ux, u.uy))));
3671 if (satdoor && badinv)
3672 return 0;
3673 avoid = !badinv;
3674 } else {
3675 avoid = (*u.ushops && distu(gx, gy) > 8);
3676 badinv = FALSE;
3679 if (((!eshkp->robbed && !eshkp->billct && !eshkp->debit) || avoid)
3680 && GDIST(omx, omy) < 3) {
3681 if (!badinv && !onlineu(omx, omy))
3682 return 0;
3683 if (satdoor)
3684 appr = gx = gy = 0;
3689 z = move_special(shkp, inhishop(shkp), appr, uondoor, avoid, omx, omy, gx,
3690 gy);
3691 if (z > 0)
3692 after_shk_move(shkp);
3694 return z;
3697 /* called after shopkeeper moves, in case themove causes re-entry into shop */
3698 void
3699 after_shk_move(shkp)
3700 struct monst *shkp;
3702 struct eshk *eshkp = ESHK(shkp);
3704 if (eshkp->bill_p == (struct bill_x *) -1000 && inhishop(shkp)) {
3705 /* reset bill_p, need to re-calc player's occupancy too */
3706 eshkp->bill_p = &eshkp->bill[0];
3707 check_special_room(FALSE);
3711 /* for use in levl_follower (mondata.c) */
3712 boolean
3713 is_fshk(mtmp)
3714 register struct monst *mtmp;
3716 return (boolean) (mtmp->isshk && ESHK(mtmp)->following);
3719 /* You are digging in the shop. */
3720 void
3721 shopdig(fall)
3722 register int fall;
3724 register struct monst *shkp = shop_keeper(*u.ushops);
3725 int lang;
3726 const char *grabs = "grabs";
3728 if (!shkp)
3729 return;
3731 /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */
3732 lang = 0;
3733 if (shkp->msleeping || !shkp->mcanmove || is_silent(shkp->data))
3734 ; /* lang stays 0 */
3735 else if (shkp->data->msound <= MS_ANIMAL)
3736 lang = 1;
3737 else if (shkp->data->msound >= MS_HUMANOID)
3738 lang = 2;
3740 if (!inhishop(shkp)) {
3741 if (Role_if(PM_KNIGHT)) {
3742 You_feel("like a common thief.");
3743 adjalign(-sgn(u.ualign.type));
3745 return;
3748 if (!fall) {
3749 if (lang == 2) {
3750 if (!Deaf && !muteshk(shkp)) {
3751 if (u.utraptype == TT_PIT)
3752 verbalize(
3753 "Be careful, %s, or you might fall through the floor.",
3754 flags.female ? "madam" : "sir");
3755 else
3756 verbalize("%s, do not damage the floor here!",
3757 flags.female ? "Madam" : "Sir");
3760 if (Role_if(PM_KNIGHT)) {
3761 You_feel("like a common thief.");
3762 adjalign(-sgn(u.ualign.type));
3764 } else if (!um_dist(shkp->mx, shkp->my, 5)
3765 && !shkp->msleeping && shkp->mcanmove
3766 && (ESHK(shkp)->billct || ESHK(shkp)->debit)) {
3767 register struct obj *obj, *obj2;
3769 if (nolimbs(shkp->data)) {
3770 grabs = "knocks off";
3771 #if 0
3772 /* This is what should happen, but for balance
3773 * reasons, it isn't currently.
3775 if (lang == 2)
3776 pline("%s curses %s inability to grab your backpack!",
3777 shkname(shkp), mhim(shkp));
3778 rile_shk(shkp);
3779 return;
3780 #endif
3782 if (distu(shkp->mx, shkp->my) > 2) {
3783 mnexto(shkp);
3784 /* for some reason the shopkeeper can't come next to you */
3785 if (distu(shkp->mx, shkp->my) > 2) {
3786 if (lang == 2)
3787 pline("%s curses you in anger and frustration!",
3788 shkname(shkp));
3789 else if (lang == 1)
3790 growl(shkp);
3791 rile_shk(shkp);
3792 return;
3793 } else
3794 pline("%s %s, and %s your backpack!", shkname(shkp),
3795 makeplural(locomotion(shkp->data, "leap")), grabs);
3796 } else
3797 pline("%s %s your backpack!", shkname(shkp), grabs);
3799 for (obj = invent; obj; obj = obj2) {
3800 obj2 = obj->nobj;
3801 if ((obj->owornmask & ~(W_SWAPWEP | W_QUIVER)) != 0
3802 || (obj == uswapwep && u.twoweap)
3803 || (obj->otyp == LEASH && obj->leashmon))
3804 continue;
3805 if (obj == current_wand)
3806 continue;
3807 setnotworn(obj);
3808 freeinv(obj);
3809 subfrombill(obj, shkp);
3810 (void) add_to_minv(shkp, obj); /* may free obj */
3815 STATIC_OVL void
3816 makekops(mm)
3817 coord *mm;
3819 static const short k_mndx[4] = { PM_KEYSTONE_KOP, PM_KOP_SERGEANT,
3820 PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN };
3821 int k_cnt[4], cnt, mndx, k;
3823 k_cnt[0] = cnt = abs(depth(&u.uz)) + rnd(5);
3824 k_cnt[1] = (cnt / 3) + 1; /* at least one sarge */
3825 k_cnt[2] = (cnt / 6); /* maybe a lieutenant */
3826 k_cnt[3] = (cnt / 9); /* and maybe a kaptain */
3828 for (k = 0; k < 4; k++) {
3829 if ((cnt = k_cnt[k]) == 0)
3830 break;
3831 mndx = k_mndx[k];
3832 if (mvitals[mndx].mvflags & G_GONE)
3833 continue;
3835 while (cnt--)
3836 if (enexto(mm, mm->x, mm->y, &mons[mndx]))
3837 (void) makemon(&mons[mndx], mm->x, mm->y, NO_MM_FLAGS);
3841 void
3842 pay_for_damage(dmgstr, cant_mollify)
3843 const char *dmgstr;
3844 boolean cant_mollify;
3846 register struct monst *shkp = (struct monst *) 0;
3847 char shops_affected[5];
3848 register boolean uinshp = (*u.ushops != '\0');
3849 char qbuf[80];
3850 register xchar x, y;
3851 boolean dugwall = (!strcmp(dmgstr, "dig into") /* wand */
3852 || !strcmp(dmgstr, "damage")); /* pick-axe */
3853 boolean animal, pursue;
3854 struct damage *tmp_dam, *appear_here = 0;
3855 /* any number >= (80*80)+(24*24) would do, actually */
3856 long cost_of_damage = 0L;
3857 unsigned int nearest_shk = 7000, nearest_damage = 7000;
3858 int picks = 0;
3860 for (tmp_dam = level.damagelist;
3861 (tmp_dam && (tmp_dam->when == monstermoves));
3862 tmp_dam = tmp_dam->next) {
3863 char *shp;
3865 if (!tmp_dam->cost)
3866 continue;
3867 cost_of_damage += tmp_dam->cost;
3868 Strcpy(shops_affected,
3869 in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
3870 for (shp = shops_affected; *shp; shp++) {
3871 struct monst *tmp_shk;
3872 unsigned int shk_distance;
3874 if (!(tmp_shk = shop_keeper(*shp)))
3875 continue;
3876 if (tmp_shk == shkp) {
3877 unsigned int damage_distance =
3878 distu(tmp_dam->place.x, tmp_dam->place.y);
3880 if (damage_distance < nearest_damage) {
3881 nearest_damage = damage_distance;
3882 appear_here = tmp_dam;
3884 continue;
3886 if (!inhishop(tmp_shk))
3887 continue;
3888 shk_distance = distu(tmp_shk->mx, tmp_shk->my);
3889 if (shk_distance > nearest_shk)
3890 continue;
3891 if ((shk_distance == nearest_shk) && picks) {
3892 if (rn2(++picks))
3893 continue;
3894 } else
3895 picks = 1;
3896 shkp = tmp_shk;
3897 nearest_shk = shk_distance;
3898 appear_here = tmp_dam;
3899 nearest_damage = distu(tmp_dam->place.x, tmp_dam->place.y);
3903 if (!cost_of_damage || !shkp)
3904 return;
3906 animal = (shkp->data->msound <= MS_ANIMAL);
3907 pursue = FALSE;
3908 x = appear_here->place.x;
3909 y = appear_here->place.y;
3911 /* not the best introduction to the shk... */
3912 (void) strncpy(ESHK(shkp)->customer, plname, PL_NSIZ);
3914 /* if the shk is already on the war path, be sure it's all out */
3915 if (ANGRY(shkp) || ESHK(shkp)->following) {
3916 hot_pursuit(shkp);
3917 return;
3920 /* if the shk is not in their shop.. */
3921 if (!*in_rooms(shkp->mx, shkp->my, SHOPBASE)) {
3922 if (!cansee(shkp->mx, shkp->my))
3923 return;
3924 pursue = TRUE;
3925 goto getcad;
3928 if (uinshp) {
3929 if (um_dist(shkp->mx, shkp->my, 1)
3930 && !um_dist(shkp->mx, shkp->my, 3)) {
3931 pline("%s leaps towards you!", shkname(shkp));
3932 mnexto(shkp);
3934 pursue = um_dist(shkp->mx, shkp->my, 1);
3935 if (pursue)
3936 goto getcad;
3937 } else {
3939 * Make shkp show up at the door. Effect: If there is a monster
3940 * in the doorway, have the hero hear the shopkeeper yell a bit,
3941 * pause, then have the shopkeeper appear at the door, having
3942 * yanked the hapless critter out of the way.
3944 if (MON_AT(x, y)) {
3945 if (!animal) {
3946 if (!Deaf && !muteshk(shkp)) {
3947 You_hear("an angry voice:");
3948 verbalize("Out of my way, scum!");
3950 wait_synch();
3951 #if defined(UNIX) || defined(VMS)
3952 #if defined(SYSV) || defined(ULTRIX) || defined(VMS)
3953 (void)
3954 #endif
3955 sleep(1);
3956 #endif
3957 } else {
3958 growl(shkp);
3961 (void) mnearto(shkp, x, y, TRUE);
3964 if ((um_dist(x, y, 1) && !uinshp) || cant_mollify
3965 || (money_cnt(invent) + ESHK(shkp)->credit) < cost_of_damage
3966 || !rn2(50)) {
3967 getcad:
3968 if (muteshk(shkp)) {
3969 if (animal && shkp->mcanmove && !shkp->msleeping)
3970 yelp(shkp);
3971 } else if (pursue || uinshp || !um_dist(x, y, 1)) {
3972 if (!Deaf)
3973 verbalize("How dare you %s my %s?", dmgstr,
3974 dugwall ? "shop" : "door");
3975 else
3976 pline("%s is %s that you decided to %s %s %s!",
3977 Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
3978 dmgstr, mhis(shkp), dugwall ? "shop" : "door");
3979 } else {
3980 if (!Deaf) {
3981 pline("%s shouts:", shkname(shkp));
3982 verbalize("Who dared %s my %s?", dmgstr,
3983 dugwall ? "shop" : "door");
3984 } else {
3985 pline("%s is %s that someone decided to %s %s %s!",
3986 Shknam(shkp), angrytexts[rn2(SIZE(angrytexts))],
3987 dmgstr, mhis(shkp), dugwall ? "shop" : "door");
3990 hot_pursuit(shkp);
3991 return;
3994 if (Invis)
3995 Your("invisibility does not fool %s!", shkname(shkp));
3996 Sprintf(qbuf, "%sYou did %ld %s worth of damage!%s Pay?",
3997 !animal ? cad(TRUE) : "", cost_of_damage,
3998 currency(cost_of_damage), !animal ? "\"" : "");
3999 if (yn(qbuf) != 'n') {
4000 cost_of_damage = check_credit(cost_of_damage, shkp);
4001 money2mon(shkp, cost_of_damage);
4002 context.botl = 1;
4003 pline("Mollified, %s accepts your restitution.", shkname(shkp));
4004 /* move shk back to his home loc */
4005 home_shk(shkp, FALSE);
4006 pacify_shk(shkp);
4007 } else {
4008 if (!animal) {
4009 if (!Deaf && !muteshk(shkp))
4010 verbalize("Oh, yes! You'll pay!");
4011 else
4012 pline("%s lunges %s %s toward your %s!",
4013 Shknam(shkp),
4014 mhis(shkp),
4015 mbodypart(shkp, HAND),
4016 body_part(NECK));
4017 } else
4018 growl(shkp);
4019 hot_pursuit(shkp);
4020 adjalign(-sgn(u.ualign.type));
4024 /* called in dokick.c when we kick an object that might be in a store */
4025 boolean
4026 costly_spot(x, y)
4027 register xchar x, y;
4029 struct monst *shkp;
4030 struct eshk *eshkp;
4032 if (!level.flags.has_shop)
4033 return FALSE;
4034 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
4035 if (!shkp || !inhishop(shkp))
4036 return FALSE;
4037 eshkp = ESHK(shkp);
4038 return (boolean) (inside_shop(x, y)
4039 && !(x == eshkp->shk.x && y == eshkp->shk.y));
4042 /* called by dotalk(sounds.c) when #chatting; returns obj if location
4043 contains shop goods and shopkeeper is willing & able to speak */
4044 struct obj *
4045 shop_object(x, y)
4046 register xchar x, y;
4048 register struct obj *otmp;
4049 register struct monst *shkp;
4051 if (!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
4052 return (struct obj *) 0;
4054 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
4055 if (otmp->oclass != COIN_CLASS)
4056 break;
4057 /* note: otmp might have ->no_charge set, but that's ok */
4058 return (otmp && costly_spot(x, y)
4059 && NOTANGRY(shkp) && shkp->mcanmove && !shkp->msleeping)
4060 ? otmp
4061 : (struct obj *) 0;
4064 /* give price quotes for all objects linked to this one (ie, on this spot) */
4065 void
4066 price_quote(first_obj)
4067 register struct obj *first_obj;
4069 register struct obj *otmp;
4070 char buf[BUFSZ], price[40];
4071 long cost = 0L;
4072 int cnt = 0;
4073 boolean contentsonly = FALSE;
4074 winid tmpwin;
4075 struct monst *shkp = shop_keeper(inside_shop(u.ux, u.uy));
4077 tmpwin = create_nhwindow(NHW_MENU);
4078 putstr(tmpwin, 0, "Fine goods for sale:");
4079 putstr(tmpwin, 0, "");
4080 for (otmp = first_obj; otmp; otmp = otmp->nexthere) {
4081 if (otmp->oclass == COIN_CLASS)
4082 continue;
4083 cost = (otmp->no_charge || otmp == uball || otmp == uchain)
4084 ? 0L
4085 : get_cost(otmp, (struct monst *) 0);
4086 contentsonly = !cost;
4087 if (Has_contents(otmp))
4088 cost += contained_cost(otmp, shkp, 0L, FALSE, FALSE);
4089 if (!cost) {
4090 Strcpy(price, "no charge");
4091 contentsonly = FALSE;
4092 } else {
4093 Sprintf(price, "%ld %s%s", cost, currency(cost),
4094 (otmp->quan) > 1L ? " each" : "");
4096 Sprintf(buf, "%s%s, %s", contentsonly ? the_contents_of : "",
4097 doname(otmp), price);
4098 putstr(tmpwin, 0, buf), cnt++;
4100 if (cnt > 1) {
4101 display_nhwindow(tmpwin, TRUE);
4102 } else if (cnt == 1) {
4103 if (!cost) {
4104 /* "<doname(obj)>, no charge" */
4105 pline("%s!", upstart(buf)); /* buf still contains the string */
4106 } else {
4107 /* print cost in slightly different format, so can't reuse buf;
4108 cost and contentsonly are already set up */
4109 Sprintf(buf, "%s%s", contentsonly ? the_contents_of : "",
4110 doname(first_obj));
4111 pline("%s, price %ld %s%s%s", upstart(buf), cost, currency(cost),
4112 (first_obj->quan > 1L) ? " each" : "",
4113 contentsonly ? "." : shk_embellish(first_obj, cost));
4116 destroy_nhwindow(tmpwin);
4119 STATIC_OVL const char *
4120 shk_embellish(itm, cost)
4121 register struct obj *itm;
4122 long cost;
4124 if (!rn2(3)) {
4125 register int o, choice = rn2(5);
4127 if (choice == 0)
4128 choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
4129 switch (choice) {
4130 case 4:
4131 if (cost < 10L)
4132 break;
4133 else
4134 o = itm->oclass;
4135 if (o == FOOD_CLASS)
4136 return ", gourmets' delight!";
4137 if (objects[itm->otyp].oc_name_known
4138 ? objects[itm->otyp].oc_magic
4139 : (o == AMULET_CLASS || o == RING_CLASS || o == WAND_CLASS
4140 || o == POTION_CLASS || o == SCROLL_CLASS
4141 || o == SPBOOK_CLASS))
4142 return ", painstakingly developed!";
4143 return ", superb craftsmanship!";
4144 case 3:
4145 return ", finest quality.";
4146 case 2:
4147 return ", an excellent choice.";
4148 case 1:
4149 return ", a real bargain.";
4150 default:
4151 break;
4153 } else if (itm->oartifact) {
4154 return ", one of a kind!";
4156 return ".";
4159 /* First 4 supplied by Ronen and Tamar, remainder by development team */
4160 const char *Izchak_speaks[] = {
4161 "%s says: 'These shopping malls give me a headache.'",
4162 "%s says: 'Slow down. Think clearly.'",
4163 "%s says: 'You need to take things one at a time.'",
4164 "%s says: 'I don't like poofy coffee... give me Columbian Supremo.'",
4165 "%s says that getting the devteam's agreement on anything is difficult.",
4166 "%s says that he has noticed those who serve their deity will prosper.",
4167 "%s says: 'Don't try to steal from me - I have friends in high places!'",
4168 "%s says: 'You may well need something from this shop in the future.'",
4169 "%s comments about the Valley of the Dead as being a gateway."
4172 void
4173 shk_chat(shkp)
4174 struct monst *shkp;
4176 struct eshk *eshk;
4177 long shkmoney;
4179 if (!shkp->isshk) {
4180 /* The monster type is shopkeeper, but this monster is
4181 not actually a shk, which could happen if someone
4182 wishes for a shopkeeper statue and then animates it.
4183 (Note: shkname() would be "" in a case like this.) */
4184 pline("%s asks whether you've seen any untended shops recently.",
4185 Monnam(shkp));
4186 /* [Perhaps we ought to check whether this conversation
4187 is taking place inside an untended shop, but a shopless
4188 shk can probably be expected to be rather disoriented.] */
4189 return;
4192 eshk = ESHK(shkp);
4193 if (ANGRY(shkp)) {
4194 pline("%s %s how much %s dislikes %s customers.",
4195 shkname(shkp),
4196 (!Deaf && !muteshk(shkp)) ? "mentions" : "indicates",
4197 mhe(shkp), eshk->robbed ? "non-paying" : "rude");
4198 } else if (eshk->following) {
4199 if (strncmp(eshk->customer, plname, PL_NSIZ)) {
4200 if (!Deaf && !muteshk(shkp))
4201 verbalize("%s %s! I was looking for %s.",
4202 Hello(shkp), plname, eshk->customer);
4203 eshk->following = 0;
4204 } else {
4205 if (!Deaf && !muteshk(shkp))
4206 verbalize("%s %s! Didn't you forget to pay?",
4207 Hello(shkp), plname);
4208 else
4209 pline("%s taps you on the %s.",
4210 Shknam(shkp), body_part(ARM));
4212 } else if (eshk->billct) {
4213 register long total = addupbill(shkp) + eshk->debit;
4215 pline("%s %s that your bill comes to %ld %s.",
4216 shkname(shkp),
4217 (!Deaf && !muteshk(shkp)) ? "says" : "indicates",
4218 total, currency(total));
4219 } else if (eshk->debit) {
4220 pline("%s %s that you owe %s %ld %s.",
4221 shkname(shkp),
4222 (!Deaf && !muteshk(shkp)) ? "reminds you" : "indicates",
4223 mhim(shkp), eshk->debit, currency(eshk->debit));
4224 } else if (eshk->credit) {
4225 pline("%s encourages you to use your %ld %s of credit.",
4226 shkname(shkp), eshk->credit, currency(eshk->credit));
4227 } else if (eshk->robbed) {
4228 pline("%s %s about a recent robbery.",
4229 Shknam(shkp),
4230 (!Deaf && !muteshk(shkp)) ? "complains" : "indicates concern");
4231 } else if ((shkmoney = money_cnt(shkp->minvent)) < 50L) {
4232 pline("%s %s that business is bad.",
4233 shkname(shkp),
4234 (!Deaf && !muteshk(shkp)) ? "complains" : "indicates");
4235 } else if (shkmoney > 4000) {
4236 pline("%s %s that business is good.",
4237 shkname(shkp),
4238 (!Deaf && !muteshk(shkp)) ? "says" : "indicates");
4239 } else if (is_izchak(shkp, FALSE)) {
4240 if (!Deaf && !muteshk(shkp))
4241 pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))], shkname(shkp));
4242 } else {
4243 if (!Deaf && !muteshk(shkp))
4244 pline("%s talks about the problem of shoplifters.", shkname(shkp));
4248 STATIC_OVL void
4249 kops_gone(silent)
4250 boolean silent;
4252 register int cnt = 0;
4253 register struct monst *mtmp, *mtmp2;
4255 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
4256 mtmp2 = mtmp->nmon;
4257 if (mtmp->data->mlet == S_KOP) {
4258 if (canspotmon(mtmp))
4259 cnt++;
4260 mongone(mtmp);
4263 if (cnt && !silent)
4264 pline_The("Kop%s (disappointed) vanish%s into thin air.",
4265 plur(cnt), (cnt == 1) ? "es" : "");
4268 STATIC_OVL long
4269 cost_per_charge(shkp, otmp, altusage)
4270 struct monst *shkp;
4271 struct obj *otmp;
4272 boolean altusage; /* some items have an "alternate" use with different cost */
4274 long tmp = 0L;
4276 if (!shkp || !inhishop(shkp))
4277 return 0L; /* insurance */
4278 tmp = get_cost(otmp, shkp);
4280 /* The idea is to make the exhaustive use of an unpaid item
4281 * more expensive than buying it outright.
4283 if (otmp->otyp == MAGIC_LAMP) { /* 1 */
4284 /* normal use (ie, as light source) of a magic lamp never
4285 degrades its value, but not charging anything would make
4286 identification too easy; charge an amount comparable to
4287 what is charged for an ordinary lamp (don't bother with
4288 angry shk surcharge) */
4289 if (!altusage)
4290 tmp = (long) objects[OIL_LAMP].oc_cost;
4291 else
4292 tmp += tmp / 3L; /* djinni is being released */
4293 } else if (otmp->otyp == MAGIC_MARKER) { /* 70 - 100 */
4294 /* No way to determine in advance how many charges will be
4295 * wasted. So, arbitrarily, one half of the price per use.
4297 tmp /= 2L;
4298 } else if (otmp->otyp == BAG_OF_TRICKS /* 1 - 20 */
4299 || otmp->otyp == HORN_OF_PLENTY) {
4300 /* altusage: emptying of all the contents at once */
4301 if (!altusage)
4302 tmp /= 5L;
4303 } else if (otmp->otyp == CRYSTAL_BALL /* 1 - 5 */
4304 || otmp->otyp == OIL_LAMP /* 1 - 10 */
4305 || otmp->otyp == BRASS_LANTERN
4306 || (otmp->otyp >= MAGIC_FLUTE
4307 && otmp->otyp <= DRUM_OF_EARTHQUAKE) /* 5 - 9 */
4308 || otmp->oclass == WAND_CLASS) { /* 3 - 11 */
4309 if (otmp->spe > 1)
4310 tmp /= 4L;
4311 } else if (otmp->oclass == SPBOOK_CLASS) {
4312 tmp -= tmp / 5L;
4313 } else if (otmp->otyp == CAN_OF_GREASE || otmp->otyp == TINNING_KIT
4314 || otmp->otyp == EXPENSIVE_CAMERA) {
4315 tmp /= 10L;
4316 } else if (otmp->otyp == POT_OIL) {
4317 tmp /= 5L;
4319 return tmp;
4322 /* Charge the player for partial use of an unpaid object.
4324 * Note that bill_dummy_object() should be used instead
4325 * when an object is completely used.
4327 void
4328 check_unpaid_usage(otmp, altusage)
4329 struct obj *otmp;
4330 boolean altusage;
4332 struct monst *shkp;
4333 const char *fmt, *arg1, *arg2;
4334 char buf[BUFSZ];
4335 long tmp;
4337 if (!otmp->unpaid || !*u.ushops
4338 || (otmp->spe <= 0 && objects[otmp->otyp].oc_charged))
4339 return;
4340 if (!(shkp = shop_keeper(*u.ushops)) || !inhishop(shkp))
4341 return;
4342 if ((tmp = cost_per_charge(shkp, otmp, altusage)) == 0L)
4343 return;
4345 arg1 = arg2 = "";
4346 if (otmp->oclass == SPBOOK_CLASS) {
4347 fmt = "%sYou owe%s %ld %s.";
4348 Sprintf(buf, "This is no free library, %s! ", cad(FALSE));
4349 arg1 = rn2(2) ? buf : "";
4350 arg2 = ESHK(shkp)->debit > 0L ? " an additional" : "";
4351 } else if (otmp->otyp == POT_OIL) {
4352 fmt = "%s%sThat will cost you %ld %s (Yendorian Fuel Tax).";
4353 } else if (altusage && (otmp->otyp == BAG_OF_TRICKS
4354 || otmp->otyp == HORN_OF_PLENTY)) {
4355 fmt = "%s%sEmptying that will cost you %ld %s.";
4356 if (!rn2(3))
4357 arg1 = "Whoa! ";
4358 if (!rn2(3))
4359 arg1 = "Watch it! ";
4360 } else {
4361 fmt = "%s%sUsage fee, %ld %s.";
4362 if (!rn2(3))
4363 arg1 = "Hey! ";
4364 if (!rn2(3))
4365 arg2 = "Ahem. ";
4368 if (!Deaf && !muteshk(shkp)) {
4369 verbalize(fmt, arg1, arg2, tmp, currency(tmp));
4370 exercise(A_WIS, TRUE); /* you just got info */
4372 ESHK(shkp)->debit += tmp;
4375 /* for using charges of unpaid objects "used in the normal manner" */
4376 void
4377 check_unpaid(otmp)
4378 struct obj *otmp;
4380 check_unpaid_usage(otmp, FALSE); /* normal item use */
4383 void
4384 costly_gold(x, y, amount)
4385 register xchar x, y;
4386 register long amount;
4388 register long delta;
4389 register struct monst *shkp;
4390 register struct eshk *eshkp;
4392 if (!costly_spot(x, y))
4393 return;
4394 /* shkp now guaranteed to exist by costly_spot() */
4395 shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
4397 eshkp = ESHK(shkp);
4398 if (eshkp->credit >= amount) {
4399 if (eshkp->credit > amount)
4400 Your("credit is reduced by %ld %s.", amount, currency(amount));
4401 else
4402 Your("credit is erased.");
4403 eshkp->credit -= amount;
4404 } else {
4405 delta = amount - eshkp->credit;
4406 if (eshkp->credit)
4407 Your("credit is erased.");
4408 if (eshkp->debit)
4409 Your("debt increases by %ld %s.", delta, currency(delta));
4410 else
4411 You("owe %s %ld %s.", shkname(shkp), delta, currency(delta));
4412 eshkp->debit += delta;
4413 eshkp->loan += delta;
4414 eshkp->credit = 0L;
4418 /* used in domove to block diagonal shop-exit */
4419 /* x,y should always be a door */
4420 boolean
4421 block_door(x, y)
4422 register xchar x, y;
4424 register int roomno = *in_rooms(x, y, SHOPBASE);
4425 register struct monst *shkp;
4427 if (roomno < 0 || !IS_SHOP(roomno))
4428 return FALSE;
4429 if (!IS_DOOR(levl[x][y].typ))
4430 return FALSE;
4431 if (roomno != *u.ushops)
4432 return FALSE;
4434 if (!(shkp = shop_keeper((char) roomno)) || !inhishop(shkp))
4435 return FALSE;
4437 if (shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y
4438 /* Actually, the shk should be made to block _any_
4439 * door, including a door the player digs, if the
4440 * shk is within a 'jumping' distance.
4442 && ESHK(shkp)->shd.x == x
4443 && ESHK(shkp)->shd.y == y
4444 && shkp->mcanmove && !shkp->msleeping
4445 && (ESHK(shkp)->debit || ESHK(shkp)->billct || ESHK(shkp)->robbed)) {
4446 pline("%s%s blocks your way!", shkname(shkp),
4447 Invis ? " senses your motion and" : "");
4448 return TRUE;
4450 return FALSE;
4453 /* used in domove to block diagonal shop-entry;
4454 u.ux, u.uy should always be a door */
4455 boolean
4456 block_entry(x, y)
4457 register xchar x, y;
4459 register xchar sx, sy;
4460 register int roomno;
4461 register struct monst *shkp;
4463 if (!(IS_DOOR(levl[u.ux][u.uy].typ)
4464 && levl[u.ux][u.uy].doormask == D_BROKEN))
4465 return FALSE;
4467 roomno = *in_rooms(x, y, SHOPBASE);
4468 if (roomno < 0 || !IS_SHOP(roomno))
4469 return FALSE;
4470 if (!(shkp = shop_keeper((char) roomno)) || !inhishop(shkp))
4471 return FALSE;
4473 if (ESHK(shkp)->shd.x != u.ux || ESHK(shkp)->shd.y != u.uy)
4474 return FALSE;
4476 sx = ESHK(shkp)->shk.x;
4477 sy = ESHK(shkp)->shk.y;
4479 if (shkp->mx == sx && shkp->my == sy && shkp->mcanmove && !shkp->msleeping
4480 && (x == sx - 1 || x == sx + 1 || y == sy - 1 || y == sy + 1)
4481 && (Invis || carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
4482 || u.usteed)) {
4483 pline("%s%s blocks your way!", shkname(shkp),
4484 Invis ? " senses your motion and" : "");
4485 return TRUE;
4487 return FALSE;
4490 /* "your " or "Foobar's " (note the trailing space) */
4491 char *
4492 shk_your(buf, obj)
4493 char *buf;
4494 struct obj *obj;
4496 if (!shk_owns(buf, obj) && !mon_owns(buf, obj))
4497 Strcpy(buf, the_your[carried(obj) ? 1 : 0]);
4498 return strcat(buf, " ");
4501 char *
4502 Shk_Your(buf, obj)
4503 char *buf;
4504 struct obj *obj;
4506 (void) shk_your(buf, obj);
4507 *buf = highc(*buf);
4508 return buf;
4511 STATIC_OVL char *
4512 shk_owns(buf, obj)
4513 char *buf;
4514 struct obj *obj;
4516 struct monst *shkp;
4517 xchar x, y;
4519 if (get_obj_location(obj, &x, &y, 0)
4520 && (obj->unpaid || (obj->where == OBJ_FLOOR && !obj->no_charge
4521 && costly_spot(x, y)))) {
4522 shkp = shop_keeper(inside_shop(x, y));
4523 return strcpy(buf, shkp ? s_suffix(shkname(shkp)) : the_your[0]);
4525 return (char *) 0;
4528 STATIC_OVL char *
4529 mon_owns(buf, obj)
4530 char *buf;
4531 struct obj *obj;
4533 if (obj->where == OBJ_MINVENT)
4534 return strcpy(buf, s_suffix(y_monnam(obj->ocarry)));
4535 return (char *) 0;
4538 STATIC_OVL const char *
4539 cad(altusage)
4540 boolean altusage; /* used as a verbalized exclamation: \"Cad! ...\" */
4542 const char *res = 0;
4544 switch (is_demon(youmonst.data) ? 3 : poly_gender()) {
4545 case 0:
4546 res = "cad";
4547 break;
4548 case 1:
4549 res = "minx";
4550 break;
4551 case 2:
4552 res = "beast";
4553 break;
4554 case 3:
4555 res = "fiend";
4556 break;
4557 default:
4558 impossible("cad: unknown gender");
4559 res = "thing";
4560 break;
4562 if (altusage) {
4563 char *cadbuf = mon_nam(&youmonst); /* snag an output buffer */
4565 /* alternate usage adds a leading double quote and trailing
4566 exclamation point plus sentence separating spaces */
4567 Sprintf(cadbuf, "\"%s! ", res);
4568 cadbuf[1] = highc(cadbuf[1]);
4569 res = cadbuf;
4571 return res;
4574 #ifdef __SASC
4575 void
4576 sasc_bug(struct obj *op, unsigned x)
4578 op->unpaid = x;
4580 #endif
4582 /*shk.c*/