1 /* NetHack 3.6 shk.c $NHDT-Date: 1457392872 2016/03/07 23:21:12 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.125 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
9 #define PAY_CANT 0 /* too poor */
11 #define PAY_BROKE (-2)
13 STATIC_DCL
void FDECL(makekops
, (coord
*));
14 STATIC_DCL
void FDECL(call_kops
, (struct monst
*, BOOLEAN_P
));
15 STATIC_DCL
void FDECL(kops_gone
, (BOOLEAN_P
));
17 #define NOTANGRY(mon) ((mon)->mpeaceful)
18 #define ANGRY(mon) (!NOTANGRY(mon))
19 #define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE)
21 #define muteshk(shkp) \
22 ((shkp)->msleeping || !(shkp)->mcanmove \
23 || (shkp)->data->msound <= MS_ANIMAL)
25 extern const struct shclass shtypes
[]; /* defined in shknam.c */
27 STATIC_VAR NEARDATA
long int followmsg
; /* last time of follow message */
28 STATIC_VAR
const char and_its_contents
[] = " and its contents";
29 STATIC_VAR
const char the_contents_of
[] = "the contents of ";
31 STATIC_DCL
void FDECL(append_honorific
, (char *));
32 STATIC_DCL
void FDECL(setpaid
, (struct monst
*));
33 STATIC_DCL
long FDECL(addupbill
, (struct monst
*));
34 STATIC_DCL
void FDECL(pacify_shk
, (struct monst
*));
35 STATIC_DCL
struct bill_x
*FDECL(onbill
, (struct obj
*, struct monst
*,
37 STATIC_DCL
struct monst
*FDECL(next_shkp
, (struct monst
*, BOOLEAN_P
));
38 STATIC_DCL
long FDECL(shop_debt
, (struct eshk
*));
39 STATIC_DCL
char *FDECL(shk_owns
, (char *, struct obj
*));
40 STATIC_DCL
char *FDECL(mon_owns
, (char *, struct obj
*));
41 STATIC_DCL
void FDECL(clear_unpaid_obj
, (struct monst
*, struct obj
*));
42 STATIC_DCL
void FDECL(clear_unpaid
, (struct monst
*, struct obj
*));
43 STATIC_DCL
long FDECL(check_credit
, (long, struct monst
*));
44 STATIC_DCL
void FDECL(pay
, (long, struct monst
*));
45 STATIC_DCL
long FDECL(get_cost
, (struct obj
*, struct monst
*));
46 STATIC_DCL
long FDECL(set_cost
, (struct obj
*, struct monst
*));
47 STATIC_DCL
const char *FDECL(shk_embellish
, (struct obj
*, long));
48 STATIC_DCL
long FDECL(cost_per_charge
, (struct monst
*, struct obj
*,
50 STATIC_DCL
long FDECL(cheapest_item
, (struct monst
*));
51 STATIC_DCL
int FDECL(dopayobj
, (struct monst
*, struct bill_x
*,
52 struct obj
**, int, BOOLEAN_P
));
53 STATIC_DCL
long FDECL(stolen_container
, (struct obj
*, struct monst
*,
55 STATIC_DCL
long FDECL(getprice
, (struct obj
*, BOOLEAN_P
));
56 STATIC_DCL
void FDECL(shk_names_obj
, (struct monst
*, struct obj
*,
57 const char *, long, const char *));
58 STATIC_DCL
struct obj
*FDECL(bp_to_obj
, (struct bill_x
*));
59 STATIC_DCL boolean
FDECL(inherits
, (struct monst
*, int, int));
60 STATIC_DCL
void FDECL(set_repo_loc
, (struct monst
*));
61 STATIC_DCL boolean
NDECL(angry_shk_exists
);
62 STATIC_DCL
void FDECL(rile_shk
, (struct monst
*));
63 STATIC_DCL
void FDECL(rouse_shk
, (struct monst
*, BOOLEAN_P
));
64 STATIC_DCL
void FDECL(remove_damage
, (struct monst
*, BOOLEAN_P
));
65 STATIC_DCL
void FDECL(sub_one_frombill
, (struct obj
*, struct monst
*));
66 STATIC_DCL
void FDECL(add_one_tobill
, (struct obj
*, BOOLEAN_P
,
68 STATIC_DCL
void FDECL(dropped_container
, (struct obj
*, struct monst
*,
70 STATIC_DCL
void FDECL(add_to_billobjs
, (struct obj
*));
71 STATIC_DCL
void FDECL(bill_box_content
, (struct obj
*, BOOLEAN_P
, BOOLEAN_P
,
73 STATIC_DCL boolean
FDECL(rob_shop
, (struct monst
*));
74 STATIC_DCL
void FDECL(deserted_shop
, (char *));
75 STATIC_DCL boolean
FDECL(special_stock
, (struct obj
*, struct monst
*,
77 STATIC_DCL
const char *FDECL(cad
, (BOOLEAN_P
));
80 invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
81 obj->quan <= bp->bquan
84 static const char *angrytexts
[] = { "quite upset", "ticked off", "furious" };
87 * Transfer money from inventory to monster when paying
88 * shopkeepers, priests, oracle, succubus, and other demons.
89 * Simple with only gold coins.
90 * This routine will handle money changing when multiple
91 * coin types is implemented, only appropriate
92 * monsters will pay change. (Peaceful shopkeepers, priests
93 * and the oracle try to maintain goodwill while selling
94 * their wares or services. Angry monsters and all demons
95 * will keep anything they get their hands on.
96 * Returns the amount actually paid, so we can know
97 * if the monster kept the change.
100 money2mon(mon
, amount
)
104 struct obj
*ygold
= findgold(invent
);
107 impossible("%s payment in money2mon!", amount
? "negative" : "zero");
110 if (!ygold
|| ygold
->quan
< amount
) {
111 impossible("Paying without %s money?", ygold
? "enough" : "");
115 if (ygold
->quan
> amount
)
116 ygold
= splitobj(ygold
, amount
);
117 else if (ygold
->owornmask
)
118 remove_worn_item(ygold
, FALSE
); /* quiver */
120 add_to_minv(mon
, ygold
);
126 * Transfer money from monster to inventory.
127 * Used when the shopkeeper pay for items, and when
128 * the priest gives you money for an ale.
135 struct obj
*mongold
= findgold(mon
->minvent
);
138 impossible("%s payment in money2u!", amount
? "negative" : "zero");
141 if (!mongold
|| mongold
->quan
< amount
) {
142 impossible("%s paying without %s money?", a_monnam(mon
),
143 mongold
? "enough" : "");
147 if (mongold
->quan
> amount
)
148 mongold
= splitobj(mongold
, amount
);
149 obj_extract_self(mongold
);
151 if (!merge_choice(invent
, mongold
) && inv_cnt(FALSE
) >= 52) {
152 You("have no room for the money!");
160 STATIC_OVL
struct monst
*
161 next_shkp(shkp
, withbill
)
162 register struct monst
*shkp
;
163 register boolean withbill
;
165 for (; shkp
; shkp
= shkp
->nmon
) {
166 if (DEADMONSTER(shkp
))
168 if (shkp
->isshk
&& (ESHK(shkp
)->billct
|| !withbill
))
173 if (NOTANGRY(shkp
)) {
174 if (ESHK(shkp
)->surcharge
)
177 if (!ESHK(shkp
)->surcharge
)
184 /* called in mon.c */
189 struct eshk
*eshk
= ESHK(mtmp
);
190 struct mkroom
*sroom
= &rooms
[eshk
->shoproom
- ROOMOFFSET
];
195 /* [BUG: some of this should be done on the shop level */
196 /* even when the shk dies on a different level.] */
197 if (on_level(&eshk
->shoplevel
, &u
.uz
)) {
198 remove_damage(mtmp
, TRUE
);
199 sroom
->resident
= (struct monst
*) 0;
200 if (!search_special(ANY_SHOP
))
201 level
.flags
.has_shop
= 0;
203 /* items on shop floor revert to ordinary objects */
204 for (sx
= sroom
->lx
; sx
<= sroom
->hx
; sx
++)
205 for (sy
= sroom
->ly
; sy
<= sroom
->hy
; sy
++)
206 for (otmp
= level
.objects
[sx
][sy
]; otmp
;
207 otmp
= otmp
->nexthere
)
210 /* Make sure bill is set only when the
211 dead shk is the resident shk. */
212 if ((p
= index(u
.ushops
, eshk
->shoproom
)) != 0) {
214 eshk
->bill_p
= (struct bill_x
*) 0;
215 /* remove eshk->shoproom from u.ushops */
224 set_residency(shkp
, zero_out
)
225 register struct monst
*shkp
;
226 register boolean zero_out
;
228 if (on_level(&(ESHK(shkp
)->shoplevel
), &u
.uz
))
229 rooms
[ESHK(shkp
)->shoproom
- ROOMOFFSET
].resident
=
230 (zero_out
) ? (struct monst
*) 0 : shkp
;
235 register struct monst
*mtmp
, *mtmp2
;
237 rooms
[ESHK(mtmp2
)->shoproom
- ROOMOFFSET
].resident
= mtmp2
;
238 if (inhishop(mtmp
) && *u
.ushops
== ESHK(mtmp
)->shoproom
) {
239 ESHK(mtmp2
)->bill_p
= &(ESHK(mtmp2
)->bill
[0]);
243 /* do shopkeeper specific structure munging -dlc */
245 restshk(shkp
, ghostly
)
250 struct eshk
*eshkp
= ESHK(shkp
);
252 if (eshkp
->bill_p
!= (struct bill_x
*) -1000)
253 eshkp
->bill_p
= &eshkp
->bill
[0];
254 /* shoplevel can change as dungeons move around */
255 /* savebones guarantees that non-homed shk's will be gone */
257 assign_level(&eshkp
->shoplevel
, &u
.uz
);
258 if (ANGRY(shkp
) && strncmpi(eshkp
->customer
, plname
, PL_NSIZ
))
264 /* Clear the unpaid bit on a single object and its contents. */
266 clear_unpaid_obj(shkp
, otmp
)
270 if (Has_contents(otmp
))
271 clear_unpaid(shkp
, otmp
->cobj
);
272 if (onbill(otmp
, shkp
, TRUE
))
276 /* Clear the unpaid bit on all of the objects in the list. */
278 clear_unpaid(shkp
, list
)
283 clear_unpaid_obj(shkp
, list
);
288 /* either you paid or left the shop or the shopkeeper died */
291 register struct monst
*shkp
;
293 register struct obj
*obj
;
294 register struct monst
*mtmp
;
296 clear_unpaid(shkp
, invent
);
297 clear_unpaid(shkp
, fobj
);
298 clear_unpaid(shkp
, level
.buriedobjlist
);
300 clear_unpaid_obj(shkp
, thrownobj
);
302 clear_unpaid_obj(shkp
, kickedobj
);
303 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp
->nmon
)
304 clear_unpaid(shkp
, mtmp
->minvent
);
305 for (mtmp
= migrating_mons
; mtmp
; mtmp
= mtmp
->nmon
)
306 clear_unpaid(shkp
, mtmp
->minvent
);
308 while ((obj
= billobjs
) != 0) {
309 obj_extract_self(obj
);
313 ESHK(shkp
)->billct
= 0;
314 ESHK(shkp
)->credit
= 0L;
315 ESHK(shkp
)->debit
= 0L;
316 ESHK(shkp
)->loan
= 0L;
322 register struct monst
*shkp
;
324 register int ct
= ESHK(shkp
)->billct
;
325 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
326 register long total
= 0L;
329 total
+= bp
->price
* bp
->bquan
;
336 call_kops(shkp
, nearshop
)
337 register struct monst
*shkp
;
338 register boolean nearshop
;
340 /* Keystone Kops srt@ucla */
341 register boolean nokops
;
347 pline("An alarm sounds!");
349 nokops
= ((mvitals
[PM_KEYSTONE_KOP
].mvflags
& G_GONE
)
350 && (mvitals
[PM_KOP_SERGEANT
].mvflags
& G_GONE
)
351 && (mvitals
[PM_KOP_LIEUTENANT
].mvflags
& G_GONE
)
352 && (mvitals
[PM_KOP_KAPTAIN
].mvflags
& G_GONE
));
354 if (!angry_guards(!!Deaf
) && nokops
) {
355 if (flags
.verbose
&& !Deaf
)
356 pline("But no one seems to respond to it.");
367 /* Create swarm around you, if you merely "stepped out" */
369 pline_The("Keystone Kops appear!");
376 pline_The("Keystone Kops are after you!");
377 /* Create swarm near down staircase (hinders return to level) */
381 /* Create swarm near shopkeeper (hinders return to shop) */
388 /* x,y is strictly inside shop */
395 rno
= levl
[x
][y
].roomno
;
396 if ((rno
< ROOMOFFSET
) || levl
[x
][y
].edge
|| !IS_SHOP(rno
- ROOMOFFSET
))
402 u_left_shop(leavestring
, newlev
)
411 * ((didn't leave outright) AND
412 * ((he is now strictly-inside the shop) OR
413 * (he wasn't strictly-inside last turn anyway)))
414 * THEN (there's nothing to do, so just return)
416 if (!*leavestring
&& (!levl
[u
.ux
][u
.uy
].edge
|| levl
[u
.ux0
][u
.uy0
].edge
))
419 shkp
= shop_keeper(*u
.ushops0
);
420 if (!shkp
|| !inhishop(shkp
))
421 return; /* shk died, teleported, changed levels... */
424 if (!eshkp
->billct
&& !eshkp
->debit
) /* bill is settled */
427 if (!*leavestring
&& !muteshk(shkp
)) {
429 * Player just stepped onto shop-boundary (known from above logic).
430 * Try to intimidate him into paying his bill
432 if (!Deaf
&& !muteshk(shkp
))
433 verbalize(NOTANGRY(shkp
) ? "%s! Please pay before leaving."
434 : "%s! Don't you leave without paying!",
437 pline("%s %s that you need to pay before leaving%s",
439 NOTANGRY(shkp
) ? "points out" : "makes it clear",
440 NOTANGRY(shkp
) ? "." : "!");
444 if (rob_shop(shkp
)) {
445 call_kops(shkp
, (!newlev
&& levl
[u
.ux0
][u
.uy0
].edge
));
449 /* robbery from outside the shop via telekinesis or grappling hook */
451 remote_burglary(x
, y
)
457 shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
));
458 if (!shkp
|| !inhishop(shkp
))
459 return; /* shk died, teleported, changed levels... */
462 if (!eshkp
->billct
&& !eshkp
->debit
) /* bill is settled */
465 if (rob_shop(shkp
)) {
466 /*[might want to set 2nd arg based on distance from shop doorway]*/
467 call_kops(shkp
, FALSE
);
471 /* shop merchandise has been taken; pay for it with any credit available;
472 return false if the debt is fully covered by credit, true otherwise */
481 rouse_shk(shkp
, TRUE
);
482 total
= (addupbill(shkp
) + eshkp
->debit
);
483 if (eshkp
->credit
>= total
) {
484 Your("credit of %ld %s is used to cover your shopping bill.",
485 eshkp
->credit
, currency(eshkp
->credit
));
486 total
= 0L; /* credit gets cleared by setpaid() */
488 You("escaped the shop without paying!");
489 total
-= eshkp
->credit
;
495 /* by this point, we know an actual robbery has taken place */
496 eshkp
->robbed
+= total
;
497 You("stole %ld %s worth of merchandise.", total
, currency(total
));
498 if (!Role_if(PM_ROGUE
)) /* stealing is unlawful */
499 adjalign(-sgn(u
.ualign
.type
));
505 /* give a message when entering an untended shop (caller has verified that) */
507 deserted_shop(enterstring
)
508 /*const*/ char *enterstring
;
511 struct mkroom
*r
= &rooms
[(int) *enterstring
- ROOMOFFSET
];
512 int x
, y
, m
= 0, n
= 0;
514 for (x
= r
->lx
; x
<= r
->hx
; ++x
)
515 for (y
= r
->ly
; y
<= r
->hy
; ++y
) {
516 if (x
== u
.ux
&& y
== u
.uy
)
518 if ((mtmp
= m_at(x
, y
)) != 0) {
520 if (sensemon(mtmp
) || ((mtmp
->m_ap_type
== M_AP_NOTHING
521 || mtmp
->m_ap_type
== M_AP_MONSTER
)
527 if (Blind
&& !(Blind_telepat
|| Detect_monsters
))
528 ++n
; /* force feedback to be less specific */
530 pline("This shop %s %s.", (m
< n
) ? "seems to be" : "is",
531 !n
? "deserted" : "untended");
535 u_entered_shop(enterstring
)
539 register struct monst
*shkp
;
540 register struct eshk
*eshkp
;
541 static char empty_shops
[5];
546 if (!(shkp
= shop_keeper(*enterstring
))) {
547 if (!index(empty_shops
, *enterstring
)
548 && in_rooms(u
.ux
, u
.uy
, SHOPBASE
)
549 != in_rooms(u
.ux0
, u
.uy0
, SHOPBASE
))
550 deserted_shop(enterstring
);
551 Strcpy(empty_shops
, u
.ushops
);
558 if (!inhishop(shkp
)) {
559 /* dump core when referenced */
560 eshkp
->bill_p
= (struct bill_x
*) -1000;
561 if (!index(empty_shops
, *enterstring
))
562 deserted_shop(enterstring
);
563 Strcpy(empty_shops
, u
.ushops
);
568 eshkp
->bill_p
= &(eshkp
->bill
[0]);
570 if ((!eshkp
->visitct
|| *eshkp
->customer
)
571 && strncmpi(eshkp
->customer
, plname
, PL_NSIZ
)) {
572 /* You seem to be new here */
574 eshkp
->following
= 0;
575 (void) strncpy(eshkp
->customer
, plname
, PL_NSIZ
);
579 if (muteshk(shkp
) || eshkp
->following
)
580 return; /* no dialog */
583 pline("%s senses your presence.", shkname(shkp
));
584 if (!Deaf
&& !muteshk(shkp
))
585 verbalize("Invisible customers are not welcome!");
587 pline("%s stands firm as if %s knows you are there.",
588 Shknam(shkp
), mhe(shkp
));
592 rt
= rooms
[*enterstring
- ROOMOFFSET
].rtype
;
595 if (!Deaf
&& !muteshk(shkp
))
596 verbalize("So, %s, you dare return to %s %s?!", plname
,
597 s_suffix(shkname(shkp
)), shtypes
[rt
- SHOPBASE
].name
);
599 pline("%s seems %s over your return to %s %s!",
601 angrytexts
[rn2(SIZE(angrytexts
))],
603 shtypes
[rt
- SHOPBASE
].name
);
604 } else if (eshkp
->robbed
) {
606 pline("%s mutters imprecations against shoplifters.",
609 pline("%s is combing through %s inventory list.",
613 if (!Deaf
&& !muteshk(shkp
))
614 verbalize("%s, %s! Welcome%s to %s %s!", Hello(shkp
), plname
,
615 eshkp
->visitct
++ ? " again" : "",
616 s_suffix(shkname(shkp
)), shtypes
[rt
- SHOPBASE
].name
);
618 You("enter %s %s%s!",
619 s_suffix(shkname(shkp
)),
620 shtypes
[rt
- SHOPBASE
].name
,
621 eshkp
->visitct
++ ? " again" : "");
623 /* can't do anything about blocking if teleported in */
624 if (!inside_shop(u
.ux
, u
.uy
)) {
625 boolean should_block
;
628 struct obj
*pick
= carrying(PICK_AXE
),
629 *mattock
= carrying(DWARVISH_MATTOCK
);
631 if (pick
|| mattock
) {
632 cnt
= 1; /* so far */
633 if (pick
&& mattock
) { /* carrying both types */
634 tool
= "digging tool";
635 cnt
= 2; /* `more than 1' is all that matters */
638 /* hack: `pick' already points somewhere into inventory */
639 while ((pick
= pick
->nobj
) != 0)
640 if (pick
->otyp
== PICK_AXE
)
642 } else { /* assert(mattock != 0) */
644 while ((mattock
= mattock
->nobj
) != 0)
645 if (mattock
->otyp
== DWARVISH_MATTOCK
)
647 /* [ALI] Shopkeeper identifies mattock(s) */
649 makeknown(DWARVISH_MATTOCK
);
651 if (!Deaf
&& !muteshk(shkp
))
652 verbalize(NOTANGRY(shkp
)
653 ? "Will you please leave your %s%s outside?"
654 : "Leave the %s%s outside.",
657 pline("%s %s to let you in with your %s%s.",
659 NOTANGRY(shkp
) ? "is hesitant" : "refuses",
662 } else if (u
.usteed
) {
663 if (!Deaf
&& !muteshk(shkp
))
664 verbalize(NOTANGRY(shkp
) ? "Will you please leave %s outside?"
665 : "Leave %s outside.",
668 pline("%s %s to let you in while you're riding %s.",
670 NOTANGRY(shkp
) ? "doesn't want" : "refuses",
675 (Fast
&& (sobj_at(PICK_AXE
, u
.ux
, u
.uy
)
676 || sobj_at(DWARVISH_MATTOCK
, u
.ux
, u
.uy
)));
679 (void) dochug(shkp
); /* shk gets extra move */
684 /* called when removing a pick-axe or mattock from a container */
691 if (obj
->unpaid
|| !is_pick(obj
))
693 shkp
= shop_keeper(*u
.ushops
);
694 if (shkp
&& inhishop(shkp
)) {
695 static NEARDATA
long pickmovetime
= 0L;
697 /* if you bring a sack of N picks into a shop to sell,
698 don't repeat this N times when they're taken out */
699 if (moves
!= pickmovetime
) {
700 if (!Deaf
&& !muteshk(shkp
))
701 verbalize("You sneaky %s! Get out of here with that pick!",
704 pline("%s %s your pick!",
706 haseyes(shkp
->data
) ? "glares at"
707 : "is dismayed because of");
709 pickmovetime
= moves
;
714 Decide whether two unpaid items are mergable; caller is responsible for
715 making sure they're unpaid and the same type of object; we check the price
716 quoted by the shopkeeper and also that they both belong to the same shk.
719 same_price(obj1
, obj2
)
720 struct obj
*obj1
, *obj2
;
722 register struct monst
*shkp1
, *shkp2
;
723 struct bill_x
*bp1
= 0, *bp2
= 0;
724 boolean are_mergable
= FALSE
;
726 /* look up the first object by finding shk whose bill it's on */
727 for (shkp1
= next_shkp(fmon
, TRUE
); shkp1
;
728 shkp1
= next_shkp(shkp1
->nmon
, TRUE
))
729 if ((bp1
= onbill(obj1
, shkp1
, TRUE
)) != 0)
731 /* second object is probably owned by same shk; if not, look harder */
732 if (shkp1
&& (bp2
= onbill(obj2
, shkp1
, TRUE
)) != 0) {
735 for (shkp2
= next_shkp(fmon
, TRUE
); shkp2
;
736 shkp2
= next_shkp(shkp2
->nmon
, TRUE
))
737 if ((bp2
= onbill(obj2
, shkp2
, TRUE
)) != 0)
742 impossible("same_price: object wasn't on any bill!");
744 are_mergable
= (shkp1
== shkp2
&& bp1
->price
== bp2
->price
);
749 * Figure out how much is owed to a given shopkeeper.
750 * At present, we ignore any amount robbed from the shop, to avoid
751 * turning the `$' command into a way to discover that the current
752 * level is bones data which has a shk on the warpath.
760 long debt
= eshkp
->debit
;
762 for (bp
= eshkp
->bill_p
, ct
= eshkp
->billct
; ct
> 0; bp
++, ct
--)
763 debt
+= bp
->price
* bp
->bquan
;
767 /* called in response to the `$' command */
769 shopper_financial_report()
771 struct monst
*shkp
, *this_shkp
= shop_keeper(inside_shop(u
.ux
, u
.uy
));
776 eshkp
= this_shkp
? ESHK(this_shkp
) : 0;
777 if (eshkp
&& !(eshkp
->credit
|| shop_debt(eshkp
))) {
778 You("have no credit or debt in here.");
779 this_shkp
= 0; /* skip first pass */
782 /* pass 0: report for the shop we're currently in, if any;
783 pass 1: report for all other shops on this level. */
784 for (pass
= this_shkp
? 0 : 1; pass
<= 1; pass
++)
785 for (shkp
= next_shkp(fmon
, FALSE
); shkp
;
786 shkp
= next_shkp(shkp
->nmon
, FALSE
)) {
787 if ((shkp
!= this_shkp
) ^ pass
)
790 if ((amt
= eshkp
->credit
) != 0)
791 You("have %ld %s credit at %s %s.", amt
, currency(amt
),
792 s_suffix(shkname(shkp
)),
793 shtypes
[eshkp
->shoptype
- SHOPBASE
].name
);
794 else if (shkp
== this_shkp
)
795 You("have no credit in here.");
796 if ((amt
= shop_debt(eshkp
)) != 0)
797 You("owe %s %ld %s.", shkname(shkp
), amt
, currency(amt
));
798 else if (shkp
== this_shkp
)
799 You("don't owe any money here.");
805 register struct monst
*mtmp
;
807 struct eshk
*eshkp
= ESHK(mtmp
);
809 return (index(in_rooms(mtmp
->mx
, mtmp
->my
, SHOPBASE
), eshkp
->shoproom
)
810 && on_level(&eshkp
->shoplevel
, &u
.uz
));
818 rmno
>= ROOMOFFSET
? rooms
[rmno
- ROOMOFFSET
].resident
: 0;
821 if (has_eshk(shkp
)) {
822 if (NOTANGRY(shkp
)) {
823 if (ESHK(shkp
)->surcharge
)
826 if (!ESHK(shkp
)->surcharge
)
830 /* would have segfaulted on ESHK dereference previously */
832 "shopkeeper career change? (rmno=%d, ROOMOFFSET=%d, mnum=%d, %s)",
833 (int)rmno
, ROOMOFFSET
, shkp
->mnum
,
834 has_mname(shkp
) ? MNAME(shkp
) : "anonymous"
837 /* not sure if this is appropriate, because it does nothing to
838 correct the underlying rooms[].resident issue but... */
839 return (struct monst
*)0;
847 struct mkroom
*sroom
;
849 struct monst
*mtmp
= sroom
->resident
;
851 return !mtmp
? FALSE
: (boolean
) inhishop(mtmp
);
854 STATIC_OVL
struct bill_x
*
855 onbill(obj
, shkp
, silent
)
861 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
862 register int ct
= ESHK(shkp
)->billct
;
865 if (bp
->bo_id
== obj
->o_id
) {
867 pline("onbill: paid obj on bill?");
872 if (obj
->unpaid
&& !silent
)
873 pline("onbill: unpaid obj not on bill?");
874 return (struct bill_x
*) 0;
877 /* check whether an object or any of its contents belongs to a shop */
882 return (boolean
) (obj
->unpaid
883 || (Has_contents(obj
) && count_unpaid(obj
->cobj
)));
886 /* Delete the contents of the given object. */
889 register struct obj
*obj
;
891 register struct obj
*curr
;
893 while ((curr
= obj
->cobj
) != 0) {
894 obj_extract_self(curr
);
895 obfree(curr
, (struct obj
*) 0);
899 /* called with two args on merge */
902 register struct obj
*obj
, *merge
;
904 register struct bill_x
*bp
;
905 register struct bill_x
*bpm
;
906 register struct monst
*shkp
;
908 if (obj
->otyp
== LEASH
&& obj
->leashmon
)
910 if (obj
->oclass
== FOOD_CLASS
)
911 food_disappears(obj
);
912 if (obj
->oclass
== SPBOOK_CLASS
)
913 book_disappears(obj
);
914 if (Has_contents(obj
))
915 delete_contents(obj
);
919 /* look for a shopkeeper who owns this object */
920 for (shkp
= next_shkp(fmon
, TRUE
); shkp
;
921 shkp
= next_shkp(shkp
->nmon
, TRUE
))
922 if (onbill(obj
, shkp
, TRUE
))
925 /* sanity check, more or less */
927 shkp
= shop_keeper(*u
.ushops
);
929 * Note: `shkp = shop_keeper(*u.ushops)' used to be
930 * unconditional. But obfree() is used all over
931 * the place, so making its behavior be dependent
932 * upon player location doesn't make much sense.
935 if ((bp
= onbill(obj
, shkp
, FALSE
)) != 0) {
938 obj
->unpaid
= 0; /* only for doinvbill */
939 add_to_billobjs(obj
);
942 bpm
= onbill(merge
, shkp
, FALSE
);
944 /* this used to be a rename */
945 impossible("obfree: not on bill??");
948 /* this was a merger */
949 bpm
->bquan
+= bp
->bquan
;
950 ESHK(shkp
)->billct
--;
953 /* DRS/NS 2.2.6 messes up -- Peter Kendell */
954 int indx
= ESHK(shkp
)->billct
;
956 *bp
= ESHK(shkp
)->bill_p
[indx
];
959 *bp
= ESHK(shkp
)->bill_p
[ESHK(shkp
)->billct
];
963 if (obj
->owornmask
) {
964 impossible("obfree: deleting worn obj (%d: %ld)", obj
->otyp
,
966 /* unfortunately at this point we don't know whether worn mask
967 applied to hero or a monster or perhaps something bogus, so
968 can't call remove_worn_item() to get <X>_off() side-effects */
975 check_credit(tmp
, shkp
)
977 register struct monst
*shkp
;
979 long credit
= ESHK(shkp
)->credit
;
982 ; /* nothing to do; just 'return tmp;' */
983 } else if (credit
>= tmp
) {
984 pline_The("price is deducted from your credit.");
985 ESHK(shkp
)->credit
-= tmp
;
988 pline_The("price is partially covered by your credit.");
989 ESHK(shkp
)->credit
= 0L;
998 register struct monst
*shkp
;
1000 long robbed
= ESHK(shkp
)->robbed
;
1001 long balance
= ((tmp
<= 0L) ? tmp
: check_credit(tmp
, shkp
));
1004 money2mon(shkp
, balance
);
1005 else if (balance
< 0)
1006 money2u(shkp
, -balance
);
1012 ESHK(shkp
)->robbed
= robbed
;
1016 /* return shkp to home position */
1018 home_shk(shkp
, killkops
)
1019 register struct monst
*shkp
;
1020 register boolean killkops
;
1022 register xchar x
= ESHK(shkp
)->shk
.x
, y
= ESHK(shkp
)->shk
.y
;
1024 (void) mnearto(shkp
, x
, y
, TRUE
);
1025 level
.flags
.has_shop
= 1;
1030 after_shk_move(shkp
);
1036 register struct monst
*shkp
;
1038 for (shkp
= next_shkp(fmon
, FALSE
); shkp
;
1039 shkp
= next_shkp(shkp
->nmon
, FALSE
))
1045 /* remove previously applied surcharge from all billed items */
1048 register struct monst
*shkp
;
1050 NOTANGRY(shkp
) = TRUE
; /* make peaceful */
1051 if (ESHK(shkp
)->surcharge
) {
1052 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
1053 register int ct
= ESHK(shkp
)->billct
;
1055 ESHK(shkp
)->surcharge
= FALSE
;
1057 register long reduction
= (bp
->price
+ 3L) / 4L;
1058 bp
->price
-= reduction
; /* undo 33% increase */
1064 /* add aggravation surcharge to all billed items */
1067 register struct monst
*shkp
;
1069 NOTANGRY(shkp
) = FALSE
; /* make angry */
1070 if (!ESHK(shkp
)->surcharge
) {
1071 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
1072 register int ct
= ESHK(shkp
)->billct
;
1074 ESHK(shkp
)->surcharge
= TRUE
;
1076 register long surcharge
= (bp
->price
+ 2L) / 3L;
1077 bp
->price
+= surcharge
;
1083 /* wakeup and/or unparalyze shopkeeper */
1085 rouse_shk(shkp
, verbosely
)
1089 if (!shkp
->mcanmove
|| shkp
->msleeping
) {
1090 /* greed induced recovery... */
1091 if (verbosely
&& canspotmon(shkp
))
1092 pline("%s %s.", Shknam(shkp
),
1093 shkp
->msleeping
? "wakes up" : "can move again");
1094 shkp
->msleeping
= 0;
1101 make_happy_shk(shkp
, silentkops
)
1102 register struct monst
*shkp
;
1103 register boolean silentkops
;
1105 boolean wasmad
= ANGRY(shkp
);
1106 struct eshk
*eshkp
= ESHK(shkp
);
1109 eshkp
->following
= 0;
1111 if (!Role_if(PM_ROGUE
))
1112 adjalign(sgn(u
.ualign
.type
));
1113 if (!inhishop(shkp
)) {
1114 char shk_nam
[BUFSZ
];
1115 boolean vanished
= canseemon(shkp
);
1117 Strcpy(shk_nam
, shkname(shkp
));
1118 if (on_level(&eshkp
->shoplevel
, &u
.uz
)) {
1119 home_shk(shkp
, FALSE
);
1120 /* didn't disappear if shk can still be seen */
1121 if (canseemon(shkp
))
1124 /* if sensed, does disappear regardless whether seen */
1127 /* can't act as porter for the Amulet, even if shk
1128 happens to be going farther down rather than up */
1129 mdrop_special_objs(shkp
);
1130 /* arrive near shop's door */
1131 migrate_to_level(shkp
, ledger_no(&eshkp
->shoplevel
),
1132 MIGR_APPROX_XY
, &eshkp
->shd
);
1133 /* dismiss kops on that level when shk arrives */
1134 eshkp
->dismiss_kops
= TRUE
;
1137 pline("Satisfied, %s suddenly disappears!", shk_nam
);
1139 pline("%s calms down.", Shknam(shkp
));
1141 make_happy_shoppers(silentkops
);
1144 /* called by make_happy_shk() and also by losedogs() for migrating shk */
1146 make_happy_shoppers(silentkops
)
1149 if (!angry_shk_exists()) {
1150 kops_gone(silentkops
);
1157 register struct monst
*shkp
;
1163 (void) strncpy(ESHK(shkp
)->customer
, plname
, PL_NSIZ
);
1164 ESHK(shkp
)->following
= 1;
1167 /* Used when the shkp is teleported or falls (ox == 0) out of his shop, or
1168 when the player is not on a costly_spot and he damages something inside
1169 the shop. These conditions must be checked by the calling function. */
1172 make_angry_shk(shkp
, ox
, oy
)
1174 xchar ox UNUSED
; /* <ox,oy> predate 'noit_Monnam()', let alone Shknam() */
1177 struct eshk
*eshkp
= ESHK(shkp
);
1179 /* all pending shop transactions are now "past due" */
1180 if (eshkp
->billct
|| eshkp
->debit
|| eshkp
->loan
|| eshkp
->credit
) {
1181 eshkp
->robbed
+= (addupbill(shkp
) + eshkp
->debit
+ eshkp
->loan
);
1182 eshkp
->robbed
-= eshkp
->credit
;
1183 if (eshkp
->robbed
< 0L)
1185 /* billct, debit, loan, and credit will be cleared by setpaid */
1189 pline("%s %s!", Shknam(shkp
), !ANGRY(shkp
) ? "gets angry" : "is furious");
1193 STATIC_VAR
const char
1194 no_money
[] = "Moreover, you%s have no money.",
1195 not_enough_money
[] = "Besides, you don't have enough to interest %s.";
1197 /* delivers the cheapest item on the list */
1200 register struct monst
*shkp
;
1202 register int ct
= ESHK(shkp
)->billct
;
1203 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
1204 register long gmin
= (bp
->price
* bp
->bquan
);
1207 if (bp
->price
* bp
->bquan
< gmin
)
1208 gmin
= bp
->price
* bp
->bquan
;
1217 register struct eshk
*eshkp
;
1218 register struct monst
*shkp
;
1219 struct monst
*nxtm
, *resident
;
1222 int pass
, tmp
, sk
= 0, seensk
= 0;
1223 boolean paid
= FALSE
, stashed_gold
= (hidden_gold() > 0L);
1227 /* Find how many shk's there are, how many are in
1228 * sight, and are you in a shop room with one.
1230 nxtm
= resident
= 0;
1231 for (shkp
= next_shkp(fmon
, FALSE
); shkp
;
1232 shkp
= next_shkp(shkp
->nmon
, FALSE
)) {
1234 if (ANGRY(shkp
) && distu(shkp
->mx
, shkp
->my
) <= 2)
1236 if (canspotmon(shkp
))
1238 if (inhishop(shkp
) && (*u
.ushops
== ESHK(shkp
)->shoproom
))
1242 if (nxtm
) { /* Player should always appease an */
1243 shkp
= nxtm
; /* irate shk standing next to them. */
1247 if ((!sk
&& (!Blind
|| Blind_telepat
)) || (!Blind
&& !seensk
)) {
1248 There("appears to be no shopkeeper here to receive your payment.");
1257 /* The usual case. Allow paying at a distance when
1258 * inside a tended shop. Should we change that?
1260 if (sk
== 1 && resident
) {
1266 for (shkp
= next_shkp(fmon
, FALSE
); shkp
;
1267 shkp
= next_shkp(shkp
->nmon
, FALSE
))
1268 if (canspotmon(shkp
))
1270 if (shkp
!= resident
&& distu(shkp
->mx
, shkp
->my
) > 2) {
1271 pline("%s is not near enough to receive your payment.",
1283 if (getpos(&cc
, TRUE
, "the creature you want to pay") < 0)
1284 return 0; /* player pressed ESC */
1288 pline("Try again...");
1291 if (u
.ux
== cx
&& u
.uy
== cy
) {
1292 You("are generous to yourself.");
1295 mtmp
= m_at(cx
, cy
);
1296 if (!cansee(cx
, cy
) && (!mtmp
|| !canspotmon(mtmp
))) {
1297 You("can't %s anyone there.", !Blind
? "see" : "sense");
1301 There("is no one there to receive your payment.");
1305 pline("%s is not interested in your payment.", Monnam(mtmp
));
1308 if (mtmp
!= resident
&& distu(mtmp
->mx
, mtmp
->my
) > 2) {
1309 pline("%s is too far to receive your payment.", Shknam(mtmp
));
1316 debugpline0("dopay: null shkp.");
1321 ltmp
= eshkp
->robbed
;
1323 /* wake sleeping shk when someone who owes money offers payment */
1324 if (ltmp
|| eshkp
->billct
|| eshkp
->debit
)
1325 rouse_shk(shkp
, TRUE
);
1327 if (!shkp
->mcanmove
|| shkp
->msleeping
) { /* still asleep/paralyzed */
1328 pline("%s %s.", Shknam(shkp
),
1329 rn2(2) ? "seems to be napping" : "doesn't respond");
1333 if (shkp
!= resident
&& NOTANGRY(shkp
)) {
1334 umoney
= money_cnt(invent
);
1336 You("do not owe %s anything.", shkname(shkp
));
1338 You("%shave no money.", stashed_gold
? "seem to " : "");
1340 pline("But you have some gold stashed away.");
1342 if (umoney
> ltmp
) {
1343 You("give %s the %ld gold piece%s %s asked for.",
1344 shkname(shkp
), ltmp
, plur(ltmp
), mhe(shkp
));
1347 You("give %s all your%s gold.", shkname(shkp
),
1348 stashed_gold
? " openly kept" : "");
1351 pline("But you have hidden gold!");
1353 if ((umoney
< ltmp
/ 2L) || (umoney
< ltmp
&& stashed_gold
))
1354 pline("Unfortunately, %s doesn't look satisfied.", mhe(shkp
));
1356 make_happy_shk(shkp
, FALSE
);
1361 /* ltmp is still eshkp->robbed here */
1362 if (!eshkp
->billct
&& !eshkp
->debit
) {
1363 umoney
= money_cnt(invent
);
1364 if (!ltmp
&& NOTANGRY(shkp
)) {
1365 You("do not owe %s anything.", shkname(shkp
));
1367 pline(no_money
, stashed_gold
? " seem to" : "");
1369 pline("%s is after blood, not money!", shkname(shkp
));
1370 if (umoney
< ltmp
/ 2L || (umoney
< ltmp
&& stashed_gold
)) {
1372 pline(no_money
, stashed_gold
? " seem to" : "");
1374 pline(not_enough_money
, mhim(shkp
));
1377 pline("But since %s shop has been robbed recently,", mhis(shkp
));
1378 pline("you %scompensate %s for %s losses.",
1379 (umoney
< ltmp
) ? "partially " : "", shkname(shkp
),
1381 pay(umoney
< ltmp
? umoney
: ltmp
, shkp
);
1382 make_happy_shk(shkp
, FALSE
);
1384 /* shopkeeper is angry, but has not been robbed --
1385 * door broken, attacked, etc. */
1386 pline("%s is after your hide, not your money!", Shknam(shkp
));
1387 if (umoney
< 1000L) {
1389 pline(no_money
, stashed_gold
? " seem to" : "");
1391 pline(not_enough_money
, mhim(shkp
));
1394 You("try to appease %s by giving %s 1000 gold pieces.",
1395 x_monnam(shkp
, ARTICLE_THE
, "angry", 0, FALSE
), mhim(shkp
));
1397 if (strncmp(eshkp
->customer
, plname
, PL_NSIZ
) || rn2(3))
1398 make_happy_shk(shkp
, FALSE
);
1400 pline("But %s is as angry as ever.", shkname(shkp
));
1404 if (shkp
!= resident
) {
1405 impossible("dopay: not to shopkeeper?");
1410 /* pay debt, if any, first */
1412 long dtmp
= eshkp
->debit
;
1413 long loan
= eshkp
->loan
;
1416 umoney
= money_cnt(invent
);
1417 Sprintf(sbuf
, "You owe %s %ld %s ", shkname(shkp
), dtmp
,
1421 Strcat(sbuf
, "you picked up in the store.");
1424 "for gold picked up and the use of merchandise.");
1426 Strcat(sbuf
, "for the use of merchandise.");
1428 if (umoney
+ eshkp
->credit
< dtmp
) {
1429 pline("But you don't%s have enough gold%s.",
1430 stashed_gold
? " seem to" : "",
1431 eshkp
->credit
? " or credit" : "");
1434 if (eshkp
->credit
>= dtmp
) {
1435 eshkp
->credit
-= dtmp
;
1438 Your("debt is covered by your credit.");
1439 } else if (!eshkp
->credit
) {
1440 money2mon(shkp
, dtmp
);
1443 You("pay that debt.");
1446 dtmp
-= eshkp
->credit
;
1448 money2mon(shkp
, dtmp
);
1451 pline("That debt is partially offset by your credit.");
1452 You("pay the remainder.");
1458 /* now check items on bill */
1459 if (eshkp
->billct
) {
1460 register boolean itemize
;
1463 umoney
= money_cnt(invent
);
1464 if (!umoney
&& !eshkp
->credit
) {
1465 You("%shave no money or credit%s.",
1466 stashed_gold
? "seem to " : "", paid
? " left" : "");
1469 if ((umoney
+ eshkp
->credit
) < cheapest_item(shkp
)) {
1470 You("don't have enough money to buy%s the item%s you picked.",
1471 eshkp
->billct
> 1 ? " any of" : "", plur(eshkp
->billct
));
1473 pline("Maybe you have some gold stashed away?");
1477 /* this isn't quite right; it itemizes without asking if the
1478 * single item on the bill is partly used up and partly unpaid */
1479 iprompt
= (eshkp
->billct
> 1 ? ynq("Itemized billing?") : 'y');
1480 itemize
= (iprompt
== 'y');
1484 for (pass
= 0; pass
<= 1; pass
++) {
1486 while (tmp
< eshkp
->billct
) {
1488 register struct bill_x
*bp
= &(eshkp
->bill_p
[tmp
]);
1490 /* find the object on one of the lists */
1491 if ((otmp
= bp_to_obj(bp
)) != 0) {
1492 /* if completely used up, object quantity is stale;
1493 restoring it to its original value here avoids
1494 making the partly-used-up code more complicated */
1496 otmp
->quan
= bp
->bquan
;
1498 impossible("Shopkeeper administration out of order.");
1499 setpaid(shkp
); /* be nice to the player */
1502 if (pass
== bp
->useup
&& otmp
->quan
== bp
->bquan
) {
1503 /* pay for used-up items on first pass and others
1504 * on second, so player will be stuck in the store
1505 * less often; things which are partly used up
1506 * are processed on both passes */
1509 switch (dopayobj(shkp
, bp
, &otmp
, pass
, itemize
)) {
1514 goto thanks
; /*break*/
1529 *bp
= eshkp
->bill_p
[--eshkp
->billct
];
1535 update_inventory(); /* Done in dopayobj() if itemize. */
1537 if (!ANGRY(shkp
) && paid
) {
1538 if (!Deaf
&& !muteshk(shkp
))
1539 verbalize("Thank you for shopping in %s %s!", s_suffix(shkname(shkp
)),
1540 shtypes
[eshkp
->shoptype
- SHOPBASE
].name
);
1542 pline("%s nods appreciatively at you for shopping in %s %s!",
1545 shtypes
[eshkp
->shoptype
- SHOPBASE
].name
);
1550 /* return 2 if used-up portion paid
1551 * 1 if paid successfully
1552 * 0 if not enough money
1553 * -1 if skip this object
1554 * -2 if no money/credit left
1557 dopayobj(shkp
, bp
, obj_p
, which
, itemize
)
1558 register struct monst
*shkp
;
1559 register struct bill_x
*bp
;
1561 int which
; /* 0 => used-up item, 1 => other (unpaid or lost) */
1564 register struct obj
*obj
= *obj_p
;
1565 long ltmp
, quan
, save_quan
;
1566 long umoney
= money_cnt(invent
);
1568 boolean stashed_gold
= (hidden_gold() > 0L), consumed
= (which
== 0);
1570 if (!obj
->unpaid
&& !bp
->useup
) {
1571 impossible("Paid object on bill??");
1574 if (itemize
&& umoney
+ ESHK(shkp
)->credit
== 0L) {
1575 You("%shave no money or credit left.",
1576 stashed_gold
? "seem to " : "");
1579 /* we may need to temporarily adjust the object, if part of the
1580 original quantity has been used up but part remains unpaid */
1581 save_quan
= obj
->quan
;
1583 /* either completely used up (simple), or split needed */
1585 if (quan
> obj
->quan
) /* difference is amount used up */
1588 /* dealing with ordinary unpaid item */
1591 obj
->quan
= quan
; /* to be used by doname() */
1592 obj
->unpaid
= 0; /* ditto */
1593 iflags
.suppress_price
++; /* affects containers */
1594 ltmp
= bp
->price
* quan
;
1595 buy
= PAY_BUY
; /* flag; if changed then return early */
1598 char qbuf
[BUFSZ
], qsfx
[BUFSZ
];
1600 Sprintf(qsfx
, " for %ld %s. Pay?", ltmp
, currency(ltmp
));
1601 (void) safe_qbuf(qbuf
, (char *) 0, qsfx
, obj
,
1602 (quan
== 1L) ? Doname2
: doname
, ansimpleoname
,
1603 (quan
== 1L) ? "that" : "those");
1604 if (yn(qbuf
) == 'n') {
1605 buy
= PAY_SKIP
; /* don't want to buy */
1606 } else if (quan
< bp
->bquan
&& !consumed
) { /* partly used goods */
1607 obj
->quan
= bp
->bquan
- save_quan
; /* used up amount */
1608 if (!Deaf
&& !muteshk(shkp
)) {
1609 verbalize("%s for the other %s before buying %s.",
1610 ANGRY(shkp
) ? "Pay" : "Please pay",
1611 simpleonames(obj
), /* short name suffices */
1612 save_quan
> 1L ? "these" : "this one");
1614 pline("%s %s%s your bill for the other %s first.",
1616 ANGRY(shkp
) ? "angrily " : "",
1617 nolimbs(shkp
->data
) ? "motions to" : "points out",
1620 buy
= PAY_SKIP
; /* shk won't sell */
1623 if (buy
== PAY_BUY
&& umoney
+ ESHK(shkp
)->credit
< ltmp
) {
1624 You("don't%s have gold%s enough to pay for %s.",
1625 stashed_gold
? " seem to" : "",
1626 (ESHK(shkp
)->credit
> 0L) ? " or credit" : "",
1627 thesimpleoname(obj
));
1628 buy
= itemize
? PAY_SKIP
: PAY_CANT
;
1631 if (buy
!= PAY_BUY
) {
1632 /* restore unpaid object to original state */
1633 obj
->quan
= save_quan
;
1635 iflags
.suppress_price
--;
1640 shk_names_obj(shkp
, obj
,
1641 consumed
? "paid for %s at a cost of %ld gold piece%s.%s"
1642 : "bought %s for %ld gold piece%s.%s",
1644 obj
->quan
= save_quan
; /* restore original count */
1645 /* quan => amount just bought, save_quan => remaining unpaid count */
1647 if (quan
!= bp
->bquan
) {
1648 /* eliminate used-up portion; remainder is still unpaid */
1649 bp
->bquan
= obj
->quan
;
1653 } else { /* completely used-up, so get rid of it */
1654 obj_extract_self(obj
);
1655 /* assert( obj == *obj_p ); */
1657 *obj_p
= 0; /* destroy pointer to freed object */
1660 update_inventory(); /* Done just once in dopay() if !itemize. */
1661 iflags
.suppress_price
--;
1665 static struct repo
{ /* repossession context */
1666 struct monst
*shopkeeper
;
1670 /* routine called after dying (or quitting) */
1673 int croaked
; /* -1: escaped dungeon; 0: quit; 1: died */
1675 struct monst
*mtmp
, *mtmp2
, *firstshk
, *resident
, *creditor
, *hostile
,
1678 boolean taken
= FALSE
, local
;
1681 /* if we escaped from the dungeon, shopkeepers can't reach us;
1682 shops don't occur on level 1, but this could happen if hero
1683 level teleports out of the dungeon and manages not to die */
1686 /* [should probably also return false when dead hero has been
1687 petrified since shk shouldn't be able to grab inventory
1688 which has been shut inside a statue] */
1690 /* this is where inventory will end up if any shk takes it */
1691 repo
.location
.x
= repo
.location
.y
= 0;
1692 repo
.shopkeeper
= 0;
1695 * Scan all shopkeepers on the level, to prioritize them:
1696 * 1) keeper of shop hero is inside and who is owed money,
1697 * 2) keeper of shop hero is inside who isn't owed any money,
1698 * 3) other shk who is owed money, 4) other shk who is angry,
1699 * 5) any shk local to this level, and if none is found,
1700 * 6) first shk on monster list (last resort; unlikely, since
1701 * any nonlocal shk will probably be in the owed category
1702 * and almost certainly be in the angry category).
1704 resident
= creditor
= hostile
= localshk
= (struct monst
*) 0;
1705 for (mtmp
= next_shkp(fmon
, FALSE
); mtmp
;
1706 mtmp
= next_shkp(mtmp2
, FALSE
)) {
1709 local
= on_level(&eshkp
->shoplevel
, &u
.uz
);
1710 if (local
&& index(u
.ushops
, eshkp
->shoproom
)) {
1711 /* inside this shk's shop [there might be more than one
1712 resident shk if hero is standing in a breech of a shared
1713 wall, so give priority to one who's also owed money] */
1714 if (!resident
|| eshkp
->billct
|| eshkp
->debit
|| eshkp
->robbed
)
1716 } else if (eshkp
->billct
|| eshkp
->debit
|| eshkp
->robbed
) {
1717 /* owe this shopkeeper money (might also owe others) */
1720 } else if (eshkp
->following
|| ANGRY(mtmp
)) {
1721 /* this shopkeeper is antagonistic (others might be too) */
1725 /* this shopkeeper's shop is on current level */
1731 /* give highest priority shopkeeper first crack */
1732 firstshk
= resident
? resident
1733 : creditor
? creditor
1738 taken
= inherits(firstshk
, numsk
, croaked
);
1741 /* now handle the rest */
1742 for (mtmp
= next_shkp(fmon
, FALSE
); mtmp
;
1743 mtmp
= next_shkp(mtmp2
, FALSE
)) {
1746 local
= on_level(&eshkp
->shoplevel
, &u
.uz
);
1747 if (mtmp
!= firstshk
) {
1749 taken
|= inherits(mtmp
, numsk
, croaked
);
1751 /* for bones: we don't want a shopless shk around */
1759 inherits(shkp
, numsk
, croaked
)
1766 struct eshk
*eshkp
= ESHK(shkp
);
1767 boolean take
= FALSE
, taken
= FALSE
;
1768 unsigned save_minvis
= shkp
->minvis
;
1769 int roomno
= *u
.ushops
;
1773 /* The simplifying principle is that first-come
1774 already took everything you had. */
1776 if (cansee(shkp
->mx
, shkp
->my
) && croaked
) {
1778 if (has_head(shkp
->data
) && !rn2(2))
1779 Sprintf(takes
, ", shakes %s %s,", mhis(shkp
),
1780 mbodypart(shkp
, HEAD
));
1781 pline("%s %slooks at your corpse%s and %s.", Shknam(shkp
),
1782 (!shkp
->mcanmove
|| shkp
->msleeping
) ? "wakes up, " : "",
1783 takes
, !inhishop(shkp
) ? "disappears" : "sighs");
1785 rouse_shk(shkp
, FALSE
); /* wake shk for bones */
1786 taken
= (roomno
== eshkp
->shoproom
);
1790 /* get one case out of the way: you die in the shop, the */
1791 /* shopkeeper is peaceful, nothing stolen, nothing owed. */
1792 if (roomno
== eshkp
->shoproom
&& inhishop(shkp
) && !eshkp
->billct
1793 && !eshkp
->robbed
&& !eshkp
->debit
&& NOTANGRY(shkp
)
1794 && !eshkp
->following
&& u
.ugrave_arise
< LOW_PM
) {
1795 taken
= (invent
!= 0);
1797 pline("%s gratefully inherits all your possessions.",
1803 if (eshkp
->billct
|| eshkp
->debit
|| eshkp
->robbed
) {
1804 if (roomno
== eshkp
->shoproom
&& inhishop(shkp
))
1805 loss
= addupbill(shkp
) + eshkp
->debit
;
1806 if (loss
< eshkp
->robbed
)
1807 loss
= eshkp
->robbed
;
1811 if (eshkp
->following
|| ANGRY(shkp
) || take
) {
1814 umoney
= money_cnt(invent
);
1816 if (!shkp
->mcanmove
|| shkp
->msleeping
)
1817 Strcat(takes
, "wakes up and ");
1818 if (distu(shkp
->mx
, shkp
->my
) > 2)
1819 Strcat(takes
, "comes and ");
1820 Strcat(takes
, "takes");
1822 if (loss
> umoney
|| !loss
|| roomno
== eshkp
->shoproom
) {
1823 eshkp
->robbed
-= umoney
;
1824 if (eshkp
->robbed
< 0L)
1827 money2mon(shkp
, umoney
);
1829 pline("%s %s all your possessions.", shkname(shkp
), takes
);
1831 /* where to put player's invent (after disclosure) */
1834 money2mon(shkp
, loss
);
1836 pline("%s %s the %ld %s %sowed %s.", Shknam(shkp
),
1837 takes
, loss
, currency(loss
),
1838 strncmp(eshkp
->customer
, plname
, PL_NSIZ
) ? "" : "you ",
1840 /* shopkeeper has now been paid in full */
1842 eshkp
->following
= 0;
1846 /* in case we create bones */
1847 rouse_shk(shkp
, FALSE
); /* wake up */
1848 if (!inhishop(shkp
))
1849 home_shk(shkp
, FALSE
);
1852 shkp
->minvis
= save_minvis
;
1861 register xchar ox
, oy
;
1862 struct eshk
*eshkp
= ESHK(shkp
);
1864 /* if you're not in this shk's shop room, or if you're in its doorway
1865 or entry spot, then your gear gets dumped all the way inside */
1866 if (*u
.ushops
!= eshkp
->shoproom
|| IS_DOOR(levl
[u
.ux
][u
.uy
].typ
)
1867 || (u
.ux
== eshkp
->shk
.x
&& u
.uy
== eshkp
->shk
.y
)) {
1868 /* shk.x,shk.y is the position immediately in
1869 * front of the door -- move in one more space
1873 ox
+= sgn(ox
- eshkp
->shd
.x
);
1874 oy
+= sgn(oy
- eshkp
->shd
.y
);
1875 } else { /* already inside this shk's shop */
1879 /* finish_paybill will deposit invent here */
1880 repo
.location
.x
= ox
;
1881 repo
.location
.y
= oy
;
1882 repo
.shopkeeper
= shkp
;
1885 /* called at game exit, after inventory disclosure but before making bones */
1889 struct monst
*shkp
= repo
.shopkeeper
;
1890 int ox
= repo
.location
.x
, oy
= repo
.location
.y
;
1892 #if 0 /* don't bother */
1893 if (ox
== 0 && oy
== 0)
1894 impossible("finish_paybill: no location");
1896 /* normally done by savebones(), but that's too late in this case */
1898 /* if hero has any gold left, take it into shopkeeper's possession */
1900 long umoney
= money_cnt(invent
);
1903 money2mon(shkp
, umoney
);
1905 /* transfer rest of the character's inventory to the shop floor */
1906 drop_upon_death((struct monst
*) 0, (struct obj
*) 0, ox
, oy
);
1909 /* find obj on one of the lists */
1910 STATIC_OVL
struct obj
*
1912 register struct bill_x
*bp
;
1914 register struct obj
*obj
;
1915 register unsigned int id
= bp
->bo_id
;
1918 obj
= o_on(id
, billobjs
);
1925 * Look for o_id on all lists but billobj. Return obj or NULL if not found.
1926 * Its OK for restore_timers() to call this function, there should not
1927 * be any timeouts on the billobjs chain.
1934 struct monst
*mon
, *mmtmp
[3];
1937 /* first check various obj lists directly */
1938 if ((obj
= o_on(id
, invent
)) != 0)
1940 if ((obj
= o_on(id
, fobj
)) != 0)
1942 if ((obj
= o_on(id
, level
.buriedobjlist
)) != 0)
1944 if ((obj
= o_on(id
, migrating_objs
)) != 0)
1947 /* not found yet; check inventory for members of various monst lists */
1949 mmtmp
[1] = migrating_mons
;
1950 mmtmp
[2] = mydogs
; /* for use during level changes */
1951 for (i
= 0; i
< 3; i
++)
1952 for (mon
= mmtmp
[i
]; mon
; mon
= mon
->nmon
)
1953 if ((obj
= o_on(id
, mon
->minvent
)) != 0)
1956 /* not found at all */
1957 return (struct obj
*) 0;
1960 /* Returns the price of an arbitrary item in the shop.
1961 Returns 0 if the item doesn't belong to a shopkeeper. */
1963 get_cost_of_shop_item(obj
)
1964 register struct obj
*obj
;
1971 && obj
->oclass
!= COIN_CLASS
1972 && obj
!= uball
&& obj
!= uchain
1973 && get_obj_location(obj
, &x
, &y
, 0)
1975 || (obj
->where
== OBJ_FLOOR
1976 && !obj
->no_charge
&& costly_spot(x
, y
)))
1977 && (shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
))) != 0
1978 && inhishop(shkp
)) {
1979 cost
= obj
->quan
* get_cost(obj
, shkp
);
1980 if (Has_contents(obj
))
1981 cost
+= contained_cost(obj
, shkp
, 0L, FALSE
, FALSE
);
1986 /* calculate the value that the shk will charge for [one of] an object */
1989 register struct obj
*obj
;
1990 register struct monst
*shkp
; /* if angry, impose a surcharge */
1992 long tmp
= getprice(obj
, FALSE
),
1993 /* used to perform a single calculation even when multiple
1994 adjustments (unID'd, dunce/tourist, charisma) are made */
1995 multiplier
= 1L, divisor
= 1L;
1999 /* shopkeeper may notice if the player isn't very knowledgeable -
2000 especially when gem prices are concerned */
2001 if (!obj
->dknown
|| !objects
[obj
->otyp
].oc_name_known
) {
2002 if (obj
->oclass
== GEM_CLASS
2003 && objects
[obj
->otyp
].oc_material
== GLASS
) {
2005 /* get a value that's 'random' from game to game, but the
2006 same within the same game */
2007 boolean pseudorand
=
2008 (((int) ubirthday
% obj
->otyp
) >= obj
->otyp
/ 2);
2010 /* all gems are priced high - real or not */
2011 switch (obj
->otyp
- LAST_GEM
) {
2013 i
= pseudorand
? DIAMOND
: OPAL
;
2016 i
= pseudorand
? SAPPHIRE
: AQUAMARINE
;
2019 i
= pseudorand
? RUBY
: JASPER
;
2021 case 4: /* yellowish brown */
2022 i
= pseudorand
? AMBER
: TOPAZ
;
2024 case 5: /* orange */
2025 i
= pseudorand
? JACINTH
: AGATE
;
2027 case 6: /* yellow */
2028 i
= pseudorand
? CITRINE
: CHRYSOBERYL
;
2031 i
= pseudorand
? BLACK_OPAL
: JET
;
2034 i
= pseudorand
? EMERALD
: JADE
;
2036 case 9: /* violet */
2037 i
= pseudorand
? AMETHYST
: FLUORITE
;
2040 impossible("bad glass gem %d?", obj
->otyp
);
2044 tmp
= (long) objects
[i
].oc_cost
;
2045 } else if (!(obj
->o_id
% 4)) {
2046 /* unid'd, arbitrarily impose surcharge: tmp *= 4/3 */
2051 if (uarmh
&& uarmh
->otyp
== DUNCE_CAP
)
2052 multiplier
*= 4L, divisor
*= 3L;
2053 else if ((Role_if(PM_TOURIST
) && u
.ulevel
< (MAXULEV
/ 2))
2054 || (uarmu
&& !uarm
&& !uarmc
)) /* touristy shirt visible */
2055 multiplier
*= 4L, divisor
*= 3L;
2057 if (ACURR(A_CHA
) > 18)
2059 else if (ACURR(A_CHA
) == 18)
2060 multiplier
*= 2L, divisor
*= 3L;
2061 else if (ACURR(A_CHA
) >= 16)
2062 multiplier
*= 3L, divisor
*= 4L;
2063 else if (ACURR(A_CHA
) <= 5)
2065 else if (ACURR(A_CHA
) <= 7)
2066 multiplier
*= 3L, divisor
*= 2L;
2067 else if (ACURR(A_CHA
) <= 10)
2068 multiplier
*= 4L, divisor
*= 3L;
2070 /* tmp = (tmp * multiplier) / divisor [with roundoff tweak] */
2073 /* tmp = (((tmp * 10) / divisor) + 5) / 10 */
2082 /* the artifact prices in artilist[] are also used as a score bonus;
2083 inflate their shop price here without affecting score calculation */
2087 /* anger surcharge should match rile_shk's, so we do it separately
2088 from the multiplier/divisor calculation */
2089 if (shkp
&& ESHK(shkp
)->surcharge
)
2090 tmp
+= (tmp
+ 2L) / 3L;
2094 /* returns the price of a container's content. the price
2095 * of the "top" container is added in the calling functions.
2096 * a different price quoted for selling as vs. buying.
2099 contained_cost(obj
, shkp
, price
, usell
, unpaid_only
)
2104 boolean unpaid_only
;
2106 register struct obj
*otmp
;
2108 /* price of contained objects; "top" container handled by caller */
2109 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2110 if (otmp
->oclass
== COIN_CLASS
)
2114 if (saleable(shkp
, otmp
) && !otmp
->unpaid
2115 && otmp
->oclass
!= BALL_CLASS
2116 && !(otmp
->oclass
== FOOD_CLASS
&& otmp
->oeaten
)
2117 && !(Is_candle(otmp
)
2118 && otmp
->age
< 20L * (long) objects
[otmp
->otyp
].oc_cost
))
2119 price
+= set_cost(otmp
, shkp
);
2120 } else if (!otmp
->no_charge
&& (otmp
->unpaid
|| !unpaid_only
)) {
2121 price
+= get_cost(otmp
, shkp
) * otmp
->quan
;
2124 if (Has_contents(otmp
))
2125 price
= contained_cost(otmp
, shkp
, price
, usell
, unpaid_only
);
2133 register struct obj
*obj
;
2135 register struct obj
*otmp
;
2136 register long value
= 0L;
2138 /* accumulate contained gold */
2139 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
)
2140 if (otmp
->oclass
== COIN_CLASS
)
2141 value
+= otmp
->quan
;
2142 else if (Has_contents(otmp
))
2143 value
+= contained_gold(otmp
);
2149 dropped_container(obj
, shkp
, sale
)
2150 register struct obj
*obj
;
2151 register struct monst
*shkp
;
2152 register boolean sale
;
2154 register struct obj
*otmp
;
2156 /* the "top" container is treated in the calling fn */
2157 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2158 if (otmp
->oclass
== COIN_CLASS
)
2161 if (!otmp
->unpaid
&& !(sale
&& saleable(shkp
, otmp
)))
2162 otmp
->no_charge
= 1;
2164 if (Has_contents(otmp
))
2165 dropped_container(otmp
, shkp
, sale
);
2170 picked_container(obj
)
2171 register struct obj
*obj
;
2173 register struct obj
*otmp
;
2175 /* the "top" container is treated in the calling fn */
2176 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2177 if (otmp
->oclass
== COIN_CLASS
)
2180 if (otmp
->no_charge
)
2181 otmp
->no_charge
= 0;
2183 if (Has_contents(otmp
))
2184 picked_container(otmp
);
2189 special_stock(obj
, shkp
, quietly
)
2194 /* for unique situations */
2195 if (ESHK(shkp
)->shoptype
== CANDLESHOP
2196 && obj
->otyp
== CANDELABRUM_OF_INVOCATION
) {
2198 if (is_izchak(shkp
, TRUE
) && !u
.uevent
.invoked
) {
2199 if (Deaf
|| muteshk(shkp
)) {
2200 pline("%s seems %s that you want to sell that.",
2202 (obj
->spe
< 7) ? "horrified" : "concerned");
2204 verbalize("No thanks, I'd hang onto that if I were you.");
2207 "You'll need %d%s candle%s to go along with it.",
2208 (7 - obj
->spe
), (obj
->spe
> 0) ? " more" : "",
2209 plur(7 - obj
->spe
));
2210 /* [what if hero is already carrying enough candles?
2211 should Izchak explain how to attach them instead?] */
2214 if (!Deaf
&& !muteshk(shkp
))
2215 verbalize("I won't stock that. Take it out of here!");
2217 pline("%s shakes %s %s in refusal.",
2220 mbodypart(shkp
, HEAD
));
2228 /* calculate how much the shk will pay when buying [all of] an object */
2231 register struct obj
*obj
;
2232 register struct monst
*shkp
;
2234 long tmp
= getprice(obj
, TRUE
) * obj
->quan
, multiplier
= 1L, divisor
= 1L;
2236 if (uarmh
&& uarmh
->otyp
== DUNCE_CAP
)
2238 else if ((Role_if(PM_TOURIST
) && u
.ulevel
< (MAXULEV
/ 2))
2239 || (uarmu
&& !uarm
&& !uarmc
)) /* touristy shirt visible */
2244 /* shopkeeper may notice if the player isn't very knowledgeable -
2245 especially when gem prices are concerned */
2246 if (!obj
->dknown
|| !objects
[obj
->otyp
].oc_name_known
) {
2247 if (obj
->oclass
== GEM_CLASS
) {
2248 /* different shop keepers give different prices */
2249 if (objects
[obj
->otyp
].oc_material
== GEMSTONE
2250 || objects
[obj
->otyp
].oc_material
== GLASS
) {
2251 tmp
= (obj
->otyp
% (6 - shkp
->m_id
% 3));
2252 tmp
= (tmp
+ 3) * obj
->quan
;
2254 } else if (tmp
> 1L && !(shkp
->m_id
% 4))
2255 multiplier
*= 3L, divisor
*= 4L;
2259 /* [see get_cost()] */
2267 /* avoid adjusting nonzero to zero */
2272 /* (no adjustment for angry shk here) */
2276 /* called when an item's value has been enhanced; if it happens to be
2277 on any shop bill, update that bill to reflect the new higher price
2278 [if the new price drops for some reason, keep the old one in place] */
2280 alter_cost(obj
, amt
)
2282 long amt
; /* if 0, use regular shop pricing, otherwise force amount;
2283 if negative, use abs(amt) even if it's less than old cost */
2285 struct bill_x
*bp
= 0;
2289 for (shkp
= next_shkp(fmon
, TRUE
); shkp
; shkp
= next_shkp(shkp
, TRUE
))
2290 if ((bp
= onbill(obj
, shkp
, TRUE
)) != 0) {
2291 new_price
= !amt
? get_cost(obj
, shkp
) : (amt
< 0L) ? -amt
: amt
;
2292 if (new_price
> bp
->price
|| amt
< 0L) {
2293 bp
->price
= new_price
;
2301 /* called from doinv(invent.c) for inventory of unpaid objects */
2303 unpaid_cost(unp_obj
, include_contents
)
2304 struct obj
*unp_obj
; /* known to be unpaid or contain unpaid */
2305 boolean include_contents
;
2307 struct bill_x
*bp
= (struct bill_x
*) 0;
2312 if (!get_obj_location(unp_obj
, &ox
, &oy
, BURIED_TOO
| CONTAINED_TOO
))
2313 ox
= u
.ux
, oy
= u
.uy
; /* (shouldn't happen) */
2314 if ((shkp
= shop_keeper(*in_rooms(ox
, oy
, SHOPBASE
))) != 0) {
2315 bp
= onbill(unp_obj
, shkp
, TRUE
);
2317 /* didn't find shk? try searching bills */
2318 for (shkp
= next_shkp(fmon
, TRUE
); shkp
;
2319 shkp
= next_shkp(shkp
->nmon
, TRUE
))
2320 if ((bp
= onbill(unp_obj
, shkp
, TRUE
)) != 0)
2324 /* onbill() gave no message if unexpected problem occurred */
2325 if (!shkp
|| (unp_obj
->unpaid
&& !bp
)) {
2326 impossible("unpaid_cost: object wasn't on any bill.");
2329 amt
= unp_obj
->quan
* bp
->price
;
2330 if (include_contents
&& Has_contents(unp_obj
))
2331 amt
= contained_cost(unp_obj
, shkp
, amt
, FALSE
, TRUE
);
2337 add_one_tobill(obj
, dummy
, shkp
)
2346 if (!billable(&shkp
, obj
, *u
.ushops
, TRUE
))
2350 if (eshkp
->billct
== BILLSZ
) {
2351 You("got that for free!");
2355 bct
= eshkp
->billct
;
2356 bp
= &(eshkp
->bill_p
[bct
]);
2357 bp
->bo_id
= obj
->o_id
;
2358 bp
->bquan
= obj
->quan
;
2359 if (dummy
) { /* a dummy object must be inserted into */
2360 bp
->useup
= 1; /* the billobjs chain here. crucial for */
2361 add_to_billobjs(obj
); /* eating floorfood in shop. see eat.c */
2364 bp
->price
= get_cost(obj
, shkp
);
2370 add_to_billobjs(obj
)
2373 if (obj
->where
!= OBJ_FREE
)
2374 panic("add_to_billobjs: obj not free");
2376 obj_stop_timers(obj
);
2378 obj
->nobj
= billobjs
;
2380 obj
->where
= OBJ_ONBILL
;
2383 /* recursive billing of objects within containers. */
2385 bill_box_content(obj
, ininv
, dummy
, shkp
)
2386 register struct obj
*obj
;
2387 register boolean ininv
, dummy
;
2388 register struct monst
*shkp
;
2390 register struct obj
*otmp
;
2392 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2393 if (otmp
->oclass
== COIN_CLASS
)
2396 /* the "top" box is added in addtobill() */
2397 if (!otmp
->no_charge
)
2398 add_one_tobill(otmp
, dummy
, shkp
);
2399 if (Has_contents(otmp
))
2400 bill_box_content(otmp
, ininv
, dummy
, shkp
);
2404 /* shopkeeper tells you what you bought or sold, sometimes partly IDing it */
2406 shk_names_obj(shkp
, obj
, fmt
, amt
, arg
)
2409 const char *fmt
; /* "%s %ld %s %s", doname(obj), amt, plur(amt), arg */
2413 char *obj_name
, fmtbuf
[BUFSZ
];
2414 boolean was_unknown
= !obj
->dknown
;
2417 /* Use real name for ordinary weapons/armor, and spell-less
2418 * scrolls/books (that is, blank and mail), but only if the
2419 * object is within the shk's area of interest/expertise.
2421 if (!objects
[obj
->otyp
].oc_magic
&& saleable(shkp
, obj
)
2422 && (obj
->oclass
== WEAPON_CLASS
|| obj
->oclass
== ARMOR_CLASS
2423 || obj
->oclass
== SCROLL_CLASS
|| obj
->oclass
== SPBOOK_CLASS
2424 || obj
->otyp
== MIRROR
)) {
2425 was_unknown
|= !objects
[obj
->otyp
].oc_name_known
;
2426 makeknown(obj
->otyp
);
2428 obj_name
= doname(obj
);
2429 /* Use an alternate message when extra information is being provided */
2431 Sprintf(fmtbuf
, "%%s; you %s", fmt
);
2432 obj_name
[0] = highc(obj_name
[0]);
2433 pline(fmtbuf
, obj_name
, (obj
->quan
> 1L) ? "them" : "it", amt
,
2436 You(fmt
, obj_name
, amt
, plur(amt
), arg
);
2440 /* decide whether a shopkeeper thinks an item belongs to her */
2442 billable(shkpp
, obj
, roomno
, reset_nocharge
)
2443 struct monst
**shkpp
; /* in: non-null if shk has been validated; out: shk */
2446 boolean reset_nocharge
;
2448 struct monst
*shkp
= *shkpp
;
2450 /* if caller hasn't supplied a shopkeeper, look one up now */
2454 shkp
= shop_keeper(roomno
);
2455 if (!shkp
|| !inhishop(shkp
))
2459 /* perhaps we threw it away earlier */
2460 if (onbill(obj
, shkp
, FALSE
)
2461 || (obj
->oclass
== FOOD_CLASS
&& obj
->oeaten
))
2463 /* outer container might be marked no_charge but still have contents
2464 which should be charged for; clear no_charge when picking things up */
2465 if (obj
->no_charge
) {
2466 if (!Has_contents(obj
) || (contained_gold(obj
) == 0L
2467 && contained_cost(obj
, shkp
, 0L, FALSE
,
2468 !reset_nocharge
) == 0L))
2469 shkp
= 0; /* not billable */
2470 if (reset_nocharge
&& !shkp
&& obj
->oclass
!= COIN_CLASS
) {
2472 if (Has_contents(obj
))
2473 picked_container(obj
); /* clear no_charge */
2476 return shkp
? TRUE
: FALSE
;
2480 addtobill(obj
, ininv
, dummy
, silent
)
2482 boolean ininv
, dummy
, silent
;
2484 struct monst
*shkp
= 0;
2485 long ltmp
, cltmp
, gltmp
;
2489 if (!billable(&shkp
, obj
, *u
.ushops
, TRUE
))
2492 if (obj
->oclass
== COIN_CLASS
) {
2493 costly_gold(obj
->ox
, obj
->oy
, obj
->quan
);
2495 } else if (ESHK(shkp
)->billct
== BILLSZ
) {
2497 You("got that for free!");
2501 ltmp
= cltmp
= gltmp
= 0L;
2502 container
= Has_contents(obj
);
2504 if (!obj
->no_charge
)
2505 ltmp
= get_cost(obj
, shkp
);
2507 if (obj
->no_charge
&& !container
) {
2513 cltmp
= contained_cost(obj
, shkp
, cltmp
, FALSE
, FALSE
);
2514 gltmp
= contained_gold(obj
);
2517 add_one_tobill(obj
, dummy
, shkp
);
2519 bill_box_content(obj
, ininv
, dummy
, shkp
);
2520 picked_container(obj
); /* reset contained obj->no_charge */
2525 costly_gold(obj
->ox
, obj
->oy
, gltmp
);
2532 contentscount
= count_unpaid(obj
->cobj
);
2533 } else { /* !container */
2534 add_one_tobill(obj
, dummy
, shkp
);
2538 if (!Deaf
&& !muteshk(shkp
) && !silent
) {
2542 pline("%s has no interest in %s.", Shknam(shkp
), the(xname(obj
)));
2546 pline("%s will cost you %ld %s%s.", The(xname(obj
)), ltmp
,
2547 currency(ltmp
), (obj
->quan
> 1L) ? " each" : "");
2549 long save_quan
= obj
->quan
;
2551 Strcpy(buf
, "\"For you, ");
2553 Strcat(buf
, "scum;");
2555 append_honorific(buf
);
2556 Strcat(buf
, "; only");
2558 obj
->quan
= 1L; /* fool xname() into giving singular */
2559 pline("%s %ld %s %s %s%s.\"", buf
, ltmp
, currency(ltmp
),
2560 (save_quan
> 1L) ? "per" : (contentscount
&& !obj
->unpaid
)
2561 ? "for the contents of this"
2564 (contentscount
&& obj
->unpaid
) ? and_its_contents
: "");
2565 obj
->quan
= save_quan
;
2567 } else if (!silent
) {
2569 pline_The("list price of %s%s%s is %ld %s%s.",
2570 (contentscount
&& !obj
->unpaid
) ? the_contents_of
: "",
2572 (contentscount
&& obj
->unpaid
) ? and_its_contents
: "",
2573 ltmp
, currency(ltmp
), (obj
->quan
> 1L) ? " each" : "");
2575 pline("%s does not notice.", Shknam(shkp
));
2580 append_honorific(buf
)
2583 /* (chooses among [0]..[3] normally; [1]..[4] after the
2584 Wizard has been killed or invocation ritual performed) */
2585 static const char *const honored
[] = { "good", "honored", "most gracious",
2587 "most renowned and sacred" };
2588 Strcat(buf
, honored
[rn2(SIZE(honored
) - 1) + u
.uevent
.udemigod
]);
2589 if (is_vampire(youmonst
.data
))
2590 Strcat(buf
, (flags
.female
) ? " dark lady" : " dark lord");
2591 else if (is_elf(youmonst
.data
))
2592 Strcat(buf
, (flags
.female
) ? " hiril" : " hir");
2594 Strcat(buf
, !is_human(youmonst
.data
) ? " creature" : (flags
.female
)
2600 splitbill(obj
, otmp
)
2601 register struct obj
*obj
, *otmp
;
2603 /* otmp has been split off from obj */
2604 register struct bill_x
*bp
;
2606 register struct monst
*shkp
= shop_keeper(*u
.ushops
);
2608 if (!shkp
|| !inhishop(shkp
)) {
2609 impossible("splitbill: no resident shopkeeper??");
2612 bp
= onbill(obj
, shkp
, FALSE
);
2614 impossible("splitbill: not on bill?");
2617 if (bp
->bquan
< otmp
->quan
) {
2618 impossible("Negative quantity on bill??");
2620 if (bp
->bquan
== otmp
->quan
) {
2621 impossible("Zero quantity on bill??");
2623 bp
->bquan
-= otmp
->quan
;
2625 if (ESHK(shkp
)->billct
== BILLSZ
)
2629 bp
= &(ESHK(shkp
)->bill_p
[ESHK(shkp
)->billct
]);
2630 bp
->bo_id
= otmp
->o_id
;
2631 bp
->bquan
= otmp
->quan
;
2634 ESHK(shkp
)->billct
++;
2639 sub_one_frombill(obj
, shkp
)
2640 register struct obj
*obj
;
2641 register struct monst
*shkp
;
2643 register struct bill_x
*bp
;
2645 if ((bp
= onbill(obj
, shkp
, FALSE
)) != 0) {
2646 register struct obj
*otmp
;
2649 if (bp
->bquan
> obj
->quan
) {
2652 otmp
->oextra
= (struct oextra
*) 0;
2653 bp
->bo_id
= otmp
->o_id
= context
.ident
++;
2654 otmp
->where
= OBJ_FREE
;
2655 otmp
->quan
= (bp
->bquan
-= obj
->quan
);
2656 otmp
->owt
= 0; /* superfluous */
2658 add_to_billobjs(otmp
);
2661 ESHK(shkp
)->billct
--;
2664 /* DRS/NS 2.2.6 messes up -- Peter Kendell */
2665 int indx
= ESHK(shkp
)->billct
;
2667 *bp
= ESHK(shkp
)->bill_p
[indx
];
2670 *bp
= ESHK(shkp
)->bill_p
[ESHK(shkp
)->billct
];
2673 } else if (obj
->unpaid
) {
2674 impossible("sub_one_frombill: unpaid object not on bill");
2679 /* recursive check of unpaid objects within nested containers. */
2681 subfrombill(obj
, shkp
)
2682 register struct obj
*obj
;
2683 register struct monst
*shkp
;
2685 register struct obj
*otmp
;
2687 sub_one_frombill(obj
, shkp
);
2689 if (Has_contents(obj
))
2690 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2691 if (otmp
->oclass
== COIN_CLASS
)
2694 if (Has_contents(otmp
))
2695 subfrombill(otmp
, shkp
);
2697 sub_one_frombill(otmp
, shkp
);
2702 stolen_container(obj
, shkp
, price
, ininv
)
2712 /* the price of contained objects; caller handles top container */
2713 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2714 if (otmp
->oclass
== COIN_CLASS
)
2717 if (!billable(&shkp
, otmp
, ESHK(shkp
)->shoproom
, TRUE
)) {
2718 /* billable() returns false for objects already on bill */
2719 if ((bp
= onbill(otmp
, shkp
, FALSE
)) == 0)
2721 /* this assumes that we're being called by stolen_value()
2722 (or by a recursive call to self on behalf of it) where
2723 the cost of this object is about to be added to shop
2724 debt in place of having it remain on the current bill */
2725 billamt
= bp
->bquan
* bp
->price
;
2726 sub_one_frombill(otmp
, shkp
); /* avoid double billing */
2731 else if (ininv
? otmp
->unpaid
: !otmp
->no_charge
)
2732 price
+= otmp
->quan
* get_cost(otmp
, shkp
);
2734 if (Has_contents(otmp
))
2735 price
= stolen_container(otmp
, shkp
, price
, ininv
);
2742 stolen_value(obj
, x
, y
, peaceful
, silent
)
2745 boolean peaceful
, silent
;
2747 long value
= 0L, gvalue
= 0L, billamt
= 0L;
2748 char roomno
= *in_rooms(x
, y
, SHOPBASE
);
2750 struct monst
*shkp
= 0;
2752 if (!billable(&shkp
, obj
, roomno
, FALSE
)) {
2753 /* things already on the bill yield a not-billable result, so
2754 we need to check bill before deciding that shk doesn't care */
2755 if ((bp
= onbill(obj
, shkp
, FALSE
)) == 0)
2757 /* shk does care; take obj off bill to avoid double billing */
2758 billamt
= bp
->bquan
* bp
->price
;
2759 sub_one_frombill(obj
, shkp
);
2762 if (obj
->oclass
== COIN_CLASS
) {
2763 gvalue
+= obj
->quan
;
2767 else if (!obj
->no_charge
)
2768 value
+= obj
->quan
* get_cost(obj
, shkp
);
2770 if (Has_contents(obj
)) {
2772 (obj
->where
== OBJ_INVENT
|| obj
->where
== OBJ_FREE
);
2774 value
+= stolen_container(obj
, shkp
, 0L, ininv
);
2776 gvalue
+= contained_gold(obj
);
2780 if (gvalue
+ value
== 0L)
2786 boolean credit_use
= !!ESHK(shkp
)->credit
;
2787 value
= check_credit(value
, shkp
);
2788 /* 'peaceful' affects general treatment, but doesn't affect
2789 * the fact that other code expects that all charges after the
2790 * shopkeeper is angry are included in robbed, not debit */
2792 ESHK(shkp
)->robbed
+= value
;
2794 ESHK(shkp
)->debit
+= value
;
2797 const char *still
= "";
2800 if (ESHK(shkp
)->credit
) {
2801 You("have %ld %s credit remaining.", ESHK(shkp
)->credit
,
2802 currency(ESHK(shkp
)->credit
));
2804 } else if (!value
) {
2805 You("have no credit remaining.");
2810 if (obj
->oclass
== COIN_CLASS
)
2811 You("%sowe %s %ld %s!", still
, shkname(shkp
), value
,
2814 You("%sowe %s %ld %s for %s!", still
, shkname(shkp
),
2815 value
, currency(value
), (obj
->quan
> 1L) ? "them" : "it");
2818 ESHK(shkp
)->robbed
+= value
;
2821 if (canseemon(shkp
)) {
2822 Norep("%s booms: \"%s, you are a thief!\"",
2823 Shknam(shkp
), plname
);
2825 Norep("You hear a scream, \"Thief!\"");
2828 (void) angry_guards(FALSE
);
2833 /* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */
2834 static char sell_response
= 'a';
2835 static int sell_how
= SELL_NORMAL
;
2836 /* can't just use sell_response='y' for auto_credit because the 'a' response
2837 shouldn't carry over from ordinary selling to credit selling */
2838 static boolean auto_credit
= FALSE
;
2841 sellobj_state(deliberate
)
2844 /* If we're deliberately dropping something, there's no automatic
2845 response to the shopkeeper's "want to sell" query; however, if we
2846 accidentally drop anything, the shk will buy it/them without asking.
2847 This retains the old pre-query risk that slippery fingers while in
2848 shops entailed: you drop it, you've lost it.
2850 sell_response
= (deliberate
!= SELL_NORMAL
) ? '\0' : 'a';
2851 sell_how
= deliberate
;
2852 auto_credit
= FALSE
;
2857 register struct obj
*obj
;
2860 register struct monst
*shkp
;
2861 register struct eshk
*eshkp
;
2862 long ltmp
= 0L, cltmp
= 0L, gltmp
= 0L, offer
, shkmoney
;
2863 boolean saleitem
, cgold
= FALSE
, container
= Has_contents(obj
);
2864 boolean isgold
= (obj
->oclass
== COIN_CLASS
);
2865 boolean only_partially_your_contents
= FALSE
;
2867 if (!(shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
))) || !inhishop(shkp
))
2869 if (!costly_spot(x
, y
))
2874 if (obj
->unpaid
&& !container
&& !isgold
) {
2875 sub_one_frombill(obj
, shkp
);
2879 /* find the price of content before subfrombill */
2880 cltmp
= contained_cost(obj
, shkp
, cltmp
, TRUE
, FALSE
);
2881 /* find the value of contained gold */
2882 gltmp
+= contained_gold(obj
);
2883 cgold
= (gltmp
> 0L);
2886 saleitem
= saleable(shkp
, obj
);
2887 if (!isgold
&& !obj
->unpaid
&& saleitem
)
2888 ltmp
= set_cost(obj
, shkp
);
2890 offer
= ltmp
+ cltmp
;
2892 /* get one case out of the way: nothing to sell, and no gold */
2893 if (!(isgold
|| cgold
)
2894 && ((offer
+ gltmp
) == 0L || sell_how
== SELL_DONTSELL
)) {
2895 boolean unpaid
= is_unpaid(obj
);
2898 dropped_container(obj
, shkp
, FALSE
);
2902 subfrombill(obj
, shkp
);
2906 if (!unpaid
&& (sell_how
!= SELL_DONTSELL
)
2907 && !special_stock(obj
, shkp
, FALSE
))
2908 pline("%s seems uninterested.", Shknam(shkp
));
2912 /* you dropped something of your own - probably want to sell it */
2913 rouse_shk(shkp
, TRUE
); /* wake up sleeping or paralyzed shk */
2916 if (ANGRY(shkp
)) { /* they become shop-objects, no pay */
2917 if (!Deaf
&& !muteshk(shkp
))
2918 verbalize("Thank you, scum!");
2920 pline("%s smirks with satisfaction.", Shknam(shkp
));
2921 subfrombill(obj
, shkp
);
2925 if (eshkp
->robbed
) { /* shkp is not angry? */
2930 if ((eshkp
->robbed
-= offer
< 0L))
2932 if (offer
&& !Deaf
&& !muteshk(shkp
))
2934 "Thank you for your contribution to restock this recently plundered shop.");
2935 subfrombill(obj
, shkp
);
2939 if (isgold
|| cgold
) {
2943 if (eshkp
->debit
>= gltmp
) {
2944 if (eshkp
->loan
) { /* you carry shop's gold */
2945 if (eshkp
->loan
>= gltmp
)
2946 eshkp
->loan
-= gltmp
;
2950 eshkp
->debit
-= gltmp
;
2951 Your("debt is %spaid off.", eshkp
->debit
? "partially " : "");
2953 long delta
= gltmp
- eshkp
->debit
;
2955 eshkp
->credit
+= delta
;
2959 Your("debt is paid off.");
2961 if (eshkp
->credit
== delta
)
2962 You("have established %ld %s credit.", delta
,
2965 pline("%ld %s added to your credit; total is now %ld %s.",
2966 delta
, currency(delta
), eshkp
->credit
,
2967 currency(eshkp
->credit
));
2970 if (!offer
|| sell_how
== SELL_DONTSELL
) {
2973 dropped_container(obj
, shkp
, FALSE
);
2976 subfrombill(obj
, shkp
);
2982 if ((!saleitem
&& !(container
&& cltmp
> 0L)) || eshkp
->billct
== BILLSZ
2983 || obj
->oclass
== BALL_CLASS
|| obj
->oclass
== CHAIN_CLASS
2984 || offer
== 0L || (obj
->oclass
== FOOD_CLASS
&& obj
->oeaten
)
2986 && obj
->age
< 20L * (long) objects
[obj
->otyp
].oc_cost
)) {
2987 pline("%s seems uninterested%s.", Shknam(shkp
),
2988 cgold
? " in the rest" : "");
2990 dropped_container(obj
, shkp
, FALSE
);
2995 shkmoney
= money_cnt(shkp
->minvent
);
2997 char c
, qbuf
[BUFSZ
];
2998 long tmpcr
= ((offer
* 9L) / 10L) + (offer
<= 1L);
3000 if (sell_how
== SELL_NORMAL
|| auto_credit
) {
3001 c
= sell_response
= 'y';
3002 } else if (sell_response
!= 'n') {
3003 pline("%s cannot pay you at present.", shkname(shkp
));
3004 Sprintf(qbuf
, "Will you accept %ld %s in credit for ", tmpcr
,
3006 c
= ynaq(safe_qbuf(qbuf
, qbuf
, "?", obj
, doname
, thesimpleoname
,
3007 (obj
->quan
== 1L) ? "that" : "those"));
3012 } else /* previously specified "quit" */
3018 (sell_how
!= SELL_NORMAL
)
3019 ? "traded %s for %ld zorkmid%s in %scredit."
3020 : "relinquish %s and acquire %ld zorkmid%s in %scredit.",
3021 tmpcr
, (eshkp
->credit
> 0L) ? "additional " : "");
3022 eshkp
->credit
+= tmpcr
;
3023 subfrombill(obj
, shkp
);
3026 sell_response
= 'n';
3028 dropped_container(obj
, shkp
, FALSE
);
3031 subfrombill(obj
, shkp
);
3034 char qbuf
[BUFSZ
], qsfx
[BUFSZ
];
3035 boolean short_funds
= (offer
> shkmoney
), one
;
3039 if (!sell_response
) {
3040 long yourc
= 0L, shksc
;
3043 /* number of items owned by shk */
3044 shksc
= count_contents(obj
, TRUE
, TRUE
, FALSE
);
3045 /* number of items owned by you (total - shksc) */
3046 yourc
= count_contents(obj
, TRUE
, TRUE
, TRUE
) - shksc
;
3047 only_partially_your_contents
= shksc
&& yourc
;
3050 "<shk> offers * for ..." query formatting.
3052 "... your <object>. Sell it?"
3053 "... your <objects>. Sell them?"
3054 A container is either owned by the hero, or already
3055 owned by the shk (!ltmp), or the shk isn't interested
3056 in buying it (also !ltmp). It's either empty (!cltmp)
3057 or it has contents owned by the hero or it has some
3058 contents owned by the hero and others by the shk.
3059 (The case where it has contents already entirely owned
3060 by the shk is treated the same was if it were empty
3061 since the hero isn't selling any of those contents.)
3063 "... your <empty bag>. Sell it?"
3064 "... your <bag> and its contents. Sell them?"
3065 "... your <bag> and item inside. Sell them?"
3066 "... your <bag> and items inside. Sell them?"
3068 "... your item in the <bag>. Sell it?"
3069 "... your items in the <bag>. Sell them?"
3071 Sprintf(qbuf
, "%s offers%s %ld gold piece%s for %s%s ",
3072 shkname(shkp
), short_funds
? " only" : "", offer
,
3075 ? ((yourc
== 1L) ? "your item in " : "your items in ")
3077 obj
->unpaid
? "the" : "your");
3078 one
= obj
->unpaid
? (yourc
== 1L) : (obj
->quan
== 1L && !cltmp
);
3079 Sprintf(qsfx
, "%s. Sell %s?",
3081 ? (only_partially_your_contents
3082 ? ((yourc
== 1L) ? " and item inside"
3083 : " and items inside")
3086 one
? "it" : "them");
3087 (void) safe_qbuf(qbuf
, qbuf
, qsfx
, obj
, xname
, simpleonames
,
3088 one
? "that" : "those");
3090 qbuf
[0] = '\0'; /* just to pacify lint */
3092 switch (sell_response
? sell_response
: ynaq(qbuf
)) {
3094 sell_response
= 'n';
3097 dropped_container(obj
, shkp
, FALSE
);
3100 subfrombill(obj
, shkp
);
3103 sell_response
= 'y';
3106 dropped_container(obj
, shkp
, TRUE
);
3107 if (!obj
->unpaid
&& !saleitem
)
3109 subfrombill(obj
, shkp
);
3111 shk_names_obj(shkp
, obj
,
3112 (sell_how
!= SELL_NORMAL
)
3113 ? ((!ltmp
&& cltmp
&& only_partially_your_contents
)
3114 ? "sold some items inside %s for %ld gold piece%s.%s"
3115 : "sold %s for %ld gold piece%s.%s")
3116 : "relinquish %s and receive %ld gold piece%s in compensation.%s",
3120 impossible("invalid sell response");
3127 int mode
; /* 0: deliver count 1: paged */
3130 void sasc_bug(struct obj
*, unsigned);
3134 struct bill_x
*bp
, *end_bp
;
3140 shkp
= shop_keeper(*u
.ushops
);
3141 if (!shkp
|| !inhishop(shkp
)) {
3143 impossible("doinvbill: no shopkeeper?");
3149 /* count expended items, so that the `I' command can decide
3150 whether to include 'x' in its prompt string */
3151 int cnt
= !eshkp
->debit
? 0 : 1;
3153 for (bp
= eshkp
->bill_p
, end_bp
= &eshkp
->bill_p
[eshkp
->billct
];
3156 || ((obj
= bp_to_obj(bp
)) != 0 && obj
->quan
< bp
->bquan
))
3161 datawin
= create_nhwindow(NHW_MENU
);
3162 putstr(datawin
, 0, "Unpaid articles already used up:");
3163 putstr(datawin
, 0, "");
3166 for (bp
= eshkp
->bill_p
, end_bp
= &eshkp
->bill_p
[eshkp
->billct
];
3167 bp
< end_bp
; bp
++) {
3168 obj
= bp_to_obj(bp
);
3170 impossible("Bad shopkeeper administration.");
3173 if (bp
->useup
|| bp
->bquan
> obj
->quan
) {
3174 long oquan
, uquan
, thisused
;
3177 uquan
= (bp
->useup
? bp
->bquan
: bp
->bquan
- oquan
);
3178 thisused
= bp
->price
* uquan
;
3179 totused
+= thisused
;
3180 iflags
.suppress_price
++; /* suppress "(unpaid)" suffix */
3181 /* Why 'x'? To match `I x', more or less. */
3182 buf_p
= xprname(obj
, (char *) 0, 'x', FALSE
, thisused
, uquan
);
3183 iflags
.suppress_price
--;
3184 putstr(datawin
, 0, buf_p
);
3188 /* additional shop debt which has no itemization available */
3190 putstr(datawin
, 0, "");
3191 totused
+= eshkp
->debit
;
3192 buf_p
= xprname((struct obj
*) 0, "usage charges and/or other fees",
3193 GOLD_SYM
, FALSE
, eshkp
->debit
, 0L);
3194 putstr(datawin
, 0, buf_p
);
3196 buf_p
= xprname((struct obj
*) 0, "Total:", '*', FALSE
, totused
, 0L);
3197 putstr(datawin
, 0, "");
3198 putstr(datawin
, 0, buf_p
);
3199 display_nhwindow(datawin
, FALSE
);
3201 destroy_nhwindow(datawin
);
3206 getprice(obj
, shk_buying
)
3207 register struct obj
*obj
;
3210 register long tmp
= (long) objects
[obj
->otyp
].oc_cost
;
3212 if (obj
->oartifact
) {
3213 tmp
= arti_cost(obj
);
3217 switch (obj
->oclass
) {
3219 /* simpler hunger check, (2-4)*cost */
3220 if (u
.uhs
>= HUNGRY
&& !shk_buying
)
3221 tmp
*= (long) u
.uhs
;
3230 if (obj
->otyp
== POT_WATER
&& !obj
->blessed
&& !obj
->cursed
)
3236 tmp
+= 10L * (long) obj
->spe
;
3240 && obj
->age
< 20L * (long) objects
[obj
->otyp
].oc_cost
)
3247 /* shk catches thrown pick-axe */
3250 register struct obj
*obj
;
3251 register xchar x
, y
;
3253 register struct monst
*shkp
;
3255 if (!(shkp
= shop_keeper(inside_shop(x
, y
))) || !inhishop(shkp
))
3258 if (shkp
->mcanmove
&& !shkp
->msleeping
3259 && (*u
.ushops
!= ESHK(shkp
)->shoproom
|| !inside_shop(u
.ux
, u
.uy
))
3260 && dist2(shkp
->mx
, shkp
->my
, x
, y
) < 3
3261 /* if it is the shk's pos, you hit and anger him */
3262 && (shkp
->mx
!= x
|| shkp
->my
!= y
)) {
3263 if (mnearto(shkp
, x
, y
, TRUE
) && !Deaf
&& !muteshk(shkp
))
3264 verbalize("Out of my way, scum!");
3266 pline("%s nimbly%s catches %s.", Shknam(shkp
),
3267 (x
== shkp
->mx
&& y
== shkp
->my
) ? "" : " reaches over and",
3269 if (!canspotmon(shkp
))
3270 map_invisible(x
, y
);
3274 subfrombill(obj
, shkp
);
3275 (void) mpickobj(shkp
, obj
);
3278 return (struct monst
*) 0;
3282 add_damage(x
, y
, cost
)
3283 register xchar x
, y
;
3286 struct damage
*tmp_dam
;
3289 if (IS_DOOR(levl
[x
][y
].typ
)) {
3292 /* Don't schedule for repair unless it's a real shop entrance */
3293 for (shops
= in_rooms(x
, y
, SHOPBASE
); *shops
; shops
++)
3294 if ((mtmp
= shop_keeper(*shops
)) != 0 && x
== ESHK(mtmp
)->shd
.x
3295 && y
== ESHK(mtmp
)->shd
.y
)
3300 for (tmp_dam
= level
.damagelist
; tmp_dam
; tmp_dam
= tmp_dam
->next
)
3301 if (tmp_dam
->place
.x
== x
&& tmp_dam
->place
.y
== y
) {
3302 tmp_dam
->cost
+= cost
;
3305 tmp_dam
= (struct damage
*) alloc((unsigned) sizeof(struct damage
));
3306 tmp_dam
->when
= monstermoves
;
3307 tmp_dam
->place
.x
= x
;
3308 tmp_dam
->place
.y
= y
;
3309 tmp_dam
->cost
= cost
;
3310 tmp_dam
->typ
= levl
[x
][y
].typ
;
3311 tmp_dam
->next
= level
.damagelist
;
3312 level
.damagelist
= tmp_dam
;
3313 /* If player saw damage, display as a wall forever */
3315 levl
[x
][y
].seenv
= SVALL
;
3319 * Do something about damage. Either (!croaked) try to repair it, or
3320 * (croaked) just discard damage structs for non-shared locations, since
3321 * they'll never get repaired. Assume that shared locations will get
3322 * repaired eventually by the other shopkeeper(s). This might be an erroneous
3323 * assumption (they might all be dead too), but we have no reasonable way of
3328 remove_damage(shkp
, croaked
)
3332 struct damage
*tmp_dam
, *tmp2_dam
;
3333 boolean did_repair
= FALSE
, saw_door
= FALSE
, saw_floor
= FALSE
,
3334 stop_picking
= FALSE
, doorway_trap
= FALSE
;
3335 int saw_walls
= 0, saw_untrap
= 0;
3336 char trapmsg
[BUFSZ
];
3338 tmp_dam
= level
.damagelist
;
3341 register xchar x
= tmp_dam
->place
.x
, y
= tmp_dam
->place
.y
;
3344 unsigned old_doormask
= 0;
3347 Strcpy(shops
, in_rooms(x
, y
, SHOPBASE
));
3348 if (index(shops
, ESHK(shkp
)->shoproom
)) {
3349 if (IS_DOOR(levl
[x
][y
].typ
))
3350 old_doormask
= levl
[x
][y
].doormask
;
3353 disposition
= (shops
[1]) ? 0 : 1;
3354 else if (stop_picking
)
3355 disposition
= repair_damage(shkp
, tmp_dam
, FALSE
);
3357 /* Defer the stop_occupation() until after repair msgs */
3358 if (closed_door(x
, y
))
3359 stop_picking
= picking_at(x
, y
);
3360 disposition
= repair_damage(shkp
, tmp_dam
, FALSE
);
3362 stop_picking
= FALSE
;
3368 tmp_dam
= tmp_dam
->next
;
3372 if (disposition
> 1) {
3375 if (IS_WALL(levl
[x
][y
].typ
)) {
3377 } else if (IS_DOOR(levl
[x
][y
].typ
)
3378 /* an existing door here implies trap removal */
3379 && !(old_doormask
& (D_ISOPEN
| D_CLOSED
))) {
3381 } else if (disposition
== 3) { /* untrapped */
3383 if (IS_DOOR(levl
[x
][y
].typ
))
3384 doorway_trap
= TRUE
;
3391 tmp_dam
= tmp_dam
->next
;
3393 free((genericptr_t
) level
.damagelist
);
3394 level
.damagelist
= tmp_dam
;
3396 free((genericptr_t
) tmp2_dam
->next
);
3397 tmp2_dam
->next
= tmp_dam
;
3404 Sprintf(trapmsg
, "%s trap%s",
3405 (saw_untrap
> 3) ? "several" : (saw_untrap
> 1) ? "some"
3408 Sprintf(eos(trapmsg
), " %s", vtense(trapmsg
, "are"));
3409 Sprintf(eos(trapmsg
), " removed from the %s",
3410 (doorway_trap
&& saw_untrap
== 1) ? "doorway" : "floor");
3412 trapmsg
[0] = '\0'; /* not just lint suppression... */
3415 char wallbuf
[BUFSZ
];
3417 Sprintf(wallbuf
, "section%s", plur(saw_walls
));
3418 pline("Suddenly, %s %s of wall %s up!",
3419 (saw_walls
== 1) ? "a" : (saw_walls
<= 3) ? "some" : "several",
3420 wallbuf
, vtense(wallbuf
, "close"));
3423 pline_The("shop door reappears!");
3425 pline_The("floor is repaired!");
3427 pline("%s!", upstart(trapmsg
));
3429 if (saw_door
|| saw_floor
|| saw_untrap
)
3430 pline("Suddenly, %s%s%s%s%s!",
3431 saw_door
? "the shop door reappears" : "",
3432 (saw_door
&& saw_floor
) ? " and " : "",
3433 saw_floor
? "the floor damage is gone" : "",
3434 ((saw_door
|| saw_floor
) && *trapmsg
) ? " and " : "",
3436 else if (inside_shop(u
.ux
, u
.uy
) == ESHK(shkp
)->shoproom
)
3437 You_feel("more claustrophobic than before.");
3438 else if (!Deaf
&& !rn2(10))
3439 Norep("The dungeon acoustics noticeably change.");
3446 * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
3450 repair_damage(shkp
, tmp_dam
, catchup
)
3451 register struct monst
*shkp
;
3452 register struct damage
*tmp_dam
;
3453 boolean catchup
; /* restoring a level */
3455 register xchar x
, y
, i
;
3457 register struct monst
*mtmp
;
3458 register struct obj
*otmp
;
3459 register struct trap
*ttmp
;
3461 if ((monstermoves
- tmp_dam
->when
) < REPAIR_DELAY
)
3463 if (shkp
->msleeping
|| !shkp
->mcanmove
|| ESHK(shkp
)->following
)
3465 x
= tmp_dam
->place
.x
;
3466 y
= tmp_dam
->place
.y
;
3467 if (!IS_ROOM(tmp_dam
->typ
)) {
3468 if (x
== u
.ux
&& y
== u
.uy
)
3471 if (x
== shkp
->mx
&& y
== shkp
->my
)
3473 if ((mtmp
= m_at(x
, y
)) && (!passes_walls(mtmp
->data
)))
3476 if ((ttmp
= t_at(x
, y
)) != 0) {
3477 if (x
== u
.ux
&& y
== u
.uy
)
3480 if (ttmp
->ttyp
== LANDMINE
|| ttmp
->ttyp
== BEAR_TRAP
) {
3481 /* convert to an object */
3482 otmp
= mksobj((ttmp
->ttyp
== LANDMINE
) ? LAND_MINE
: BEARTRAP
,
3485 otmp
->owt
= weight(otmp
);
3486 (void) mpickobj(shkp
, otmp
);
3489 if (IS_DOOR(tmp_dam
->typ
) && !(levl
[x
][y
].doormask
& D_ISOPEN
)) {
3490 levl
[x
][y
].doormask
= D_CLOSED
;
3492 } else if (IS_WALL(tmp_dam
->typ
)) {
3493 levl
[x
][y
].typ
= tmp_dam
->typ
;
3499 if (IS_ROOM(tmp_dam
->typ
)) {
3500 /* No messages, because player already filled trap door */
3503 if ((tmp_dam
->typ
== levl
[x
][y
].typ
)
3504 && (!IS_DOOR(tmp_dam
->typ
) || (levl
[x
][y
].doormask
> D_BROKEN
)))
3505 /* No messages if player already replaced shop door */
3507 levl
[x
][y
].typ
= tmp_dam
->typ
;
3508 (void) memset((genericptr_t
) litter
, 0, sizeof(litter
));
3509 if ((otmp
= level
.objects
[x
][y
]) != 0) {
3510 /* Scatter objects haphazardly into the shop */
3511 #define NEED_UPDATE 1
3514 #define horiz(i) ((i % 3) - 1)
3515 #define vert(i) ((i / 3) - 1)
3516 for (i
= 0; i
< 9; i
++) {
3517 if ((i
== 4) || (!ZAP_POS(levl
[x
+ horiz(i
)][y
+ vert(i
)].typ
)))
3520 if (inside_shop(x
+ horiz(i
), y
+ vert(i
))
3521 == ESHK(shkp
)->shoproom
)
3522 litter
[i
] |= INSHOP
;
3524 if (Punished
&& !u
.uswallow
3525 && ((uchain
->ox
== x
&& uchain
->oy
== y
)
3526 || (uball
->ox
== x
&& uball
->oy
== y
))) {
3528 * Either the ball or chain is in the repair location.
3530 * Take the easy way out and put ball&chain under hero.
3532 if (!Deaf
&& !muteshk(shkp
))
3533 verbalize("Get your junk out of my wall!");
3534 unplacebc(); /* pick 'em up */
3535 placebc(); /* put 'em down */
3537 while ((otmp
= level
.objects
[x
][y
]) != 0)
3538 /* Don't mess w/ boulders -- just merge into wall */
3539 if ((otmp
->otyp
== BOULDER
) || (otmp
->otyp
== ROCK
)) {
3540 obj_extract_self(otmp
);
3541 obfree(otmp
, (struct obj
*) 0);
3543 while (!(litter
[i
= rn2(9)] & INSHOP
))
3545 remove_object(otmp
);
3546 place_object(otmp
, x
+ horiz(i
), y
+ vert(i
));
3547 litter
[i
] |= NEED_UPDATE
;
3551 return 1; /* repair occurred while off level */
3554 if (IS_DOOR(tmp_dam
->typ
)) {
3555 levl
[x
][y
].doormask
= D_CLOSED
; /* arbitrary */
3558 /* don't set doormask - it is (hopefully) the same as it was
3559 if not, perhaps save it with the damage array... */
3561 if (IS_WALL(tmp_dam
->typ
) && cansee(x
, y
)) {
3562 /* Player sees actual repair process, so they KNOW it's a wall */
3563 levl
[x
][y
].seenv
= SVALL
;
3566 /* Mark this wall as "repaired". There currently is no code
3567 to do anything about repaired walls, so don't do it. */
3569 for (i
= 0; i
< 9; i
++)
3570 if (litter
[i
] & NEED_UPDATE
)
3571 newsym(x
+ horiz(i
), y
+ vert(i
));
3581 * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
3585 register struct monst
*shkp
;
3587 register xchar gx
, gy
, omx
, omy
;
3589 register schar appr
;
3590 register struct eshk
*eshkp
= ESHK(shkp
);
3592 boolean uondoor
= FALSE
, satdoor
, avoid
= FALSE
, badinv
;
3598 remove_damage(shkp
, FALSE
);
3600 if ((udist
= distu(omx
, omy
)) < 3 && (shkp
->data
!= &mons
[PM_GRID_BUG
]
3601 || (omx
== u
.ux
|| omy
== u
.uy
))) {
3602 if (ANGRY(shkp
) || (Conflict
&& !resist(shkp
, RING_CLASS
, 0, 0))) {
3604 Your("displaced image doesn't fool %s!", shkname(shkp
));
3605 (void) mattacku(shkp
);
3608 if (eshkp
->following
) {
3609 if (strncmp(eshkp
->customer
, plname
, PL_NSIZ
)) {
3610 if (!Deaf
&& !muteshk(shkp
))
3611 verbalize("%s, %s! I was looking for %s.", Hello(shkp
),
3612 plname
, eshkp
->customer
);
3613 eshkp
->following
= 0;
3616 if (moves
> followmsg
+ 4) {
3617 if (!Deaf
&& !muteshk(shkp
))
3618 verbalize("%s, %s! Didn't you forget to pay?",
3619 Hello(shkp
), plname
);
3621 pline("%s holds out %s upturned %s.",
3624 mbodypart(shkp
, HAND
));
3627 pline("%s doesn't like customers who don't pay.",
3640 satdoor
= (gx
== omx
&& gy
== omy
);
3641 if (eshkp
->following
|| ((z
= holetime()) >= 0 && z
* z
<= udist
)) {
3642 /* [This distance check used to apply regardless of
3643 whether the shk was following, but that resulted in
3644 m_move() sometimes taking the shk out of the shop if
3645 the player had fenced him in with boulders or traps.
3646 Such voluntary abandonment left unpaid objects in
3647 invent, triggering billing impossibilities on the
3648 next level once the character fell through the hole.] */
3649 if (udist
> 4 && eshkp
->following
&& !eshkp
->billct
)
3650 return -1; /* leave it to m_move */
3653 } else if (ANGRY(shkp
)) {
3654 /* Move towards the hero if the shopkeeper can see him. */
3655 if (shkp
->mcansee
&& m_canseeu(shkp
)) {
3661 #define GDIST(x, y) (dist2(x, y, gx, gy))
3662 if (Invis
|| u
.usteed
) {
3665 uondoor
= (u
.ux
== eshkp
->shd
.x
&& u
.uy
== eshkp
->shd
.y
);
3668 (carrying(PICK_AXE
) || carrying(DWARVISH_MATTOCK
)
3669 || (Fast
&& (sobj_at(PICK_AXE
, u
.ux
, u
.uy
)
3670 || sobj_at(DWARVISH_MATTOCK
, u
.ux
, u
.uy
))));
3671 if (satdoor
&& badinv
)
3675 avoid
= (*u
.ushops
&& distu(gx
, gy
) > 8);
3679 if (((!eshkp
->robbed
&& !eshkp
->billct
&& !eshkp
->debit
) || avoid
)
3680 && GDIST(omx
, omy
) < 3) {
3681 if (!badinv
&& !onlineu(omx
, omy
))
3689 z
= move_special(shkp
, inhishop(shkp
), appr
, uondoor
, avoid
, omx
, omy
, gx
,
3692 after_shk_move(shkp
);
3697 /* called after shopkeeper moves, in case themove causes re-entry into shop */
3699 after_shk_move(shkp
)
3702 struct eshk
*eshkp
= ESHK(shkp
);
3704 if (eshkp
->bill_p
== (struct bill_x
*) -1000 && inhishop(shkp
)) {
3705 /* reset bill_p, need to re-calc player's occupancy too */
3706 eshkp
->bill_p
= &eshkp
->bill
[0];
3707 check_special_room(FALSE
);
3711 /* for use in levl_follower (mondata.c) */
3714 register struct monst
*mtmp
;
3716 return (boolean
) (mtmp
->isshk
&& ESHK(mtmp
)->following
);
3719 /* You are digging in the shop. */
3724 register struct monst
*shkp
= shop_keeper(*u
.ushops
);
3726 const char *grabs
= "grabs";
3731 /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */
3733 if (shkp
->msleeping
|| !shkp
->mcanmove
|| is_silent(shkp
->data
))
3734 ; /* lang stays 0 */
3735 else if (shkp
->data
->msound
<= MS_ANIMAL
)
3737 else if (shkp
->data
->msound
>= MS_HUMANOID
)
3740 if (!inhishop(shkp
)) {
3741 if (Role_if(PM_KNIGHT
)) {
3742 You_feel("like a common thief.");
3743 adjalign(-sgn(u
.ualign
.type
));
3750 if (!Deaf
&& !muteshk(shkp
)) {
3751 if (u
.utraptype
== TT_PIT
)
3753 "Be careful, %s, or you might fall through the floor.",
3754 flags
.female
? "madam" : "sir");
3756 verbalize("%s, do not damage the floor here!",
3757 flags
.female
? "Madam" : "Sir");
3760 if (Role_if(PM_KNIGHT
)) {
3761 You_feel("like a common thief.");
3762 adjalign(-sgn(u
.ualign
.type
));
3764 } else if (!um_dist(shkp
->mx
, shkp
->my
, 5)
3765 && !shkp
->msleeping
&& shkp
->mcanmove
3766 && (ESHK(shkp
)->billct
|| ESHK(shkp
)->debit
)) {
3767 register struct obj
*obj
, *obj2
;
3769 if (nolimbs(shkp
->data
)) {
3770 grabs
= "knocks off";
3772 /* This is what should happen, but for balance
3773 * reasons, it isn't currently.
3776 pline("%s curses %s inability to grab your backpack!",
3777 shkname(shkp
), mhim(shkp
));
3782 if (distu(shkp
->mx
, shkp
->my
) > 2) {
3784 /* for some reason the shopkeeper can't come next to you */
3785 if (distu(shkp
->mx
, shkp
->my
) > 2) {
3787 pline("%s curses you in anger and frustration!",
3794 pline("%s %s, and %s your backpack!", shkname(shkp
),
3795 makeplural(locomotion(shkp
->data
, "leap")), grabs
);
3797 pline("%s %s your backpack!", shkname(shkp
), grabs
);
3799 for (obj
= invent
; obj
; obj
= obj2
) {
3801 if ((obj
->owornmask
& ~(W_SWAPWEP
| W_QUIVER
)) != 0
3802 || (obj
== uswapwep
&& u
.twoweap
)
3803 || (obj
->otyp
== LEASH
&& obj
->leashmon
))
3805 if (obj
== current_wand
)
3809 subfrombill(obj
, shkp
);
3810 (void) add_to_minv(shkp
, obj
); /* may free obj */
3819 static const short k_mndx
[4] = { PM_KEYSTONE_KOP
, PM_KOP_SERGEANT
,
3820 PM_KOP_LIEUTENANT
, PM_KOP_KAPTAIN
};
3821 int k_cnt
[4], cnt
, mndx
, k
;
3823 k_cnt
[0] = cnt
= abs(depth(&u
.uz
)) + rnd(5);
3824 k_cnt
[1] = (cnt
/ 3) + 1; /* at least one sarge */
3825 k_cnt
[2] = (cnt
/ 6); /* maybe a lieutenant */
3826 k_cnt
[3] = (cnt
/ 9); /* and maybe a kaptain */
3828 for (k
= 0; k
< 4; k
++) {
3829 if ((cnt
= k_cnt
[k
]) == 0)
3832 if (mvitals
[mndx
].mvflags
& G_GONE
)
3836 if (enexto(mm
, mm
->x
, mm
->y
, &mons
[mndx
]))
3837 (void) makemon(&mons
[mndx
], mm
->x
, mm
->y
, NO_MM_FLAGS
);
3842 pay_for_damage(dmgstr
, cant_mollify
)
3844 boolean cant_mollify
;
3846 register struct monst
*shkp
= (struct monst
*) 0;
3847 char shops_affected
[5];
3848 register boolean uinshp
= (*u
.ushops
!= '\0');
3850 register xchar x
, y
;
3851 boolean dugwall
= (!strcmp(dmgstr
, "dig into") /* wand */
3852 || !strcmp(dmgstr
, "damage")); /* pick-axe */
3853 boolean animal
, pursue
;
3854 struct damage
*tmp_dam
, *appear_here
= 0;
3855 /* any number >= (80*80)+(24*24) would do, actually */
3856 long cost_of_damage
= 0L;
3857 unsigned int nearest_shk
= 7000, nearest_damage
= 7000;
3860 for (tmp_dam
= level
.damagelist
;
3861 (tmp_dam
&& (tmp_dam
->when
== monstermoves
));
3862 tmp_dam
= tmp_dam
->next
) {
3867 cost_of_damage
+= tmp_dam
->cost
;
3868 Strcpy(shops_affected
,
3869 in_rooms(tmp_dam
->place
.x
, tmp_dam
->place
.y
, SHOPBASE
));
3870 for (shp
= shops_affected
; *shp
; shp
++) {
3871 struct monst
*tmp_shk
;
3872 unsigned int shk_distance
;
3874 if (!(tmp_shk
= shop_keeper(*shp
)))
3876 if (tmp_shk
== shkp
) {
3877 unsigned int damage_distance
=
3878 distu(tmp_dam
->place
.x
, tmp_dam
->place
.y
);
3880 if (damage_distance
< nearest_damage
) {
3881 nearest_damage
= damage_distance
;
3882 appear_here
= tmp_dam
;
3886 if (!inhishop(tmp_shk
))
3888 shk_distance
= distu(tmp_shk
->mx
, tmp_shk
->my
);
3889 if (shk_distance
> nearest_shk
)
3891 if ((shk_distance
== nearest_shk
) && picks
) {
3897 nearest_shk
= shk_distance
;
3898 appear_here
= tmp_dam
;
3899 nearest_damage
= distu(tmp_dam
->place
.x
, tmp_dam
->place
.y
);
3903 if (!cost_of_damage
|| !shkp
)
3906 animal
= (shkp
->data
->msound
<= MS_ANIMAL
);
3908 x
= appear_here
->place
.x
;
3909 y
= appear_here
->place
.y
;
3911 /* not the best introduction to the shk... */
3912 (void) strncpy(ESHK(shkp
)->customer
, plname
, PL_NSIZ
);
3914 /* if the shk is already on the war path, be sure it's all out */
3915 if (ANGRY(shkp
) || ESHK(shkp
)->following
) {
3920 /* if the shk is not in their shop.. */
3921 if (!*in_rooms(shkp
->mx
, shkp
->my
, SHOPBASE
)) {
3922 if (!cansee(shkp
->mx
, shkp
->my
))
3929 if (um_dist(shkp
->mx
, shkp
->my
, 1)
3930 && !um_dist(shkp
->mx
, shkp
->my
, 3)) {
3931 pline("%s leaps towards you!", shkname(shkp
));
3934 pursue
= um_dist(shkp
->mx
, shkp
->my
, 1);
3939 * Make shkp show up at the door. Effect: If there is a monster
3940 * in the doorway, have the hero hear the shopkeeper yell a bit,
3941 * pause, then have the shopkeeper appear at the door, having
3942 * yanked the hapless critter out of the way.
3946 if (!Deaf
&& !muteshk(shkp
)) {
3947 You_hear("an angry voice:");
3948 verbalize("Out of my way, scum!");
3951 #if defined(UNIX) || defined(VMS)
3952 #if defined(SYSV) || defined(ULTRIX) || defined(VMS)
3961 (void) mnearto(shkp
, x
, y
, TRUE
);
3964 if ((um_dist(x
, y
, 1) && !uinshp
) || cant_mollify
3965 || (money_cnt(invent
) + ESHK(shkp
)->credit
) < cost_of_damage
3968 if (muteshk(shkp
)) {
3969 if (animal
&& shkp
->mcanmove
&& !shkp
->msleeping
)
3971 } else if (pursue
|| uinshp
|| !um_dist(x
, y
, 1)) {
3973 verbalize("How dare you %s my %s?", dmgstr
,
3974 dugwall
? "shop" : "door");
3976 pline("%s is %s that you decided to %s %s %s!",
3977 Shknam(shkp
), angrytexts
[rn2(SIZE(angrytexts
))],
3978 dmgstr
, mhis(shkp
), dugwall
? "shop" : "door");
3981 pline("%s shouts:", shkname(shkp
));
3982 verbalize("Who dared %s my %s?", dmgstr
,
3983 dugwall
? "shop" : "door");
3985 pline("%s is %s that someone decided to %s %s %s!",
3986 Shknam(shkp
), angrytexts
[rn2(SIZE(angrytexts
))],
3987 dmgstr
, mhis(shkp
), dugwall
? "shop" : "door");
3995 Your("invisibility does not fool %s!", shkname(shkp
));
3996 Sprintf(qbuf
, "%sYou did %ld %s worth of damage!%s Pay?",
3997 !animal
? cad(TRUE
) : "", cost_of_damage
,
3998 currency(cost_of_damage
), !animal
? "\"" : "");
3999 if (yn(qbuf
) != 'n') {
4000 cost_of_damage
= check_credit(cost_of_damage
, shkp
);
4001 money2mon(shkp
, cost_of_damage
);
4003 pline("Mollified, %s accepts your restitution.", shkname(shkp
));
4004 /* move shk back to his home loc */
4005 home_shk(shkp
, FALSE
);
4009 if (!Deaf
&& !muteshk(shkp
))
4010 verbalize("Oh, yes! You'll pay!");
4012 pline("%s lunges %s %s toward your %s!",
4015 mbodypart(shkp
, HAND
),
4020 adjalign(-sgn(u
.ualign
.type
));
4024 /* called in dokick.c when we kick an object that might be in a store */
4027 register xchar x
, y
;
4032 if (!level
.flags
.has_shop
)
4034 shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
));
4035 if (!shkp
|| !inhishop(shkp
))
4038 return (boolean
) (inside_shop(x
, y
)
4039 && !(x
== eshkp
->shk
.x
&& y
== eshkp
->shk
.y
));
4042 /* called by dotalk(sounds.c) when #chatting; returns obj if location
4043 contains shop goods and shopkeeper is willing & able to speak */
4046 register xchar x
, y
;
4048 register struct obj
*otmp
;
4049 register struct monst
*shkp
;
4051 if (!(shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
))) || !inhishop(shkp
))
4052 return (struct obj
*) 0;
4054 for (otmp
= level
.objects
[x
][y
]; otmp
; otmp
= otmp
->nexthere
)
4055 if (otmp
->oclass
!= COIN_CLASS
)
4057 /* note: otmp might have ->no_charge set, but that's ok */
4058 return (otmp
&& costly_spot(x
, y
)
4059 && NOTANGRY(shkp
) && shkp
->mcanmove
&& !shkp
->msleeping
)
4064 /* give price quotes for all objects linked to this one (ie, on this spot) */
4066 price_quote(first_obj
)
4067 register struct obj
*first_obj
;
4069 register struct obj
*otmp
;
4070 char buf
[BUFSZ
], price
[40];
4073 boolean contentsonly
= FALSE
;
4075 struct monst
*shkp
= shop_keeper(inside_shop(u
.ux
, u
.uy
));
4077 tmpwin
= create_nhwindow(NHW_MENU
);
4078 putstr(tmpwin
, 0, "Fine goods for sale:");
4079 putstr(tmpwin
, 0, "");
4080 for (otmp
= first_obj
; otmp
; otmp
= otmp
->nexthere
) {
4081 if (otmp
->oclass
== COIN_CLASS
)
4083 cost
= (otmp
->no_charge
|| otmp
== uball
|| otmp
== uchain
)
4085 : get_cost(otmp
, (struct monst
*) 0);
4086 contentsonly
= !cost
;
4087 if (Has_contents(otmp
))
4088 cost
+= contained_cost(otmp
, shkp
, 0L, FALSE
, FALSE
);
4090 Strcpy(price
, "no charge");
4091 contentsonly
= FALSE
;
4093 Sprintf(price
, "%ld %s%s", cost
, currency(cost
),
4094 (otmp
->quan
) > 1L ? " each" : "");
4096 Sprintf(buf
, "%s%s, %s", contentsonly
? the_contents_of
: "",
4097 doname(otmp
), price
);
4098 putstr(tmpwin
, 0, buf
), cnt
++;
4101 display_nhwindow(tmpwin
, TRUE
);
4102 } else if (cnt
== 1) {
4104 /* "<doname(obj)>, no charge" */
4105 pline("%s!", upstart(buf
)); /* buf still contains the string */
4107 /* print cost in slightly different format, so can't reuse buf;
4108 cost and contentsonly are already set up */
4109 Sprintf(buf
, "%s%s", contentsonly
? the_contents_of
: "",
4111 pline("%s, price %ld %s%s%s", upstart(buf
), cost
, currency(cost
),
4112 (first_obj
->quan
> 1L) ? " each" : "",
4113 contentsonly
? "." : shk_embellish(first_obj
, cost
));
4116 destroy_nhwindow(tmpwin
);
4119 STATIC_OVL
const char *
4120 shk_embellish(itm
, cost
)
4121 register struct obj
*itm
;
4125 register int o
, choice
= rn2(5);
4128 choice
= (cost
< 100L ? 1 : cost
< 500L ? 2 : 3);
4135 if (o
== FOOD_CLASS
)
4136 return ", gourmets' delight!";
4137 if (objects
[itm
->otyp
].oc_name_known
4138 ? objects
[itm
->otyp
].oc_magic
4139 : (o
== AMULET_CLASS
|| o
== RING_CLASS
|| o
== WAND_CLASS
4140 || o
== POTION_CLASS
|| o
== SCROLL_CLASS
4141 || o
== SPBOOK_CLASS
))
4142 return ", painstakingly developed!";
4143 return ", superb craftsmanship!";
4145 return ", finest quality.";
4147 return ", an excellent choice.";
4149 return ", a real bargain.";
4153 } else if (itm
->oartifact
) {
4154 return ", one of a kind!";
4159 /* First 4 supplied by Ronen and Tamar, remainder by development team */
4160 const char *Izchak_speaks
[] = {
4161 "%s says: 'These shopping malls give me a headache.'",
4162 "%s says: 'Slow down. Think clearly.'",
4163 "%s says: 'You need to take things one at a time.'",
4164 "%s says: 'I don't like poofy coffee... give me Columbian Supremo.'",
4165 "%s says that getting the devteam's agreement on anything is difficult.",
4166 "%s says that he has noticed those who serve their deity will prosper.",
4167 "%s says: 'Don't try to steal from me - I have friends in high places!'",
4168 "%s says: 'You may well need something from this shop in the future.'",
4169 "%s comments about the Valley of the Dead as being a gateway."
4180 /* The monster type is shopkeeper, but this monster is
4181 not actually a shk, which could happen if someone
4182 wishes for a shopkeeper statue and then animates it.
4183 (Note: shkname() would be "" in a case like this.) */
4184 pline("%s asks whether you've seen any untended shops recently.",
4186 /* [Perhaps we ought to check whether this conversation
4187 is taking place inside an untended shop, but a shopless
4188 shk can probably be expected to be rather disoriented.] */
4194 pline("%s %s how much %s dislikes %s customers.",
4196 (!Deaf
&& !muteshk(shkp
)) ? "mentions" : "indicates",
4197 mhe(shkp
), eshk
->robbed
? "non-paying" : "rude");
4198 } else if (eshk
->following
) {
4199 if (strncmp(eshk
->customer
, plname
, PL_NSIZ
)) {
4200 if (!Deaf
&& !muteshk(shkp
))
4201 verbalize("%s %s! I was looking for %s.",
4202 Hello(shkp
), plname
, eshk
->customer
);
4203 eshk
->following
= 0;
4205 if (!Deaf
&& !muteshk(shkp
))
4206 verbalize("%s %s! Didn't you forget to pay?",
4207 Hello(shkp
), plname
);
4209 pline("%s taps you on the %s.",
4210 Shknam(shkp
), body_part(ARM
));
4212 } else if (eshk
->billct
) {
4213 register long total
= addupbill(shkp
) + eshk
->debit
;
4215 pline("%s %s that your bill comes to %ld %s.",
4217 (!Deaf
&& !muteshk(shkp
)) ? "says" : "indicates",
4218 total
, currency(total
));
4219 } else if (eshk
->debit
) {
4220 pline("%s %s that you owe %s %ld %s.",
4222 (!Deaf
&& !muteshk(shkp
)) ? "reminds you" : "indicates",
4223 mhim(shkp
), eshk
->debit
, currency(eshk
->debit
));
4224 } else if (eshk
->credit
) {
4225 pline("%s encourages you to use your %ld %s of credit.",
4226 shkname(shkp
), eshk
->credit
, currency(eshk
->credit
));
4227 } else if (eshk
->robbed
) {
4228 pline("%s %s about a recent robbery.",
4230 (!Deaf
&& !muteshk(shkp
)) ? "complains" : "indicates concern");
4231 } else if ((shkmoney
= money_cnt(shkp
->minvent
)) < 50L) {
4232 pline("%s %s that business is bad.",
4234 (!Deaf
&& !muteshk(shkp
)) ? "complains" : "indicates");
4235 } else if (shkmoney
> 4000) {
4236 pline("%s %s that business is good.",
4238 (!Deaf
&& !muteshk(shkp
)) ? "says" : "indicates");
4239 } else if (is_izchak(shkp
, FALSE
)) {
4240 if (!Deaf
&& !muteshk(shkp
))
4241 pline(Izchak_speaks
[rn2(SIZE(Izchak_speaks
))], shkname(shkp
));
4243 if (!Deaf
&& !muteshk(shkp
))
4244 pline("%s talks about the problem of shoplifters.", shkname(shkp
));
4252 register int cnt
= 0;
4253 register struct monst
*mtmp
, *mtmp2
;
4255 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp2
) {
4257 if (mtmp
->data
->mlet
== S_KOP
) {
4258 if (canspotmon(mtmp
))
4264 pline_The("Kop%s (disappointed) vanish%s into thin air.",
4265 plur(cnt
), (cnt
== 1) ? "es" : "");
4269 cost_per_charge(shkp
, otmp
, altusage
)
4272 boolean altusage
; /* some items have an "alternate" use with different cost */
4276 if (!shkp
|| !inhishop(shkp
))
4277 return 0L; /* insurance */
4278 tmp
= get_cost(otmp
, shkp
);
4280 /* The idea is to make the exhaustive use of an unpaid item
4281 * more expensive than buying it outright.
4283 if (otmp
->otyp
== MAGIC_LAMP
) { /* 1 */
4284 /* normal use (ie, as light source) of a magic lamp never
4285 degrades its value, but not charging anything would make
4286 identification too easy; charge an amount comparable to
4287 what is charged for an ordinary lamp (don't bother with
4288 angry shk surcharge) */
4290 tmp
= (long) objects
[OIL_LAMP
].oc_cost
;
4292 tmp
+= tmp
/ 3L; /* djinni is being released */
4293 } else if (otmp
->otyp
== MAGIC_MARKER
) { /* 70 - 100 */
4294 /* No way to determine in advance how many charges will be
4295 * wasted. So, arbitrarily, one half of the price per use.
4298 } else if (otmp
->otyp
== BAG_OF_TRICKS
/* 1 - 20 */
4299 || otmp
->otyp
== HORN_OF_PLENTY
) {
4300 /* altusage: emptying of all the contents at once */
4303 } else if (otmp
->otyp
== CRYSTAL_BALL
/* 1 - 5 */
4304 || otmp
->otyp
== OIL_LAMP
/* 1 - 10 */
4305 || otmp
->otyp
== BRASS_LANTERN
4306 || (otmp
->otyp
>= MAGIC_FLUTE
4307 && otmp
->otyp
<= DRUM_OF_EARTHQUAKE
) /* 5 - 9 */
4308 || otmp
->oclass
== WAND_CLASS
) { /* 3 - 11 */
4311 } else if (otmp
->oclass
== SPBOOK_CLASS
) {
4313 } else if (otmp
->otyp
== CAN_OF_GREASE
|| otmp
->otyp
== TINNING_KIT
4314 || otmp
->otyp
== EXPENSIVE_CAMERA
) {
4316 } else if (otmp
->otyp
== POT_OIL
) {
4322 /* Charge the player for partial use of an unpaid object.
4324 * Note that bill_dummy_object() should be used instead
4325 * when an object is completely used.
4328 check_unpaid_usage(otmp
, altusage
)
4333 const char *fmt
, *arg1
, *arg2
;
4337 if (!otmp
->unpaid
|| !*u
.ushops
4338 || (otmp
->spe
<= 0 && objects
[otmp
->otyp
].oc_charged
))
4340 if (!(shkp
= shop_keeper(*u
.ushops
)) || !inhishop(shkp
))
4342 if ((tmp
= cost_per_charge(shkp
, otmp
, altusage
)) == 0L)
4346 if (otmp
->oclass
== SPBOOK_CLASS
) {
4347 fmt
= "%sYou owe%s %ld %s.";
4348 Sprintf(buf
, "This is no free library, %s! ", cad(FALSE
));
4349 arg1
= rn2(2) ? buf
: "";
4350 arg2
= ESHK(shkp
)->debit
> 0L ? " an additional" : "";
4351 } else if (otmp
->otyp
== POT_OIL
) {
4352 fmt
= "%s%sThat will cost you %ld %s (Yendorian Fuel Tax).";
4353 } else if (altusage
&& (otmp
->otyp
== BAG_OF_TRICKS
4354 || otmp
->otyp
== HORN_OF_PLENTY
)) {
4355 fmt
= "%s%sEmptying that will cost you %ld %s.";
4359 arg1
= "Watch it! ";
4361 fmt
= "%s%sUsage fee, %ld %s.";
4368 if (!Deaf
&& !muteshk(shkp
)) {
4369 verbalize(fmt
, arg1
, arg2
, tmp
, currency(tmp
));
4370 exercise(A_WIS
, TRUE
); /* you just got info */
4372 ESHK(shkp
)->debit
+= tmp
;
4375 /* for using charges of unpaid objects "used in the normal manner" */
4380 check_unpaid_usage(otmp
, FALSE
); /* normal item use */
4384 costly_gold(x
, y
, amount
)
4385 register xchar x
, y
;
4386 register long amount
;
4388 register long delta
;
4389 register struct monst
*shkp
;
4390 register struct eshk
*eshkp
;
4392 if (!costly_spot(x
, y
))
4394 /* shkp now guaranteed to exist by costly_spot() */
4395 shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
));
4398 if (eshkp
->credit
>= amount
) {
4399 if (eshkp
->credit
> amount
)
4400 Your("credit is reduced by %ld %s.", amount
, currency(amount
));
4402 Your("credit is erased.");
4403 eshkp
->credit
-= amount
;
4405 delta
= amount
- eshkp
->credit
;
4407 Your("credit is erased.");
4409 Your("debt increases by %ld %s.", delta
, currency(delta
));
4411 You("owe %s %ld %s.", shkname(shkp
), delta
, currency(delta
));
4412 eshkp
->debit
+= delta
;
4413 eshkp
->loan
+= delta
;
4418 /* used in domove to block diagonal shop-exit */
4419 /* x,y should always be a door */
4422 register xchar x
, y
;
4424 register int roomno
= *in_rooms(x
, y
, SHOPBASE
);
4425 register struct monst
*shkp
;
4427 if (roomno
< 0 || !IS_SHOP(roomno
))
4429 if (!IS_DOOR(levl
[x
][y
].typ
))
4431 if (roomno
!= *u
.ushops
)
4434 if (!(shkp
= shop_keeper((char) roomno
)) || !inhishop(shkp
))
4437 if (shkp
->mx
== ESHK(shkp
)->shk
.x
&& shkp
->my
== ESHK(shkp
)->shk
.y
4438 /* Actually, the shk should be made to block _any_
4439 * door, including a door the player digs, if the
4440 * shk is within a 'jumping' distance.
4442 && ESHK(shkp
)->shd
.x
== x
4443 && ESHK(shkp
)->shd
.y
== y
4444 && shkp
->mcanmove
&& !shkp
->msleeping
4445 && (ESHK(shkp
)->debit
|| ESHK(shkp
)->billct
|| ESHK(shkp
)->robbed
)) {
4446 pline("%s%s blocks your way!", shkname(shkp
),
4447 Invis
? " senses your motion and" : "");
4453 /* used in domove to block diagonal shop-entry;
4454 u.ux, u.uy should always be a door */
4457 register xchar x
, y
;
4459 register xchar sx
, sy
;
4460 register int roomno
;
4461 register struct monst
*shkp
;
4463 if (!(IS_DOOR(levl
[u
.ux
][u
.uy
].typ
)
4464 && levl
[u
.ux
][u
.uy
].doormask
== D_BROKEN
))
4467 roomno
= *in_rooms(x
, y
, SHOPBASE
);
4468 if (roomno
< 0 || !IS_SHOP(roomno
))
4470 if (!(shkp
= shop_keeper((char) roomno
)) || !inhishop(shkp
))
4473 if (ESHK(shkp
)->shd
.x
!= u
.ux
|| ESHK(shkp
)->shd
.y
!= u
.uy
)
4476 sx
= ESHK(shkp
)->shk
.x
;
4477 sy
= ESHK(shkp
)->shk
.y
;
4479 if (shkp
->mx
== sx
&& shkp
->my
== sy
&& shkp
->mcanmove
&& !shkp
->msleeping
4480 && (x
== sx
- 1 || x
== sx
+ 1 || y
== sy
- 1 || y
== sy
+ 1)
4481 && (Invis
|| carrying(PICK_AXE
) || carrying(DWARVISH_MATTOCK
)
4483 pline("%s%s blocks your way!", shkname(shkp
),
4484 Invis
? " senses your motion and" : "");
4490 /* "your " or "Foobar's " (note the trailing space) */
4496 if (!shk_owns(buf
, obj
) && !mon_owns(buf
, obj
))
4497 Strcpy(buf
, the_your
[carried(obj
) ? 1 : 0]);
4498 return strcat(buf
, " ");
4506 (void) shk_your(buf
, obj
);
4519 if (get_obj_location(obj
, &x
, &y
, 0)
4520 && (obj
->unpaid
|| (obj
->where
== OBJ_FLOOR
&& !obj
->no_charge
4521 && costly_spot(x
, y
)))) {
4522 shkp
= shop_keeper(inside_shop(x
, y
));
4523 return strcpy(buf
, shkp
? s_suffix(shkname(shkp
)) : the_your
[0]);
4533 if (obj
->where
== OBJ_MINVENT
)
4534 return strcpy(buf
, s_suffix(y_monnam(obj
->ocarry
)));
4538 STATIC_OVL
const char *
4540 boolean altusage
; /* used as a verbalized exclamation: \"Cad! ...\" */
4542 const char *res
= 0;
4544 switch (is_demon(youmonst
.data
) ? 3 : poly_gender()) {
4558 impossible("cad: unknown gender");
4563 char *cadbuf
= mon_nam(&youmonst
); /* snag an output buffer */
4565 /* alternate usage adds a leading double quote and trailing
4566 exclamation point plus sentence separating spaces */
4567 Sprintf(cadbuf
, "\"%s! ", res
);
4568 cadbuf
[1] = highc(cadbuf
[1]);
4576 sasc_bug(struct obj
*op
, unsigned x
)