1 /* $NetBSD: hack.shk.c,v 1.14 2012/06/19 05:46:08 dholland Exp $ */
4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * - Neither the name of the Stichting Centrum voor Wiskunde en
20 * Informatica, nor the names of its contributors may be used to endorse or
21 * promote products derived from this software without specific prior
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39 * All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 static void setpaid(void);
70 static void addupbill(void);
71 static void findshk(int);
72 static struct bill_x *onbill(struct obj *);
73 static void pay(long, struct monst *);
74 static int dopayobj(struct bill_x *);
75 static struct obj *bp_to_obj(struct bill_x *);
76 static int getprice(struct obj *);
77 static int realhunger(void);
82 struct monst *shopkeeper = 0;
83 struct obj *billobjs = 0;
85 obfree(struct obj *obj, struct obj *merge)
98 addtobill(struct obj *obj)
102 subfrombill(struct obj *obj)
106 splitbill(struct obj *o1, struct obj *o2)
124 shkdead(struct monst *m)
128 shkcatch(struct obj *obj)
133 shk_move(struct monst *m)
138 replshk(struct monst *mtmp, struct monst *mtmp2)
142 shkname(struct monst *m)
148 #include "hack.mfndpos.h"
149 #include "def.mkroom.h"
150 #include "def.eshk.h"
152 #define ESHK(mon) ((struct eshk *)(&(mon->mextra[0])))
153 #define NOTANGRY(mon) mon->mpeaceful
154 #define ANGRY(mon) !NOTANGRY(mon)
157 * Descriptor of current shopkeeper. Note that the bill need not be
158 * per-shopkeeper, since it is valid only when in a shop.
160 static struct monst *shopkeeper = 0;
161 static struct bill_x *bill;
162 static int shlevel = 0; /* level of this shopkeeper */
163 struct obj *billobjs; /* objects on bill with bp->useup */
164 /* only accessed here and by save & restore */
165 static long int total; /* filled by addupbill() */
166 static long int followmsg; /* last time of follow message */
169 invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
170 obj->quan <= bp->bquan
174 const char shtypes[] = { /* 8 shoptypes: 7 specialized, 1 mixed */
175 RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM,
176 POTION_SYM, ARMOR_SYM, 0
179 static const char *const shopnam[] = {
180 "engagement ring", "walking cane", "antique weapon",
181 "delicatessen", "second hand book", "liquor",
182 "used armor", "assorted antiques"
186 shkname(struct monst *mtmp) /* called in do_name.c */
188 return (ESHK(mtmp)->shknam);
192 shkdead(struct monst *mtmp) /* called in mon.c */
194 struct eshk *eshk = ESHK(mtmp);
196 if (eshk->shoplevel == dlevel)
197 rooms[eshk->shoproom].rtype = 0;
198 if (mtmp == shopkeeper) {
201 bill = (struct bill_x *) - 1000; /* dump core when
207 replshk(struct monst *mtmp, struct monst *mtmp2)
209 if (mtmp == shopkeeper) {
211 bill = &(ESHK(shopkeeper)->bill[0]);
217 { /* caller has checked that shopkeeper exists */
218 /* either we paid or left the shop or he just died */
221 for (obj = invent; obj; obj = obj->nobj)
223 for (obj = fobj; obj; obj = obj->nobj)
225 for (obj = fcobj; obj; obj = obj->nobj)
227 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
228 for (obj = mtmp->minvent; obj; obj = obj->nobj)
230 for (mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
231 for (obj = mtmp->minvent; obj; obj = obj->nobj)
233 while ((obj = billobjs) != NULL) {
234 billobjs = obj->nobj;
237 ESHK(shopkeeper)->billct = 0;
242 { /* delivers result in total */
243 /* caller has checked that shopkeeper exists */
244 int ct = ESHK(shopkeeper)->billct;
245 struct bill_x *bp = bill;
248 total += bp->price * bp->bquan;
256 int roomno = inroom(u.ux, u.uy);
258 /* Did we just leave a shop? */
260 (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
262 if (ESHK(shopkeeper)->billct) {
263 if (inroom(shopkeeper->mx, shopkeeper->my)
264 == u.uinshop - 1) /* ab@unido */
265 pline("Somehow you escaped the shop without paying!");
267 pline("You stole for a total worth of %ld zorkmids.",
269 ESHK(shopkeeper)->robbed += total;
271 if ((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)
273 ESHK(shopkeeper)->following = 1;
280 /* Did we just enter a zoo of some kind? */
282 int rt = rooms[roomno].rtype;
285 pline("Welcome to David's treasure zoo!");
286 } else if (rt == SWAMP) {
287 pline("It looks rather muddy down here.");
288 } else if (rt == MORGUE) {
290 pline("Go away! Go away!");
292 pline("You get an uncanny feeling ...");
296 rooms[roomno].rtype = 0;
297 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
298 if (rt != ZOO || !rn2(3))
302 /* Did we just enter a shop? */
303 if (roomno >= 0 && rooms[roomno].rtype >= 8) {
304 if (shlevel != dlevel || !shopkeeper
305 || ESHK(shopkeeper)->shoproom != roomno)
308 rooms[roomno].rtype = 0;
310 } else if (!u.uinshop) {
311 if (!ESHK(shopkeeper)->visitct ||
312 strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)) {
314 /* He seems to be new here */
315 ESHK(shopkeeper)->visitct = 0;
316 ESHK(shopkeeper)->following = 0;
317 (void) strncpy(ESHK(shopkeeper)->customer, plname, PL_NSIZ);
318 NOTANGRY(shopkeeper) = 1;
320 if (!ESHK(shopkeeper)->following) {
323 pline("Hello %s! Welcome%s to %s's %s shop!",
325 ESHK(shopkeeper)->visitct++ ? " again" : "",
327 shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]);
328 box = carrying(ICE_BOX);
329 pick = carrying(PICK_AXE);
331 if (dochug(shopkeeper)) {
332 u.uinshop = 0; /* he died moving */
335 pline("Will you please leave your %s outside?",
336 (box && pick) ? "box and pick-axe" :
337 box ? "box" : "pick-axe");
340 u.uinshop = roomno + 1;
350 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
351 if (mtmp->isshk && ESHK(mtmp)->shoproom == roomno
352 && ESHK(mtmp)->shoplevel == dlevel) {
354 bill = &(ESHK(shopkeeper)->bill[0]);
356 if (ANGRY(shopkeeper) &&
357 strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ))
358 NOTANGRY(shopkeeper) = 1;
360 * billobjs = 0; -- this is wrong if we save in a
364 * (and it is harmless to have too many things in
371 bill = (struct bill_x *) - 1000; /* dump core when referenced */
374 static struct bill_x *
375 onbill(struct obj *obj)
380 for (bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
381 if (bp->bo_id == obj->o_id) {
383 pline("onbill: paid obj on bill?");
387 pline("onbill: unpaid obj not on bill?");
391 /* called with two args on merge */
393 obfree(struct obj *obj, struct obj *merge)
395 struct bill_x *bp = onbill(obj);
400 obj->unpaid = 0; /* only for doinvbill */
401 obj->nobj = billobjs;
407 /* this used to be a rename */
408 impossible("obfree: not on bill??");
411 /* this was a merger */
412 bpm->bquan += bp->bquan;
413 ESHK(shopkeeper)->billct--;
414 *bp = bill[ESHK(shopkeeper)->billct];
421 pay(long tmp, struct monst *shkp)
423 long robbed = ESHK(shkp)->robbed;
432 ESHK(shkp)->robbed = robbed;
446 for (shkp = fmon; shkp; shkp = shkp->nmon)
447 if (shkp->isshk && dist(shkp->mx, shkp->my) < 3)
449 if (!shkp && u.uinshop &&
450 inroom(shopkeeper->mx, shopkeeper->my) == ESHK(shopkeeper)->shoproom)
454 pline("There is nobody here to receive your payment.");
457 ltmp = ESHK(shkp)->robbed;
458 if (shkp != shopkeeper && NOTANGRY(shkp)) {
460 pline("You do not owe %s anything.", monnam(shkp));
461 } else if (!u.ugold) {
462 pline("You have no money.");
464 long ugold = u.ugold;
466 if (u.ugold > ltmp) {
467 pline("You give %s the %ld gold pieces he asked for.",
471 pline("You give %s all your gold.", monnam(shkp));
474 if (ugold < ltmp / 2) {
475 pline("Unfortunately, he doesn't look satisfied.");
477 ESHK(shkp)->robbed = 0;
478 ESHK(shkp)->following = 0;
479 if (ESHK(shkp)->shoplevel != dlevel) {
481 * For convenience's sake, let him
484 shkp->minvent = 0; /* %% */
492 if (!ESHK(shkp)->billct) {
493 pline("You do not owe %s anything.", monnam(shkp));
495 pline("Moreover, you have no money.");
498 if (ESHK(shkp)->robbed) {
499 #define min(a,b) ((a<b)?a:b)
500 pline("But since his shop has been robbed recently,");
501 pline("you %srepay %s's expenses.",
502 (u.ugold < ESHK(shkp)->robbed) ? "partially " : "",
504 pay(min(u.ugold, ESHK(shkp)->robbed), shkp);
505 ESHK(shkp)->robbed = 0;
509 pline("But in order to appease %s,",
510 amonnam(shkp, "angry"));
511 if (u.ugold >= 1000) {
513 pline(" you give him 1000 gold pieces.");
516 pline(" you give him all your money.");
519 if (strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
521 pline("%s calms down.", Monnam(shkp));
524 pline("%s is as angry as ever.",
529 if (shkp != shopkeeper) {
530 impossible("dopay: not to shopkeeper?");
535 for (pass = 0; pass <= 1; pass++) {
537 while (tmp < ESHK(shopkeeper)->billct) {
539 if (!pass && !bp->useup) {
545 bill[tmp] = bill[--ESHK(shopkeeper)->billct];
548 pline("Thank you for shopping in %s's %s store!",
550 shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]);
551 NOTANGRY(shopkeeper) = 1;
555 /* return 1 if paid successfully */
556 /* 0 if not enough money */
557 /* -1 if object could not be found (but was paid) */
559 dopayobj(struct bill_x *bp)
564 /* find the object on one of the lists */
568 impossible("Shopkeeper administration out of order.");
569 setpaid(); /* be nice to the player */
572 if (!obj->unpaid && !bp->useup) {
573 impossible("Paid object on bill??");
577 ltmp = bp->price * bp->bquan;
578 if (ANGRY(shopkeeper))
580 if (u.ugold < ltmp) {
581 pline("You don't have gold enough to pay %s.",
586 pay(ltmp, shopkeeper);
587 pline("You bought %s for %ld gold piece%s.",
588 doname(obj), ltmp, plur(ltmp));
590 struct obj *otmp = billobjs;
592 billobjs = obj->nobj;
594 while (otmp && otmp->nobj != obj)
597 otmp->nobj = obj->nobj;
599 pline("Error in shopkeeper administration.");
606 /* routine called after dying (or quitting) with nonempty bill */
610 if (shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct) {
612 if (total > u.ugold) {
613 shopkeeper->mgold += u.ugold;
615 pline("%s comes and takes all your possessions.",
619 shopkeeper->mgold += total;
620 pline("%s comes and takes the %ld zorkmids you owed him.",
621 Monnam(shopkeeper), total);
623 setpaid(); /* in case we create bones */
627 /* find obj on one of the lists */
629 bp_to_obj(struct bill_x *bp)
633 unsigned id = bp->bo_id;
636 obj = o_on(id, billobjs);
637 else if (!(obj = o_on(id, invent)) &&
638 !(obj = o_on(id, fobj)) &&
639 !(obj = o_on(id, fcobj))) {
640 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
641 if ((obj = o_on(id, mtmp->minvent)) != NULL)
643 for (mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
644 if ((obj = o_on(id, mtmp->minvent)) != NULL)
650 /* called in hack.c when we pickup an object */
652 addtobill(struct obj *obj)
656 (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
657 (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y) ||
658 onbill(obj) /* perhaps we threw it away earlier */
661 if (ESHK(shopkeeper)->billct == BILLSZ) {
662 pline("You got that for free!");
665 bp = &bill[ESHK(shopkeeper)->billct];
666 bp->bo_id = obj->o_id;
667 bp->bquan = obj->quan;
669 bp->price = getprice(obj);
670 ESHK(shopkeeper)->billct++;
675 splitbill(struct obj *obj, struct obj *otmp)
677 /* otmp has been split off from obj */
682 impossible("splitbill: not on bill?");
685 if (bp->bquan < otmp->quan) {
686 impossible("Negative quantity on bill??");
688 if (bp->bquan == otmp->quan) {
689 impossible("Zero quantity on bill??");
691 bp->bquan -= otmp->quan;
693 /* addtobill(otmp); */
694 if (ESHK(shopkeeper)->billct == BILLSZ)
698 bp = &bill[ESHK(shopkeeper)->billct];
699 bp->bo_id = otmp->o_id;
700 bp->bquan = otmp->quan;
703 ESHK(shopkeeper)->billct++;
708 subfrombill(struct obj *obj)
714 if (!inshop() || (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
715 (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y))
717 if ((bp = onbill(obj)) != 0) {
719 if (bp->bquan > obj->quan) {
722 bp->bo_id = otmp->o_id = flags.ident++;
723 otmp->quan = (bp->bquan -= obj->quan);
724 otmp->owt = 0; /* superfluous */
727 otmp->nobj = billobjs;
731 ESHK(shopkeeper)->billct--;
732 *bp = bill[ESHK(shopkeeper)->billct];
736 pline("%s didn't notice.", Monnam(shopkeeper));
740 /* he dropped something of his own - probably wants to sell it */
741 if (shopkeeper->msleep || shopkeeper->mfroz ||
742 inroom(shopkeeper->mx, shopkeeper->my) != ESHK(shopkeeper)->shoproom)
744 if (ESHK(shopkeeper)->billct == BILLSZ ||
745 ((tmp = shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]) && tmp != obj->olet)
746 || strchr("_0", obj->olet)) {
747 pline("%s seems not interested.", Monnam(shopkeeper));
750 ltmp = getprice(obj) * obj->quan;
751 if (ANGRY(shopkeeper)) {
753 NOTANGRY(shopkeeper) = 1;
756 if (ESHK(shopkeeper)->robbed) {
757 if ((ESHK(shopkeeper)->robbed -= ltmp) < 0)
758 ESHK(shopkeeper)->robbed = 0;
759 pline("Thank you for your contribution to restock this recently plundered shop.");
762 if (ltmp > shopkeeper->mgold)
763 ltmp = shopkeeper->mgold;
764 pay(-ltmp, shopkeeper);
766 pline("%s gladly accepts %s but cannot pay you at present.",
767 Monnam(shopkeeper), doname(obj));
769 pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp,
773 /* mode: 0: deliver count 1: paged */
779 long totused, thisused;
786 for (bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)
788 ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
793 impossible("doinvbill: no shopkeeper?");
797 if (page_line("Unpaid articles already used up:") || page_line(""))
801 for (bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {
804 impossible("Bad shopkeeper administration.");
807 if (bp->useup || bp->bquan > obj->quan) {
808 int cnt, oquan, uquan;
811 uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
812 thisused = bp->price * uquan;
814 obj->quan = uquan; /* cheat doname */
815 (void) snprintf(buf, sizeof(buf),
816 "x - %s", doname(obj));
817 obj->quan = oquan; /* restore value */
818 for (cnt = 0; buf[cnt]; cnt++);
821 (void) snprintf(buf+cnt, sizeof(buf)-cnt,
822 " %5ld zorkmids", thisused);
827 (void) snprintf(buf, sizeof(buf), "Total:%50ld zorkmids", totused);
828 if (page_line("") || page_line(buf))
838 getprice(struct obj *obj)
847 tmp = 10 * rnd((obj->otyp == EXPENSIVE_CAMERA) ? 150 : 30);
858 if (obj->otyp == SCR_MAIL)
866 tmp = 10 * rnd(5 + (2000 / realhunger()));
873 if (ac <= -10) /* probably impossible */
875 tmp = 100 + ac * ac * rnd(10 + ac);
878 if (obj->otyp < BOOMERANG)
880 else if (obj->otyp == LONG_SWORD ||
881 obj->otyp == TWO_HANDED_SWORD)
887 pline("Strange ..., carrying a chain?");
900 { /* not completely foolproof */
902 struct obj *otmp = invent;
904 if (otmp->olet == FOOD_SYM && !otmp->unpaid)
905 tmp += objects[otmp->otyp].nutrition;
908 return ((tmp <= 0) ? 1 : tmp);
912 shkcatch(struct obj *obj)
914 struct monst *shkp = shopkeeper;
916 if (u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&
918 inroom(u.ux + u.dx, u.uy + u.dy) + 1 == u.uinshop &&
919 shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&
920 u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {
921 pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));
922 obj->nobj = shkp->minvent;
930 * shk_move: return 1: he moved 0: he didnt -1: let m_move do it
933 shk_move(struct monst *shkp)
936 const struct permonst *mdat = shkp->data;
937 xchar gx, gy, omx, omy, nx, ny, nix, niy;
941 schar shkroom, chi, chcnt, cnt;
942 boolean uondoor = 0, satdoor, avoid = 0, badinv;
950 if ((udist = dist(omx, omy)) < 3) {
952 (void) hitu(shkp, d(mdat->damn, mdat->damd) + 1);
955 if (ESHK(shkp)->following) {
956 if (strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)) {
957 pline("Hello %s! I was looking for %s.",
958 plname, ESHK(shkp)->customer);
959 ESHK(shkp)->following = 0;
962 if (!ESHK(shkp)->robbed) { /* impossible? */
963 ESHK(shkp)->following = 0;
966 if (moves > followmsg + 4) {
967 pline("Hello %s! Didn't you forget to pay?",
975 shkroom = inroom(omx, omy);
977 gx = ESHK(shkp)->shk.x;
978 gy = ESHK(shkp)->shk.y;
979 satdoor = (gx == omx && gy == omy);
980 if (ESHK(shkp)->following || ((z = holetime()) >= 0 && z * z <= udist)) {
983 if (shkroom < 0 || shkroom != inroom(u.ux, u.uy))
985 return (-1); /* leave it to m_move */
986 } else if (ANGRY(shkp)) {
987 long saveBlind = Blind;
989 if (shkp->mcansee && !Invis && cansee(omx, omy)) {
996 #define GDIST(x,y) ((x-gx)*(x-gx)+(y-gy)*(y-gy))
1000 uondoor = (u.ux == ESHK(shkp)->shd.x &&
1001 u.uy == ESHK(shkp)->shd.y);
1003 if (ESHK(shkp)->billct)
1004 pline("Hello %s! Will you please pay before leaving?",
1006 badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
1007 if (satdoor && badinv)
1011 avoid = (u.uinshop && dist(gx, gy) > 8);
1015 if (((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
1016 && GDIST(omx, omy) < 3) {
1017 if (!badinv && !online(omx, omy))
1024 if (omx == gx && omy == gy)
1032 cnt = mfndpos(shkp, poss, info, ALLOW_SSM);
1033 if (avoid && uondoor) { /* perhaps we cannot avoid him */
1034 for (i = 0; i < cnt; i++)
1035 if (!(info[i] & NOTONL))
1043 for (i = 0; i < cnt; i++) {
1046 if (levl[nx][ny].typ == ROOM
1047 || shkroom != ESHK(shkp)->shoproom
1048 || ESHK(shkp)->following) {
1050 /* cater for stupid compilers */
1053 if (uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
1059 if (avoid && (info[i] & NOTONL))
1061 if ((!appr && !rn2(++chcnt)) ||
1063 (appr && (zz = GDIST(nix, niy)) && zz > GDIST(nx, ny))
1065 (appr && GDIST(nx, ny) < GDIST(nix, niy))
1074 if (nix != omx || niy != omy) {
1075 if (info[chi] & ALLOW_M) {
1076 mtmp = m_at(nix, niy);
1078 panic("error in shk_move");
1079 if (hitmm(shkp, mtmp) == 1 && rn2(3) &&
1080 hitmm(mtmp, shkp) == 2)
1083 } else if (info[chi] & ALLOW_U) {
1084 (void) hitu(shkp, d(mdat->damn, mdat->damd) + 1);
1099 /* He is digging in the shop. */
1104 if (u.utraptype == TT_PIT)
1105 pline("\"Be careful, sir, or you might fall through the floor.\"");
1107 pline("\"Please, do not damage the floor here.\"");
1108 } else if (dist(shopkeeper->mx, shopkeeper->my) < 3) {
1109 struct obj *obj, *obj2;
1111 pline("%s grabs your backpack!", shkname(shopkeeper));
1112 for (obj = invent; obj; obj = obj2) {
1117 obj->nobj = shopkeeper->minvent;
1118 shopkeeper->minvent = obj;
1127 online(int x, int y)
1129 return (x == u.ux || y == u.uy ||
1130 (x - u.ux) * (x - u.ux) == (y - u.uy) * (y - u.uy));
1133 /* Does this monster follow me downstairs? */
1135 follower(struct monst *mtmp)
1137 return (mtmp->mtame || strchr("1TVWZi&, ", mtmp->data->mlet)
1139 || (mtmp->isshk && ESHK(mtmp)->following)