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