1 /* aNetHack 0.0.1 shk.c $ANH-Date: 1464138042 2016/05/25 01:00:42 $ $ANH-Branch: master $:$ANH-Revision: 1.132 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* aNetHack 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 (void) memset((genericptr_t
)tmp_dam
, 0, sizeof(struct damage
));
3311 tmp_dam
->when
= monstermoves
;
3312 tmp_dam
->place
.x
= x
;
3313 tmp_dam
->place
.y
= y
;
3314 tmp_dam
->cost
= cost
;
3315 tmp_dam
->typ
= levl
[x
][y
].typ
;
3316 tmp_dam
->next
= level
.damagelist
;
3317 level
.damagelist
= tmp_dam
;
3318 /* If player saw damage, display as a wall forever */
3320 levl
[x
][y
].seenv
= SVALL
;
3324 * Do something about damage. Either (!croaked) try to repair it, or
3325 * (croaked) just discard damage structs for non-shared locations, since
3326 * they'll never get repaired. Assume that shared locations will get
3327 * repaired eventually by the other shopkeeper(s). This might be an erroneous
3328 * assumption (they might all be dead too), but we have no reasonable way of
3333 remove_damage(shkp
, croaked
)
3337 struct damage
*tmp_dam
, *tmp2_dam
;
3338 boolean did_repair
= FALSE
, saw_door
= FALSE
, saw_floor
= FALSE
,
3339 stop_picking
= FALSE
, doorway_trap
= FALSE
;
3340 int saw_walls
= 0, saw_untrap
= 0;
3341 char trapmsg
[BUFSZ
];
3343 tmp_dam
= level
.damagelist
;
3346 register xchar x
= tmp_dam
->place
.x
, y
= tmp_dam
->place
.y
;
3349 unsigned old_doormask
= 0;
3352 Strcpy(shops
, in_rooms(x
, y
, SHOPBASE
));
3353 if (index(shops
, ESHK(shkp
)->shoproom
)) {
3354 if (IS_DOOR(levl
[x
][y
].typ
))
3355 old_doormask
= levl
[x
][y
].doormask
;
3358 disposition
= (shops
[1]) ? 0 : 1;
3359 else if (stop_picking
)
3360 disposition
= repair_damage(shkp
, tmp_dam
, FALSE
);
3362 /* Defer the stop_occupation() until after repair msgs */
3363 if (closed_door(x
, y
))
3364 stop_picking
= picking_at(x
, y
);
3365 disposition
= repair_damage(shkp
, tmp_dam
, FALSE
);
3367 stop_picking
= FALSE
;
3373 tmp_dam
= tmp_dam
->next
;
3377 if (disposition
> 1) {
3380 if (IS_WALL(levl
[x
][y
].typ
)) {
3382 } else if (IS_DOOR(levl
[x
][y
].typ
)
3383 /* an existing door here implies trap removal */
3384 && !(old_doormask
& (D_ISOPEN
| D_CLOSED
))) {
3386 } else if (disposition
== 3) { /* untrapped */
3388 if (IS_DOOR(levl
[x
][y
].typ
))
3389 doorway_trap
= TRUE
;
3396 tmp_dam
= tmp_dam
->next
;
3398 free((genericptr_t
) level
.damagelist
);
3399 level
.damagelist
= tmp_dam
;
3401 free((genericptr_t
) tmp2_dam
->next
);
3402 tmp2_dam
->next
= tmp_dam
;
3409 Sprintf(trapmsg
, "%s trap%s",
3410 (saw_untrap
> 3) ? "several" : (saw_untrap
> 1) ? "some"
3413 Sprintf(eos(trapmsg
), " %s", vtense(trapmsg
, "are"));
3414 Sprintf(eos(trapmsg
), " removed from the %s",
3415 (doorway_trap
&& saw_untrap
== 1) ? "doorway" : "floor");
3417 trapmsg
[0] = '\0'; /* not just lint suppression... */
3420 char wallbuf
[BUFSZ
];
3422 Sprintf(wallbuf
, "section%s", plur(saw_walls
));
3423 pline("Suddenly, %s %s of wall %s up!",
3424 (saw_walls
== 1) ? "a" : (saw_walls
<= 3) ? "some" : "several",
3425 wallbuf
, vtense(wallbuf
, "close"));
3428 pline_The("shop door reappears!");
3430 pline_The("floor is repaired!");
3432 pline("%s!", upstart(trapmsg
));
3434 if (saw_door
|| saw_floor
|| saw_untrap
)
3435 pline("Suddenly, %s%s%s%s%s!",
3436 saw_door
? "the shop door reappears" : "",
3437 (saw_door
&& saw_floor
) ? " and " : "",
3438 saw_floor
? "the floor damage is gone" : "",
3439 ((saw_door
|| saw_floor
) && *trapmsg
) ? " and " : "",
3441 else if (inside_shop(u
.ux
, u
.uy
) == ESHK(shkp
)->shoproom
)
3442 You_feel("more claustrophobic than before.");
3443 else if (!Deaf
&& !rn2(10))
3444 Norep("The dungeon acoustics noticeably change.");
3451 * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
3455 repair_damage(shkp
, tmp_dam
, catchup
)
3456 register struct monst
*shkp
;
3457 register struct damage
*tmp_dam
;
3458 boolean catchup
; /* restoring a level */
3460 register xchar x
, y
, i
;
3462 register struct monst
*mtmp
;
3463 register struct obj
*otmp
;
3464 register struct trap
*ttmp
;
3466 if ((monstermoves
- tmp_dam
->when
) < REPAIR_DELAY
)
3468 if (shkp
->msleeping
|| !shkp
->mcanmove
|| ESHK(shkp
)->following
)
3470 x
= tmp_dam
->place
.x
;
3471 y
= tmp_dam
->place
.y
;
3472 if (!IS_ROOM(tmp_dam
->typ
)) {
3473 if (x
== u
.ux
&& y
== u
.uy
)
3476 if (x
== shkp
->mx
&& y
== shkp
->my
)
3478 if ((mtmp
= m_at(x
, y
)) && (!passes_walls(mtmp
->data
)))
3481 if ((ttmp
= t_at(x
, y
)) != 0) {
3482 if (x
== u
.ux
&& y
== u
.uy
)
3485 if (ttmp
->ttyp
== LANDMINE
|| ttmp
->ttyp
== BEAR_TRAP
) {
3486 /* convert to an object */
3487 otmp
= mksobj((ttmp
->ttyp
== LANDMINE
) ? LAND_MINE
: BEARTRAP
,
3490 otmp
->owt
= weight(otmp
);
3491 (void) mpickobj(shkp
, otmp
);
3494 if (IS_DOOR(tmp_dam
->typ
) && !(levl
[x
][y
].doormask
& D_ISOPEN
)) {
3495 levl
[x
][y
].doormask
= D_CLOSED
;
3497 } else if (IS_WALL(tmp_dam
->typ
)) {
3498 levl
[x
][y
].typ
= tmp_dam
->typ
;
3504 if (IS_ROOM(tmp_dam
->typ
)) {
3505 /* No messages, because player already filled trap door */
3508 if ((tmp_dam
->typ
== levl
[x
][y
].typ
)
3509 && (!IS_DOOR(tmp_dam
->typ
) || (levl
[x
][y
].doormask
> D_BROKEN
)))
3510 /* No messages if player already replaced shop door */
3512 levl
[x
][y
].typ
= tmp_dam
->typ
;
3513 (void) memset((genericptr_t
) litter
, 0, sizeof(litter
));
3514 if ((otmp
= level
.objects
[x
][y
]) != 0) {
3515 /* Scatter objects haphazardly into the shop */
3516 #define NEED_UPDATE 1
3519 #define horiz(i) ((i % 3) - 1)
3520 #define vert(i) ((i / 3) - 1)
3521 for (i
= 0; i
< 9; i
++) {
3522 if ((i
== 4) || (!ZAP_POS(levl
[x
+ horiz(i
)][y
+ vert(i
)].typ
)))
3525 if (inside_shop(x
+ horiz(i
), y
+ vert(i
))
3526 == ESHK(shkp
)->shoproom
)
3527 litter
[i
] |= INSHOP
;
3529 if (Punished
&& !u
.uswallow
3530 && ((uchain
->ox
== x
&& uchain
->oy
== y
)
3531 || (uball
->ox
== x
&& uball
->oy
== y
))) {
3533 * Either the ball or chain is in the repair location.
3535 * Take the easy way out and put ball&chain under hero.
3537 if (!Deaf
&& !muteshk(shkp
))
3538 verbalize("Get your junk out of my wall!");
3539 unplacebc(); /* pick 'em up */
3540 placebc(); /* put 'em down */
3542 while ((otmp
= level
.objects
[x
][y
]) != 0)
3543 /* Don't mess w/ boulders -- just merge into wall */
3544 if ((otmp
->otyp
== BOULDER
) || (otmp
->otyp
== ROCK
)) {
3545 obj_extract_self(otmp
);
3546 obfree(otmp
, (struct obj
*) 0);
3548 while (!(litter
[i
= rn2(9)] & INSHOP
))
3550 remove_object(otmp
);
3551 place_object(otmp
, x
+ horiz(i
), y
+ vert(i
));
3552 litter
[i
] |= NEED_UPDATE
;
3556 return 1; /* repair occurred while off level */
3559 if (IS_DOOR(tmp_dam
->typ
)) {
3560 levl
[x
][y
].doormask
= D_CLOSED
; /* arbitrary */
3563 /* don't set doormask - it is (hopefully) the same as it was
3564 if not, perhaps save it with the damage array... */
3566 if (IS_WALL(tmp_dam
->typ
) && cansee(x
, y
)) {
3567 /* Player sees actual repair process, so they KNOW it's a wall */
3568 levl
[x
][y
].seenv
= SVALL
;
3571 /* Mark this wall as "repaired". There currently is no code
3572 to do anything about repaired walls, so don't do it. */
3574 for (i
= 0; i
< 9; i
++)
3575 if (litter
[i
] & NEED_UPDATE
)
3576 newsym(x
+ horiz(i
), y
+ vert(i
));
3586 * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
3590 register struct monst
*shkp
;
3592 register xchar gx
, gy
, omx
, omy
;
3594 register schar appr
;
3595 register struct eshk
*eshkp
= ESHK(shkp
);
3597 boolean uondoor
= FALSE
, satdoor
, avoid
= FALSE
, badinv
;
3603 remove_damage(shkp
, FALSE
);
3605 if ((udist
= distu(omx
, omy
)) < 3 && (shkp
->data
!= &mons
[PM_GRID_BUG
]
3606 || (omx
== u
.ux
|| omy
== u
.uy
))) {
3607 if (ANGRY(shkp
) || (Conflict
&& !resist(shkp
, RING_CLASS
, 0, 0))) {
3609 Your("displaced image doesn't fool %s!", shkname(shkp
));
3610 (void) mattacku(shkp
);
3613 if (eshkp
->following
) {
3614 if (strncmp(eshkp
->customer
, plname
, PL_NSIZ
)) {
3615 if (!Deaf
&& !muteshk(shkp
))
3616 verbalize("%s, %s! I was looking for %s.", Hello(shkp
),
3617 plname
, eshkp
->customer
);
3618 eshkp
->following
= 0;
3621 if (moves
> followmsg
+ 4) {
3622 if (!Deaf
&& !muteshk(shkp
))
3623 verbalize("%s, %s! Didn't you forget to pay?",
3624 Hello(shkp
), plname
);
3626 pline("%s holds out %s upturned %s.",
3629 mbodypart(shkp
, HAND
));
3632 pline("%s doesn't like customers who don't pay.",
3645 satdoor
= (gx
== omx
&& gy
== omy
);
3646 if (eshkp
->following
|| ((z
= holetime()) >= 0 && z
* z
<= udist
)) {
3647 /* [This distance check used to apply regardless of
3648 whether the shk was following, but that resulted in
3649 m_move() sometimes taking the shk out of the shop if
3650 the player had fenced him in with boulders or traps.
3651 Such voluntary abandonment left unpaid objects in
3652 invent, triggering billing impossibilities on the
3653 next level once the character fell through the hole.] */
3654 if (udist
> 4 && eshkp
->following
&& !eshkp
->billct
)
3655 return -1; /* leave it to m_move */
3658 } else if (ANGRY(shkp
)) {
3659 /* Move towards the hero if the shopkeeper can see him. */
3660 if (shkp
->mcansee
&& m_canseeu(shkp
)) {
3666 #define GDIST(x, y) (dist2(x, y, gx, gy))
3667 if (Invis
|| u
.usteed
) {
3670 uondoor
= (u
.ux
== eshkp
->shd
.x
&& u
.uy
== eshkp
->shd
.y
);
3673 (carrying(PICK_AXE
) || carrying(DWARVISH_MATTOCK
)
3674 || (Fast
&& (sobj_at(PICK_AXE
, u
.ux
, u
.uy
)
3675 || sobj_at(DWARVISH_MATTOCK
, u
.ux
, u
.uy
))));
3676 if (satdoor
&& badinv
)
3680 avoid
= (*u
.ushops
&& distu(gx
, gy
) > 8);
3684 if (((!eshkp
->robbed
&& !eshkp
->billct
&& !eshkp
->debit
) || avoid
)
3685 && GDIST(omx
, omy
) < 3) {
3686 if (!badinv
&& !onlineu(omx
, omy
))
3694 z
= move_special(shkp
, inhishop(shkp
), appr
, uondoor
, avoid
, omx
, omy
, gx
,
3697 after_shk_move(shkp
);
3702 /* called after shopkeeper moves, in case themove causes re-entry into shop */
3704 after_shk_move(shkp
)
3707 struct eshk
*eshkp
= ESHK(shkp
);
3709 if (eshkp
->bill_p
== (struct bill_x
*) -1000 && inhishop(shkp
)) {
3710 /* reset bill_p, need to re-calc player's occupancy too */
3711 eshkp
->bill_p
= &eshkp
->bill
[0];
3712 check_special_room(FALSE
);
3716 /* for use in levl_follower (mondata.c) */
3719 register struct monst
*mtmp
;
3721 return (boolean
) (mtmp
->isshk
&& ESHK(mtmp
)->following
);
3724 /* You are digging in the shop. */
3729 register struct monst
*shkp
= shop_keeper(*u
.ushops
);
3731 const char *grabs
= "grabs";
3736 /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */
3738 if (shkp
->msleeping
|| !shkp
->mcanmove
|| is_silent(shkp
->data
))
3739 ; /* lang stays 0 */
3740 else if (shkp
->data
->msound
<= MS_ANIMAL
)
3742 else if (shkp
->data
->msound
>= MS_HUMANOID
)
3745 if (!inhishop(shkp
)) {
3746 if (Role_if(PM_KNIGHT
)) {
3747 You_feel("like a common thief.");
3748 adjalign(-sgn(u
.ualign
.type
));
3755 if (!Deaf
&& !muteshk(shkp
)) {
3756 if (u
.utraptype
== TT_PIT
)
3758 "Be careful, %s, or you might fall through the floor.",
3759 flags
.female
? "madam" : "sir");
3761 verbalize("%s, do not damage the floor here!",
3762 flags
.female
? "Madam" : "Sir");
3765 if (Role_if(PM_KNIGHT
)) {
3766 You_feel("like a common thief.");
3767 adjalign(-sgn(u
.ualign
.type
));
3769 } else if (!um_dist(shkp
->mx
, shkp
->my
, 5)
3770 && !shkp
->msleeping
&& shkp
->mcanmove
3771 && (ESHK(shkp
)->billct
|| ESHK(shkp
)->debit
)) {
3772 register struct obj
*obj
, *obj2
;
3774 if (nolimbs(shkp
->data
)) {
3775 grabs
= "knocks off";
3777 /* This is what should happen, but for balance
3778 * reasons, it isn't currently.
3781 pline("%s curses %s inability to grab your backpack!",
3782 shkname(shkp
), mhim(shkp
));
3787 if (distu(shkp
->mx
, shkp
->my
) > 2) {
3789 /* for some reason the shopkeeper can't come next to you */
3790 if (distu(shkp
->mx
, shkp
->my
) > 2) {
3792 pline("%s curses you in anger and frustration!",
3799 pline("%s %s, and %s your backpack!", shkname(shkp
),
3800 makeplural(locomotion(shkp
->data
, "leap")), grabs
);
3802 pline("%s %s your backpack!", shkname(shkp
), grabs
);
3804 for (obj
= invent
; obj
; obj
= obj2
) {
3806 if ((obj
->owornmask
& ~(W_SWAPWEP
| W_QUIVER
)) != 0
3807 || (obj
== uswapwep
&& u
.twoweap
)
3808 || (obj
->otyp
== LEASH
&& obj
->leashmon
))
3810 if (obj
== current_wand
)
3814 subfrombill(obj
, shkp
);
3815 (void) add_to_minv(shkp
, obj
); /* may free obj */
3824 static const short k_mndx
[4] = { PM_KEYSTONE_KOP
, PM_KOP_SERGEANT
,
3825 PM_KOP_LIEUTENANT
, PM_KOP_KAPTAIN
};
3826 int k_cnt
[4], cnt
, mndx
, k
;
3828 k_cnt
[0] = cnt
= abs(depth(&u
.uz
)) + rnd(5);
3829 k_cnt
[1] = (cnt
/ 3) + 1; /* at least one sarge */
3830 k_cnt
[2] = (cnt
/ 6); /* maybe a lieutenant */
3831 k_cnt
[3] = (cnt
/ 9); /* and maybe a kaptain */
3833 for (k
= 0; k
< 4; k
++) {
3834 if ((cnt
= k_cnt
[k
]) == 0)
3837 if (mvitals
[mndx
].mvflags
& G_GONE
)
3841 if (enexto(mm
, mm
->x
, mm
->y
, &mons
[mndx
]))
3842 (void) makemon(&mons
[mndx
], mm
->x
, mm
->y
, NO_MM_FLAGS
);
3847 pay_for_damage(dmgstr
, cant_mollify
)
3849 boolean cant_mollify
;
3851 register struct monst
*shkp
= (struct monst
*) 0;
3852 char shops_affected
[5];
3853 register boolean uinshp
= (*u
.ushops
!= '\0');
3855 register xchar x
, y
;
3856 boolean dugwall
= (!strcmp(dmgstr
, "dig into") /* wand */
3857 || !strcmp(dmgstr
, "damage")); /* pick-axe */
3858 boolean animal
, pursue
;
3859 struct damage
*tmp_dam
, *appear_here
= 0;
3860 /* any number >= (80*80)+(24*24) would do, actually */
3861 long cost_of_damage
= 0L;
3862 unsigned int nearest_shk
= 7000, nearest_damage
= 7000;
3865 for (tmp_dam
= level
.damagelist
;
3866 (tmp_dam
&& (tmp_dam
->when
== monstermoves
));
3867 tmp_dam
= tmp_dam
->next
) {
3872 cost_of_damage
+= tmp_dam
->cost
;
3873 Strcpy(shops_affected
,
3874 in_rooms(tmp_dam
->place
.x
, tmp_dam
->place
.y
, SHOPBASE
));
3875 for (shp
= shops_affected
; *shp
; shp
++) {
3876 struct monst
*tmp_shk
;
3877 unsigned int shk_distance
;
3879 if (!(tmp_shk
= shop_keeper(*shp
)))
3881 if (tmp_shk
== shkp
) {
3882 unsigned int damage_distance
=
3883 distu(tmp_dam
->place
.x
, tmp_dam
->place
.y
);
3885 if (damage_distance
< nearest_damage
) {
3886 nearest_damage
= damage_distance
;
3887 appear_here
= tmp_dam
;
3891 if (!inhishop(tmp_shk
))
3893 shk_distance
= distu(tmp_shk
->mx
, tmp_shk
->my
);
3894 if (shk_distance
> nearest_shk
)
3896 if ((shk_distance
== nearest_shk
) && picks
) {
3902 nearest_shk
= shk_distance
;
3903 appear_here
= tmp_dam
;
3904 nearest_damage
= distu(tmp_dam
->place
.x
, tmp_dam
->place
.y
);
3908 if (!cost_of_damage
|| !shkp
)
3911 animal
= (shkp
->data
->msound
<= MS_ANIMAL
);
3913 x
= appear_here
->place
.x
;
3914 y
= appear_here
->place
.y
;
3916 /* not the best introduction to the shk... */
3917 (void) strncpy(ESHK(shkp
)->customer
, plname
, PL_NSIZ
);
3919 /* if the shk is already on the war path, be sure it's all out */
3920 if (ANGRY(shkp
) || ESHK(shkp
)->following
) {
3925 /* if the shk is not in their shop.. */
3926 if (!*in_rooms(shkp
->mx
, shkp
->my
, SHOPBASE
)) {
3927 if (!cansee(shkp
->mx
, shkp
->my
))
3934 if (um_dist(shkp
->mx
, shkp
->my
, 1)
3935 && !um_dist(shkp
->mx
, shkp
->my
, 3)) {
3936 pline("%s leaps towards you!", shkname(shkp
));
3939 pursue
= um_dist(shkp
->mx
, shkp
->my
, 1);
3944 * Make shkp show up at the door. Effect: If there is a monster
3945 * in the doorway, have the hero hear the shopkeeper yell a bit,
3946 * pause, then have the shopkeeper appear at the door, having
3947 * yanked the hapless critter out of the way.
3951 if (!Deaf
&& !muteshk(shkp
)) {
3952 You_hear("an angry voice:");
3953 verbalize("Out of my way, scum!");
3956 #if defined(UNIX) || defined(VMS)
3957 #if defined(SYSV) || defined(ULTRIX) || defined(VMS)
3966 (void) mnearto(shkp
, x
, y
, TRUE
);
3969 if ((um_dist(x
, y
, 1) && !uinshp
) || cant_mollify
3970 || (money_cnt(invent
) + ESHK(shkp
)->credit
) < cost_of_damage
3973 if (muteshk(shkp
)) {
3974 if (animal
&& shkp
->mcanmove
&& !shkp
->msleeping
)
3976 } else if (pursue
|| uinshp
|| !um_dist(x
, y
, 1)) {
3978 verbalize("How dare you %s my %s?", dmgstr
,
3979 dugwall
? "shop" : "door");
3981 pline("%s is %s that you decided to %s %s %s!",
3982 Shknam(shkp
), angrytexts
[rn2(SIZE(angrytexts
))],
3983 dmgstr
, mhis(shkp
), dugwall
? "shop" : "door");
3986 pline("%s shouts:", shkname(shkp
));
3987 verbalize("Who dared %s my %s?", dmgstr
,
3988 dugwall
? "shop" : "door");
3990 pline("%s is %s that someone decided to %s %s %s!",
3991 Shknam(shkp
), angrytexts
[rn2(SIZE(angrytexts
))],
3992 dmgstr
, mhis(shkp
), dugwall
? "shop" : "door");
4000 Your("invisibility does not fool %s!", shkname(shkp
));
4001 Sprintf(qbuf
, "%sYou did %ld %s worth of damage!%s Pay?",
4002 !animal
? cad(TRUE
) : "", cost_of_damage
,
4003 currency(cost_of_damage
), !animal
? "\"" : "");
4004 if (yn(qbuf
) != 'n') {
4005 cost_of_damage
= check_credit(cost_of_damage
, shkp
);
4006 money2mon(shkp
, cost_of_damage
);
4008 pline("Mollified, %s accepts your restitution.", shkname(shkp
));
4009 /* move shk back to his home loc */
4010 home_shk(shkp
, FALSE
);
4014 if (!Deaf
&& !muteshk(shkp
))
4015 verbalize("Oh, yes! You'll pay!");
4017 pline("%s lunges %s %s toward your %s!",
4020 mbodypart(shkp
, HAND
),
4025 adjalign(-sgn(u
.ualign
.type
));
4029 /* called in dokick.c when we kick an object that might be in a store */
4032 register xchar x
, y
;
4037 if (!level
.flags
.has_shop
)
4039 shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
));
4040 if (!shkp
|| !inhishop(shkp
))
4043 return (boolean
) (inside_shop(x
, y
)
4044 && !(x
== eshkp
->shk
.x
&& y
== eshkp
->shk
.y
));
4047 /* called by dotalk(sounds.c) when #chatting; returns obj if location
4048 contains shop goods and shopkeeper is willing & able to speak */
4051 register xchar x
, y
;
4053 register struct obj
*otmp
;
4054 register struct monst
*shkp
;
4056 if (!(shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
))) || !inhishop(shkp
))
4057 return (struct obj
*) 0;
4059 for (otmp
= level
.objects
[x
][y
]; otmp
; otmp
= otmp
->nexthere
)
4060 if (otmp
->oclass
!= COIN_CLASS
)
4062 /* note: otmp might have ->no_charge set, but that's ok */
4063 return (otmp
&& costly_spot(x
, y
)
4064 && NOTANGRY(shkp
) && shkp
->mcanmove
&& !shkp
->msleeping
)
4069 /* give price quotes for all objects linked to this one (ie, on this spot) */
4071 price_quote(first_obj
)
4072 register struct obj
*first_obj
;
4074 register struct obj
*otmp
;
4075 char buf
[BUFSZ
], price
[40];
4078 boolean contentsonly
= FALSE
;
4080 struct monst
*shkp
= shop_keeper(inside_shop(u
.ux
, u
.uy
));
4082 tmpwin
= create_nhwindow(NHW_MENU
);
4083 putstr(tmpwin
, 0, "Fine goods for sale:");
4084 putstr(tmpwin
, 0, "");
4085 for (otmp
= first_obj
; otmp
; otmp
= otmp
->nexthere
) {
4086 if (otmp
->oclass
== COIN_CLASS
)
4088 cost
= (otmp
->no_charge
|| otmp
== uball
|| otmp
== uchain
)
4090 : get_cost(otmp
, (struct monst
*) 0);
4091 contentsonly
= !cost
;
4092 if (Has_contents(otmp
))
4093 cost
+= contained_cost(otmp
, shkp
, 0L, FALSE
, FALSE
);
4095 Strcpy(price
, "no charge");
4096 contentsonly
= FALSE
;
4098 Sprintf(price
, "%ld %s%s", cost
, currency(cost
),
4099 (otmp
->quan
) > 1L ? " each" : "");
4101 Sprintf(buf
, "%s%s, %s", contentsonly
? the_contents_of
: "",
4102 doname(otmp
), price
);
4103 putstr(tmpwin
, 0, buf
), cnt
++;
4106 display_nhwindow(tmpwin
, TRUE
);
4107 } else if (cnt
== 1) {
4109 /* "<doname(obj)>, no charge" */
4110 pline("%s!", upstart(buf
)); /* buf still contains the string */
4112 /* print cost in slightly different format, so can't reuse buf;
4113 cost and contentsonly are already set up */
4114 Sprintf(buf
, "%s%s", contentsonly
? the_contents_of
: "",
4116 pline("%s, price %ld %s%s%s", upstart(buf
), cost
, currency(cost
),
4117 (first_obj
->quan
> 1L) ? " each" : "",
4118 contentsonly
? "." : shk_embellish(first_obj
, cost
));
4121 destroy_nhwindow(tmpwin
);
4124 STATIC_OVL
const char *
4125 shk_embellish(itm
, cost
)
4126 register struct obj
*itm
;
4130 register int o
, choice
= rn2(5);
4133 choice
= (cost
< 100L ? 1 : cost
< 500L ? 2 : 3);
4140 if (o
== FOOD_CLASS
)
4141 return ", gourmets' delight!";
4142 if (objects
[itm
->otyp
].oc_name_known
4143 ? objects
[itm
->otyp
].oc_magic
4144 : (o
== AMULET_CLASS
|| o
== RING_CLASS
|| o
== WAND_CLASS
4145 || o
== POTION_CLASS
|| o
== SCROLL_CLASS
4146 || o
== SPBOOK_CLASS
))
4147 return ", painstakingly developed!";
4148 return ", superb craftsmanship!";
4150 return ", finest quality.";
4152 return ", an excellent choice.";
4154 return ", a real bargain.";
4158 } else if (itm
->oartifact
) {
4159 return ", one of a kind!";
4164 /* First 4 supplied by Ronen and Tamar, remainder by development team */
4165 const char *Izchak_speaks
[] = {
4166 "%s says: 'These shopping malls give me a headache.'",
4167 "%s says: 'Slow down. Think clearly.'",
4168 "%s says: 'You need to take things one at a time.'",
4169 "%s says: 'I don't like poofy coffee... give me Columbian Supremo.'",
4170 "%s says that getting the devteam's agreement on anything is difficult.",
4171 "%s says that he has noticed those who serve their deity will prosper.",
4172 "%s says: 'Don't try to steal from me - I have friends in high places!'",
4173 "%s says: 'You may well need something from this shop in the future.'",
4174 "%s comments about the Valley of the Dead as being a gateway."
4185 /* The monster type is shopkeeper, but this monster is
4186 not actually a shk, which could happen if someone
4187 wishes for a shopkeeper statue and then animates it.
4188 (Note: shkname() would be "" in a case like this.) */
4189 pline("%s asks whether you've seen any untended shops recently.",
4191 /* [Perhaps we ought to check whether this conversation
4192 is taking place inside an untended shop, but a shopless
4193 shk can probably be expected to be rather disoriented.] */
4199 pline("%s %s how much %s dislikes %s customers.",
4201 (!Deaf
&& !muteshk(shkp
)) ? "mentions" : "indicates",
4202 mhe(shkp
), eshk
->robbed
? "non-paying" : "rude");
4203 } else if (eshk
->following
) {
4204 if (strncmp(eshk
->customer
, plname
, PL_NSIZ
)) {
4205 if (!Deaf
&& !muteshk(shkp
))
4206 verbalize("%s %s! I was looking for %s.",
4207 Hello(shkp
), plname
, eshk
->customer
);
4208 eshk
->following
= 0;
4210 if (!Deaf
&& !muteshk(shkp
))
4211 verbalize("%s %s! Didn't you forget to pay?",
4212 Hello(shkp
), plname
);
4214 pline("%s taps you on the %s.",
4215 Shknam(shkp
), body_part(ARM
));
4217 } else if (eshk
->billct
) {
4218 register long total
= addupbill(shkp
) + eshk
->debit
;
4220 pline("%s %s that your bill comes to %ld %s.",
4222 (!Deaf
&& !muteshk(shkp
)) ? "says" : "indicates",
4223 total
, currency(total
));
4224 } else if (eshk
->debit
) {
4225 pline("%s %s that you owe %s %ld %s.",
4227 (!Deaf
&& !muteshk(shkp
)) ? "reminds you" : "indicates",
4228 mhim(shkp
), eshk
->debit
, currency(eshk
->debit
));
4229 } else if (eshk
->credit
) {
4230 pline("%s encourages you to use your %ld %s of credit.",
4231 shkname(shkp
), eshk
->credit
, currency(eshk
->credit
));
4232 } else if (eshk
->robbed
) {
4233 pline("%s %s about a recent robbery.",
4235 (!Deaf
&& !muteshk(shkp
)) ? "complains" : "indicates concern");
4236 } else if ((shkmoney
= money_cnt(shkp
->minvent
)) < 50L) {
4237 pline("%s %s that business is bad.",
4239 (!Deaf
&& !muteshk(shkp
)) ? "complains" : "indicates");
4240 } else if (shkmoney
> 4000) {
4241 pline("%s %s that business is good.",
4243 (!Deaf
&& !muteshk(shkp
)) ? "says" : "indicates");
4244 } else if (is_izchak(shkp
, FALSE
)) {
4245 if (!Deaf
&& !muteshk(shkp
))
4246 pline(Izchak_speaks
[rn2(SIZE(Izchak_speaks
))], shkname(shkp
));
4248 if (!Deaf
&& !muteshk(shkp
))
4249 pline("%s talks about the problem of shoplifters.", shkname(shkp
));
4257 register int cnt
= 0;
4258 register struct monst
*mtmp
, *mtmp2
;
4260 for (mtmp
= fmon
; mtmp
; mtmp
= mtmp2
) {
4262 if (mtmp
->data
->mlet
== S_KOP
) {
4263 if (canspotmon(mtmp
))
4269 pline_The("Kop%s (disappointed) vanish%s into thin air.",
4270 plur(cnt
), (cnt
== 1) ? "es" : "");
4274 cost_per_charge(shkp
, otmp
, altusage
)
4277 boolean altusage
; /* some items have an "alternate" use with different cost */
4281 if (!shkp
|| !inhishop(shkp
))
4282 return 0L; /* insurance */
4283 tmp
= get_cost(otmp
, shkp
);
4285 /* The idea is to make the exhaustive use of an unpaid item
4286 * more expensive than buying it outright.
4288 if (otmp
->otyp
== MAGIC_LAMP
) { /* 1 */
4289 /* normal use (ie, as light source) of a magic lamp never
4290 degrades its value, but not charging anything would make
4291 identification too easy; charge an amount comparable to
4292 what is charged for an ordinary lamp (don't bother with
4293 angry shk surcharge) */
4295 tmp
= (long) objects
[OIL_LAMP
].oc_cost
;
4297 tmp
+= tmp
/ 3L; /* djinni is being released */
4298 } else if (otmp
->otyp
== MAGIC_MARKER
) { /* 70 - 100 */
4299 /* No way to determine in advance how many charges will be
4300 * wasted. So, arbitrarily, one half of the price per use.
4303 } else if (otmp
->otyp
== BAG_OF_TRICKS
/* 1 - 20 */
4304 || otmp
->otyp
== HORN_OF_PLENTY
) {
4305 /* altusage: emptying of all the contents at once */
4308 } else if (otmp
->otyp
== CRYSTAL_BALL
/* 1 - 5 */
4309 || otmp
->otyp
== OIL_LAMP
/* 1 - 10 */
4310 || otmp
->otyp
== BRASS_LANTERN
4311 || (otmp
->otyp
>= MAGIC_FLUTE
4312 && otmp
->otyp
<= DRUM_OF_EARTHQUAKE
) /* 5 - 9 */
4313 || otmp
->oclass
== WAND_CLASS
) { /* 3 - 11 */
4316 } else if (otmp
->oclass
== SPBOOK_CLASS
) {
4318 } else if (otmp
->otyp
== CAN_OF_GREASE
|| otmp
->otyp
== TINNING_KIT
4319 || otmp
->otyp
== EXPENSIVE_CAMERA
) {
4321 } else if (otmp
->otyp
== POT_OIL
) {
4327 /* Charge the player for partial use of an unpaid object.
4329 * Note that bill_dummy_object() should be used instead
4330 * when an object is completely used.
4333 check_unpaid_usage(otmp
, altusage
)
4338 const char *fmt
, *arg1
, *arg2
;
4342 if (!otmp
->unpaid
|| !*u
.ushops
4343 || (otmp
->spe
<= 0 && objects
[otmp
->otyp
].oc_charged
))
4345 if (!(shkp
= shop_keeper(*u
.ushops
)) || !inhishop(shkp
))
4347 if ((tmp
= cost_per_charge(shkp
, otmp
, altusage
)) == 0L)
4351 if (otmp
->oclass
== SPBOOK_CLASS
) {
4352 fmt
= "%sYou owe%s %ld %s.";
4353 Sprintf(buf
, "This is no free library, %s! ", cad(FALSE
));
4354 arg1
= rn2(2) ? buf
: "";
4355 arg2
= ESHK(shkp
)->debit
> 0L ? " an additional" : "";
4356 } else if (otmp
->otyp
== POT_OIL
) {
4357 fmt
= "%s%sThat will cost you %ld %s (Yendorian Fuel Tax).";
4358 } else if (altusage
&& (otmp
->otyp
== BAG_OF_TRICKS
4359 || otmp
->otyp
== HORN_OF_PLENTY
)) {
4360 fmt
= "%s%sEmptying that will cost you %ld %s.";
4364 arg1
= "Watch it! ";
4366 fmt
= "%s%sUsage fee, %ld %s.";
4373 if (!Deaf
&& !muteshk(shkp
)) {
4374 verbalize(fmt
, arg1
, arg2
, tmp
, currency(tmp
));
4375 exercise(A_WIS
, TRUE
); /* you just got info */
4377 ESHK(shkp
)->debit
+= tmp
;
4380 /* for using charges of unpaid objects "used in the normal manner" */
4385 check_unpaid_usage(otmp
, FALSE
); /* normal item use */
4389 costly_gold(x
, y
, amount
)
4390 register xchar x
, y
;
4391 register long amount
;
4393 register long delta
;
4394 register struct monst
*shkp
;
4395 register struct eshk
*eshkp
;
4397 if (!costly_spot(x
, y
))
4399 /* shkp now guaranteed to exist by costly_spot() */
4400 shkp
= shop_keeper(*in_rooms(x
, y
, SHOPBASE
));
4403 if (eshkp
->credit
>= amount
) {
4404 if (eshkp
->credit
> amount
)
4405 Your("credit is reduced by %ld %s.", amount
, currency(amount
));
4407 Your("credit is erased.");
4408 eshkp
->credit
-= amount
;
4410 delta
= amount
- eshkp
->credit
;
4412 Your("credit is erased.");
4414 Your("debt increases by %ld %s.", delta
, currency(delta
));
4416 You("owe %s %ld %s.", shkname(shkp
), delta
, currency(delta
));
4417 eshkp
->debit
+= delta
;
4418 eshkp
->loan
+= delta
;
4423 /* used in domove to block diagonal shop-exit */
4424 /* x,y should always be a door */
4427 register xchar x
, y
;
4429 register int roomno
= *in_rooms(x
, y
, SHOPBASE
);
4430 register struct monst
*shkp
;
4432 if (roomno
< 0 || !IS_SHOP(roomno
))
4434 if (!IS_DOOR(levl
[x
][y
].typ
))
4436 if (roomno
!= *u
.ushops
)
4439 if (!(shkp
= shop_keeper((char) roomno
)) || !inhishop(shkp
))
4442 if (shkp
->mx
== ESHK(shkp
)->shk
.x
&& shkp
->my
== ESHK(shkp
)->shk
.y
4443 /* Actually, the shk should be made to block _any_
4444 * door, including a door the player digs, if the
4445 * shk is within a 'jumping' distance.
4447 && ESHK(shkp
)->shd
.x
== x
4448 && ESHK(shkp
)->shd
.y
== y
4449 && shkp
->mcanmove
&& !shkp
->msleeping
4450 && (ESHK(shkp
)->debit
|| ESHK(shkp
)->billct
|| ESHK(shkp
)->robbed
)) {
4451 pline("%s%s blocks your way!", shkname(shkp
),
4452 Invis
? " senses your motion and" : "");
4458 /* used in domove to block diagonal shop-entry;
4459 u.ux, u.uy should always be a door */
4462 register xchar x
, y
;
4464 register xchar sx
, sy
;
4465 register int roomno
;
4466 register struct monst
*shkp
;
4468 if (!(IS_DOOR(levl
[u
.ux
][u
.uy
].typ
)
4469 && levl
[u
.ux
][u
.uy
].doormask
== D_BROKEN
))
4472 roomno
= *in_rooms(x
, y
, SHOPBASE
);
4473 if (roomno
< 0 || !IS_SHOP(roomno
))
4475 if (!(shkp
= shop_keeper((char) roomno
)) || !inhishop(shkp
))
4478 if (ESHK(shkp
)->shd
.x
!= u
.ux
|| ESHK(shkp
)->shd
.y
!= u
.uy
)
4481 sx
= ESHK(shkp
)->shk
.x
;
4482 sy
= ESHK(shkp
)->shk
.y
;
4484 if (shkp
->mx
== sx
&& shkp
->my
== sy
&& shkp
->mcanmove
&& !shkp
->msleeping
4485 && (x
== sx
- 1 || x
== sx
+ 1 || y
== sy
- 1 || y
== sy
+ 1)
4486 && (Invis
|| carrying(PICK_AXE
) || carrying(DWARVISH_MATTOCK
)
4488 pline("%s%s blocks your way!", shkname(shkp
),
4489 Invis
? " senses your motion and" : "");
4495 /* "your " or "Foobar's " (note the trailing space) */
4501 if (!shk_owns(buf
, obj
) && !mon_owns(buf
, obj
))
4502 Strcpy(buf
, the_your
[carried(obj
) ? 1 : 0]);
4503 return strcat(buf
, " ");
4511 (void) shk_your(buf
, obj
);
4524 if (get_obj_location(obj
, &x
, &y
, 0)
4525 && (obj
->unpaid
|| (obj
->where
== OBJ_FLOOR
&& !obj
->no_charge
4526 && costly_spot(x
, y
)))) {
4527 shkp
= shop_keeper(inside_shop(x
, y
));
4528 return strcpy(buf
, shkp
? s_suffix(shkname(shkp
)) : the_your
[0]);
4538 if (obj
->where
== OBJ_MINVENT
)
4539 return strcpy(buf
, s_suffix(y_monnam(obj
->ocarry
)));
4543 STATIC_OVL
const char *
4545 boolean altusage
; /* used as a verbalized exclamation: \"Cad! ...\" */
4547 const char *res
= 0;
4549 switch (is_demon(youmonst
.data
) ? 3 : poly_gender()) {
4563 impossible("cad: unknown gender");
4568 char *cadbuf
= mon_nam(&youmonst
); /* snag an output buffer */
4570 /* alternate usage adds a leading double quote and trailing
4571 exclamation point plus sentence separating spaces */
4572 Sprintf(cadbuf
, "\"%s! ", res
);
4573 cadbuf
[1] = highc(cadbuf
[1]);
4581 sasc_bug(struct obj
*op
, unsigned x
)