1 /* NetHack 3.6 shk.c $NHDT-Date: 1464138042 2016/05/25 01:00:42 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.132 $ */
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
));
819 shkp
= (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 */
831 impossible("%s? (rmno=%d, rtype=%d, mnum=%d, \"%s\")",
832 shkp
->isshk
? "shopkeeper career change"
833 : "shop resident not shopkeeper",
835 (int) rooms
[rmno
- ROOMOFFSET
].rtype
,
837 /* [real shopkeeper name is kept in ESHK, not MNAME] */
838 has_mname(shkp
) ? MNAME(shkp
) : "anonymous");
839 /* not sure if this is appropriate, because it does nothing to
840 correct the underlying rooms[].resident issue but... */
841 return (struct monst
*) 0;
849 struct mkroom
*sroom
;
851 struct monst
*mtmp
= sroom
->resident
;
853 return !mtmp
? FALSE
: (boolean
) inhishop(mtmp
);
856 STATIC_OVL
struct bill_x
*
857 onbill(obj
, shkp
, silent
)
863 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
864 register int ct
= ESHK(shkp
)->billct
;
867 if (bp
->bo_id
== obj
->o_id
) {
869 pline("onbill: paid obj on bill?");
874 if (obj
->unpaid
&& !silent
)
875 pline("onbill: unpaid obj not on bill?");
876 return (struct bill_x
*) 0;
879 /* check whether an object or any of its contents belongs to a shop */
884 return (boolean
) (obj
->unpaid
885 || (Has_contents(obj
) && count_unpaid(obj
->cobj
)));
888 /* Delete the contents of the given object. */
891 register struct obj
*obj
;
893 register struct obj
*curr
;
895 while ((curr
= obj
->cobj
) != 0) {
896 obj_extract_self(curr
);
897 obfree(curr
, (struct obj
*) 0);
901 /* called with two args on merge */
904 register struct obj
*obj
, *merge
;
906 register struct bill_x
*bp
;
907 register struct bill_x
*bpm
;
908 register struct monst
*shkp
;
910 if (obj
->otyp
== LEASH
&& obj
->leashmon
)
912 if (obj
->oclass
== FOOD_CLASS
)
913 food_disappears(obj
);
914 if (obj
->oclass
== SPBOOK_CLASS
)
915 book_disappears(obj
);
916 if (Has_contents(obj
))
917 delete_contents(obj
);
921 /* look for a shopkeeper who owns this object */
922 for (shkp
= next_shkp(fmon
, TRUE
); shkp
;
923 shkp
= next_shkp(shkp
->nmon
, TRUE
))
924 if (onbill(obj
, shkp
, TRUE
))
927 /* sanity check, more or less */
929 shkp
= shop_keeper(*u
.ushops
);
931 * Note: `shkp = shop_keeper(*u.ushops)' used to be
932 * unconditional. But obfree() is used all over
933 * the place, so making its behavior be dependent
934 * upon player location doesn't make much sense.
937 if ((bp
= onbill(obj
, shkp
, FALSE
)) != 0) {
940 obj
->unpaid
= 0; /* only for doinvbill */
941 add_to_billobjs(obj
);
944 bpm
= onbill(merge
, shkp
, FALSE
);
946 /* this used to be a rename */
947 impossible("obfree: not on bill??");
950 /* this was a merger */
951 bpm
->bquan
+= bp
->bquan
;
952 ESHK(shkp
)->billct
--;
955 /* DRS/NS 2.2.6 messes up -- Peter Kendell */
956 int indx
= ESHK(shkp
)->billct
;
958 *bp
= ESHK(shkp
)->bill_p
[indx
];
961 *bp
= ESHK(shkp
)->bill_p
[ESHK(shkp
)->billct
];
965 if (obj
->owornmask
) {
966 impossible("obfree: deleting worn obj (%d: %ld)", obj
->otyp
,
968 /* unfortunately at this point we don't know whether worn mask
969 applied to hero or a monster or perhaps something bogus, so
970 can't call remove_worn_item() to get <X>_off() side-effects */
977 check_credit(tmp
, shkp
)
979 register struct monst
*shkp
;
981 long credit
= ESHK(shkp
)->credit
;
984 ; /* nothing to do; just 'return tmp;' */
985 } else if (credit
>= tmp
) {
986 pline_The("price is deducted from your credit.");
987 ESHK(shkp
)->credit
-= tmp
;
990 pline_The("price is partially covered by your credit.");
991 ESHK(shkp
)->credit
= 0L;
1000 register struct monst
*shkp
;
1002 long robbed
= ESHK(shkp
)->robbed
;
1003 long balance
= ((tmp
<= 0L) ? tmp
: check_credit(tmp
, shkp
));
1006 money2mon(shkp
, balance
);
1007 else if (balance
< 0)
1008 money2u(shkp
, -balance
);
1014 ESHK(shkp
)->robbed
= robbed
;
1018 /* return shkp to home position */
1020 home_shk(shkp
, killkops
)
1021 register struct monst
*shkp
;
1022 register boolean killkops
;
1024 register xchar x
= ESHK(shkp
)->shk
.x
, y
= ESHK(shkp
)->shk
.y
;
1026 (void) mnearto(shkp
, x
, y
, TRUE
);
1027 level
.flags
.has_shop
= 1;
1032 after_shk_move(shkp
);
1038 register struct monst
*shkp
;
1040 for (shkp
= next_shkp(fmon
, FALSE
); shkp
;
1041 shkp
= next_shkp(shkp
->nmon
, FALSE
))
1047 /* remove previously applied surcharge from all billed items */
1050 register struct monst
*shkp
;
1052 NOTANGRY(shkp
) = TRUE
; /* make peaceful */
1053 if (ESHK(shkp
)->surcharge
) {
1054 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
1055 register int ct
= ESHK(shkp
)->billct
;
1057 ESHK(shkp
)->surcharge
= FALSE
;
1059 register long reduction
= (bp
->price
+ 3L) / 4L;
1060 bp
->price
-= reduction
; /* undo 33% increase */
1066 /* add aggravation surcharge to all billed items */
1069 register struct monst
*shkp
;
1071 NOTANGRY(shkp
) = FALSE
; /* make angry */
1072 if (!ESHK(shkp
)->surcharge
) {
1073 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
1074 register int ct
= ESHK(shkp
)->billct
;
1076 ESHK(shkp
)->surcharge
= TRUE
;
1078 register long surcharge
= (bp
->price
+ 2L) / 3L;
1079 bp
->price
+= surcharge
;
1085 /* wakeup and/or unparalyze shopkeeper */
1087 rouse_shk(shkp
, verbosely
)
1091 if (!shkp
->mcanmove
|| shkp
->msleeping
) {
1092 /* greed induced recovery... */
1093 if (verbosely
&& canspotmon(shkp
))
1094 pline("%s %s.", Shknam(shkp
),
1095 shkp
->msleeping
? "wakes up" : "can move again");
1096 shkp
->msleeping
= 0;
1103 make_happy_shk(shkp
, silentkops
)
1104 register struct monst
*shkp
;
1105 register boolean silentkops
;
1107 boolean wasmad
= ANGRY(shkp
);
1108 struct eshk
*eshkp
= ESHK(shkp
);
1111 eshkp
->following
= 0;
1113 if (!Role_if(PM_ROGUE
))
1114 adjalign(sgn(u
.ualign
.type
));
1115 if (!inhishop(shkp
)) {
1116 char shk_nam
[BUFSZ
];
1117 boolean vanished
= canseemon(shkp
);
1119 Strcpy(shk_nam
, shkname(shkp
));
1120 if (on_level(&eshkp
->shoplevel
, &u
.uz
)) {
1121 home_shk(shkp
, FALSE
);
1122 /* didn't disappear if shk can still be seen */
1123 if (canseemon(shkp
))
1126 /* if sensed, does disappear regardless whether seen */
1129 /* can't act as porter for the Amulet, even if shk
1130 happens to be going farther down rather than up */
1131 mdrop_special_objs(shkp
);
1132 /* arrive near shop's door */
1133 migrate_to_level(shkp
, ledger_no(&eshkp
->shoplevel
),
1134 MIGR_APPROX_XY
, &eshkp
->shd
);
1135 /* dismiss kops on that level when shk arrives */
1136 eshkp
->dismiss_kops
= TRUE
;
1139 pline("Satisfied, %s suddenly disappears!", shk_nam
);
1141 pline("%s calms down.", Shknam(shkp
));
1143 make_happy_shoppers(silentkops
);
1146 /* called by make_happy_shk() and also by losedogs() for migrating shk */
1148 make_happy_shoppers(silentkops
)
1151 if (!angry_shk_exists()) {
1152 kops_gone(silentkops
);
1159 register struct monst
*shkp
;
1165 (void) strncpy(ESHK(shkp
)->customer
, plname
, PL_NSIZ
);
1166 ESHK(shkp
)->following
= 1;
1169 /* Used when the shkp is teleported or falls (ox == 0) out of his shop, or
1170 when the player is not on a costly_spot and he damages something inside
1171 the shop. These conditions must be checked by the calling function. */
1174 make_angry_shk(shkp
, ox
, oy
)
1176 xchar ox UNUSED
; /* <ox,oy> predate 'noit_Monnam()', let alone Shknam() */
1179 struct eshk
*eshkp
= ESHK(shkp
);
1181 /* all pending shop transactions are now "past due" */
1182 if (eshkp
->billct
|| eshkp
->debit
|| eshkp
->loan
|| eshkp
->credit
) {
1183 eshkp
->robbed
+= (addupbill(shkp
) + eshkp
->debit
+ eshkp
->loan
);
1184 eshkp
->robbed
-= eshkp
->credit
;
1185 if (eshkp
->robbed
< 0L)
1187 /* billct, debit, loan, and credit will be cleared by setpaid */
1191 pline("%s %s!", Shknam(shkp
), !ANGRY(shkp
) ? "gets angry" : "is furious");
1195 STATIC_VAR
const char
1196 no_money
[] = "Moreover, you%s have no money.",
1197 not_enough_money
[] = "Besides, you don't have enough to interest %s.";
1199 /* delivers the cheapest item on the list */
1202 register struct monst
*shkp
;
1204 register int ct
= ESHK(shkp
)->billct
;
1205 register struct bill_x
*bp
= ESHK(shkp
)->bill_p
;
1206 register long gmin
= (bp
->price
* bp
->bquan
);
1209 if (bp
->price
* bp
->bquan
< gmin
)
1210 gmin
= bp
->price
* bp
->bquan
;
1219 register struct eshk
*eshkp
;
1220 register struct monst
*shkp
;
1221 struct monst
*nxtm
, *resident
;
1224 int pass
, tmp
, sk
= 0, seensk
= 0;
1225 boolean paid
= FALSE
, stashed_gold
= (hidden_gold() > 0L);
1229 /* Find how many shk's there are, how many are in
1230 * sight, and are you in a shop room with one.
1232 nxtm
= resident
= 0;
1233 for (shkp
= next_shkp(fmon
, FALSE
); shkp
;
1234 shkp
= next_shkp(shkp
->nmon
, FALSE
)) {
1236 if (ANGRY(shkp
) && distu(shkp
->mx
, shkp
->my
) <= 2)
1238 if (canspotmon(shkp
))
1240 if (inhishop(shkp
) && (*u
.ushops
== ESHK(shkp
)->shoproom
))
1244 if (nxtm
) { /* Player should always appease an */
1245 shkp
= nxtm
; /* irate shk standing next to them. */
1249 if ((!sk
&& (!Blind
|| Blind_telepat
)) || (!Blind
&& !seensk
)) {
1250 There("appears to be no shopkeeper here to receive your payment.");
1259 /* The usual case. Allow paying at a distance when
1260 * inside a tended shop. Should we change that?
1262 if (sk
== 1 && resident
) {
1268 for (shkp
= next_shkp(fmon
, FALSE
); shkp
;
1269 shkp
= next_shkp(shkp
->nmon
, FALSE
))
1270 if (canspotmon(shkp
))
1272 if (shkp
!= resident
&& distu(shkp
->mx
, shkp
->my
) > 2) {
1273 pline("%s is not near enough to receive your payment.",
1285 if (getpos(&cc
, TRUE
, "the creature you want to pay") < 0)
1286 return 0; /* player pressed ESC */
1290 pline("Try again...");
1293 if (u
.ux
== cx
&& u
.uy
== cy
) {
1294 You("are generous to yourself.");
1297 mtmp
= m_at(cx
, cy
);
1298 if (!cansee(cx
, cy
) && (!mtmp
|| !canspotmon(mtmp
))) {
1299 You("can't %s anyone there.", !Blind
? "see" : "sense");
1303 There("is no one there to receive your payment.");
1307 pline("%s is not interested in your payment.", Monnam(mtmp
));
1310 if (mtmp
!= resident
&& distu(mtmp
->mx
, mtmp
->my
) > 2) {
1311 pline("%s is too far to receive your payment.", Shknam(mtmp
));
1318 debugpline0("dopay: null shkp.");
1323 ltmp
= eshkp
->robbed
;
1325 /* wake sleeping shk when someone who owes money offers payment */
1326 if (ltmp
|| eshkp
->billct
|| eshkp
->debit
)
1327 rouse_shk(shkp
, TRUE
);
1329 if (!shkp
->mcanmove
|| shkp
->msleeping
) { /* still asleep/paralyzed */
1330 pline("%s %s.", Shknam(shkp
),
1331 rn2(2) ? "seems to be napping" : "doesn't respond");
1335 if (shkp
!= resident
&& NOTANGRY(shkp
)) {
1336 umoney
= money_cnt(invent
);
1338 You("do not owe %s anything.", shkname(shkp
));
1340 You("%shave no money.", stashed_gold
? "seem to " : "");
1342 pline("But you have some gold stashed away.");
1344 if (umoney
> ltmp
) {
1345 You("give %s the %ld gold piece%s %s asked for.",
1346 shkname(shkp
), ltmp
, plur(ltmp
), mhe(shkp
));
1349 You("give %s all your%s gold.", shkname(shkp
),
1350 stashed_gold
? " openly kept" : "");
1353 pline("But you have hidden gold!");
1355 if ((umoney
< ltmp
/ 2L) || (umoney
< ltmp
&& stashed_gold
))
1356 pline("Unfortunately, %s doesn't look satisfied.", mhe(shkp
));
1358 make_happy_shk(shkp
, FALSE
);
1363 /* ltmp is still eshkp->robbed here */
1364 if (!eshkp
->billct
&& !eshkp
->debit
) {
1365 umoney
= money_cnt(invent
);
1366 if (!ltmp
&& NOTANGRY(shkp
)) {
1367 You("do not owe %s anything.", shkname(shkp
));
1369 pline(no_money
, stashed_gold
? " seem to" : "");
1371 pline("%s is after blood, not money!", shkname(shkp
));
1372 if (umoney
< ltmp
/ 2L || (umoney
< ltmp
&& stashed_gold
)) {
1374 pline(no_money
, stashed_gold
? " seem to" : "");
1376 pline(not_enough_money
, mhim(shkp
));
1379 pline("But since %s shop has been robbed recently,", mhis(shkp
));
1380 pline("you %scompensate %s for %s losses.",
1381 (umoney
< ltmp
) ? "partially " : "", shkname(shkp
),
1383 pay(umoney
< ltmp
? umoney
: ltmp
, shkp
);
1384 make_happy_shk(shkp
, FALSE
);
1386 /* shopkeeper is angry, but has not been robbed --
1387 * door broken, attacked, etc. */
1388 pline("%s is after your hide, not your money!", Shknam(shkp
));
1389 if (umoney
< 1000L) {
1391 pline(no_money
, stashed_gold
? " seem to" : "");
1393 pline(not_enough_money
, mhim(shkp
));
1396 You("try to appease %s by giving %s 1000 gold pieces.",
1397 x_monnam(shkp
, ARTICLE_THE
, "angry", 0, FALSE
), mhim(shkp
));
1399 if (strncmp(eshkp
->customer
, plname
, PL_NSIZ
) || rn2(3))
1400 make_happy_shk(shkp
, FALSE
);
1402 pline("But %s is as angry as ever.", shkname(shkp
));
1406 if (shkp
!= resident
) {
1407 impossible("dopay: not to shopkeeper?");
1412 /* pay debt, if any, first */
1414 long dtmp
= eshkp
->debit
;
1415 long loan
= eshkp
->loan
;
1418 umoney
= money_cnt(invent
);
1419 Sprintf(sbuf
, "You owe %s %ld %s ", shkname(shkp
), dtmp
,
1423 Strcat(sbuf
, "you picked up in the store.");
1426 "for gold picked up and the use of merchandise.");
1428 Strcat(sbuf
, "for the use of merchandise.");
1430 if (umoney
+ eshkp
->credit
< dtmp
) {
1431 pline("But you don't%s have enough gold%s.",
1432 stashed_gold
? " seem to" : "",
1433 eshkp
->credit
? " or credit" : "");
1436 if (eshkp
->credit
>= dtmp
) {
1437 eshkp
->credit
-= dtmp
;
1440 Your("debt is covered by your credit.");
1441 } else if (!eshkp
->credit
) {
1442 money2mon(shkp
, dtmp
);
1445 You("pay that debt.");
1448 dtmp
-= eshkp
->credit
;
1450 money2mon(shkp
, dtmp
);
1453 pline("That debt is partially offset by your credit.");
1454 You("pay the remainder.");
1460 /* now check items on bill */
1461 if (eshkp
->billct
) {
1462 register boolean itemize
;
1465 umoney
= money_cnt(invent
);
1466 if (!umoney
&& !eshkp
->credit
) {
1467 You("%shave no money or credit%s.",
1468 stashed_gold
? "seem to " : "", paid
? " left" : "");
1471 if ((umoney
+ eshkp
->credit
) < cheapest_item(shkp
)) {
1472 You("don't have enough money to buy%s the item%s you picked.",
1473 eshkp
->billct
> 1 ? " any of" : "", plur(eshkp
->billct
));
1475 pline("Maybe you have some gold stashed away?");
1479 /* this isn't quite right; it itemizes without asking if the
1480 * single item on the bill is partly used up and partly unpaid */
1481 iprompt
= (eshkp
->billct
> 1 ? ynq("Itemized billing?") : 'y');
1482 itemize
= (iprompt
== 'y');
1486 for (pass
= 0; pass
<= 1; pass
++) {
1488 while (tmp
< eshkp
->billct
) {
1490 register struct bill_x
*bp
= &(eshkp
->bill_p
[tmp
]);
1492 /* find the object on one of the lists */
1493 if ((otmp
= bp_to_obj(bp
)) != 0) {
1494 /* if completely used up, object quantity is stale;
1495 restoring it to its original value here avoids
1496 making the partly-used-up code more complicated */
1498 otmp
->quan
= bp
->bquan
;
1500 impossible("Shopkeeper administration out of order.");
1501 setpaid(shkp
); /* be nice to the player */
1504 if (pass
== bp
->useup
&& otmp
->quan
== bp
->bquan
) {
1505 /* pay for used-up items on first pass and others
1506 * on second, so player will be stuck in the store
1507 * less often; things which are partly used up
1508 * are processed on both passes */
1511 switch (dopayobj(shkp
, bp
, &otmp
, pass
, itemize
)) {
1516 goto thanks
; /*break*/
1531 *bp
= eshkp
->bill_p
[--eshkp
->billct
];
1537 update_inventory(); /* Done in dopayobj() if itemize. */
1539 if (!ANGRY(shkp
) && paid
) {
1540 if (!Deaf
&& !muteshk(shkp
))
1541 verbalize("Thank you for shopping in %s %s!", s_suffix(shkname(shkp
)),
1542 shtypes
[eshkp
->shoptype
- SHOPBASE
].name
);
1544 pline("%s nods appreciatively at you for shopping in %s %s!",
1547 shtypes
[eshkp
->shoptype
- SHOPBASE
].name
);
1552 /* return 2 if used-up portion paid
1553 * 1 if paid successfully
1554 * 0 if not enough money
1555 * -1 if skip this object
1556 * -2 if no money/credit left
1559 dopayobj(shkp
, bp
, obj_p
, which
, itemize
)
1560 register struct monst
*shkp
;
1561 register struct bill_x
*bp
;
1563 int which
; /* 0 => used-up item, 1 => other (unpaid or lost) */
1566 register struct obj
*obj
= *obj_p
;
1567 long ltmp
, quan
, save_quan
;
1568 long umoney
= money_cnt(invent
);
1570 boolean stashed_gold
= (hidden_gold() > 0L), consumed
= (which
== 0);
1572 if (!obj
->unpaid
&& !bp
->useup
) {
1573 impossible("Paid object on bill??");
1576 if (itemize
&& umoney
+ ESHK(shkp
)->credit
== 0L) {
1577 You("%shave no money or credit left.",
1578 stashed_gold
? "seem to " : "");
1581 /* we may need to temporarily adjust the object, if part of the
1582 original quantity has been used up but part remains unpaid */
1583 save_quan
= obj
->quan
;
1585 /* either completely used up (simple), or split needed */
1587 if (quan
> obj
->quan
) /* difference is amount used up */
1590 /* dealing with ordinary unpaid item */
1593 obj
->quan
= quan
; /* to be used by doname() */
1594 obj
->unpaid
= 0; /* ditto */
1595 iflags
.suppress_price
++; /* affects containers */
1596 ltmp
= bp
->price
* quan
;
1597 buy
= PAY_BUY
; /* flag; if changed then return early */
1600 char qbuf
[BUFSZ
], qsfx
[BUFSZ
];
1602 Sprintf(qsfx
, " for %ld %s. Pay?", ltmp
, currency(ltmp
));
1603 (void) safe_qbuf(qbuf
, (char *) 0, qsfx
, obj
,
1604 (quan
== 1L) ? Doname2
: doname
, ansimpleoname
,
1605 (quan
== 1L) ? "that" : "those");
1606 if (yn(qbuf
) == 'n') {
1607 buy
= PAY_SKIP
; /* don't want to buy */
1608 } else if (quan
< bp
->bquan
&& !consumed
) { /* partly used goods */
1609 obj
->quan
= bp
->bquan
- save_quan
; /* used up amount */
1610 if (!Deaf
&& !muteshk(shkp
)) {
1611 verbalize("%s for the other %s before buying %s.",
1612 ANGRY(shkp
) ? "Pay" : "Please pay",
1613 simpleonames(obj
), /* short name suffices */
1614 save_quan
> 1L ? "these" : "this one");
1616 pline("%s %s%s your bill for the other %s first.",
1618 ANGRY(shkp
) ? "angrily " : "",
1619 nolimbs(shkp
->data
) ? "motions to" : "points out",
1622 buy
= PAY_SKIP
; /* shk won't sell */
1625 if (buy
== PAY_BUY
&& umoney
+ ESHK(shkp
)->credit
< ltmp
) {
1626 You("don't%s have gold%s enough to pay for %s.",
1627 stashed_gold
? " seem to" : "",
1628 (ESHK(shkp
)->credit
> 0L) ? " or credit" : "",
1629 thesimpleoname(obj
));
1630 buy
= itemize
? PAY_SKIP
: PAY_CANT
;
1633 if (buy
!= PAY_BUY
) {
1634 /* restore unpaid object to original state */
1635 obj
->quan
= save_quan
;
1637 iflags
.suppress_price
--;
1642 shk_names_obj(shkp
, obj
,
1643 consumed
? "paid for %s at a cost of %ld gold piece%s.%s"
1644 : "bought %s for %ld gold piece%s.%s",
1646 obj
->quan
= save_quan
; /* restore original count */
1647 /* quan => amount just bought, save_quan => remaining unpaid count */
1649 if (quan
!= bp
->bquan
) {
1650 /* eliminate used-up portion; remainder is still unpaid */
1651 bp
->bquan
= obj
->quan
;
1655 } else { /* completely used-up, so get rid of it */
1656 obj_extract_self(obj
);
1657 /* assert( obj == *obj_p ); */
1659 *obj_p
= 0; /* destroy pointer to freed object */
1662 update_inventory(); /* Done just once in dopay() if !itemize. */
1663 iflags
.suppress_price
--;
1667 static struct repo
{ /* repossession context */
1668 struct monst
*shopkeeper
;
1672 /* routine called after dying (or quitting) */
1675 int croaked
; /* -1: escaped dungeon; 0: quit; 1: died */
1677 struct monst
*mtmp
, *mtmp2
, *firstshk
, *resident
, *creditor
, *hostile
,
1680 boolean taken
= FALSE
, local
;
1683 /* if we escaped from the dungeon, shopkeepers can't reach us;
1684 shops don't occur on level 1, but this could happen if hero
1685 level teleports out of the dungeon and manages not to die */
1688 /* [should probably also return false when dead hero has been
1689 petrified since shk shouldn't be able to grab inventory
1690 which has been shut inside a statue] */
1692 /* this is where inventory will end up if any shk takes it */
1693 repo
.location
.x
= repo
.location
.y
= 0;
1694 repo
.shopkeeper
= 0;
1697 * Scan all shopkeepers on the level, to prioritize them:
1698 * 1) keeper of shop hero is inside and who is owed money,
1699 * 2) keeper of shop hero is inside who isn't owed any money,
1700 * 3) other shk who is owed money, 4) other shk who is angry,
1701 * 5) any shk local to this level, and if none is found,
1702 * 6) first shk on monster list (last resort; unlikely, since
1703 * any nonlocal shk will probably be in the owed category
1704 * and almost certainly be in the angry category).
1706 resident
= creditor
= hostile
= localshk
= (struct monst
*) 0;
1707 for (mtmp
= next_shkp(fmon
, FALSE
); mtmp
;
1708 mtmp
= next_shkp(mtmp2
, FALSE
)) {
1711 local
= on_level(&eshkp
->shoplevel
, &u
.uz
);
1712 if (local
&& index(u
.ushops
, eshkp
->shoproom
)) {
1713 /* inside this shk's shop [there might be more than one
1714 resident shk if hero is standing in a breech of a shared
1715 wall, so give priority to one who's also owed money] */
1716 if (!resident
|| eshkp
->billct
|| eshkp
->debit
|| eshkp
->robbed
)
1718 } else if (eshkp
->billct
|| eshkp
->debit
|| eshkp
->robbed
) {
1719 /* owe this shopkeeper money (might also owe others) */
1722 } else if (eshkp
->following
|| ANGRY(mtmp
)) {
1723 /* this shopkeeper is antagonistic (others might be too) */
1727 /* this shopkeeper's shop is on current level */
1733 /* give highest priority shopkeeper first crack */
1734 firstshk
= resident
? resident
1735 : creditor
? creditor
1740 taken
= inherits(firstshk
, numsk
, croaked
);
1743 /* now handle the rest */
1744 for (mtmp
= next_shkp(fmon
, FALSE
); mtmp
;
1745 mtmp
= next_shkp(mtmp2
, FALSE
)) {
1748 local
= on_level(&eshkp
->shoplevel
, &u
.uz
);
1749 if (mtmp
!= firstshk
) {
1751 taken
|= inherits(mtmp
, numsk
, croaked
);
1753 /* for bones: we don't want a shopless shk around */
1761 inherits(shkp
, numsk
, croaked
)
1768 struct eshk
*eshkp
= ESHK(shkp
);
1769 boolean take
= FALSE
, taken
= FALSE
;
1770 unsigned save_minvis
= shkp
->minvis
;
1771 int roomno
= *u
.ushops
;
1775 /* The simplifying principle is that first-come
1776 already took everything you had. */
1778 if (cansee(shkp
->mx
, shkp
->my
) && croaked
) {
1780 if (has_head(shkp
->data
) && !rn2(2))
1781 Sprintf(takes
, ", shakes %s %s,", mhis(shkp
),
1782 mbodypart(shkp
, HEAD
));
1783 pline("%s %slooks at your corpse%s and %s.", Shknam(shkp
),
1784 (!shkp
->mcanmove
|| shkp
->msleeping
) ? "wakes up, " : "",
1785 takes
, !inhishop(shkp
) ? "disappears" : "sighs");
1787 rouse_shk(shkp
, FALSE
); /* wake shk for bones */
1788 taken
= (roomno
== eshkp
->shoproom
);
1792 /* get one case out of the way: you die in the shop, the */
1793 /* shopkeeper is peaceful, nothing stolen, nothing owed. */
1794 if (roomno
== eshkp
->shoproom
&& inhishop(shkp
) && !eshkp
->billct
1795 && !eshkp
->robbed
&& !eshkp
->debit
&& NOTANGRY(shkp
)
1796 && !eshkp
->following
&& u
.ugrave_arise
< LOW_PM
) {
1797 taken
= (invent
!= 0);
1799 pline("%s gratefully inherits all your possessions.",
1805 if (eshkp
->billct
|| eshkp
->debit
|| eshkp
->robbed
) {
1806 if (roomno
== eshkp
->shoproom
&& inhishop(shkp
))
1807 loss
= addupbill(shkp
) + eshkp
->debit
;
1808 if (loss
< eshkp
->robbed
)
1809 loss
= eshkp
->robbed
;
1813 if (eshkp
->following
|| ANGRY(shkp
) || take
) {
1816 umoney
= money_cnt(invent
);
1818 if (!shkp
->mcanmove
|| shkp
->msleeping
)
1819 Strcat(takes
, "wakes up and ");
1820 if (distu(shkp
->mx
, shkp
->my
) > 2)
1821 Strcat(takes
, "comes and ");
1822 Strcat(takes
, "takes");
1824 if (loss
> umoney
|| !loss
|| roomno
== eshkp
->shoproom
) {
1825 eshkp
->robbed
-= umoney
;
1826 if (eshkp
->robbed
< 0L)
1829 money2mon(shkp
, umoney
);
1831 pline("%s %s all your possessions.", shkname(shkp
), takes
);
1833 /* where to put player's invent (after disclosure) */
1836 money2mon(shkp
, loss
);
1838 pline("%s %s the %ld %s %sowed %s.", Shknam(shkp
),
1839 takes
, loss
, currency(loss
),
1840 strncmp(eshkp
->customer
, plname
, PL_NSIZ
) ? "" : "you ",
1842 /* shopkeeper has now been paid in full */
1844 eshkp
->following
= 0;
1848 /* in case we create bones */
1849 rouse_shk(shkp
, FALSE
); /* wake up */
1850 if (!inhishop(shkp
))
1851 home_shk(shkp
, FALSE
);
1854 shkp
->minvis
= save_minvis
;
1863 register xchar ox
, oy
;
1864 struct eshk
*eshkp
= ESHK(shkp
);
1866 /* if you're not in this shk's shop room, or if you're in its doorway
1867 or entry spot, then your gear gets dumped all the way inside */
1868 if (*u
.ushops
!= eshkp
->shoproom
|| IS_DOOR(levl
[u
.ux
][u
.uy
].typ
)
1869 || (u
.ux
== eshkp
->shk
.x
&& u
.uy
== eshkp
->shk
.y
)) {
1870 /* shk.x,shk.y is the position immediately in
1871 * front of the door -- move in one more space
1875 ox
+= sgn(ox
- eshkp
->shd
.x
);
1876 oy
+= sgn(oy
- eshkp
->shd
.y
);
1877 } else { /* already inside this shk's shop */
1881 /* finish_paybill will deposit invent here */
1882 repo
.location
.x
= ox
;
1883 repo
.location
.y
= oy
;
1884 repo
.shopkeeper
= shkp
;
1887 /* called at game exit, after inventory disclosure but before making bones */
1891 struct monst
*shkp
= repo
.shopkeeper
;
1892 int ox
= repo
.location
.x
, oy
= repo
.location
.y
;
1894 #if 0 /* don't bother */
1895 if (ox
== 0 && oy
== 0)
1896 impossible("finish_paybill: no location");
1898 /* normally done by savebones(), but that's too late in this case */
1900 /* if hero has any gold left, take it into shopkeeper's possession */
1902 long umoney
= money_cnt(invent
);
1905 money2mon(shkp
, umoney
);
1907 /* transfer rest of the character's inventory to the shop floor */
1908 drop_upon_death((struct monst
*) 0, (struct obj
*) 0, ox
, oy
);
1911 /* find obj on one of the lists */
1912 STATIC_OVL
struct obj
*
1914 register struct bill_x
*bp
;
1916 register struct obj
*obj
;
1917 register unsigned int id
= bp
->bo_id
;
1920 obj
= o_on(id
, billobjs
);
1927 * Look for o_id on all lists but billobj. Return obj or NULL if not found.
1928 * Its OK for restore_timers() to call this function, there should not
1929 * be any timeouts on the billobjs chain.
1936 struct monst
*mon
, *mmtmp
[3];
1939 /* first check various obj lists directly */
1940 if ((obj
= o_on(id
, invent
)) != 0)
1942 if ((obj
= o_on(id
, fobj
)) != 0)
1944 if ((obj
= o_on(id
, level
.buriedobjlist
)) != 0)
1946 if ((obj
= o_on(id
, migrating_objs
)) != 0)
1949 /* not found yet; check inventory for members of various monst lists */
1951 mmtmp
[1] = migrating_mons
;
1952 mmtmp
[2] = mydogs
; /* for use during level changes */
1953 for (i
= 0; i
< 3; i
++)
1954 for (mon
= mmtmp
[i
]; mon
; mon
= mon
->nmon
)
1955 if ((obj
= o_on(id
, mon
->minvent
)) != 0)
1958 /* not found at all */
1959 return (struct obj
*) 0;
1962 /* Returns the price of an arbitrary item in the shop.
1963 Returns 0 if the item doesn't belong to a shopkeeper. */
1965 get_cost_of_shop_item(obj
)
1966 register struct obj
*obj
;
1973 && obj
->oclass
!= COIN_CLASS
1974 && obj
!= uball
&& obj
!= uchain
1975 && get_obj_location(obj
, &x
, &y
, 0)
1977 || (obj
->where
== OBJ_FLOOR
1978 && !obj
->no_charge
&& costly_spot(x
, y
)))
1979 && (shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
))) != 0
1980 && inhishop(shkp
)) {
1981 cost
= obj
->quan
* get_cost(obj
, shkp
);
1982 if (Has_contents(obj
))
1983 cost
+= contained_cost(obj
, shkp
, 0L, FALSE
, FALSE
);
1988 /* calculate the value that the shk will charge for [one of] an object */
1991 register struct obj
*obj
;
1992 register struct monst
*shkp
; /* if angry, impose a surcharge */
1994 long tmp
= getprice(obj
, FALSE
),
1995 /* used to perform a single calculation even when multiple
1996 adjustments (unID'd, dunce/tourist, charisma) are made */
1997 multiplier
= 1L, divisor
= 1L;
2001 /* shopkeeper may notice if the player isn't very knowledgeable -
2002 especially when gem prices are concerned */
2003 if (!obj
->dknown
|| !objects
[obj
->otyp
].oc_name_known
) {
2004 if (obj
->oclass
== GEM_CLASS
2005 && objects
[obj
->otyp
].oc_material
== GLASS
) {
2007 /* get a value that's 'random' from game to game, but the
2008 same within the same game */
2009 boolean pseudorand
=
2010 (((int) ubirthday
% obj
->otyp
) >= obj
->otyp
/ 2);
2012 /* all gems are priced high - real or not */
2013 switch (obj
->otyp
- LAST_GEM
) {
2015 i
= pseudorand
? DIAMOND
: OPAL
;
2018 i
= pseudorand
? SAPPHIRE
: AQUAMARINE
;
2021 i
= pseudorand
? RUBY
: JASPER
;
2023 case 4: /* yellowish brown */
2024 i
= pseudorand
? AMBER
: TOPAZ
;
2026 case 5: /* orange */
2027 i
= pseudorand
? JACINTH
: AGATE
;
2029 case 6: /* yellow */
2030 i
= pseudorand
? CITRINE
: CHRYSOBERYL
;
2033 i
= pseudorand
? BLACK_OPAL
: JET
;
2036 i
= pseudorand
? EMERALD
: JADE
;
2038 case 9: /* violet */
2039 i
= pseudorand
? AMETHYST
: FLUORITE
;
2042 impossible("bad glass gem %d?", obj
->otyp
);
2046 tmp
= (long) objects
[i
].oc_cost
;
2047 } else if (!(obj
->o_id
% 4)) {
2048 /* unid'd, arbitrarily impose surcharge: tmp *= 4/3 */
2053 if (uarmh
&& uarmh
->otyp
== DUNCE_CAP
)
2054 multiplier
*= 4L, divisor
*= 3L;
2055 else if ((Role_if(PM_TOURIST
) && u
.ulevel
< (MAXULEV
/ 2))
2056 || (uarmu
&& !uarm
&& !uarmc
)) /* touristy shirt visible */
2057 multiplier
*= 4L, divisor
*= 3L;
2059 if (ACURR(A_CHA
) > 18)
2061 else if (ACURR(A_CHA
) == 18)
2062 multiplier
*= 2L, divisor
*= 3L;
2063 else if (ACURR(A_CHA
) >= 16)
2064 multiplier
*= 3L, divisor
*= 4L;
2065 else if (ACURR(A_CHA
) <= 5)
2067 else if (ACURR(A_CHA
) <= 7)
2068 multiplier
*= 3L, divisor
*= 2L;
2069 else if (ACURR(A_CHA
) <= 10)
2070 multiplier
*= 4L, divisor
*= 3L;
2072 /* tmp = (tmp * multiplier) / divisor [with roundoff tweak] */
2075 /* tmp = (((tmp * 10) / divisor) + 5) / 10 */
2084 /* the artifact prices in artilist[] are also used as a score bonus;
2085 inflate their shop price here without affecting score calculation */
2089 /* anger surcharge should match rile_shk's, so we do it separately
2090 from the multiplier/divisor calculation */
2091 if (shkp
&& ESHK(shkp
)->surcharge
)
2092 tmp
+= (tmp
+ 2L) / 3L;
2096 /* returns the price of a container's content. the price
2097 * of the "top" container is added in the calling functions.
2098 * a different price quoted for selling as vs. buying.
2101 contained_cost(obj
, shkp
, price
, usell
, unpaid_only
)
2106 boolean unpaid_only
;
2108 register struct obj
*otmp
;
2110 /* price of contained objects; "top" container handled by caller */
2111 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2112 if (otmp
->oclass
== COIN_CLASS
)
2116 if (saleable(shkp
, otmp
) && !otmp
->unpaid
2117 && otmp
->oclass
!= BALL_CLASS
2118 && !(otmp
->oclass
== FOOD_CLASS
&& otmp
->oeaten
)
2119 && !(Is_candle(otmp
)
2120 && otmp
->age
< 20L * (long) objects
[otmp
->otyp
].oc_cost
))
2121 price
+= set_cost(otmp
, shkp
);
2122 } else if (!otmp
->no_charge
&& (otmp
->unpaid
|| !unpaid_only
)) {
2123 price
+= get_cost(otmp
, shkp
) * otmp
->quan
;
2126 if (Has_contents(otmp
))
2127 price
= contained_cost(otmp
, shkp
, price
, usell
, unpaid_only
);
2133 /* count amount of gold inside container 'obj' and any nested containers */
2138 register struct obj
*otmp
;
2139 register long value
= 0L;
2141 /* accumulate contained gold */
2142 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
)
2143 if (otmp
->oclass
== COIN_CLASS
)
2144 value
+= otmp
->quan
;
2145 else if (Has_contents(otmp
))
2146 value
+= contained_gold(otmp
);
2152 dropped_container(obj
, shkp
, sale
)
2153 register struct obj
*obj
;
2154 register struct monst
*shkp
;
2155 register boolean sale
;
2157 register struct obj
*otmp
;
2159 /* the "top" container is treated in the calling fn */
2160 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2161 if (otmp
->oclass
== COIN_CLASS
)
2164 if (!otmp
->unpaid
&& !(sale
&& saleable(shkp
, otmp
)))
2165 otmp
->no_charge
= 1;
2167 if (Has_contents(otmp
))
2168 dropped_container(otmp
, shkp
, sale
);
2173 picked_container(obj
)
2174 register struct obj
*obj
;
2176 register struct obj
*otmp
;
2178 /* the "top" container is treated in the calling fn */
2179 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2180 if (otmp
->oclass
== COIN_CLASS
)
2183 if (otmp
->no_charge
)
2184 otmp
->no_charge
= 0;
2186 if (Has_contents(otmp
))
2187 picked_container(otmp
);
2192 special_stock(obj
, shkp
, quietly
)
2197 /* for unique situations */
2198 if (ESHK(shkp
)->shoptype
== CANDLESHOP
2199 && obj
->otyp
== CANDELABRUM_OF_INVOCATION
) {
2201 if (is_izchak(shkp
, TRUE
) && !u
.uevent
.invoked
) {
2202 if (Deaf
|| muteshk(shkp
)) {
2203 pline("%s seems %s that you want to sell that.",
2205 (obj
->spe
< 7) ? "horrified" : "concerned");
2207 verbalize("No thanks, I'd hang onto that if I were you.");
2210 "You'll need %d%s candle%s to go along with it.",
2211 (7 - obj
->spe
), (obj
->spe
> 0) ? " more" : "",
2212 plur(7 - obj
->spe
));
2213 /* [what if hero is already carrying enough candles?
2214 should Izchak explain how to attach them instead?] */
2217 if (!Deaf
&& !muteshk(shkp
))
2218 verbalize("I won't stock that. Take it out of here!");
2220 pline("%s shakes %s %s in refusal.",
2223 mbodypart(shkp
, HEAD
));
2231 /* calculate how much the shk will pay when buying [all of] an object */
2234 register struct obj
*obj
;
2235 register struct monst
*shkp
;
2237 long tmp
= getprice(obj
, TRUE
) * obj
->quan
, multiplier
= 1L, divisor
= 1L;
2239 if (uarmh
&& uarmh
->otyp
== DUNCE_CAP
)
2241 else if ((Role_if(PM_TOURIST
) && u
.ulevel
< (MAXULEV
/ 2))
2242 || (uarmu
&& !uarm
&& !uarmc
)) /* touristy shirt visible */
2247 /* shopkeeper may notice if the player isn't very knowledgeable -
2248 especially when gem prices are concerned */
2249 if (!obj
->dknown
|| !objects
[obj
->otyp
].oc_name_known
) {
2250 if (obj
->oclass
== GEM_CLASS
) {
2251 /* different shop keepers give different prices */
2252 if (objects
[obj
->otyp
].oc_material
== GEMSTONE
2253 || objects
[obj
->otyp
].oc_material
== GLASS
) {
2254 tmp
= (obj
->otyp
% (6 - shkp
->m_id
% 3));
2255 tmp
= (tmp
+ 3) * obj
->quan
;
2257 } else if (tmp
> 1L && !(shkp
->m_id
% 4))
2258 multiplier
*= 3L, divisor
*= 4L;
2262 /* [see get_cost()] */
2270 /* avoid adjusting nonzero to zero */
2275 /* (no adjustment for angry shk here) */
2279 /* called when an item's value has been enhanced; if it happens to be
2280 on any shop bill, update that bill to reflect the new higher price
2281 [if the new price drops for some reason, keep the old one in place] */
2283 alter_cost(obj
, amt
)
2285 long amt
; /* if 0, use regular shop pricing, otherwise force amount;
2286 if negative, use abs(amt) even if it's less than old cost */
2288 struct bill_x
*bp
= 0;
2292 for (shkp
= next_shkp(fmon
, TRUE
); shkp
; shkp
= next_shkp(shkp
, TRUE
))
2293 if ((bp
= onbill(obj
, shkp
, TRUE
)) != 0) {
2294 new_price
= !amt
? get_cost(obj
, shkp
) : (amt
< 0L) ? -amt
: amt
;
2295 if (new_price
> bp
->price
|| amt
< 0L) {
2296 bp
->price
= new_price
;
2304 /* called from doinv(invent.c) for inventory of unpaid objects */
2306 unpaid_cost(unp_obj
, include_contents
)
2307 struct obj
*unp_obj
; /* known to be unpaid or contain unpaid */
2308 boolean include_contents
;
2310 struct bill_x
*bp
= (struct bill_x
*) 0;
2315 if (!get_obj_location(unp_obj
, &ox
, &oy
, BURIED_TOO
| CONTAINED_TOO
))
2316 ox
= u
.ux
, oy
= u
.uy
; /* (shouldn't happen) */
2317 if ((shkp
= shop_keeper(*in_rooms(ox
, oy
, SHOPBASE
))) != 0) {
2318 bp
= onbill(unp_obj
, shkp
, TRUE
);
2320 /* didn't find shk? try searching bills */
2321 for (shkp
= next_shkp(fmon
, TRUE
); shkp
;
2322 shkp
= next_shkp(shkp
->nmon
, TRUE
))
2323 if ((bp
= onbill(unp_obj
, shkp
, TRUE
)) != 0)
2327 /* onbill() gave no message if unexpected problem occurred */
2328 if (!shkp
|| (unp_obj
->unpaid
&& !bp
)) {
2329 impossible("unpaid_cost: object wasn't on any bill.");
2332 amt
= unp_obj
->quan
* bp
->price
;
2333 if (include_contents
&& Has_contents(unp_obj
))
2334 amt
= contained_cost(unp_obj
, shkp
, amt
, FALSE
, TRUE
);
2340 add_one_tobill(obj
, dummy
, shkp
)
2349 if (!billable(&shkp
, obj
, *u
.ushops
, TRUE
))
2353 if (eshkp
->billct
== BILLSZ
) {
2354 You("got that for free!");
2358 bct
= eshkp
->billct
;
2359 bp
= &(eshkp
->bill_p
[bct
]);
2360 bp
->bo_id
= obj
->o_id
;
2361 bp
->bquan
= obj
->quan
;
2362 if (dummy
) { /* a dummy object must be inserted into */
2363 bp
->useup
= 1; /* the billobjs chain here. crucial for */
2364 add_to_billobjs(obj
); /* eating floorfood in shop. see eat.c */
2367 bp
->price
= get_cost(obj
, shkp
);
2373 add_to_billobjs(obj
)
2376 if (obj
->where
!= OBJ_FREE
)
2377 panic("add_to_billobjs: obj not free");
2379 obj_stop_timers(obj
);
2381 obj
->nobj
= billobjs
;
2383 obj
->where
= OBJ_ONBILL
;
2386 /* recursive billing of objects within containers. */
2388 bill_box_content(obj
, ininv
, dummy
, shkp
)
2389 register struct obj
*obj
;
2390 register boolean ininv
, dummy
;
2391 register struct monst
*shkp
;
2393 register struct obj
*otmp
;
2395 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2396 if (otmp
->oclass
== COIN_CLASS
)
2399 /* the "top" box is added in addtobill() */
2400 if (!otmp
->no_charge
)
2401 add_one_tobill(otmp
, dummy
, shkp
);
2402 if (Has_contents(otmp
))
2403 bill_box_content(otmp
, ininv
, dummy
, shkp
);
2407 /* shopkeeper tells you what you bought or sold, sometimes partly IDing it */
2409 shk_names_obj(shkp
, obj
, fmt
, amt
, arg
)
2412 const char *fmt
; /* "%s %ld %s %s", doname(obj), amt, plur(amt), arg */
2416 char *obj_name
, fmtbuf
[BUFSZ
];
2417 boolean was_unknown
= !obj
->dknown
;
2420 /* Use real name for ordinary weapons/armor, and spell-less
2421 * scrolls/books (that is, blank and mail), but only if the
2422 * object is within the shk's area of interest/expertise.
2424 if (!objects
[obj
->otyp
].oc_magic
&& saleable(shkp
, obj
)
2425 && (obj
->oclass
== WEAPON_CLASS
|| obj
->oclass
== ARMOR_CLASS
2426 || obj
->oclass
== SCROLL_CLASS
|| obj
->oclass
== SPBOOK_CLASS
2427 || obj
->otyp
== MIRROR
)) {
2428 was_unknown
|= !objects
[obj
->otyp
].oc_name_known
;
2429 makeknown(obj
->otyp
);
2431 obj_name
= doname(obj
);
2432 /* Use an alternate message when extra information is being provided */
2434 Sprintf(fmtbuf
, "%%s; you %s", fmt
);
2435 obj_name
[0] = highc(obj_name
[0]);
2436 pline(fmtbuf
, obj_name
, (obj
->quan
> 1L) ? "them" : "it", amt
,
2439 You(fmt
, obj_name
, amt
, plur(amt
), arg
);
2443 /* decide whether a shopkeeper thinks an item belongs to her */
2445 billable(shkpp
, obj
, roomno
, reset_nocharge
)
2446 struct monst
**shkpp
; /* in: non-null if shk has been validated; out: shk */
2449 boolean reset_nocharge
;
2451 struct monst
*shkp
= *shkpp
;
2453 /* if caller hasn't supplied a shopkeeper, look one up now */
2457 shkp
= shop_keeper(roomno
);
2458 if (!shkp
|| !inhishop(shkp
))
2462 /* perhaps we threw it away earlier */
2463 if (onbill(obj
, shkp
, FALSE
)
2464 || (obj
->oclass
== FOOD_CLASS
&& obj
->oeaten
))
2466 /* outer container might be marked no_charge but still have contents
2467 which should be charged for; clear no_charge when picking things up */
2468 if (obj
->no_charge
) {
2469 if (!Has_contents(obj
) || (contained_gold(obj
) == 0L
2470 && contained_cost(obj
, shkp
, 0L, FALSE
,
2471 !reset_nocharge
) == 0L))
2472 shkp
= 0; /* not billable */
2473 if (reset_nocharge
&& !shkp
&& obj
->oclass
!= COIN_CLASS
) {
2475 if (Has_contents(obj
))
2476 picked_container(obj
); /* clear no_charge */
2479 return shkp
? TRUE
: FALSE
;
2483 addtobill(obj
, ininv
, dummy
, silent
)
2485 boolean ininv
, dummy
, silent
;
2487 struct monst
*shkp
= 0;
2488 long ltmp
, cltmp
, gltmp
;
2492 if (!billable(&shkp
, obj
, *u
.ushops
, TRUE
))
2495 if (obj
->oclass
== COIN_CLASS
) {
2496 costly_gold(obj
->ox
, obj
->oy
, obj
->quan
);
2498 } else if (ESHK(shkp
)->billct
== BILLSZ
) {
2500 You("got that for free!");
2504 ltmp
= cltmp
= gltmp
= 0L;
2505 container
= Has_contents(obj
);
2507 if (!obj
->no_charge
)
2508 ltmp
= get_cost(obj
, shkp
);
2510 if (obj
->no_charge
&& !container
) {
2516 cltmp
= contained_cost(obj
, shkp
, cltmp
, FALSE
, FALSE
);
2517 gltmp
= contained_gold(obj
);
2520 add_one_tobill(obj
, dummy
, shkp
);
2522 bill_box_content(obj
, ininv
, dummy
, shkp
);
2523 picked_container(obj
); /* reset contained obj->no_charge */
2528 costly_gold(obj
->ox
, obj
->oy
, gltmp
);
2535 contentscount
= count_unpaid(obj
->cobj
);
2536 } else { /* !container */
2537 add_one_tobill(obj
, dummy
, shkp
);
2541 if (!Deaf
&& !muteshk(shkp
) && !silent
) {
2545 pline("%s has no interest in %s.", Shknam(shkp
), the(xname(obj
)));
2549 pline("%s will cost you %ld %s%s.", The(xname(obj
)), ltmp
,
2550 currency(ltmp
), (obj
->quan
> 1L) ? " each" : "");
2552 long save_quan
= obj
->quan
;
2554 Strcpy(buf
, "\"For you, ");
2556 Strcat(buf
, "scum;");
2558 append_honorific(buf
);
2559 Strcat(buf
, "; only");
2561 obj
->quan
= 1L; /* fool xname() into giving singular */
2562 pline("%s %ld %s %s %s%s.\"", buf
, ltmp
, currency(ltmp
),
2563 (save_quan
> 1L) ? "per"
2564 : (contentscount
&& !obj
->unpaid
)
2565 ? "for the contents of this"
2568 (contentscount
&& obj
->unpaid
) ? and_its_contents
: "");
2569 obj
->quan
= save_quan
;
2571 } else if (!silent
) {
2573 pline_The("list price of %s%s%s is %ld %s%s.",
2574 (contentscount
&& !obj
->unpaid
) ? the_contents_of
: "",
2576 (contentscount
&& obj
->unpaid
) ? and_its_contents
: "",
2577 ltmp
, currency(ltmp
), (obj
->quan
> 1L) ? " each" : "");
2579 pline("%s does not notice.", Shknam(shkp
));
2584 append_honorific(buf
)
2587 /* (chooses among [0]..[3] normally; [1]..[4] after the
2588 Wizard has been killed or invocation ritual performed) */
2589 static const char *const honored
[] = { "good", "honored", "most gracious",
2591 "most renowned and sacred" };
2592 Strcat(buf
, honored
[rn2(SIZE(honored
) - 1) + u
.uevent
.udemigod
]);
2593 if (is_vampire(youmonst
.data
))
2594 Strcat(buf
, (flags
.female
) ? " dark lady" : " dark lord");
2595 else if (is_elf(youmonst
.data
))
2596 Strcat(buf
, (flags
.female
) ? " hiril" : " hir");
2598 Strcat(buf
, !is_human(youmonst
.data
) ? " creature" : (flags
.female
)
2604 splitbill(obj
, otmp
)
2605 register struct obj
*obj
, *otmp
;
2607 /* otmp has been split off from obj */
2608 register struct bill_x
*bp
;
2610 register struct monst
*shkp
= shop_keeper(*u
.ushops
);
2612 if (!shkp
|| !inhishop(shkp
)) {
2613 impossible("splitbill: no resident shopkeeper??");
2616 bp
= onbill(obj
, shkp
, FALSE
);
2618 impossible("splitbill: not on bill?");
2621 if (bp
->bquan
< otmp
->quan
) {
2622 impossible("Negative quantity on bill??");
2624 if (bp
->bquan
== otmp
->quan
) {
2625 impossible("Zero quantity on bill??");
2627 bp
->bquan
-= otmp
->quan
;
2629 if (ESHK(shkp
)->billct
== BILLSZ
)
2633 bp
= &(ESHK(shkp
)->bill_p
[ESHK(shkp
)->billct
]);
2634 bp
->bo_id
= otmp
->o_id
;
2635 bp
->bquan
= otmp
->quan
;
2638 ESHK(shkp
)->billct
++;
2643 sub_one_frombill(obj
, shkp
)
2644 register struct obj
*obj
;
2645 register struct monst
*shkp
;
2647 register struct bill_x
*bp
;
2649 if ((bp
= onbill(obj
, shkp
, FALSE
)) != 0) {
2650 register struct obj
*otmp
;
2653 if (bp
->bquan
> obj
->quan
) {
2656 otmp
->oextra
= (struct oextra
*) 0;
2657 bp
->bo_id
= otmp
->o_id
= context
.ident
++;
2658 otmp
->where
= OBJ_FREE
;
2659 otmp
->quan
= (bp
->bquan
-= obj
->quan
);
2660 otmp
->owt
= 0; /* superfluous */
2662 add_to_billobjs(otmp
);
2665 ESHK(shkp
)->billct
--;
2668 /* DRS/NS 2.2.6 messes up -- Peter Kendell */
2669 int indx
= ESHK(shkp
)->billct
;
2671 *bp
= ESHK(shkp
)->bill_p
[indx
];
2674 *bp
= ESHK(shkp
)->bill_p
[ESHK(shkp
)->billct
];
2677 } else if (obj
->unpaid
) {
2678 impossible("sub_one_frombill: unpaid object not on bill");
2683 /* recursive check of unpaid objects within nested containers. */
2685 subfrombill(obj
, shkp
)
2686 register struct obj
*obj
;
2687 register struct monst
*shkp
;
2689 register struct obj
*otmp
;
2691 sub_one_frombill(obj
, shkp
);
2693 if (Has_contents(obj
))
2694 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2695 if (otmp
->oclass
== COIN_CLASS
)
2698 if (Has_contents(otmp
))
2699 subfrombill(otmp
, shkp
);
2701 sub_one_frombill(otmp
, shkp
);
2706 stolen_container(obj
, shkp
, price
, ininv
)
2716 /* the price of contained objects; caller handles top container */
2717 for (otmp
= obj
->cobj
; otmp
; otmp
= otmp
->nobj
) {
2718 if (otmp
->oclass
== COIN_CLASS
)
2721 if (!billable(&shkp
, otmp
, ESHK(shkp
)->shoproom
, TRUE
)) {
2722 /* billable() returns false for objects already on bill */
2723 if ((bp
= onbill(otmp
, shkp
, FALSE
)) == 0)
2725 /* this assumes that we're being called by stolen_value()
2726 (or by a recursive call to self on behalf of it) where
2727 the cost of this object is about to be added to shop
2728 debt in place of having it remain on the current bill */
2729 billamt
= bp
->bquan
* bp
->price
;
2730 sub_one_frombill(otmp
, shkp
); /* avoid double billing */
2735 else if (ininv
? otmp
->unpaid
: !otmp
->no_charge
)
2736 price
+= otmp
->quan
* get_cost(otmp
, shkp
);
2738 if (Has_contents(otmp
))
2739 price
= stolen_container(otmp
, shkp
, price
, ininv
);
2746 stolen_value(obj
, x
, y
, peaceful
, silent
)
2749 boolean peaceful
, silent
;
2751 long value
= 0L, gvalue
= 0L, billamt
= 0L;
2752 char roomno
= *in_rooms(x
, y
, SHOPBASE
);
2754 struct monst
*shkp
= 0;
2756 if (!billable(&shkp
, obj
, roomno
, FALSE
)) {
2757 /* things already on the bill yield a not-billable result, so
2758 we need to check bill before deciding that shk doesn't care */
2759 if ((bp
= onbill(obj
, shkp
, FALSE
)) == 0)
2761 /* shk does care; take obj off bill to avoid double billing */
2762 billamt
= bp
->bquan
* bp
->price
;
2763 sub_one_frombill(obj
, shkp
);
2766 if (obj
->oclass
== COIN_CLASS
) {
2767 gvalue
+= obj
->quan
;
2771 else if (!obj
->no_charge
)
2772 value
+= obj
->quan
* get_cost(obj
, shkp
);
2774 if (Has_contents(obj
)) {
2776 (obj
->where
== OBJ_INVENT
|| obj
->where
== OBJ_FREE
);
2778 value
+= stolen_container(obj
, shkp
, 0L, ininv
);
2780 gvalue
+= contained_gold(obj
);
2784 if (gvalue
+ value
== 0L)
2790 boolean credit_use
= !!ESHK(shkp
)->credit
;
2791 value
= check_credit(value
, shkp
);
2792 /* 'peaceful' affects general treatment, but doesn't affect
2793 * the fact that other code expects that all charges after the
2794 * shopkeeper is angry are included in robbed, not debit */
2796 ESHK(shkp
)->robbed
+= value
;
2798 ESHK(shkp
)->debit
+= value
;
2801 const char *still
= "";
2804 if (ESHK(shkp
)->credit
) {
2805 You("have %ld %s credit remaining.", ESHK(shkp
)->credit
,
2806 currency(ESHK(shkp
)->credit
));
2808 } else if (!value
) {
2809 You("have no credit remaining.");
2814 if (obj
->oclass
== COIN_CLASS
)
2815 You("%sowe %s %ld %s!", still
, shkname(shkp
), value
,
2818 You("%sowe %s %ld %s for %s!", still
, shkname(shkp
),
2819 value
, currency(value
), (obj
->quan
> 1L) ? "them" : "it");
2822 ESHK(shkp
)->robbed
+= value
;
2825 if (canseemon(shkp
)) {
2826 Norep("%s booms: \"%s, you are a thief!\"",
2827 Shknam(shkp
), plname
);
2829 Norep("You hear a scream, \"Thief!\"");
2832 (void) angry_guards(FALSE
);
2837 /* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */
2838 static char sell_response
= 'a';
2839 static int sell_how
= SELL_NORMAL
;
2840 /* can't just use sell_response='y' for auto_credit because the 'a' response
2841 shouldn't carry over from ordinary selling to credit selling */
2842 static boolean auto_credit
= FALSE
;
2845 sellobj_state(deliberate
)
2848 /* If we're deliberately dropping something, there's no automatic
2849 response to the shopkeeper's "want to sell" query; however, if we
2850 accidentally drop anything, the shk will buy it/them without asking.
2851 This retains the old pre-query risk that slippery fingers while in
2852 shops entailed: you drop it, you've lost it.
2854 sell_response
= (deliberate
!= SELL_NORMAL
) ? '\0' : 'a';
2855 sell_how
= deliberate
;
2856 auto_credit
= FALSE
;
2861 register struct obj
*obj
;
2864 register struct monst
*shkp
;
2865 register struct eshk
*eshkp
;
2866 long ltmp
= 0L, cltmp
= 0L, gltmp
= 0L, offer
, shkmoney
;
2867 boolean saleitem
, cgold
= FALSE
, container
= Has_contents(obj
);
2868 boolean isgold
= (obj
->oclass
== COIN_CLASS
);
2869 boolean only_partially_your_contents
= FALSE
;
2871 if (!*u
.ushops
) /* do cheapest exclusion test first */
2873 if (!(shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
))) || !inhishop(shkp
))
2875 if (!costly_spot(x
, y
))
2878 if (obj
->unpaid
&& !container
&& !isgold
) {
2879 sub_one_frombill(obj
, shkp
);
2883 /* find the price of content before subfrombill */
2884 cltmp
= contained_cost(obj
, shkp
, cltmp
, TRUE
, FALSE
);
2885 /* find the value of contained gold */
2886 gltmp
+= contained_gold(obj
);
2887 cgold
= (gltmp
> 0L);
2890 saleitem
= saleable(shkp
, obj
);
2891 if (!isgold
&& !obj
->unpaid
&& saleitem
)
2892 ltmp
= set_cost(obj
, shkp
);
2894 offer
= ltmp
+ cltmp
;
2896 /* get one case out of the way: nothing to sell, and no gold */
2897 if (!(isgold
|| cgold
)
2898 && ((offer
+ gltmp
) == 0L || sell_how
== SELL_DONTSELL
)) {
2899 boolean unpaid
= is_unpaid(obj
);
2902 dropped_container(obj
, shkp
, FALSE
);
2906 subfrombill(obj
, shkp
);
2910 if (!unpaid
&& (sell_how
!= SELL_DONTSELL
)
2911 && !special_stock(obj
, shkp
, FALSE
))
2912 pline("%s seems uninterested.", Shknam(shkp
));
2916 /* you dropped something of your own - probably want to sell it */
2917 rouse_shk(shkp
, TRUE
); /* wake up sleeping or paralyzed shk */
2920 if (ANGRY(shkp
)) { /* they become shop-objects, no pay */
2921 if (!Deaf
&& !muteshk(shkp
))
2922 verbalize("Thank you, scum!");
2924 pline("%s smirks with satisfaction.", Shknam(shkp
));
2925 subfrombill(obj
, shkp
);
2929 if (eshkp
->robbed
) { /* shkp is not angry? */
2934 if ((eshkp
->robbed
-= offer
< 0L))
2936 if (offer
&& !Deaf
&& !muteshk(shkp
))
2938 "Thank you for your contribution to restock this recently plundered shop.");
2939 subfrombill(obj
, shkp
);
2943 if (isgold
|| cgold
) {
2947 if (eshkp
->debit
>= gltmp
) {
2948 if (eshkp
->loan
) { /* you carry shop's gold */
2949 if (eshkp
->loan
>= gltmp
)
2950 eshkp
->loan
-= gltmp
;
2954 eshkp
->debit
-= gltmp
;
2955 Your("debt is %spaid off.", eshkp
->debit
? "partially " : "");
2957 long delta
= gltmp
- eshkp
->debit
;
2959 eshkp
->credit
+= delta
;
2963 Your("debt is paid off.");
2965 if (eshkp
->credit
== delta
)
2966 You("have established %ld %s credit.", delta
,
2969 pline("%ld %s added to your credit; total is now %ld %s.",
2970 delta
, currency(delta
), eshkp
->credit
,
2971 currency(eshkp
->credit
));
2974 if (!offer
|| sell_how
== SELL_DONTSELL
) {
2977 dropped_container(obj
, shkp
, FALSE
);
2980 subfrombill(obj
, shkp
);
2986 if ((!saleitem
&& !(container
&& cltmp
> 0L)) || eshkp
->billct
== BILLSZ
2987 || obj
->oclass
== BALL_CLASS
|| obj
->oclass
== CHAIN_CLASS
2988 || offer
== 0L || (obj
->oclass
== FOOD_CLASS
&& obj
->oeaten
)
2990 && obj
->age
< 20L * (long) objects
[obj
->otyp
].oc_cost
)) {
2991 pline("%s seems uninterested%s.", Shknam(shkp
),
2992 cgold
? " in the rest" : "");
2994 dropped_container(obj
, shkp
, FALSE
);
2999 shkmoney
= money_cnt(shkp
->minvent
);
3001 char c
, qbuf
[BUFSZ
];
3002 long tmpcr
= ((offer
* 9L) / 10L) + (offer
<= 1L);
3004 if (sell_how
== SELL_NORMAL
|| auto_credit
) {
3005 c
= sell_response
= 'y';
3006 } else if (sell_response
!= 'n') {
3007 pline("%s cannot pay you at present.", shkname(shkp
));
3008 Sprintf(qbuf
, "Will you accept %ld %s in credit for ", tmpcr
,
3010 c
= ynaq(safe_qbuf(qbuf
, qbuf
, "?", obj
, doname
, thesimpleoname
,
3011 (obj
->quan
== 1L) ? "that" : "those"));
3016 } else /* previously specified "quit" */
3022 (sell_how
!= SELL_NORMAL
)
3023 ? "traded %s for %ld zorkmid%s in %scredit."
3024 : "relinquish %s and acquire %ld zorkmid%s in %scredit.",
3025 tmpcr
, (eshkp
->credit
> 0L) ? "additional " : "");
3026 eshkp
->credit
+= tmpcr
;
3027 subfrombill(obj
, shkp
);
3030 sell_response
= 'n';
3032 dropped_container(obj
, shkp
, FALSE
);
3035 subfrombill(obj
, shkp
);
3038 char qbuf
[BUFSZ
], qsfx
[BUFSZ
];
3039 boolean short_funds
= (offer
> shkmoney
), one
;
3043 if (!sell_response
) {
3044 long yourc
= 0L, shksc
;
3047 /* number of items owned by shk */
3048 shksc
= count_contents(obj
, TRUE
, TRUE
, FALSE
);
3049 /* number of items owned by you (total - shksc) */
3050 yourc
= count_contents(obj
, TRUE
, TRUE
, TRUE
) - shksc
;
3051 only_partially_your_contents
= shksc
&& yourc
;
3054 "<shk> offers * for ..." query formatting.
3056 "... your <object>. Sell it?"
3057 "... your <objects>. Sell them?"
3058 A container is either owned by the hero, or already
3059 owned by the shk (!ltmp), or the shk isn't interested
3060 in buying it (also !ltmp). It's either empty (!cltmp)
3061 or it has contents owned by the hero or it has some
3062 contents owned by the hero and others by the shk.
3063 (The case where it has contents already entirely owned
3064 by the shk is treated the same was if it were empty
3065 since the hero isn't selling any of those contents.)
3067 "... your <empty bag>. Sell it?"
3068 "... your <bag> and its contents. Sell them?"
3069 "... your <bag> and item inside. Sell them?"
3070 "... your <bag> and items inside. Sell them?"
3072 "... your item in the <bag>. Sell it?"
3073 "... your items in the <bag>. Sell them?"
3075 Sprintf(qbuf
, "%s offers%s %ld gold piece%s for %s%s ",
3076 shkname(shkp
), short_funds
? " only" : "", offer
,
3079 ? ((yourc
== 1L) ? "your item in " : "your items in ")
3081 obj
->unpaid
? "the" : "your");
3082 one
= obj
->unpaid
? (yourc
== 1L) : (obj
->quan
== 1L && !cltmp
);
3083 Sprintf(qsfx
, "%s. Sell %s?",
3085 ? (only_partially_your_contents
3086 ? ((yourc
== 1L) ? " and item inside"
3087 : " and items inside")
3090 one
? "it" : "them");
3091 (void) safe_qbuf(qbuf
, qbuf
, qsfx
, obj
, xname
, simpleonames
,
3092 one
? "that" : "those");
3094 qbuf
[0] = '\0'; /* just to pacify lint */
3096 switch (sell_response
? sell_response
: ynaq(qbuf
)) {
3098 sell_response
= 'n';
3101 dropped_container(obj
, shkp
, FALSE
);
3104 subfrombill(obj
, shkp
);
3107 sell_response
= 'y';
3110 dropped_container(obj
, shkp
, TRUE
);
3111 if (!obj
->unpaid
&& !saleitem
)
3113 subfrombill(obj
, shkp
);
3115 shk_names_obj(shkp
, obj
,
3116 (sell_how
!= SELL_NORMAL
)
3117 ? ((!ltmp
&& cltmp
&& only_partially_your_contents
)
3118 ? "sold some items inside %s for %ld gold piece%s.%s"
3119 : "sold %s for %ld gold piece%s.%s")
3120 : "relinquish %s and receive %ld gold piece%s in compensation.%s",
3124 impossible("invalid sell response");
3131 int mode
; /* 0: deliver count 1: paged */
3134 void sasc_bug(struct obj
*, unsigned);
3138 struct bill_x
*bp
, *end_bp
;
3144 shkp
= shop_keeper(*u
.ushops
);
3145 if (!shkp
|| !inhishop(shkp
)) {
3147 impossible("doinvbill: no shopkeeper?");
3153 /* count expended items, so that the `I' command can decide
3154 whether to include 'x' in its prompt string */
3155 int cnt
= !eshkp
->debit
? 0 : 1;
3157 for (bp
= eshkp
->bill_p
, end_bp
= &eshkp
->bill_p
[eshkp
->billct
];
3160 || ((obj
= bp_to_obj(bp
)) != 0 && obj
->quan
< bp
->bquan
))
3165 datawin
= create_nhwindow(NHW_MENU
);
3166 putstr(datawin
, 0, "Unpaid articles already used up:");
3167 putstr(datawin
, 0, "");
3170 for (bp
= eshkp
->bill_p
, end_bp
= &eshkp
->bill_p
[eshkp
->billct
];
3171 bp
< end_bp
; bp
++) {
3172 obj
= bp_to_obj(bp
);
3174 impossible("Bad shopkeeper administration.");
3177 if (bp
->useup
|| bp
->bquan
> obj
->quan
) {
3178 long oquan
, uquan
, thisused
;
3181 uquan
= (bp
->useup
? bp
->bquan
: bp
->bquan
- oquan
);
3182 thisused
= bp
->price
* uquan
;
3183 totused
+= thisused
;
3184 iflags
.suppress_price
++; /* suppress "(unpaid)" suffix */
3185 /* Why 'x'? To match `I x', more or less. */
3186 buf_p
= xprname(obj
, (char *) 0, 'x', FALSE
, thisused
, uquan
);
3187 iflags
.suppress_price
--;
3188 putstr(datawin
, 0, buf_p
);
3192 /* additional shop debt which has no itemization available */
3194 putstr(datawin
, 0, "");
3195 totused
+= eshkp
->debit
;
3196 buf_p
= xprname((struct obj
*) 0, "usage charges and/or other fees",
3197 GOLD_SYM
, FALSE
, eshkp
->debit
, 0L);
3198 putstr(datawin
, 0, buf_p
);
3200 buf_p
= xprname((struct obj
*) 0, "Total:", '*', FALSE
, totused
, 0L);
3201 putstr(datawin
, 0, "");
3202 putstr(datawin
, 0, buf_p
);
3203 display_nhwindow(datawin
, FALSE
);
3205 destroy_nhwindow(datawin
);
3210 getprice(obj
, shk_buying
)
3211 register struct obj
*obj
;
3214 register long tmp
= (long) objects
[obj
->otyp
].oc_cost
;
3216 if (obj
->oartifact
) {
3217 tmp
= arti_cost(obj
);
3221 switch (obj
->oclass
) {
3223 /* simpler hunger check, (2-4)*cost */
3224 if (u
.uhs
>= HUNGRY
&& !shk_buying
)
3225 tmp
*= (long) u
.uhs
;
3234 if (obj
->otyp
== POT_WATER
&& !obj
->blessed
&& !obj
->cursed
)
3240 tmp
+= 10L * (long) obj
->spe
;
3244 && obj
->age
< 20L * (long) objects
[obj
->otyp
].oc_cost
)
3251 /* shk catches thrown pick-axe */
3254 register struct obj
*obj
;
3255 register xchar x
, y
;
3257 register struct monst
*shkp
;
3259 if (!(shkp
= shop_keeper(inside_shop(x
, y
))) || !inhishop(shkp
))
3262 if (shkp
->mcanmove
&& !shkp
->msleeping
3263 && (*u
.ushops
!= ESHK(shkp
)->shoproom
|| !inside_shop(u
.ux
, u
.uy
))
3264 && dist2(shkp
->mx
, shkp
->my
, x
, y
) < 3
3265 /* if it is the shk's pos, you hit and anger him */
3266 && (shkp
->mx
!= x
|| shkp
->my
!= y
)) {
3267 if (mnearto(shkp
, x
, y
, TRUE
) && !Deaf
&& !muteshk(shkp
))
3268 verbalize("Out of my way, scum!");
3270 pline("%s nimbly%s catches %s.", Shknam(shkp
),
3271 (x
== shkp
->mx
&& y
== shkp
->my
) ? "" : " reaches over and",
3273 if (!canspotmon(shkp
))
3274 map_invisible(x
, y
);
3278 subfrombill(obj
, shkp
);
3279 (void) mpickobj(shkp
, obj
);
3282 return (struct monst
*) 0;
3286 add_damage(x
, y
, cost
)
3287 register xchar x
, y
;
3290 struct damage
*tmp_dam
;
3293 if (IS_DOOR(levl
[x
][y
].typ
)) {
3296 /* Don't schedule for repair unless it's a real shop entrance */
3297 for (shops
= in_rooms(x
, y
, SHOPBASE
); *shops
; shops
++)
3298 if ((mtmp
= shop_keeper(*shops
)) != 0 && x
== ESHK(mtmp
)->shd
.x
3299 && y
== ESHK(mtmp
)->shd
.y
)
3304 for (tmp_dam
= level
.damagelist
; tmp_dam
; tmp_dam
= tmp_dam
->next
)
3305 if (tmp_dam
->place
.x
== x
&& tmp_dam
->place
.y
== y
) {
3306 tmp_dam
->cost
+= cost
;
3309 tmp_dam
= (struct damage
*) alloc((unsigned) sizeof(struct damage
));
3310 tmp_dam
->when
= monstermoves
;
3311 tmp_dam
->place
.x
= x
;
3312 tmp_dam
->place
.y
= y
;
3313 tmp_dam
->cost
= cost
;
3314 tmp_dam
->typ
= levl
[x
][y
].typ
;
3315 tmp_dam
->next
= level
.damagelist
;
3316 level
.damagelist
= tmp_dam
;
3317 /* If player saw damage, display as a wall forever */
3319 levl
[x
][y
].seenv
= SVALL
;
3323 * Do something about damage. Either (!croaked) try to repair it, or
3324 * (croaked) just discard damage structs for non-shared locations, since
3325 * they'll never get repaired. Assume that shared locations will get
3326 * repaired eventually by the other shopkeeper(s). This might be an erroneous
3327 * assumption (they might all be dead too), but we have no reasonable way of
3332 remove_damage(shkp
, croaked
)
3336 struct damage
*tmp_dam
, *tmp2_dam
;
3337 boolean did_repair
= FALSE
, saw_door
= FALSE
, saw_floor
= FALSE
,
3338 stop_picking
= FALSE
, doorway_trap
= FALSE
;
3339 int saw_walls
= 0, saw_untrap
= 0;
3340 char trapmsg
[BUFSZ
];
3342 tmp_dam
= level
.damagelist
;
3345 register xchar x
= tmp_dam
->place
.x
, y
= tmp_dam
->place
.y
;
3348 unsigned old_doormask
= 0;
3351 Strcpy(shops
, in_rooms(x
, y
, SHOPBASE
));
3352 if (index(shops
, ESHK(shkp
)->shoproom
)) {
3353 if (IS_DOOR(levl
[x
][y
].typ
))
3354 old_doormask
= levl
[x
][y
].doormask
;
3357 disposition
= (shops
[1]) ? 0 : 1;
3358 else if (stop_picking
)
3359 disposition
= repair_damage(shkp
, tmp_dam
, FALSE
);
3361 /* Defer the stop_occupation() until after repair msgs */
3362 if (closed_door(x
, y
))
3363 stop_picking
= picking_at(x
, y
);
3364 disposition
= repair_damage(shkp
, tmp_dam
, FALSE
);
3366 stop_picking
= FALSE
;
3372 tmp_dam
= tmp_dam
->next
;
3376 if (disposition
> 1) {
3379 if (IS_WALL(levl
[x
][y
].typ
)) {
3381 } else if (IS_DOOR(levl
[x
][y
].typ
)
3382 /* an existing door here implies trap removal */
3383 && !(old_doormask
& (D_ISOPEN
| D_CLOSED
))) {
3385 } else if (disposition
== 3) { /* untrapped */
3387 if (IS_DOOR(levl
[x
][y
].typ
))
3388 doorway_trap
= TRUE
;
3395 tmp_dam
= tmp_dam
->next
;
3397 free((genericptr_t
) level
.damagelist
);
3398 level
.damagelist
= tmp_dam
;
3400 free((genericptr_t
) tmp2_dam
->next
);
3401 tmp2_dam
->next
= tmp_dam
;
3408 Sprintf(trapmsg
, "%s trap%s",
3409 (saw_untrap
> 3) ? "several" : (saw_untrap
> 1) ? "some"
3412 Sprintf(eos(trapmsg
), " %s", vtense(trapmsg
, "are"));
3413 Sprintf(eos(trapmsg
), " removed from the %s",
3414 (doorway_trap
&& saw_untrap
== 1) ? "doorway" : "floor");
3416 trapmsg
[0] = '\0'; /* not just lint suppression... */
3419 char wallbuf
[BUFSZ
];
3421 Sprintf(wallbuf
, "section%s", plur(saw_walls
));
3422 pline("Suddenly, %s %s of wall %s up!",
3423 (saw_walls
== 1) ? "a" : (saw_walls
<= 3) ? "some" : "several",
3424 wallbuf
, vtense(wallbuf
, "close"));
3427 pline_The("shop door reappears!");
3429 pline_The("floor is repaired!");
3431 pline("%s!", upstart(trapmsg
));
3433 if (saw_door
|| saw_floor
|| saw_untrap
)
3434 pline("Suddenly, %s%s%s%s%s!",
3435 saw_door
? "the shop door reappears" : "",
3436 (saw_door
&& saw_floor
) ? " and " : "",
3437 saw_floor
? "the floor damage is gone" : "",
3438 ((saw_door
|| saw_floor
) && *trapmsg
) ? " and " : "",
3440 else if (inside_shop(u
.ux
, u
.uy
) == ESHK(shkp
)->shoproom
)
3441 You_feel("more claustrophobic than before.");
3442 else if (!Deaf
&& !rn2(10))
3443 Norep("The dungeon acoustics noticeably change.");
3450 * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
3454 repair_damage(shkp
, tmp_dam
, catchup
)
3455 register struct monst
*shkp
;
3456 register struct damage
*tmp_dam
;
3457 boolean catchup
; /* restoring a level */
3459 register xchar x
, y
, i
;
3461 register struct monst
*mtmp
;
3462 register struct obj
*otmp
;
3463 register struct trap
*ttmp
;
3465 if ((monstermoves
- tmp_dam
->when
) < REPAIR_DELAY
)
3467 if (shkp
->msleeping
|| !shkp
->mcanmove
|| ESHK(shkp
)->following
)
3469 x
= tmp_dam
->place
.x
;
3470 y
= tmp_dam
->place
.y
;
3471 if (!IS_ROOM(tmp_dam
->typ
)) {
3472 if (x
== u
.ux
&& y
== u
.uy
)
3475 if (x
== shkp
->mx
&& y
== shkp
->my
)
3477 if ((mtmp
= m_at(x
, y
)) && (!passes_walls(mtmp
->data
)))
3480 if ((ttmp
= t_at(x
, y
)) != 0) {
3481 if (x
== u
.ux
&& y
== u
.uy
)
3484 if (ttmp
->ttyp
== LANDMINE
|| ttmp
->ttyp
== BEAR_TRAP
) {
3485 /* convert to an object */
3486 otmp
= mksobj((ttmp
->ttyp
== LANDMINE
) ? LAND_MINE
: BEARTRAP
,
3489 otmp
->owt
= weight(otmp
);
3490 (void) mpickobj(shkp
, otmp
);
3493 if (IS_DOOR(tmp_dam
->typ
) && !(levl
[x
][y
].doormask
& D_ISOPEN
)) {
3494 levl
[x
][y
].doormask
= D_CLOSED
;
3496 } else if (IS_WALL(tmp_dam
->typ
)) {
3497 levl
[x
][y
].typ
= tmp_dam
->typ
;
3503 if (IS_ROOM(tmp_dam
->typ
)) {
3504 /* No messages, because player already filled trap door */
3507 if ((tmp_dam
->typ
== levl
[x
][y
].typ
)
3508 && (!IS_DOOR(tmp_dam
->typ
) || (levl
[x
][y
].doormask
> D_BROKEN
)))
3509 /* No messages if player already replaced shop door */
3511 levl
[x
][y
].typ
= tmp_dam
->typ
;
3512 (void) memset((genericptr_t
) litter
, 0, sizeof(litter
));
3513 if ((otmp
= level
.objects
[x
][y
]) != 0) {
3514 /* Scatter objects haphazardly into the shop */
3515 #define NEED_UPDATE 1
3518 #define horiz(i) ((i % 3) - 1)
3519 #define vert(i) ((i / 3) - 1)
3520 for (i
= 0; i
< 9; i
++) {
3521 if ((i
== 4) || (!ZAP_POS(levl
[x
+ horiz(i
)][y
+ vert(i
)].typ
)))
3524 if (inside_shop(x
+ horiz(i
), y
+ vert(i
))
3525 == ESHK(shkp
)->shoproom
)
3526 litter
[i
] |= INSHOP
;
3528 if (Punished
&& !u
.uswallow
3529 && ((uchain
->ox
== x
&& uchain
->oy
== y
)
3530 || (uball
->ox
== x
&& uball
->oy
== y
))) {
3532 * Either the ball or chain is in the repair location.
3534 * Take the easy way out and put ball&chain under hero.
3536 if (!Deaf
&& !muteshk(shkp
))
3537 verbalize("Get your junk out of my wall!");
3538 unplacebc(); /* pick 'em up */
3539 placebc(); /* put 'em down */
3541 while ((otmp
= level
.objects
[x
][y
]) != 0)
3542 /* Don't mess w/ boulders -- just merge into wall */
3543 if ((otmp
->otyp
== BOULDER
) || (otmp
->otyp
== ROCK
)) {
3544 obj_extract_self(otmp
);
3545 obfree(otmp
, (struct obj
*) 0);
3547 while (!(litter
[i
= rn2(9)] & INSHOP
))
3549 remove_object(otmp
);
3550 place_object(otmp
, x
+ horiz(i
), y
+ vert(i
));
3551 litter
[i
] |= NEED_UPDATE
;
3555 return 1; /* repair occurred while off level */
3558 if (IS_DOOR(tmp_dam
->typ
)) {
3559 levl
[x
][y
].doormask
= D_CLOSED
; /* arbitrary */
3562 /* don't set doormask - it is (hopefully) the same as it was
3563 if not, perhaps save it with the damage array... */
3565 if (IS_WALL(tmp_dam
->typ
) && cansee(x
, y
)) {
3566 /* Player sees actual repair process, so they KNOW it's a wall */
3567 levl
[x
][y
].seenv
= SVALL
;
3570 /* Mark this wall as "repaired". There currently is no code
3571 to do anything about repaired walls, so don't do it. */
3573 for (i
= 0; i
< 9; i
++)
3574 if (litter
[i
] & NEED_UPDATE
)
3575 newsym(x
+ horiz(i
), y
+ vert(i
));
3585 * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
3589 register struct monst
*shkp
;
3591 register xchar gx
, gy
, omx
, omy
;
3593 register schar appr
;
3594 register struct eshk
*eshkp
= ESHK(shkp
);
3596 boolean uondoor
= FALSE
, satdoor
, avoid
= FALSE
, badinv
;
3602 remove_damage(shkp
, FALSE
);
3604 if ((udist
= distu(omx
, omy
)) < 3 && (shkp
->data
!= &mons
[PM_GRID_BUG
]
3605 || (omx
== u
.ux
|| omy
== u
.uy
))) {
3606 if (ANGRY(shkp
) || (Conflict
&& !resist(shkp
, RING_CLASS
, 0, 0))) {
3608 Your("displaced image doesn't fool %s!", shkname(shkp
));
3609 (void) mattacku(shkp
);
3612 if (eshkp
->following
) {
3613 if (strncmp(eshkp
->customer
, plname
, PL_NSIZ
)) {
3614 if (!Deaf
&& !muteshk(shkp
))
3615 verbalize("%s, %s! I was looking for %s.", Hello(shkp
),
3616 plname
, eshkp
->customer
);
3617 eshkp
->following
= 0;
3620 if (moves
> followmsg
+ 4) {
3621 if (!Deaf
&& !muteshk(shkp
))
3622 verbalize("%s, %s! Didn't you forget to pay?",
3623 Hello(shkp
), plname
);
3625 pline("%s holds out %s upturned %s.",
3628 mbodypart(shkp
, HAND
));
3631 pline("%s doesn't like customers who don't pay.",
3644 satdoor
= (gx
== omx
&& gy
== omy
);
3645 if (eshkp
->following
|| ((z
= holetime()) >= 0 && z
* z
<= udist
)) {
3646 /* [This distance check used to apply regardless of
3647 whether the shk was following, but that resulted in
3648 m_move() sometimes taking the shk out of the shop if
3649 the player had fenced him in with boulders or traps.
3650 Such voluntary abandonment left unpaid objects in
3651 invent, triggering billing impossibilities on the
3652 next level once the character fell through the hole.] */
3653 if (udist
> 4 && eshkp
->following
&& !eshkp
->billct
)
3654 return -1; /* leave it to m_move */
3657 } else if (ANGRY(shkp
)) {
3658 /* Move towards the hero if the shopkeeper can see him. */
3659 if (shkp
->mcansee
&& m_canseeu(shkp
)) {
3665 #define GDIST(x, y) (dist2(x, y, gx, gy))
3666 if (Invis
|| u
.usteed
) {
3669 uondoor
= (u
.ux
== eshkp
->shd
.x
&& u
.uy
== eshkp
->shd
.y
);
3672 (carrying(PICK_AXE
) || carrying(DWARVISH_MATTOCK
)
3673 || (Fast
&& (sobj_at(PICK_AXE
, u
.ux
, u
.uy
)
3674 || sobj_at(DWARVISH_MATTOCK
, u
.ux
, u
.uy
))));
3675 if (satdoor
&& badinv
)
3679 avoid
= (*u
.ushops
&& distu(gx
, gy
) > 8);
3683 if (((!eshkp
->robbed
&& !eshkp
->billct
&& !eshkp
->debit
) || avoid
)
3684 && GDIST(omx
, omy
) < 3) {
3685 if (!badinv
&& !onlineu(omx
, omy
))
3693 z
= move_special(shkp
, inhishop(shkp
), appr
, uondoor
, avoid
, omx
, omy
, gx
,
3696 after_shk_move(shkp
);
3701 /* called after shopkeeper moves, in case themove causes re-entry into shop */
3703 after_shk_move(shkp
)
3706 struct eshk
*eshkp
= ESHK(shkp
);
3708 if (eshkp
->bill_p
== (struct bill_x
*) -1000 && inhishop(shkp
)) {
3709 /* reset bill_p, need to re-calc player's occupancy too */
3710 eshkp
->bill_p
= &eshkp
->bill
[0];
3711 check_special_room(FALSE
);
3715 /* for use in levl_follower (mondata.c) */
3718 register struct monst
*mtmp
;
3720 return (boolean
) (mtmp
->isshk
&& ESHK(mtmp
)->following
);
3723 /* You are digging in the shop. */
3728 register struct monst
*shkp
= shop_keeper(*u
.ushops
);
3730 const char *grabs
= "grabs";
3735 /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */
3737 if (shkp
->msleeping
|| !shkp
->mcanmove
|| is_silent(shkp
->data
))
3738 ; /* lang stays 0 */
3739 else if (shkp
->data
->msound
<= MS_ANIMAL
)
3741 else if (shkp
->data
->msound
>= MS_HUMANOID
)
3744 if (!inhishop(shkp
)) {
3745 if (Role_if(PM_KNIGHT
)) {
3746 You_feel("like a common thief.");
3747 adjalign(-sgn(u
.ualign
.type
));
3754 if (!Deaf
&& !muteshk(shkp
)) {
3755 if (u
.utraptype
== TT_PIT
)
3757 "Be careful, %s, or you might fall through the floor.",
3758 flags
.female
? "madam" : "sir");
3760 verbalize("%s, do not damage the floor here!",
3761 flags
.female
? "Madam" : "Sir");
3764 if (Role_if(PM_KNIGHT
)) {
3765 You_feel("like a common thief.");
3766 adjalign(-sgn(u
.ualign
.type
));
3768 } else if (!um_dist(shkp
->mx
, shkp
->my
, 5)
3769 && !shkp
->msleeping
&& shkp
->mcanmove
3770 && (ESHK(shkp
)->billct
|| ESHK(shkp
)->debit
)) {
3771 register struct obj
*obj
, *obj2
;
3773 if (nolimbs(shkp
->data
)) {
3774 grabs
= "knocks off";
3776 /* This is what should happen, but for balance
3777 * reasons, it isn't currently.
3780 pline("%s curses %s inability to grab your backpack!",
3781 shkname(shkp
), mhim(shkp
));
3786 if (distu(shkp
->mx
, shkp
->my
) > 2) {
3788 /* for some reason the shopkeeper can't come next to you */
3789 if (distu(shkp
->mx
, shkp
->my
) > 2) {
3791 pline("%s curses you in anger and frustration!",
3798 pline("%s %s, and %s your backpack!", shkname(shkp
),
3799 makeplural(locomotion(shkp
->data
, "leap")), grabs
);
3801 pline("%s %s your backpack!", shkname(shkp
), grabs
);
3803 for (obj
= invent
; obj
; obj
= obj2
) {
3805 if ((obj
->owornmask
& ~(W_SWAPWEP
| W_QUIVER
)) != 0
3806 || (obj
== uswapwep
&& u
.twoweap
)
3807 || (obj
->otyp
== LEASH
&& obj
->leashmon
))
3809 if (obj
== current_wand
)
3813 subfrombill(obj
, shkp
);
3814 (void) add_to_minv(shkp
, obj
); /* may free obj */
3823 static const short k_mndx
[4] = { PM_KEYSTONE_KOP
, PM_KOP_SERGEANT
,
3824 PM_KOP_LIEUTENANT
, PM_KOP_KAPTAIN
};
3825 int k_cnt
[4], cnt
, mndx
, k
;
3827 k_cnt
[0] = cnt
= abs(depth(&u
.uz
)) + rnd(5);
3828 k_cnt
[1] = (cnt
/ 3) + 1; /* at least one sarge */
3829 k_cnt
[2] = (cnt
/ 6); /* maybe a lieutenant */
3830 k_cnt
[3] = (cnt
/ 9); /* and maybe a kaptain */
3832 for (k
= 0; k
< 4; k
++) {
3833 if ((cnt
= k_cnt
[k
]) == 0)
3836 if (mvitals
[mndx
].mvflags
& G_GONE
)
3840 if (enexto(mm
, mm
->x
, mm
->y
, &mons
[mndx
]))
3841 (void) makemon(&mons
[mndx
], mm
->x
, mm
->y
, NO_MM_FLAGS
);
3846 pay_for_damage(dmgstr
, cant_mollify
)
3848 boolean cant_mollify
;
3850 register struct monst
*shkp
= (struct monst
*) 0;
3851 char shops_affected
[5];
3852 register boolean uinshp
= (*u
.ushops
!= '\0');
3854 register xchar x
, y
;
3855 boolean dugwall
= (!strcmp(dmgstr
, "dig into") /* wand */
3856 || !strcmp(dmgstr
, "damage")); /* pick-axe */
3857 boolean animal
, pursue
;
3858 struct damage
*tmp_dam
, *appear_here
= 0;
3859 /* any number >= (80*80)+(24*24) would do, actually */
3860 long cost_of_damage
= 0L;
3861 unsigned int nearest_shk
= 7000, nearest_damage
= 7000;
3864 for (tmp_dam
= level
.damagelist
;
3865 (tmp_dam
&& (tmp_dam
->when
== monstermoves
));
3866 tmp_dam
= tmp_dam
->next
) {
3871 cost_of_damage
+= tmp_dam
->cost
;
3872 Strcpy(shops_affected
,
3873 in_rooms(tmp_dam
->place
.x
, tmp_dam
->place
.y
, SHOPBASE
));
3874 for (shp
= shops_affected
; *shp
; shp
++) {
3875 struct monst
*tmp_shk
;
3876 unsigned int shk_distance
;
3878 if (!(tmp_shk
= shop_keeper(*shp
)))
3880 if (tmp_shk
== shkp
) {
3881 unsigned int damage_distance
=
3882 distu(tmp_dam
->place
.x
, tmp_dam
->place
.y
);
3884 if (damage_distance
< nearest_damage
) {
3885 nearest_damage
= damage_distance
;
3886 appear_here
= tmp_dam
;
3890 if (!inhishop(tmp_shk
))
3892 shk_distance
= distu(tmp_shk
->mx
, tmp_shk
->my
);
3893 if (shk_distance
> nearest_shk
)
3895 if ((shk_distance
== nearest_shk
) && picks
) {
3901 nearest_shk
= shk_distance
;
3902 appear_here
= tmp_dam
;
3903 nearest_damage
= distu(tmp_dam
->place
.x
, tmp_dam
->place
.y
);
3907 if (!cost_of_damage
|| !shkp
)
3910 animal
= (shkp
->data
->msound
<= MS_ANIMAL
);
3912 x
= appear_here
->place
.x
;
3913 y
= appear_here
->place
.y
;
3915 /* not the best introduction to the shk... */
3916 (void) strncpy(ESHK(shkp
)->customer
, plname
, PL_NSIZ
);
3918 /* if the shk is already on the war path, be sure it's all out */
3919 if (ANGRY(shkp
) || ESHK(shkp
)->following
) {
3924 /* if the shk is not in their shop.. */
3925 if (!*in_rooms(shkp
->mx
, shkp
->my
, SHOPBASE
)) {
3926 if (!cansee(shkp
->mx
, shkp
->my
))
3933 if (um_dist(shkp
->mx
, shkp
->my
, 1)
3934 && !um_dist(shkp
->mx
, shkp
->my
, 3)) {
3935 pline("%s leaps towards you!", shkname(shkp
));
3938 pursue
= um_dist(shkp
->mx
, shkp
->my
, 1);
3943 * Make shkp show up at the door. Effect: If there is a monster
3944 * in the doorway, have the hero hear the shopkeeper yell a bit,
3945 * pause, then have the shopkeeper appear at the door, having
3946 * yanked the hapless critter out of the way.
3950 if (!Deaf
&& !muteshk(shkp
)) {
3951 You_hear("an angry voice:");
3952 verbalize("Out of my way, scum!");
3955 #if defined(UNIX) || defined(VMS)
3956 #if defined(SYSV) || defined(ULTRIX) || defined(VMS)
3965 (void) mnearto(shkp
, x
, y
, TRUE
);
3968 if ((um_dist(x
, y
, 1) && !uinshp
) || cant_mollify
3969 || (money_cnt(invent
) + ESHK(shkp
)->credit
) < cost_of_damage
3972 if (muteshk(shkp
)) {
3973 if (animal
&& shkp
->mcanmove
&& !shkp
->msleeping
)
3975 } else if (pursue
|| uinshp
|| !um_dist(x
, y
, 1)) {
3977 verbalize("How dare you %s my %s?", dmgstr
,
3978 dugwall
? "shop" : "door");
3980 pline("%s is %s that you decided to %s %s %s!",
3981 Shknam(shkp
), angrytexts
[rn2(SIZE(angrytexts
))],
3982 dmgstr
, mhis(shkp
), dugwall
? "shop" : "door");
3985 pline("%s shouts:", shkname(shkp
));
3986 verbalize("Who dared %s my %s?", dmgstr
,
3987 dugwall
? "shop" : "door");
3989 pline("%s is %s that someone decided to %s %s %s!",
3990 Shknam(shkp
), angrytexts
[rn2(SIZE(angrytexts
))],
3991 dmgstr
, mhis(shkp
), dugwall
? "shop" : "door");
3999 Your("invisibility does not fool %s!", shkname(shkp
));
4000 Sprintf(qbuf
, "%sYou did %ld %s worth of damage!%s Pay?",
4001 !animal
? cad(TRUE
) : "", cost_of_damage
,
4002 currency(cost_of_damage
), !animal
? "\"" : "");
4003 if (yn(qbuf
) != 'n') {
4004 cost_of_damage
= check_credit(cost_of_damage
, shkp
);
4005 money2mon(shkp
, cost_of_damage
);
4007 pline("Mollified, %s accepts your restitution.", shkname(shkp
));
4008 /* move shk back to his home loc */
4009 home_shk(shkp
, FALSE
);
4013 if (!Deaf
&& !muteshk(shkp
))
4014 verbalize("Oh, yes! You'll pay!");
4016 pline("%s lunges %s %s toward your %s!",
4019 mbodypart(shkp
, HAND
),
4024 adjalign(-sgn(u
.ualign
.type
));
4028 /* called in dokick.c when we kick an object that might be in a store */
4031 register xchar x
, y
;
4036 if (!level
.flags
.has_shop
)
4038 shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
));
4039 if (!shkp
|| !inhishop(shkp
))
4042 return (boolean
) (inside_shop(x
, y
)
4043 && !(x
== eshkp
->shk
.x
&& y
== eshkp
->shk
.y
));
4046 /* called by dotalk(sounds.c) when #chatting; returns obj if location
4047 contains shop goods and shopkeeper is willing & able to speak */
4050 register xchar x
, y
;
4052 register struct obj
*otmp
;
4053 register struct monst
*shkp
;
4055 if (!(shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
))) || !inhishop(shkp
))
4056 return (struct obj
*) 0;
4058 for (otmp
= level
.objects
[x
][y
]; otmp
; otmp
= otmp
->nexthere
)
4059 if (otmp
->oclass
!= COIN_CLASS
)
4061 /* note: otmp might have ->no_charge set, but that's ok */
4062 return (otmp
&& costly_spot(x
, y
)
4063 && NOTANGRY(shkp
) && shkp
->mcanmove
&& !shkp
->msleeping
)
4068 /* give price quotes for all objects linked to this one (ie, on this spot) */
4070 price_quote(first_obj
)
4071 register struct obj
*first_obj
;
4073 register struct obj
*otmp
;
4074 char buf
[BUFSZ
], price
[40];
4077 boolean contentsonly
= FALSE
;
4079 struct monst
*shkp
= shop_keeper(inside_shop(u
.ux
, u
.uy
));
4081 tmpwin
= create_nhwindow(NHW_MENU
);
4082 putstr(tmpwin
, 0, "Fine goods for sale:");
4083 putstr(tmpwin
, 0, "");
4084 for (otmp
= first_obj
; otmp
; otmp
= otmp
->nexthere
) {
4085 if (otmp
->oclass
== COIN_CLASS
)
4087 cost
= (otmp
->no_charge
|| otmp
== uball
|| otmp
== uchain
)
4089 : get_cost(otmp
, (struct monst
*) 0);
4090 contentsonly
= !cost
;
4091 if (Has_contents(otmp
))
4092 cost
+= contained_cost(otmp
, shkp
, 0L, FALSE
, FALSE
);
4094 Strcpy(price
, "no charge");
4095 contentsonly
= FALSE
;
4097 Sprintf(price
, "%ld %s%s", cost
, currency(cost
),
4098 (otmp
->quan
) > 1L ? " each" : "");
4100 Sprintf(buf
, "%s%s, %s", contentsonly
? the_contents_of
: "",
4101 doname(otmp
), price
);
4102 putstr(tmpwin
, 0, buf
), cnt
++;
4105 display_nhwindow(tmpwin
, TRUE
);
4106 } else if (cnt
== 1) {
4108 /* "<doname(obj)>, no charge" */
4109 pline("%s!", upstart(buf
)); /* buf still contains the string */
4111 /* print cost in slightly different format, so can't reuse buf;
4112 cost and contentsonly are already set up */
4113 Sprintf(buf
, "%s%s", contentsonly
? the_contents_of
: "",
4115 pline("%s, price %ld %s%s%s", upstart(buf
), cost
, currency(cost
),
4116 (first_obj
->quan
> 1L) ? " each" : "",
4117 contentsonly
? "." : shk_embellish(first_obj
, cost
));
4120 destroy_nhwindow(tmpwin
);
4123 STATIC_OVL
const char *
4124 shk_embellish(itm
, cost
)
4125 register struct obj
*itm
;
4129 register int o
, choice
= rn2(5);
4132 choice
= (cost
< 100L ? 1 : cost
< 500L ? 2 : 3);
4139 if (o
== FOOD_CLASS
)
4140 return ", gourmets' delight!";
4141 if (objects
[itm
->otyp
].oc_name_known
4142 ? objects
[itm
->otyp
].oc_magic
4143 : (o
== AMULET_CLASS
|| o
== RING_CLASS
|| o
== WAND_CLASS
4144 || o
== POTION_CLASS
|| o
== SCROLL_CLASS
4145 || o
== SPBOOK_CLASS
))
4146 return ", painstakingly developed!";
4147 return ", superb craftsmanship!";
4149 return ", finest quality.";
4151 return ", an excellent choice.";
4153 return ", a real bargain.";
4157 } else if (itm
->oartifact
) {
4158 return ", one of a kind!";
4163 /* First 4 supplied by Ronen and Tamar, remainder by development team */
4164 const char *Izchak_speaks
[] = {
4165 "%s says: 'These shopping malls give me a headache.'",
4166 "%s says: 'Slow down. Think clearly.'",
4167 "%s says: 'You need to take things one at a time.'",
4168 "%s says: 'I don't like poofy coffee... give me Columbian Supremo.'",
4169 "%s says that getting the devteam's agreement on anything is difficult.",
4170 "%s says that he has noticed those who serve their deity will prosper.",
4171 "%s says: 'Don't try to steal from me - I have friends in high places!'",
4172 "%s says: 'You may well need something from this shop in the future.'",
4173 "%s comments about the Valley of the Dead as being a gateway."
4184 /* The monster type is shopkeeper, but this monster is
4185 not actually a shk, which could happen if someone
4186 wishes for a shopkeeper statue and then animates it.
4187 (Note: shkname() would be "" in a case like this.) */
4188 pline("%s asks whether you've seen any untended shops recently.",
4190 /* [Perhaps we ought to check whether this conversation
4191 is taking place inside an untended shop, but a shopless
4192 shk can probably be expected to be rather disoriented.] */
4198 pline("%s %s how much %s dislikes %s customers.",
4200 (!Deaf
&& !muteshk(shkp
)) ? "mentions" : "indicates",
4201 mhe(shkp
), eshk
->robbed
? "non-paying" : "rude");
4202 } else if (eshk
->following
) {
4203 if (strncmp(eshk
->customer
, plname
, PL_NSIZ
)) {
4204 if (!Deaf
&& !muteshk(shkp
))
4205 verbalize("%s %s! I was looking for %s.",
4206 Hello(shkp
), plname
, eshk
->customer
);
4207 eshk
->following
= 0;
4209 if (!Deaf
&& !muteshk(shkp
))
4210 verbalize("%s %s! Didn't you forget to pay?",
4211 Hello(shkp
), plname
);
4213 pline("%s taps you on the %s.",
4214 Shknam(shkp
), body_part(ARM
));
4216 } else if (eshk
->billct
) {
4217 register long total
= addupbill(shkp
) + eshk
->debit
;
4219 pline("%s %s that your bill comes to %ld %s.",
4221 (!Deaf
&& !muteshk(shkp
)) ? "says" : "indicates",
4222 total
, currency(total
));
4223 } else if (eshk
->debit
) {
4224 pline("%s %s that you owe %s %ld %s.",
4226 (!Deaf
&& !muteshk(shkp
)) ? "reminds you" : "indicates",
4227 mhim(shkp
), eshk
->debit
, currency(eshk
->debit
));
4228 } else if (eshk
->credit
) {
4229 pline("%s encourages you to use your %ld %s of credit.",
4230 shkname(shkp
), eshk
->credit
, currency(eshk
->credit
));
4231 } else if (eshk
->robbed
) {
4232 pline("%s %s about a recent robbery.",
4234 (!Deaf
&& !muteshk(shkp
)) ? "complains" : "indicates concern");
4235 } else if ((shkmoney
= money_cnt(shkp
->minvent
)) < 50L) {
4236 pline("%s %s that business is bad.",
4238 (!Deaf
&& !muteshk(shkp
)) ? "complains" : "indicates");
4239 } else if (shkmoney
> 4000) {
4240 pline("%s %s that business is good.",
4242 (!Deaf
&& !muteshk(shkp
)) ? "says" : "indicates");
4243 } else if (is_izchak(shkp
, FALSE
)) {
4244 if (!Deaf
&& !muteshk(shkp
))
4245 pline(Izchak_speaks
[rn2(SIZE(Izchak_speaks
))], shkname(shkp
));
4247 if (!Deaf
&& !muteshk(shkp
))
4248 pline("%s talks about the problem of shoplifters.", shkname(shkp
));
4256 register int cnt
= 0;
4257 register struct monst
*mtmp
, *mtmp2
;
4259 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp2
) {
4261 if (mtmp
->data
->mlet
== S_KOP
) {
4262 if (canspotmon(mtmp
))
4268 pline_The("Kop%s (disappointed) vanish%s into thin air.",
4269 plur(cnt
), (cnt
== 1) ? "es" : "");
4273 cost_per_charge(shkp
, otmp
, altusage
)
4276 boolean altusage
; /* some items have an "alternate" use with different cost */
4280 if (!shkp
|| !inhishop(shkp
))
4281 return 0L; /* insurance */
4282 tmp
= get_cost(otmp
, shkp
);
4284 /* The idea is to make the exhaustive use of an unpaid item
4285 * more expensive than buying it outright.
4287 if (otmp
->otyp
== MAGIC_LAMP
) { /* 1 */
4288 /* normal use (ie, as light source) of a magic lamp never
4289 degrades its value, but not charging anything would make
4290 identification too easy; charge an amount comparable to
4291 what is charged for an ordinary lamp (don't bother with
4292 angry shk surcharge) */
4294 tmp
= (long) objects
[OIL_LAMP
].oc_cost
;
4296 tmp
+= tmp
/ 3L; /* djinni is being released */
4297 } else if (otmp
->otyp
== MAGIC_MARKER
) { /* 70 - 100 */
4298 /* No way to determine in advance how many charges will be
4299 * wasted. So, arbitrarily, one half of the price per use.
4302 } else if (otmp
->otyp
== BAG_OF_TRICKS
/* 1 - 20 */
4303 || otmp
->otyp
== HORN_OF_PLENTY
) {
4304 /* altusage: emptying of all the contents at once */
4307 } else if (otmp
->otyp
== CRYSTAL_BALL
/* 1 - 5 */
4308 || otmp
->otyp
== OIL_LAMP
/* 1 - 10 */
4309 || otmp
->otyp
== BRASS_LANTERN
4310 || (otmp
->otyp
>= MAGIC_FLUTE
4311 && otmp
->otyp
<= DRUM_OF_EARTHQUAKE
) /* 5 - 9 */
4312 || otmp
->oclass
== WAND_CLASS
) { /* 3 - 11 */
4315 } else if (otmp
->oclass
== SPBOOK_CLASS
) {
4317 } else if (otmp
->otyp
== CAN_OF_GREASE
|| otmp
->otyp
== TINNING_KIT
4318 || otmp
->otyp
== EXPENSIVE_CAMERA
) {
4320 } else if (otmp
->otyp
== POT_OIL
) {
4326 /* Charge the player for partial use of an unpaid object.
4328 * Note that bill_dummy_object() should be used instead
4329 * when an object is completely used.
4332 check_unpaid_usage(otmp
, altusage
)
4337 const char *fmt
, *arg1
, *arg2
;
4341 if (!otmp
->unpaid
|| !*u
.ushops
4342 || (otmp
->spe
<= 0 && objects
[otmp
->otyp
].oc_charged
))
4344 if (!(shkp
= shop_keeper(*u
.ushops
)) || !inhishop(shkp
))
4346 if ((tmp
= cost_per_charge(shkp
, otmp
, altusage
)) == 0L)
4350 if (otmp
->oclass
== SPBOOK_CLASS
) {
4351 fmt
= "%sYou owe%s %ld %s.";
4352 Sprintf(buf
, "This is no free library, %s! ", cad(FALSE
));
4353 arg1
= rn2(2) ? buf
: "";
4354 arg2
= ESHK(shkp
)->debit
> 0L ? " an additional" : "";
4355 } else if (otmp
->otyp
== POT_OIL
) {
4356 fmt
= "%s%sThat will cost you %ld %s (Yendorian Fuel Tax).";
4357 } else if (altusage
&& (otmp
->otyp
== BAG_OF_TRICKS
4358 || otmp
->otyp
== HORN_OF_PLENTY
)) {
4359 fmt
= "%s%sEmptying that will cost you %ld %s.";
4363 arg1
= "Watch it! ";
4365 fmt
= "%s%sUsage fee, %ld %s.";
4372 if (!Deaf
&& !muteshk(shkp
)) {
4373 verbalize(fmt
, arg1
, arg2
, tmp
, currency(tmp
));
4374 exercise(A_WIS
, TRUE
); /* you just got info */
4376 ESHK(shkp
)->debit
+= tmp
;
4379 /* for using charges of unpaid objects "used in the normal manner" */
4384 check_unpaid_usage(otmp
, FALSE
); /* normal item use */
4388 costly_gold(x
, y
, amount
)
4389 register xchar x
, y
;
4390 register long amount
;
4392 register long delta
;
4393 register struct monst
*shkp
;
4394 register struct eshk
*eshkp
;
4396 if (!costly_spot(x
, y
))
4398 /* shkp now guaranteed to exist by costly_spot() */
4399 shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
));
4402 if (eshkp
->credit
>= amount
) {
4403 if (eshkp
->credit
> amount
)
4404 Your("credit is reduced by %ld %s.", amount
, currency(amount
));
4406 Your("credit is erased.");
4407 eshkp
->credit
-= amount
;
4409 delta
= amount
- eshkp
->credit
;
4411 Your("credit is erased.");
4413 Your("debt increases by %ld %s.", delta
, currency(delta
));
4415 You("owe %s %ld %s.", shkname(shkp
), delta
, currency(delta
));
4416 eshkp
->debit
+= delta
;
4417 eshkp
->loan
+= delta
;
4422 /* used in domove to block diagonal shop-exit */
4423 /* x,y should always be a door */
4426 register xchar x
, y
;
4428 register int roomno
= *in_rooms(x
, y
, SHOPBASE
);
4429 register struct monst
*shkp
;
4431 if (roomno
< 0 || !IS_SHOP(roomno
))
4433 if (!IS_DOOR(levl
[x
][y
].typ
))
4435 if (roomno
!= *u
.ushops
)
4438 if (!(shkp
= shop_keeper((char) roomno
)) || !inhishop(shkp
))
4441 if (shkp
->mx
== ESHK(shkp
)->shk
.x
&& shkp
->my
== ESHK(shkp
)->shk
.y
4442 /* Actually, the shk should be made to block _any_
4443 * door, including a door the player digs, if the
4444 * shk is within a 'jumping' distance.
4446 && ESHK(shkp
)->shd
.x
== x
4447 && ESHK(shkp
)->shd
.y
== y
4448 && shkp
->mcanmove
&& !shkp
->msleeping
4449 && (ESHK(shkp
)->debit
|| ESHK(shkp
)->billct
|| ESHK(shkp
)->robbed
)) {
4450 pline("%s%s blocks your way!", shkname(shkp
),
4451 Invis
? " senses your motion and" : "");
4457 /* used in domove to block diagonal shop-entry;
4458 u.ux, u.uy should always be a door */
4461 register xchar x
, y
;
4463 register xchar sx
, sy
;
4464 register int roomno
;
4465 register struct monst
*shkp
;
4467 if (!(IS_DOOR(levl
[u
.ux
][u
.uy
].typ
)
4468 && levl
[u
.ux
][u
.uy
].doormask
== D_BROKEN
))
4471 roomno
= *in_rooms(x
, y
, SHOPBASE
);
4472 if (roomno
< 0 || !IS_SHOP(roomno
))
4474 if (!(shkp
= shop_keeper((char) roomno
)) || !inhishop(shkp
))
4477 if (ESHK(shkp
)->shd
.x
!= u
.ux
|| ESHK(shkp
)->shd
.y
!= u
.uy
)
4480 sx
= ESHK(shkp
)->shk
.x
;
4481 sy
= ESHK(shkp
)->shk
.y
;
4483 if (shkp
->mx
== sx
&& shkp
->my
== sy
&& shkp
->mcanmove
&& !shkp
->msleeping
4484 && (x
== sx
- 1 || x
== sx
+ 1 || y
== sy
- 1 || y
== sy
+ 1)
4485 && (Invis
|| carrying(PICK_AXE
) || carrying(DWARVISH_MATTOCK
)
4487 pline("%s%s blocks your way!", shkname(shkp
),
4488 Invis
? " senses your motion and" : "");
4494 /* "your " or "Foobar's " (note the trailing space) */
4500 if (!shk_owns(buf
, obj
) && !mon_owns(buf
, obj
))
4501 Strcpy(buf
, the_your
[carried(obj
) ? 1 : 0]);
4502 return strcat(buf
, " ");
4510 (void) shk_your(buf
, obj
);
4523 if (get_obj_location(obj
, &x
, &y
, 0)
4524 && (obj
->unpaid
|| (obj
->where
== OBJ_FLOOR
&& !obj
->no_charge
4525 && costly_spot(x
, y
)))) {
4526 shkp
= shop_keeper(inside_shop(x
, y
));
4527 return strcpy(buf
, shkp
? s_suffix(shkname(shkp
)) : the_your
[0]);
4537 if (obj
->where
== OBJ_MINVENT
)
4538 return strcpy(buf
, s_suffix(y_monnam(obj
->ocarry
)));
4542 STATIC_OVL
const char *
4544 boolean altusage
; /* used as a verbalized exclamation: \"Cad! ...\" */
4546 const char *res
= 0;
4548 switch (is_demon(youmonst
.data
) ? 3 : poly_gender()) {
4562 impossible("cad: unknown gender");
4567 char *cadbuf
= mon_nam(&youmonst
); /* snag an output buffer */
4569 /* alternate usage adds a leading double quote and trailing
4570 exclamation point plus sentence separating spaces */
4571 Sprintf(cadbuf
, "\"%s! ", res
);
4572 cadbuf
[1] = highc(cadbuf
[1]);
4580 sasc_bug(struct obj
*op
, unsigned x
)