~ubuntu-branches/ubuntu/vivid/nethack/vivid

« back to all changes in this revision

Viewing changes to .pc/0016-fix-non-constant-format-strings.patch/src/shk.c

  • Committer: Package Import Robot
  • Author(s): Vincent Cheng, Bernhard R. Link, Vincent Cheng
  • Date: 2012-06-11 00:47:38 UTC
  • mfrom: (3.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120611004738-3fy8b3wi0j45y2oq
Tags: 3.4.3-14
* Team upload.

[ Bernhard R. Link ]
* switch to "3.0 (quilt)"
* bump Standards-Version
* modernize debian/rules:
- use dpkg-buildflags
- support build-arch/-indep
- make parallel safe
- don't avoid make errors
* add patch so it can compile with -Werror=format-security
* drop no longer needed patches (-qt and -gnome are gone)
* don't use /dev/null as install template (Closes: 644647)
* drop nethack-common menu (both -console and -x11 have one)

[ Vincent Cheng ]
* Adopt package. (Closes: #673584)
  - Change Maintainer to Debian Games Team.
  - Add myself to Uploaders.
* Modify 0006-Common-config.h-for-all-binary-packages.patch to enable
  AUTOPICKUP_EXCEPTIONS. (Closes: #329318)
* Modify 0011-Pasi-Kallinen-s-patch-to-add-colors-to-inventory-ite.patch
  and 0017-Debian-and-Linux-specifics-defined-in-unixconf.h.patch; add
  0021-fix-kfreebsd-ftbfs.patch to fix FTBFS on kfreebsd.
* Convert debian/copyright to DEP-5 machine-readable format.
* Use dh_lintian to install overrides instead of manually installing them
  in debian/rules.
* Add watch file.
* Add Homepage field in debian/control.
* Add Vcs-* fields in debian/control.

Show diffs side-by-side

added added

removed removed

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