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. */
12
#define PAY_CANT 0 /* too poor */
14
#define PAY_BROKE (-2)
17
STATIC_DCL void FDECL(makekops, (coord *));
18
STATIC_DCL void FDECL(call_kops, (struct monst *,BOOLEAN_P));
20
STATIC_DCL void FDECL(kops_gone, (BOOLEAN_P));
24
#define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
26
extern const struct shclass shtypes[]; /* defined in shknam.c */
27
extern struct obj *thrownobj; /* defined in dothrow.c */
29
STATIC_VAR NEARDATA long int followmsg; /* last time of follow message */
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,
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 *,
65
STATIC_DCL void FDECL(add_to_billobjs, (struct obj *));
66
STATIC_DCL void FDECL(bill_box_content, (struct obj *, BOOLEAN_P, BOOLEAN_P,
69
static boolean FDECL(rob_shop, (struct monst *));
74
invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
75
obj->quan <= bp->bquan
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.
94
money2mon(mon, amount)
98
struct obj *ygold = findgold(invent);
101
impossible("%s payment in money2mon!", amount ? "negative" : "zero");
104
if (!ygold || ygold->quan < amount) {
105
impossible("Paying without %s money?", ygold ? "enough" : "");
109
if (ygold->quan > amount)
110
ygold = splitobj(ygold, amount);
111
else if (ygold->owornmask)
112
remove_worn_item(ygold, FALSE); /* quiver */
114
add_to_minv(mon, ygold);
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.
130
struct obj *mongold = findgold(mon->minvent);
133
impossible("%s payment in money2u!", amount ? "negative" : "zero");
136
if (!mongold || mongold->quan < amount) {
137
impossible("%s paying without %s money?", a_monnam(mon),
138
mongold ? "enough" : "");
142
if (mongold->quan > amount) mongold = splitobj(mongold, amount);
143
obj_extract_self(mongold);
145
if (!merge_choice(invent, mongold) && inv_cnt() >= 52) {
146
You("have no room for the money!");
156
STATIC_OVL struct monst *
157
next_shkp(shkp, withbill)
158
register struct monst *shkp;
159
register boolean withbill;
161
for (; shkp; shkp = shkp->nmon) {
162
if (DEADMONSTER(shkp)) continue;
163
if (shkp->isshk && (ESHK(shkp)->billct || !withbill)) break;
167
if (NOTANGRY(shkp)) {
168
if (ESHK(shkp)->surcharge) pacify_shk(shkp);
170
if (!ESHK(shkp)->surcharge) rile_shk(shkp);
177
shkname(mtmp) /* called in do_name.c */
178
register struct monst *mtmp;
180
return(ESHK(mtmp)->shknam);
184
shkgone(mtmp) /* called in mon.c */
187
struct eshk *eshk = ESHK(mtmp);
188
struct mkroom *sroom = &rooms[eshk->shoproom - ROOMOFFSET];
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;
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)
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) {
211
eshk->bill_p = (struct bill_x *)0;
212
/* remove eshk->shoproom from u.ushops */
213
do { *p = *(p + 1); } while (*++p);
219
set_residency(shkp, zero_out)
220
register struct monst *shkp;
221
register boolean zero_out;
223
if (on_level(&(ESHK(shkp)->shoplevel), &u.uz))
224
rooms[ESHK(shkp)->shoproom - ROOMOFFSET].resident =
225
(zero_out)? (struct monst *)0 : shkp;
230
register struct monst *mtmp, *mtmp2;
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]);
238
/* do shopkeeper specific structure munging -dlc */
240
restshk(shkp, ghostly)
245
struct eshk *eshkp = ESHK(shkp);
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 */
252
assign_level(&eshkp->shoplevel, &u.uz);
253
if (ANGRY(shkp) && strncmpi(eshkp->customer, plname, PL_NSIZ))
262
/* Clear the unpaid bit on all of the objects in the list. */
265
register struct obj *list;
268
if (Has_contents(list)) clear_unpaid(list->cobj);
276
/* either you paid or left the shop or the shopkeeper died */
279
register struct monst *shkp;
281
register struct obj *obj;
282
register struct monst *mtmp;
284
/* FIXME: object handling should be limited to
285
items which are on this particular shk's bill */
287
clear_unpaid(invent);
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);
296
while ((obj = billobjs) != 0) {
297
obj_extract_self(obj);
301
ESHK(shkp)->billct = 0;
302
ESHK(shkp)->credit = 0L;
303
ESHK(shkp)->debit = 0L;
304
ESHK(shkp)->loan = 0L;
310
register struct monst *shkp;
312
register int ct = ESHK(shkp)->billct;
313
register struct bill_x *bp = ESHK(shkp)->bill_p;
314
register long total = 0L;
317
total += bp->price * bp->bquan;
328
call_kops(shkp, nearshop)
329
register struct monst *shkp;
330
register boolean nearshop;
332
/* Keystone Kops srt@ucla */
333
register boolean nokops;
338
pline("An alarm sounds!");
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));
345
if(!angry_guards(!flags.soundok) && nokops) {
346
if(flags.verbose && flags.soundok)
347
pline("But no one seems to respond to it.");
357
/* Create swarm around you, if you merely "stepped out" */
359
pline_The("Keystone Kops appear!");
366
pline_The("Keystone Kops are after you!");
367
/* Create swarm near down staircase (hinders return to level) */
371
/* Create swarm near shopkeeper (hinders return to shop) */
379
/* x,y is strictly inside shop */
386
rno = levl[x][y].roomno;
387
if ((rno < ROOMOFFSET) || levl[x][y].edge || !IS_SHOP(rno-ROOMOFFSET))
394
u_left_shop(leavestring, newlev)
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)
409
(!levl[u.ux][u.uy].edge || levl[u.ux0][u.uy0].edge))
412
shkp = shop_keeper(*u.ushops0);
413
if (!shkp || !inhishop(shkp))
414
return; /* shk died, teleported, changed levels... */
417
if (!eshkp->billct && !eshkp->debit) /* bill is settled */
420
if (!*leavestring && shkp->mcanmove && !shkp->msleeping) {
422
* Player just stepped onto shop-boundary (known from above logic).
423
* Try to intimidate him into paying his bill
425
verbalize(NOTANGRY(shkp) ?
426
"%s! Please pay before leaving." :
427
"%s! Don't you leave without paying!",
432
if (rob_shop(shkp)) {
434
call_kops(shkp, (!newlev && levl[u.ux0][u.uy0].edge));
436
(void) angry_guards(FALSE);
441
/* robbery from outside the shop via telekinesis or grappling hook */
443
remote_burglary(x, y)
449
shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
450
if (!shkp || !inhishop(shkp))
451
return; /* shk died, teleported, changed levels... */
454
if (!eshkp->billct && !eshkp->debit) /* bill is settled */
457
if (rob_shop(shkp)) {
459
/*[might want to set 2nd arg based on distance from shop doorway]*/
460
call_kops(shkp, FALSE);
462
(void) angry_guards(FALSE);
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 */
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() */
484
You("escaped the shop without paying!");
485
total -= eshkp->credit;
488
if (!total) return FALSE;
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));
502
u_entered_shop(enterstring)
503
register char *enterstring;
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];
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))
520
Strcpy(empty_shops, u.ushops);
527
if (!inhishop(shkp)) {
528
/* dump core when referenced */
529
eshkp->bill_p = (struct bill_x *) -1000;
530
if (!index(empty_shops, *enterstring))
532
Strcpy(empty_shops, u.ushops);
537
eshkp->bill_p = &(eshkp->bill[0]);
539
if ((!eshkp->visitct || *eshkp->customer) &&
540
strncmpi(eshkp->customer, plname, PL_NSIZ)) {
541
/* You seem to be new here */
543
eshkp->following = 0;
544
(void) strncpy(eshkp->customer,plname,PL_NSIZ);
548
if (shkp->msleeping || !shkp->mcanmove || eshkp->following)
549
return; /* no dialog */
552
pline("%s senses your presence.", shkname(shkp));
553
verbalize("Invisible customers are not welcome!");
557
rt = rooms[*enterstring - ROOMOFFSET].rtype;
560
verbalize("So, %s, you dare return to %s %s?!",
562
s_suffix(shkname(shkp)),
563
shtypes[rt - SHOPBASE].name);
564
} else if (eshkp->robbed) {
565
pline("%s mutters imprecations against shoplifters.", shkname(shkp));
567
verbalize("%s, %s! Welcome%s to %s %s!",
569
eshkp->visitct++ ? " again" : "",
570
s_suffix(shkname(shkp)),
571
shtypes[rt - SHOPBASE].name);
573
/* can't do anything about blocking if teleported in */
574
if (!inside_shop(u.ux, u.uy)) {
575
boolean should_block;
578
struct obj *pick = carrying(PICK_AXE),
579
*mattock = carrying(DWARVISH_MATTOCK);
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 */
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) */
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);
598
verbalize(NOTANGRY(shkp) ?
599
"Will you please leave your %s%s outside?" :
600
"Leave the %s%s outside.",
604
} else if (u.usteed) {
605
verbalize(NOTANGRY(shkp) ?
606
"Will you please leave %s outside?" :
607
"Leave %s outside.", y_monnam(u.usteed));
611
should_block = (Fast && (sobj_at(PICK_AXE, u.ux, u.uy) ||
612
sobj_at(DWARVISH_MATTOCK, u.ux, u.uy)));
614
if (should_block) (void) dochug(shkp); /* shk gets extra move */
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.
625
same_price(obj1, obj2)
626
struct obj *obj1, *obj2;
628
register struct monst *shkp1, *shkp2;
629
register struct bill_x *bp1 = 0, *bp2 = 0;
630
register boolean are_mergable = FALSE;
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) {
640
for (shkp2 = next_shkp(fmon, TRUE); shkp2;
641
shkp2 = next_shkp(shkp2->nmon, TRUE))
642
if ((bp2 = onbill(obj2, shkp2, TRUE)) != 0) break;
645
if (!bp1 || !bp2) impossible("same_price: object wasn't on any bill!");
646
else are_mergable = (shkp1 == shkp2 && bp1->price == bp2->price);
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.
662
long debt = eshkp->debit;
664
for (bp = eshkp->bill_p, ct = eshkp->billct; ct > 0; bp++, ct--)
665
debt += bp->price * bp->bquan;
669
/* called in response to the `$' command */
671
shopper_financial_report()
673
struct monst *shkp, *this_shkp = shop_keeper(inside_shop(u.ux, u.uy));
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 */
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;
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.");
710
register struct monst *mtmp;
712
return(index(in_rooms(mtmp->mx, mtmp->my, SHOPBASE),
713
ESHK(mtmp)->shoproom) &&
714
on_level(&(ESHK(mtmp)->shoplevel), &u.uz));
721
struct monst *shkp = rmno >= ROOMOFFSET ?
722
rooms[rmno - ROOMOFFSET].resident : 0;
725
if (NOTANGRY(shkp)) {
726
if (ESHK(shkp)->surcharge) pacify_shk(shkp);
728
if (!ESHK(shkp)->surcharge) rile_shk(shkp);
736
register struct mkroom *sroom;
738
register struct monst *mtmp = sroom->resident;
743
return((boolean)(inhishop(mtmp)));
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;
753
register struct bill_x *bp = ESHK(shkp)->bill_p;
754
register int ct = ESHK(shkp)->billct;
757
if (bp->bo_id == obj->o_id) {
758
if (!obj->unpaid) pline("onbill: paid obj on bill?");
762
if(obj->unpaid & !silent) pline("onbill: unpaid obj not on bill?");
763
return (struct bill_x *)0;
766
/* Delete the contents of the given object. */
769
register struct obj *obj;
771
register struct obj *curr;
773
while ((curr = obj->cobj) != 0) {
774
obj_extract_self(curr);
775
obfree(curr, (struct obj *)0);
779
/* called with two args on merge */
782
register struct obj *obj, *merge;
784
register struct bill_x *bp;
785
register struct bill_x *bpm;
786
register struct monst *shkp;
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);
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;
800
/* sanity check, more or less */
801
if (!shkp) shkp = shop_keeper(*u.ushops);
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.
809
if ((bp = onbill(obj, shkp, FALSE)) != 0) {
812
obj->unpaid = 0; /* only for doinvbill */
813
add_to_billobjs(obj);
816
bpm = onbill(merge, shkp, FALSE);
818
/* this used to be a rename */
819
impossible("obfree: not on bill??");
822
/* this was a merger */
823
bpm->bquan += bp->bquan;
824
ESHK(shkp)->billct--;
827
/* DRS/NS 2.2.6 messes up -- Peter Kendell */
828
int indx = ESHK(shkp)->billct;
829
*bp = ESHK(shkp)->bill_p[indx];
832
*bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
842
check_credit(tmp, shkp)
844
register struct monst *shkp;
846
long credit = ESHK(shkp)->credit;
848
if(credit == 0L) return(tmp);
850
pline_The("price is deducted from your credit.");
851
ESHK(shkp)->credit -=tmp;
854
pline_The("price is partially covered by your credit.");
855
ESHK(shkp)->credit = 0L;
864
register struct monst *shkp;
866
long robbed = ESHK(shkp)->robbed;
867
long balance = ((tmp <= 0L) ? tmp : check_credit(tmp, shkp));
871
shkp->mgold += balance;
873
if (balance > 0) money2mon(shkp, balance);
874
else if (balance < 0) money2u(shkp, -balance);
879
if(robbed < 0) robbed = 0L;
880
ESHK(shkp)->robbed = robbed;
886
/* return shkp to home position */
888
home_shk(shkp, killkops)
889
register struct monst *shkp;
890
register boolean killkops;
892
register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y;
894
(void) mnearto(shkp, x, y, TRUE);
895
level.flags.has_shop = 1;
900
You_feel("vaguely apprehensive.");
904
after_shk_move(shkp);
910
register struct monst *shkp;
912
for (shkp = next_shkp(fmon, FALSE);
913
shkp; shkp = next_shkp(shkp->nmon, FALSE))
914
if (ANGRY(shkp)) return(TRUE);
918
/* remove previously applied surcharge from all billed items */
921
register struct monst *shkp;
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;
928
ESHK(shkp)->surcharge = FALSE;
930
register long reduction = (bp->price + 3L) / 4L;
931
bp->price -= reduction; /* undo 33% increase */
937
/* add aggravation surcharge to all billed items */
940
register struct monst *shkp;
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;
947
ESHK(shkp)->surcharge = TRUE;
949
register long surcharge = (bp->price + 2L) / 3L;
950
bp->price += surcharge;
956
/* wakeup and/or unparalyze shopkeeper */
958
rouse_shk(shkp, verbosely)
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");
974
make_happy_shk(shkp, silentkops)
975
register struct monst *shkp;
976
register boolean silentkops;
978
boolean wasmad = ANGRY(shkp);
979
struct eshk *eshkp = ESHK(shkp);
982
eshkp->following = 0;
984
if (!Role_if(PM_ROGUE))
985
adjalign(sgn(u.ualign.type));
986
if(!inhishop(shkp)) {
988
boolean vanished = canseemon(shkp);
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;
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);
1006
pline("Satisfied, %s suddenly disappears!", shk_nam);
1008
pline("%s calms down.", Monnam(shkp));
1010
if(!angry_shk_exists()) {
1012
kops_gone(silentkops);
1020
register struct monst *shkp;
1022
if(!shkp->isshk) return;
1025
(void) strncpy(ESHK(shkp)->customer, plname, PL_NSIZ);
1026
ESHK(shkp)->following = 1;
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.
1035
make_angry_shk(shkp, ox, oy)
1036
register struct monst *shkp;
1037
register xchar ox,oy;
1040
struct eshk *eshkp = ESHK(shkp);
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 */
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;
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.";
1069
STATIC_VAR const char no_money[];
1070
STATIC_VAR const char not_enough_money[];
1076
cheapest_item(shkp) /* delivers the cheapest item on the list */
1077
register struct monst *shkp;
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);
1084
if(bp->price * bp->bquan < gmin)
1085
gmin = bp->price * bp->bquan;
1096
register struct eshk *eshkp;
1097
register struct monst *shkp;
1098
struct monst *nxtm, *resident;
1103
int pass, tmp, sk = 0, seensk = 0;
1104
boolean paid = FALSE, stashed_gold = (hidden_gold() > 0L);
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)) {
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))
1120
if (nxtm) { /* Player should always appease an */
1121
shkp = nxtm; /* irate shk standing next to them. */
1125
if ((!sk && (!Blind || Blind_telepat)) || (!Blind && !seensk)) {
1126
There("appears to be no shopkeeper here to receive your payment.");
1135
/* the usual case. allow paying at a distance when */
1136
/* inside a tended shop. should we change that? */
1137
if(sk == 1 && resident) {
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.",
1159
if (getpos(&cc, TRUE, "the creature you want to pay") < 0)
1160
return 0; /* player pressed ESC */
1164
pline("Try again...");
1167
if(u.ux == cx && u.uy == cy) {
1168
You("are generous to yourself.");
1171
mtmp = m_at(cx, cy);
1173
There("is no one there to receive your payment.");
1177
pline("%s is not interested in your payment.",
1181
if (mtmp != resident && distu(mtmp->mx, mtmp->my) > 2) {
1182
pline("%s is too far to receive your payment.",
1191
pline("dopay: null shkp.");
1197
ltmp = eshkp->robbed;
1199
/* wake sleeping shk when someone who owes money offers payment */
1200
if (ltmp || eshkp->billct || eshkp->debit)
1201
rouse_shk(shkp, TRUE);
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");
1209
if(shkp != resident && NOTANGRY(shkp)) {
1211
umoney = money_cnt(invent);
1214
You("do not owe %s anything.", mon_nam(shkp));
1220
You("%shave no money.", stashed_gold ? "seem to " : "");
1222
pline("But you have some gold stashed away.");
1225
long ugold = u.ugold;
1230
You("give %s the %ld gold piece%s %s asked for.",
1231
mon_nam(shkp), ltmp, plur(ltmp), mhe(shkp));
1234
You("give %s all your%s gold.", mon_nam(shkp),
1235
stashed_gold ? " openly kept" : "");
1241
if (stashed_gold) pline("But you have hidden gold!");
1244
if((ugold < ltmp/2L) || (ugold < ltmp && stashed_gold))
1246
if((umoney < ltmp/2L) || (umoney < ltmp && stashed_gold))
1248
pline("Unfortunately, %s doesn't look satisfied.",
1251
make_happy_shk(shkp, FALSE);
1256
/* ltmp is still eshkp->robbed here */
1257
if (!eshkp->billct && !eshkp->debit) {
1259
umoney = money_cnt(invent);
1261
if(!ltmp && NOTANGRY(shkp)) {
1262
You("do not owe %s anything.", mon_nam(shkp));
1268
pline(no_money, stashed_gold ? " seem to" : "");
1270
pline("%s is after blood, not money!", Monnam(shkp));
1272
if(u.ugold < ltmp/2L ||
1273
(u.ugold < ltmp && stashed_gold)) {
1276
if(umoney < ltmp/2L ||
1277
(umoney < ltmp && stashed_gold)) {
1280
pline(no_money, stashed_gold ? " seem to" : "");
1281
else pline(not_enough_money, mhim(shkp));
1284
pline("But since %s shop has been robbed recently,",
1286
pline("you %scompensate %s for %s losses.",
1293
mon_nam(shkp), mhis(shkp));
1295
pay(u.ugold < ltmp ? u.ugold : ltmp, shkp);
1297
pay(umoney < ltmp ? umoney : ltmp, shkp);
1299
make_happy_shk(shkp, FALSE);
1301
/* shopkeeper is angry, but has not been robbed --
1302
* door broken, attacked, etc. */
1303
pline("%s is after your hide, not your money!",
1306
if(u.ugold < 1000L) {
1309
if(umoney < 1000L) {
1312
pline(no_money, stashed_gold ? " seem to" : "");
1313
else pline(not_enough_money, mhim(shkp));
1316
You("try to appease %s by giving %s 1000 gold pieces.",
1317
x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE),
1320
if (strncmp(eshkp->customer, plname, PL_NSIZ) || rn2(3))
1321
make_happy_shk(shkp, FALSE);
1323
pline("But %s is as angry as ever.", mon_nam(shkp));
1327
if(shkp != resident) {
1328
impossible("dopay: not to shopkeeper?");
1329
if(resident) setpaid(resident);
1332
/* pay debt, if any, first */
1334
long dtmp = eshkp->debit;
1335
long loan = eshkp->loan;
1338
umoney = money_cnt(invent);
1340
Sprintf(sbuf, "You owe %s %ld %s ",
1341
shkname(shkp), dtmp, currency(dtmp));
1344
Strcat(sbuf, "you picked up in the store.");
1346
"for gold picked up and the use of merchandise.");
1347
} else Strcat(sbuf, "for the use of merchandise.");
1350
if (u.ugold + eshkp->credit < dtmp) {
1352
if (umoney + eshkp->credit < dtmp) {
1354
pline("But you don't%s have enough gold%s.",
1355
stashed_gold ? " seem to" : "",
1356
eshkp->credit ? " or credit" : "");
1359
if (eshkp->credit >= dtmp) {
1360
eshkp->credit -= dtmp;
1363
Your("debt is covered by your credit.");
1364
} else if (!eshkp->credit) {
1367
shkp->mgold += dtmp;
1369
money2mon(shkp, dtmp);
1373
You("pay that debt.");
1376
dtmp -= eshkp->credit;
1380
shkp->mgold += dtmp;
1382
money2mon(shkp, dtmp);
1386
pline("That debt is partially offset by your credit.");
1387
You("pay the remainder.");
1393
/* now check items on bill */
1394
if (eshkp->billct) {
1395
register boolean itemize;
1397
if (!u.ugold && !eshkp->credit) {
1399
umoney = money_cnt(invent);
1400
if (!umoney && !eshkp->credit) {
1402
You("%shave no money or credit%s.",
1403
stashed_gold ? "seem to " : "",
1404
paid ? " left" : "");
1408
if ((u.ugold + eshkp->credit) < cheapest_item(shkp)) {
1410
if ((umoney + eshkp->credit) < cheapest_item(shkp)) {
1412
You("don't have enough money to buy%s the item%s you picked.",
1413
eshkp->billct > 1 ? " any of" : "", plur(eshkp->billct));
1415
pline("Maybe you have some gold stashed away?");
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);
1423
for (pass = 0; pass <= 1; pass++) {
1425
while (tmp < eshkp->billct) {
1427
register struct bill_x *bp = &(eshkp->bill_p[tmp]);
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;
1436
impossible("Shopkeeper administration out of order.");
1437
setpaid(shkp); /* be nice to the player */
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 */
1447
switch (dopayobj(shkp, bp, &otmp, pass, itemize)) {
1452
goto thanks; /*break*/
1465
*bp = eshkp->bill_p[--eshkp->billct];
1471
update_inventory(); /* Done in dopayobj() if itemize. */
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);
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 */
1488
dopayobj(shkp, bp, obj_p, which, itemize)
1489
register struct monst *shkp;
1490
register struct bill_x *bp;
1492
int which; /* 0 => used-up item, 1 => other (unpaid or lost) */
1495
register struct obj *obj = *obj_p;
1496
long ltmp, quan, save_quan;
1498
long umoney = money_cnt(invent);
1501
boolean stashed_gold = (hidden_gold() > 0L),
1502
consumed = (which == 0);
1504
if(!obj->unpaid && !bp->useup){
1505
impossible("Paid object on bill??");
1509
if(itemize && u.ugold + ESHK(shkp)->credit == 0L){
1511
if(itemize && umoney + ESHK(shkp)->credit == 0L){
1513
You("%shave no money or credit left.",
1514
stashed_gold ? "seem to " : "");
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;
1521
/* either completely used up (simple), or split needed */
1523
if (quan > obj->quan) /* difference is amount used up */
1526
/* dealing with ordinary unpaid item */
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 */
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 */
1549
if (buy == PAY_BUY && u.ugold + ESHK(shkp)->credit < ltmp) {
1551
if (buy == PAY_BUY && umoney + ESHK(shkp)->credit < ltmp) {
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" : "",
1557
buy = itemize ? PAY_SKIP : PAY_CANT;
1560
if (buy != PAY_BUY) {
1561
/* restore unpaid object to original state */
1562
obj->quan = save_quan;
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 */
1574
if (quan != bp->bquan) {
1575
/* eliminate used-up portion; remainder is still unpaid */
1576
bp->bquan = obj->quan;
1580
} else { /* completely used-up, so get rid of it */
1581
obj_extract_self(obj);
1582
/* assert( obj == *obj_p ); */
1584
*obj_p = 0; /* destroy pointer to freed object */
1587
update_inventory(); /* Done just once in dopay() if !itemize. */
1593
static coord repo_location; /* repossession context */
1595
/* routine called after dying (or quitting) */
1598
int croaked; /* -1: escaped dungeon; 0: quit; 1: died */
1600
register struct monst *mtmp, *mtmp2, *resident= (struct monst *)0;
1601
register boolean taken = FALSE;
1602
register int numsk = 0;
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;
1609
/* this is where inventory will end up if any shk takes it */
1610
repo_location.x = repo_location.y = 0;
1612
/* give shopkeeper first crack */
1613
if ((mtmp = shop_keeper(*u.ushops)) && inhishop(mtmp)) {
1616
taken = inherits(resident, numsk, croaked);
1618
for (mtmp = next_shkp(fmon, FALSE);
1619
mtmp; mtmp = next_shkp(mtmp2, FALSE)) {
1621
if (mtmp != resident) {
1622
/* for bones: we don't want a shopless shk around */
1623
if(!on_level(&(ESHK(mtmp)->shoplevel), &u.uz))
1627
taken |= inherits(mtmp, numsk, croaked);
1631
if(numsk == 0) return(FALSE);
1636
inherits(shkp, numsk, croaked)
1645
struct eshk *eshkp = ESHK(shkp);
1646
boolean take = FALSE, taken = FALSE;
1647
int roomno = *u.ushops;
1650
/* the simplifying principle is that first-come */
1651
/* already took everything you had. */
1653
if (cansee(shkp->mx, shkp->my && croaked))
1654
pline("%s %slooks at your corpse%s and %s.",
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);
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) {
1671
pline("%s gratefully inherits all your possessions.",
1673
set_repo_loc(eshkp);
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;
1684
if (eshkp->following || ANGRY(shkp) || take) {
1686
if (!invent && !u.ugold) goto skip;
1688
if (!invent) goto skip;
1689
umoney = money_cnt(invent);
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");
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;
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);
1711
pline("%s %s all your possessions.",
1712
shkname(shkp), takes);
1714
/* where to put player's invent (after disclosure) */
1715
set_repo_loc(eshkp);
1718
shkp->mgold += loss;
1721
money2mon(shkp, loss);
1724
pline("%s %s the %ld %s %sowed %s.",
1725
Monnam(shkp), takes,
1726
loss, currency(loss),
1727
strncmp(eshkp->customer, plname, PL_NSIZ) ?
1729
shkp->female ? "her" : "him");
1730
/* shopkeeper has now been paid in full */
1732
eshkp->following = 0;
1736
/* in case we create bones */
1737
rouse_shk(shkp, FALSE); /* wake up */
1738
if (!inhishop(shkp))
1739
home_shk(shkp, FALSE);
1750
register xchar ox, oy;
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
1762
ox += sgn(ox - eshkp->shd.x);
1763
oy += sgn(oy - eshkp->shd.y);
1764
} else { /* already inside this shk's shop */
1768
/* finish_paybill will deposit invent here */
1769
repo_location.x = ox;
1770
repo_location.y = oy;
1773
/* called at game exit, after inventory disclosure but before making bones */
1777
register struct obj *otmp;
1778
int ox = repo_location.x,
1779
oy = repo_location.y;
1781
#if 0 /* don't bother */
1782
if (ox == 0 && oy == 0) impossible("finish_paybill: no location");
1784
/* normally done by savebones(), but that's too late in this case */
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);
1796
/* find obj on one of the lists */
1797
STATIC_OVL struct obj *
1799
register struct bill_x *bp;
1801
register struct obj *obj;
1802
register unsigned int id = bp->bo_id;
1805
obj = o_on(id, billobjs);
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.
1821
struct monst *mon, *mmtmp[3];
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;
1830
/* not found yet; check inventory for members of various monst lists */
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;
1838
/* not found at all */
1839
return (struct obj *)0;
1844
/* calculate the value that the shk will charge for [one of] an object */
1847
register struct obj *obj;
1848
register struct monst *shkp; /* if angry, impose a surcharge */
1850
register long tmp = getprice(obj, FALSE);
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) {
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);
1864
/* all gems are priced high - real or not */
1865
switch(obj->otyp - LAST_GEM) {
1867
i = pseudorand ? DIAMOND : OPAL;
1870
i = pseudorand ? SAPPHIRE : AQUAMARINE;
1873
i = pseudorand ? RUBY : JASPER;
1875
case 4: /* yellowish brown */
1876
i = pseudorand ? AMBER : TOPAZ;
1878
case 5: /* orange */
1879
i = pseudorand ? JACINTH : AGATE;
1881
case 6: /* yellow */
1882
i = pseudorand ? CITRINE : CHRYSOBERYL;
1885
i = pseudorand ? BLACK_OPAL : JET;
1888
i = pseudorand ? EMERALD : JADE;
1890
case 9: /* violet */
1891
i = pseudorand ? AMETHYST : FLUORITE;
1893
default: impossible("bad glass gem %d?", obj->otyp);
1897
tmp = (long) objects[i].oc_cost;
1898
} else if (!(obj->o_id % 4)) /* arbitrarily impose surcharge */
1902
if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2))
1903
|| (uarmu && !uarm && !uarmc)) /* touristy shirt visible */
1907
if (uarmh && uarmh->otyp == DUNCE_CAP)
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;
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.
1930
contained_cost(obj, shkp, price, usell, unpaid_only)
1931
register struct obj *obj;
1932
register struct monst *shkp;
1934
register boolean usell;
1935
register boolean unpaid_only;
1937
register struct obj *otmp;
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 */
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;
1955
if (Has_contents(otmp))
1956
price += contained_cost(otmp, shkp, price, usell, unpaid_only);
1964
register struct obj *obj;
1966
register struct obj *otmp;
1967
register long value = 0L;
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);
1980
dropped_container(obj, shkp, sale)
1981
register struct obj *obj;
1982
register struct monst *shkp;
1983
register boolean sale;
1985
register struct obj *otmp;
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;
1991
if (!otmp->unpaid && !(sale && saleable(shkp, otmp)))
1992
otmp->no_charge = 1;
1994
if (Has_contents(otmp))
1995
dropped_container(otmp, shkp, sale);
2000
picked_container(obj)
2001
register struct obj *obj;
2003
register struct obj *otmp;
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;
2009
if (otmp->no_charge)
2010
otmp->no_charge = 0;
2012
if (Has_contents(otmp))
2013
picked_container(otmp);
2019
/* calculate how much the shk will pay when buying [all of] an object */
2022
register struct obj *obj;
2023
register struct monst *shkp;
2025
long tmp = getprice(obj, TRUE) * obj->quan;
2028
if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2))
2029
|| (uarmu && !uarm && !uarmc)) /* touristy shirt visible */
2033
if (uarmh && uarmh->otyp == DUNCE_CAP)
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;
2048
} else if (tmp > 1L && !rn2(4))
2057
/* called from doinv(invent.c) for inventory of unpaid objects */
2059
unpaid_cost(unp_obj)
2060
register struct obj *unp_obj; /* known to be unpaid */
2062
register struct bill_x *bp = (struct bill_x *)0;
2063
register struct monst *shkp;
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;
2069
/* onbill() gave no message if unexpected problem occurred */
2070
if(!bp) impossible("unpaid_cost: object wasn't on any bill!");
2072
return bp ? unp_obj->quan * bp->price : 0L;
2076
add_one_tobill(obj, dummy)
2077
register struct obj *obj;
2078
register boolean dummy;
2080
register struct monst *shkp;
2081
register struct bill_x *bp;
2083
register char roomno = *u.ushops;
2085
if (!roomno) return;
2086
if (!(shkp = shop_keeper(roomno))) return;
2087
if (!inhishop(shkp)) return;
2089
if (onbill(obj, shkp, FALSE) || /* perhaps thrown away earlier */
2090
(obj->oclass == FOOD_CLASS && obj->oeaten))
2093
if (ESHK(shkp)->billct == BILLSZ) {
2094
You("got that for free!");
2098
/* To recognize objects the shopkeeper is not interested in. -dgk
2100
if (obj->no_charge) {
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++;
2119
add_to_billobjs(obj)
2122
if (obj->where != OBJ_FREE)
2123
panic("add_to_billobjs: obj not free");
2125
obj_stop_timers(obj);
2127
obj->nobj = billobjs;
2129
obj->where = OBJ_ONBILL;
2132
/* recursive billing of objects within containers. */
2134
bill_box_content(obj, ininv, dummy, shkp)
2135
register struct obj *obj;
2136
register boolean ininv, dummy;
2137
register struct monst *shkp;
2139
register struct obj *otmp;
2141
for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2142
if (otmp->oclass == COIN_CLASS) continue;
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);
2153
/* shopkeeper tells you what you bought or sold, sometimes partly IDing it */
2155
shk_names_obj(shkp, obj, fmt, amt, arg)
2158
const char *fmt; /* "%s %ld %s %s", doname(obj), amt, plur(amt), arg */
2162
char *obj_name, fmtbuf[BUFSZ];
2163
boolean was_unknown = !obj->dknown;
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.
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);
2177
obj_name = doname(obj);
2178
/* Use an alternate message when extra information is being provided */
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);
2185
You(fmt, obj_name, amt, plur(amt), arg);
2190
addtobill(obj, ininv, dummy, silent)
2191
register struct obj *obj;
2192
register boolean ininv, dummy, silent;
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);
2199
if(!*u.ushops) return;
2201
if(!(shkp = shop_keeper(roomno))) return;
2203
if(!inhishop(shkp)) return;
2205
if(/* perhaps we threw it away earlier */
2206
onbill(obj, shkp, FALSE) ||
2207
(obj->oclass == FOOD_CLASS && obj->oeaten)
2210
if(ESHK(shkp)->billct == BILLSZ) {
2211
You("got that for free!");
2215
if(obj->oclass == COIN_CLASS) {
2216
costly_gold(obj->ox, obj->oy, obj->quan);
2221
ltmp = get_cost(obj, shkp);
2223
if (obj->no_charge && !container) {
2229
if(obj->cobj == (struct obj *)0) {
2230
if(obj->no_charge) {
2234
add_one_tobill(obj, dummy);
2238
cltmp += contained_cost(obj, shkp, cltmp, FALSE, FALSE);
2239
gltmp += contained_gold(obj);
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 */
2249
costly_gold(obj->ox, obj->oy, gltmp);
2256
} else /* i.e., !container */
2257
add_one_tobill(obj, dummy);
2259
if (shkp->mcanmove && !shkp->msleeping && !silent) {
2263
pline("%s has no interest in %s.", Monnam(shkp),
2267
Strcpy(buf, "\"For you, ");
2268
if (ANGRY(shkp)) Strcat(buf, "scum ");
2270
static const char *honored[5] = {
2271
"good", "honored", "most gracious", "esteemed",
2272
"most renowned and sacred"
2274
Strcat(buf, honored[rn2(4) + u.uevent.udemigod]);
2275
if (!is_human(youmonst.data)) Strcat(buf, " creature");
2277
Strcat(buf, (flags.female) ? " lady" : " sir");
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));
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));
2298
splitbill(obj, otmp)
2299
register struct obj *obj, *otmp;
2301
/* otmp has been split off from obj */
2302
register struct bill_x *bp;
2304
register struct monst *shkp = shop_keeper(*u.ushops);
2306
if(!shkp || !inhishop(shkp)) {
2307
impossible("splitbill: no resident shopkeeper??");
2310
bp = onbill(obj, shkp, FALSE);
2312
impossible("splitbill: not on bill?");
2315
if(bp->bquan < otmp->quan) {
2316
impossible("Negative quantity on bill??");
2318
if(bp->bquan == otmp->quan) {
2319
impossible("Zero quantity on bill??");
2321
bp->bquan -= otmp->quan;
2323
if(ESHK(shkp)->billct == BILLSZ) otmp->unpaid = 0;
2326
bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
2327
bp->bo_id = otmp->o_id;
2328
bp->bquan = otmp->quan;
2331
ESHK(shkp)->billct++;
2336
sub_one_frombill(obj, shkp)
2337
register struct obj *obj;
2338
register struct monst *shkp;
2340
register struct bill_x *bp;
2342
if((bp = onbill(obj, shkp, FALSE)) != 0) {
2343
register struct obj *otmp;
2346
if(bp->bquan > obj->quan){
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 */
2355
otmp->oattached = OATTACHED_NOTHING;
2357
add_to_billobjs(otmp);
2360
ESHK(shkp)->billct--;
2363
/* DRS/NS 2.2.6 messes up -- Peter Kendell */
2364
int indx = ESHK(shkp)->billct;
2365
*bp = ESHK(shkp)->bill_p[indx];
2368
*bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
2371
} else if (obj->unpaid) {
2372
impossible("sub_one_frombill: unpaid object not on bill");
2377
/* recursive check of unpaid objects within nested containers. */
2379
subfrombill(obj, shkp)
2380
register struct obj *obj;
2381
register struct monst *shkp;
2383
register struct obj *otmp;
2385
sub_one_frombill(obj, shkp);
2387
if (Has_contents(obj))
2388
for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2389
if(otmp->oclass == COIN_CLASS) continue;
2391
if (Has_contents(otmp))
2392
subfrombill(otmp, shkp);
2394
sub_one_frombill(otmp, shkp);
2402
stolen_container(obj, shkp, price, ininv)
2403
register struct obj *obj;
2404
register struct monst *shkp;
2406
register boolean ininv;
2408
register struct obj *otmp;
2410
if(ininv && obj->unpaid)
2411
price += get_cost(obj, shkp);
2414
price += get_cost(obj, shkp);
2418
/* the price of contained objects, if any */
2419
for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2421
if(otmp->oclass == COIN_CLASS) continue;
2423
if (!Has_contents(otmp)) {
2426
price += otmp->quan * get_cost(otmp, shkp);
2428
if(!otmp->no_charge) {
2429
if(otmp->oclass != FOOD_CLASS || !otmp->oeaten)
2430
price += otmp->quan * get_cost(otmp, shkp);
2432
otmp->no_charge = 0;
2435
price += stolen_container(otmp, shkp, price, ininv);
2444
stolen_value(obj, x, y, peaceful, silent)
2445
register struct obj *obj;
2446
register xchar x, y;
2447
register boolean peaceful, silent;
2449
register long value = 0L, gvalue = 0L;
2450
register struct monst *shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
2452
if (!shkp || !inhishop(shkp))
2455
if(obj->oclass == COIN_CLASS) {
2456
gvalue += obj->quan;
2457
} else if (Has_contents(obj)) {
2458
register boolean ininv = !!count_unpaid(obj->cobj);
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);
2466
if(gvalue + value == 0L) return(0L);
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 */
2477
ESHK(shkp)->robbed += value;
2479
ESHK(shkp)->debit += value;
2482
const char *still = "";
2485
if (ESHK(shkp)->credit) {
2486
You("have %ld %s credit remaining.",
2487
ESHK(shkp)->credit, currency(ESHK(shkp)->credit));
2489
} else if (!value) {
2490
You("have no credit remaining.");
2495
if(obj->oclass == COIN_CLASS)
2496
You("%sowe %s %ld %s!", still,
2497
mon_nam(shkp), value, currency(value));
2499
You("%sowe %s %ld %s for %s!", still,
2500
mon_nam(shkp), value, currency(value),
2501
obj->quan > 1L ? "them" : "it");
2504
ESHK(shkp)->robbed += value;
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!\"");
2513
(void) angry_guards(FALSE);
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;
2526
sellobj_state(deliberate)
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.
2535
sell_response = (deliberate != SELL_NORMAL) ? '\0' : 'a';
2536
sell_how = deliberate;
2537
auto_credit = FALSE;
2542
register struct obj *obj;
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;
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;
2557
if(obj->unpaid && !container && !isgold) {
2558
sub_one_frombill(obj, shkp);
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);
2569
saleitem = saleable(shkp, obj);
2570
if(!isgold && !obj->unpaid && saleitem)
2571
ltmp = set_cost(obj, shkp);
2573
offer = ltmp + cltmp;
2575
/* get one case out of the way: nothing to sell, and no gold */
2577
((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) {
2578
register boolean unpaid = (obj->unpaid ||
2579
(container && count_unpaid(obj->cobj)));
2582
dropped_container(obj, shkp, FALSE);
2583
if(!obj->unpaid && !saleitem)
2585
if(obj->unpaid || count_unpaid(obj->cobj))
2586
subfrombill(obj, shkp);
2587
} else obj->no_charge = 1;
2589
if(!unpaid && (sell_how != SELL_DONTSELL))
2590
pline("%s seems uninterested.", Monnam(shkp));
2594
/* you dropped something of your own - probably want to sell it */
2595
rouse_shk(shkp, TRUE); /* wake up sleeping or paralyzed shk */
2598
if (ANGRY(shkp)) { /* they become shop-objects, no pay */
2599
pline("Thank you, scum!");
2600
subfrombill(obj, shkp);
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))
2609
if(offer) verbalize(
2610
"Thank you for your contribution to restock this recently plundered shop.");
2611
subfrombill(obj, shkp);
2615
if(isgold || cgold) {
2616
if(!cgold) gltmp = obj->quan;
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;
2624
eshkp->debit -= gltmp;
2625
Your("debt is %spaid off.",
2626
eshkp->debit ? "partially " : "");
2628
long delta = gltmp - eshkp->debit;
2630
eshkp->credit += delta;
2634
Your("debt is paid off.");
2636
pline("%ld %s %s added to your credit.",
2637
delta, currency(delta), delta > 1L ? "are" : "is");
2639
if(offer) goto move_on;
2643
dropped_container(obj, shkp, FALSE);
2644
if (!obj->unpaid && !saleitem) obj->no_charge = 1;
2645
subfrombill(obj, shkp);
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" : "");
2661
dropped_container(obj, shkp, FALSE);
2669
if(!money_cnt(shkp->minvent)) {
2671
char c, qbuf[BUFSZ];
2672
long tmpcr = ((offer * 9L) / 10L) + (offer <= 1L);
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));
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 */
2689
} else /* previously specified "quit" */
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.",
2697
(eshkp->credit > 0L) ? "additional " : "");
2698
eshkp->credit += tmpcr;
2699
subfrombill(obj, shkp);
2701
if (c == 'q') sell_response = 'n';
2703
dropped_container(obj, shkp, FALSE);
2704
if (!obj->unpaid) obj->no_charge = 1;
2705
subfrombill(obj, shkp);
2710
boolean short_funds = (offer > shkp->mgold);
2711
if (short_funds) offer = shkp->mgold;
2713
long shkmoney = money_cnt(shkp->minvent);
2714
boolean short_funds = (offer > shkmoney);
2715
if (short_funds) offer = shkmoney;
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));
2722
"%s offers%s %ld gold piece%s for%s %s %s. Sell %s?",
2723
Monnam(shkp), short_funds ? " only" : "",
2725
(!ltmp && cltmp && only_partially_your_contents) ?
2726
" your items in" : (!ltmp && cltmp) ? " the contents of" : "",
2727
obj->unpaid ? "the" : "your", cxname(obj),
2729
!(!ltmp && cltmp && only_partially_your_contents)) ?
2731
} else qbuf[0] = '\0'; /* just to pacify lint */
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);
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);
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",
2753
default: impossible("invalid sell response");
2760
int mode; /* 0: deliver count 1: paged */
2763
void sasc_bug(struct obj *, unsigned);
2767
struct bill_x *bp, *end_bp;
2773
shkp = shop_keeper(*u.ushops);
2774
if (!shkp || !inhishop(shkp)) {
2775
if (mode != 0) impossible("doinvbill: no shopkeeper?");
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;
2785
for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct];
2788
((obj = bp_to_obj(bp)) != 0 && obj->quan < bp->bquan))
2793
datawin = create_nhwindow(NHW_MENU);
2794
putstr(datawin, 0, "Unpaid articles already used up:");
2795
putstr(datawin, 0, "");
2798
for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct];
2799
bp < end_bp; bp++) {
2800
obj = bp_to_obj(bp);
2802
impossible("Bad shopkeeper administration.");
2805
if(bp->useup || bp->bquan > obj->quan) {
2806
long oquan, uquan, thisused;
2807
unsigned save_unpaid;
2809
save_unpaid = obj->unpaid;
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);
2818
/* SAS/C 6.2 can't cope for some reason */
2819
sasc_bug(obj,save_unpaid);
2821
obj->unpaid = save_unpaid;
2823
putstr(datawin, 0, buf_p);
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);
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);
2840
destroy_nhwindow(datawin);
2847
getprice(obj, shk_buying)
2848
register struct obj *obj;
2851
register long tmp = (long) objects[obj->otyp].oc_cost;
2853
if (obj->oartifact) {
2854
tmp = arti_cost(obj);
2855
if (shk_buying) tmp /= 4;
2857
switch(obj->oclass) {
2859
/* simpler hunger check, (2-4)*cost */
2860
if (u.uhs >= HUNGRY && !shk_buying) tmp *= (long) u.uhs;
2861
if (obj->oeaten) tmp = 0L;
2864
if (obj->spe == -1) tmp = 0L;
2867
if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
2872
if (obj->spe > 0) tmp += 10L * (long) obj->spe;
2875
if (Is_candle(obj) &&
2876
obj->age < 20L * (long)objects[obj->otyp].oc_cost)
2883
/* shk catches thrown pick-axe */
2886
register struct obj *obj;
2887
register xchar x, y;
2889
register struct monst *shkp;
2891
if (!(shkp = shop_keeper(inside_shop(x, y))) ||
2892
!inhishop(shkp)) return(0);
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!");
2902
pline("%s nimbly%s catches %s.",
2904
(x == shkp->mx && y == shkp->my) ? "" : " reaches over and",
2906
if (!canspotmon(shkp))
2907
map_invisible(x, y);
2911
subfrombill(obj, shkp);
2912
(void) mpickobj(shkp, obj);
2915
return (struct monst *)0;
2919
add_damage(x, y, cost)
2920
register xchar x, y;
2923
struct damage *tmp_dam;
2926
if (IS_DOOR(levl[x][y].typ)) {
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)
2934
if (!*shops) return;
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;
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 */
2951
levl[x][y].seenv = SVALL;
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
2967
remove_damage(shkp, croaked)
2968
register struct monst *shkp;
2969
register boolean croaked;
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;
2977
tmp_dam = level.damagelist;
2980
register xchar x = tmp_dam->place.x, y = tmp_dam->place.y;
2985
Strcpy(shops, in_rooms(x, y, SHOPBASE));
2986
if (index(shops, ESHK(shkp)->shoproom)) {
2988
disposition = (shops[1])? 0 : 1;
2989
else if (stop_picking)
2990
disposition = repair_damage(shkp, tmp_dam, FALSE);
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);
2997
stop_picking = FALSE;
3003
tmp_dam = tmp_dam->next;
3007
if (disposition > 1) {
3010
if (IS_WALL(levl[x][y].typ))
3012
else if (IS_DOOR(levl[x][y].typ))
3014
else if (disposition == 3) /* untrapped */
3021
tmp_dam = tmp_dam->next;
3023
free((genericptr_t)level.damagelist);
3024
level.damagelist = tmp_dam;
3026
free((genericptr_t)tmp2_dam->next);
3027
tmp2_dam->next = tmp_dam;
3033
pline("Suddenly, %s section%s of wall close%s up!",
3034
(saw_walls == 1) ? "a" : (saw_walls <= 3) ?
3036
(saw_walls == 1) ? "" : "s", (saw_walls == 1) ? "s" : "");
3038
pline_The("shop door reappears!");
3040
pline_The("floor is repaired!");
3043
pline("Suddenly, the shop door reappears!");
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.");
3058
* 0: repair postponed, 1: silent repair (no messages), 2: normal repair
3062
repair_damage(shkp, tmp_dam, catchup)
3063
register struct monst *shkp;
3064
register struct damage *tmp_dam;
3065
boolean catchup; /* restoring a level */
3067
register xchar x, y, i;
3069
register struct monst *mtmp;
3070
register struct obj *otmp;
3071
register struct trap *ttmp;
3073
if ((monstermoves - tmp_dam->when) < REPAIR_DELAY)
3075
if (shkp->msleeping || !shkp->mcanmove || ESHK(shkp)->following)
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)
3083
if (x == shkp->mx && y == shkp->my)
3085
if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data)))
3088
if ((ttmp = t_at(x, y)) != 0) {
3089
if (x == u.ux && y == u.uy)
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);
3097
otmp->owt = weight(otmp);
3098
(void) mpickobj(shkp, otmp);
3101
if(IS_DOOR(tmp_dam->typ)) {
3102
levl[x][y].doormask = D_CLOSED; /* arbitrary */
3104
} else if (IS_WALL(tmp_dam->typ)) {
3105
levl[x][y].typ = tmp_dam->typ;
3111
if (IS_ROOM(tmp_dam->typ)) {
3112
/* No messages, because player already filled trap door */
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 */
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
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)))
3132
if (inside_shop(x+horiz(i),
3133
y+vert(i)) == ESHK(shkp)->shoproom)
3134
litter[i] |= INSHOP;
3136
if (Punished && !u.uswallow &&
3137
((uchain->ox == x && uchain->oy == y) ||
3138
(uball->ox == x && uball->oy == y))) {
3140
* Either the ball or chain is in the repair location.
3142
* Take the easy way out and put ball&chain under hero.
3144
verbalize("Get your junk out of my wall!");
3145
unplacebc(); /* pick 'em up */
3146
placebc(); /* put 'em down */
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);
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;
3160
if (catchup) return 1; /* repair occurred while off level */
3163
if(IS_DOOR(tmp_dam->typ)) {
3164
levl[x][y].doormask = D_CLOSED; /* arbitrary */
3167
/* don't set doormask - it is (hopefully) the same as it was */
3168
/* if not, perhaps save it with the damage array... */
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;
3175
/* Mark this wall as "repaired". There currently is no code */
3176
/* to do anything about repaired walls, so don't do it. */
3178
for (i = 0; i < 9; i++)
3179
if (litter[i] & NEED_UPDATE)
3180
newsym(x+horiz(i), y+vert(i));
3191
* shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
3195
register struct monst *shkp;
3197
register xchar gx,gy,omx,omy;
3199
register schar appr;
3200
register struct eshk *eshkp = ESHK(shkp);
3202
boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv;
3208
remove_damage(shkp, FALSE);
3210
if((udist = distu(omx,omy)) < 3 &&
3211
(shkp->data != &mons[PM_GRID_BUG] || (omx==u.ux || omy==u.uy))) {
3213
(Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
3215
Your("displaced image doesn't fool %s!",
3217
(void) mattacku(shkp);
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;
3227
if(moves > followmsg+4) {
3228
verbalize("%s, %s! Didn't you forget to pay?",
3229
Hello(shkp), plname);
3232
pline("%s doesn't like customers who don't pay.",
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 */
3258
} else if(ANGRY(shkp)) {
3259
/* Move towards the hero if the shopkeeper can see him. */
3260
if(shkp->mcansee && m_canseeu(shkp)) {
3266
#define GDIST(x,y) (dist2(x,y,gx,gy))
3274
uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y);
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)
3283
avoid = (*u.ushops && distu(gx,gy) > 8);
3287
if(((!eshkp->robbed && !eshkp->billct && !eshkp->debit)
3288
|| avoid) && GDIST(omx,omy) < 3) {
3289
if (!badinv && !onlineu(omx,omy))
3297
z = move_special(shkp,inhishop(shkp),appr,uondoor,avoid,omx,omy,gx,gy);
3298
if (z > 0) after_shk_move(shkp);
3303
/* called after shopkeeper moves, in case the move causes re-entry into shop */
3305
after_shk_move(shkp)
3308
struct eshk *eshkp = ESHK(shkp);
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);
3320
/* for use in levl_follower (mondata.c) */
3323
register struct monst *mtmp;
3325
return((boolean)(mtmp->isshk && ESHK(mtmp)->following));
3328
/* You are digging in the shop. */
3333
register struct monst *shkp = shop_keeper(*u.ushops);
3335
const char *grabs = "grabs";
3339
/* 0 == can't speak, 1 == makes animal noises, 2 == speaks */
3341
if (shkp->msleeping || !shkp->mcanmove || is_silent(shkp->data))
3342
; /* lang stays 0 */
3343
else if (shkp->data->msound <= MS_ANIMAL)
3345
else if (shkp->data->msound >= MS_HUMANOID)
3348
if(!inhishop(shkp)) {
3349
if (Role_if(PM_KNIGHT)) {
3350
You_feel("like a common thief.");
3351
adjalign(-sgn(u.ualign.type));
3358
if(u.utraptype == TT_PIT)
3360
"Be careful, %s, or you might fall through the floor.",
3361
flags.female ? "madam" : "sir");
3363
verbalize("%s, do not damage the floor here!",
3364
flags.female ? "Madam" : "Sir");
3366
if (Role_if(PM_KNIGHT)) {
3367
You_feel("like a common thief.");
3368
adjalign(-sgn(u.ualign.type));
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";
3377
/* This is what should happen, but for balance
3378
* reasons, it isn't currently.
3381
pline("%s curses %s inability to grab your backpack!",
3382
shkname(shkp), mhim(shkp));
3387
if (distu(shkp->mx, shkp->my) > 2) {
3389
/* for some reason the shopkeeper can't come next to you */
3390
if (distu(shkp->mx, shkp->my) > 2) {
3392
pline("%s curses you in anger and frustration!",
3397
pline("%s %s, and %s your backpack!",
3399
makeplural(locomotion(shkp->data,"leap")), grabs);
3401
pline("%s %s your backpack!", shkname(shkp), grabs);
3403
for(obj = invent; obj; obj = obj2) {
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;
3411
subfrombill(obj, shkp);
3412
(void) add_to_minv(shkp, obj); /* may free obj */
3422
static const short k_mndx[4] = {
3423
PM_KEYSTONE_KOP, PM_KOP_SERGEANT, PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN
3425
int k_cnt[4], cnt, mndx, k;
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 */
3432
for (k = 0; k < 4; k++) {
3433
if ((cnt = k_cnt[k]) == 0) break;
3435
if (mvitals[mndx].mvflags & G_GONE) continue;
3438
if (enexto(mm, mm->x, mm->y, &mons[mndx]))
3439
(void) makemon(&mons[mndx], mm->x, mm->y, NO_MM_FLAGS);
3445
pay_for_damage(dmgstr, cant_mollify)
3447
boolean cant_mollify;
3449
register struct monst *shkp = (struct monst *)0;
3450
char shops_affected[5];
3451
register boolean uinshp = (*u.ushops != '\0');
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;
3462
for (tmp_dam = level.damagelist;
3463
(tmp_dam && (tmp_dam->when == monstermoves));
3464
tmp_dam = tmp_dam->next) {
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;
3476
if (!(tmp_shk = shop_keeper(*shp)))
3478
if (tmp_shk == shkp) {
3479
unsigned int damage_distance =
3480
distu(tmp_dam->place.x, tmp_dam->place.y);
3482
if (damage_distance < nearest_damage) {
3483
nearest_damage = damage_distance;
3484
appear_here = tmp_dam;
3488
if (!inhishop(tmp_shk))
3490
shk_distance = distu(tmp_shk->mx, tmp_shk->my);
3491
if (shk_distance > nearest_shk)
3493
if ((shk_distance == nearest_shk) && picks) {
3499
nearest_shk = shk_distance;
3500
appear_here = tmp_dam;
3501
nearest_damage = distu(tmp_dam->place.x, tmp_dam->place.y);
3505
if (!cost_of_damage || !shkp)
3508
x = appear_here->place.x;
3509
y = appear_here->place.y;
3511
/* not the best introduction to the shk... */
3512
(void) strncpy(ESHK(shkp)->customer,plname,PL_NSIZ);
3514
/* if the shk is already on the war path, be sure it's all out */
3515
if(ANGRY(shkp) || ESHK(shkp)->following) {
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))
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));
3533
if(um_dist(shkp->mx, shkp->my, 1)) goto getcad;
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.
3543
You_hear("an angry voice:");
3544
verbalize("Out of my way, scum!");
3546
#if defined(UNIX) || defined(VMS)
3547
# if defined(SYSV) || defined(ULTRIX) || defined(VMS)
3554
(void) mnearto(shkp, x, y, TRUE);
3557
if((um_dist(x, y, 1) && !uinshp) || cant_mollify ||
3559
(u.ugold + ESHK(shkp)->credit) < cost_of_damage
3561
(money_cnt(invent) + ESHK(shkp)->credit) < cost_of_damage
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");
3570
verbalize("How dare you %s my %s?", dmgstr,
3571
dugwall ? "shop" : "door");
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);
3583
u.ugold -= cost_of_damage;
3584
shkp->mgold += cost_of_damage;
3586
money2mon(shkp, cost_of_damage);
3589
pline("Mollified, %s accepts your restitution.",
3591
/* move shk back to his home loc */
3592
home_shk(shkp, FALSE);
3595
verbalize("Oh, yes! You'll pay!");
3597
adjalign(-sgn(u.ualign.type));
3602
/* called in dokick.c when we kick an object that might be in a store */
3605
register xchar x, y;
3607
register struct monst *shkp;
3609
if (!level.flags.has_shop) return FALSE;
3610
shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
3611
if(!shkp || !inhishop(shkp)) return(FALSE);
3613
return((boolean)(inside_shop(x, y) &&
3614
!(x == ESHK(shkp)->shk.x &&
3615
y == ESHK(shkp)->shk.y)));
3620
/* called by dotalk(sounds.c) when #chatting; returns obj if location
3621
contains shop goods and shopkeeper is willing & able to speak */
3624
register xchar x, y;
3626
register struct obj *otmp;
3627
register struct monst *shkp;
3629
if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
3630
return(struct obj *)0;
3632
for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
3633
if (otmp->oclass != COIN_CLASS)
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;
3641
/* give price quotes for all objects linked to this one (ie, on this spot) */
3643
price_quote(first_obj)
3644
register struct obj *first_obj;
3646
register struct obj *otmp;
3647
char buf[BUFSZ], price[40];
3651
struct monst *shkp = shop_keeper(inside_shop(u.ux, u.uy));
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);
3663
Strcpy(price, "no charge");
3665
Sprintf(price, "%ld %s%s", cost, currency(cost),
3666
otmp->quan > 1L ? " each" : "");
3668
Sprintf(buf, "%s, %s", doname(otmp), price);
3669
putstr(tmpwin, 0, buf), cnt++;
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 */
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));
3686
destroy_nhwindow(tmpwin);
3691
STATIC_OVL const char *
3692
shk_embellish(itm, cost)
3693
register struct obj *itm;
3697
register int o, choice = rn2(5);
3698
if (choice == 0) choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
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.";
3715
} else if (itm->oartifact) {
3716
return ", one of a kind!";
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."
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.",
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.] */
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;
3768
verbalize("%s %s! Didn't you forget to pay?",
3769
Hello(shkp), plname);
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));
3785
else if (shkp->mgold < 50)
3787
else if ((shkmoney = money_cnt(shkp->minvent)) < 50)
3789
pline("%s complains that business is bad.", shkname(shkp));
3791
else if (shkp->mgold > 4000)
3793
else if (shkmoney > 4000)
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));
3799
pline("%s talks about the problem of shoplifters.",shkname(shkp));
3805
register boolean silent;
3807
register int cnt = 0;
3808
register struct monst *mtmp, *mtmp2;
3810
for (mtmp = fmon; mtmp; mtmp = mtmp2) {
3812
if (mtmp->data->mlet == S_KOP) {
3813
if (canspotmon(mtmp)) cnt++;
3818
pline_The("Kop%s (disappointed) vanish%s into thin air.",
3819
plur(cnt), cnt == 1 ? "es" : "");
3827
cost_per_charge(shkp, otmp, altusage)
3830
boolean altusage; /* some items have an "alternate" use with different cost */
3834
if(!shkp || !inhishop(shkp)) return(0L); /* insurance */
3835
tmp = get_cost(otmp, shkp);
3837
/* The idea is to make the exhaustive use of */
3838
/* an unpaid item more expensive than buying */
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. */
3854
} else if(otmp->otyp == BAG_OF_TRICKS || /* 1 - 20 */
3855
otmp->otyp == HORN_OF_PLENTY) {
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) {
3866
} else if (otmp->otyp == CAN_OF_GREASE ||
3867
otmp->otyp == TINNING_KIT
3869
|| otmp->otyp == EXPENSIVE_CAMERA
3873
} else if (otmp->otyp == POT_OIL) {
3881
/* Charge the player for partial use of an unpaid object.
3883
* Note that bill_dummy_object() should be used instead
3884
* when an object is completely used.
3887
check_unpaid_usage(otmp, altusage)
3892
const char *fmt, *arg1, *arg2;
3895
if (!otmp->unpaid || !*u.ushops ||
3896
(otmp->spe <= 0 && objects[otmp->otyp].oc_charged))
3898
if (!(shkp = shop_keeper(*u.ushops)) || !inhishop(shkp))
3900
if ((tmp = cost_per_charge(shkp, otmp, altusage)) == 0L)
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).";
3911
fmt = "%s%sUsage fee, %ld %s.";
3912
if (!rn2(3)) arg1 = "Hey! ";
3913
if (!rn2(3)) arg2 = "Ahem. ";
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 */
3922
/* for using charges of unpaid objects "used in the normal manner" */
3927
check_unpaid_usage(otmp, FALSE); /* normal item use */
3931
costly_gold(x, y, amount)
3932
register xchar x, y;
3933
register long amount;
3935
register long delta;
3936
register struct monst *shkp;
3937
register struct eshk *eshkp;
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));
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;
3951
delta = amount - eshkp->credit;
3953
Your("credit is erased.");
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;
3965
/* used in domove to block diagonal shop-exit */
3966
/* x,y should always be a door */
3969
register xchar x, y;
3971
register int roomno = *in_rooms(x, y, SHOPBASE);
3972
register struct monst *shkp;
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);
3978
if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp))
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.
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" : "");
3997
/* used in domove to block diagonal shop-entry */
3998
/* u.ux, u.uy should always be a door */
4001
register xchar x, y;
4003
register xchar sx, sy;
4004
register int roomno;
4005
register struct monst *shkp;
4007
if(!(IS_DOOR(levl[u.ux][u.uy].typ) &&
4008
levl[u.ux][u.uy].doormask == D_BROKEN)) return(FALSE);
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))
4015
if(ESHK(shkp)->shd.x != u.ux || ESHK(shkp)->shd.y != u.uy)
4018
sx = ESHK(shkp)->shk.x;
4019
sy = ESHK(shkp)->shk.y;
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)
4029
pline("%s%s blocks your way!", shkname(shkp),
4030
Invis ? " senses your motion and" : "");
4044
if (!shk_owns(buf, obj) && !mon_owns(buf, obj))
4045
Strcpy(buf, carried(obj) ? "your" : "the");
4054
(void) shk_your(buf, obj);
4067
if (get_obj_location(obj, &x, &y, 0) &&
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");
4081
if (obj->where == OBJ_MINVENT)
4082
return strcpy(buf, s_suffix(mon_nam(obj->ocarry)));
4091
sasc_bug(struct obj *op, unsigned x){