xref: /csrg-svn/games/hack/hack.shk.c (revision 47700)
141260Sbostic /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
241260Sbostic /* hack.shk.c - version 1.0.3 */
341260Sbostic 
441260Sbostic #include "hack.h"
541260Sbostic #ifdef QUEST
641260Sbostic int shlevel = 0;
741260Sbostic struct monst *shopkeeper = 0;
841260Sbostic struct obj *billobjs = 0;
obfree(obj,merge)941260Sbostic obfree(obj,merge) register struct obj *obj, *merge; {
1041260Sbostic 	free((char *) obj);
1141260Sbostic }
inshop()1241260Sbostic inshop(){ return(0); }
shopdig()1341260Sbostic shopdig(){}
addtobill()1441260Sbostic addtobill(){}
subfrombill()1541260Sbostic subfrombill(){}
splitbill()1641260Sbostic splitbill(){}
dopay()1741260Sbostic dopay(){ return(0); }
paybill()1841260Sbostic paybill(){}
doinvbill()1941260Sbostic doinvbill(){ return(0); }
shkdead()2041260Sbostic shkdead(){}
shkcatch()2141260Sbostic shkcatch(){ return(0); }
shk_move()2241260Sbostic shk_move(){ return(0); }
2341260Sbostic replshk(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}
shkname()2441260Sbostic char *shkname(){ return(""); }
2541260Sbostic 
2641260Sbostic #else QUEST
2741260Sbostic #include	"hack.mfndpos.h"
2841260Sbostic #include	"def.mkroom.h"
2941260Sbostic #include	"def.eshk.h"
3041260Sbostic 
3141260Sbostic #define	ESHK(mon)	((struct eshk *)(&(mon->mextra[0])))
3241260Sbostic #define	NOTANGRY(mon)	mon->mpeaceful
3341260Sbostic #define	ANGRY(mon)	!NOTANGRY(mon)
3441260Sbostic 
3541260Sbostic extern char plname[], *xname();
3641260Sbostic extern struct obj *o_on(), *bp_to_obj();
3741260Sbostic 
3841260Sbostic /* Descriptor of current shopkeeper. Note that the bill need not be
3941260Sbostic    per-shopkeeper, since it is valid only when in a shop. */
4041260Sbostic static struct monst *shopkeeper = 0;
4141260Sbostic static struct bill_x *bill;
4241260Sbostic static int shlevel = 0;	/* level of this shopkeeper */
4341260Sbostic        struct obj *billobjs;	/* objects on bill with bp->useup */
4441260Sbostic 				/* only accessed here and by save & restore */
4541260Sbostic static long int total;		/* filled by addupbill() */
4641260Sbostic static long int followmsg;	/* last time of follow message */
4741260Sbostic 
4841260Sbostic /*
4941260Sbostic 	invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
5041260Sbostic 		obj->quan <= bp->bquan
5141260Sbostic  */
5241260Sbostic 
5341260Sbostic 
5441260Sbostic char shtypes[] = {	/* 8 shoptypes: 7 specialized, 1 mixed */
5541260Sbostic 	RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM,
5641260Sbostic 	POTION_SYM, ARMOR_SYM, 0
5741260Sbostic };
5841260Sbostic 
5941260Sbostic static char *shopnam[] = {
6041260Sbostic 	"engagement ring", "walking cane", "antique weapon",
6141260Sbostic 	"delicatessen", "second hand book", "liquor",
6241260Sbostic 	"used armor", "assorted antiques"
6341260Sbostic };
6441260Sbostic 
6541260Sbostic char *
shkname(mtmp)6641260Sbostic shkname(mtmp)				/* called in do_name.c */
6741260Sbostic register struct monst *mtmp;
6841260Sbostic {
6941260Sbostic 	return(ESHK(mtmp)->shknam);
7041260Sbostic }
7141260Sbostic 
72*47700Sbostic static void setpaid();
73*47700Sbostic 
shkdead(mtmp)7441260Sbostic shkdead(mtmp)				/* called in mon.c */
7541260Sbostic register struct monst *mtmp;
7641260Sbostic {
7741260Sbostic 	register struct eshk *eshk = ESHK(mtmp);
7841260Sbostic 
7941260Sbostic 	if(eshk->shoplevel == dlevel)
8041260Sbostic 		rooms[eshk->shoproom].rtype = 0;
8141260Sbostic 	if(mtmp == shopkeeper) {
8241260Sbostic 		setpaid();
8341260Sbostic 		shopkeeper = 0;
8441260Sbostic 		bill = (struct bill_x *) -1000;	/* dump core when referenced */
8541260Sbostic 	}
8641260Sbostic }
8741260Sbostic 
replshk(mtmp,mtmp2)8841260Sbostic replshk(mtmp,mtmp2)
8941260Sbostic register struct monst *mtmp, *mtmp2;
9041260Sbostic {
9141260Sbostic 	if(mtmp == shopkeeper) {
9241260Sbostic 		shopkeeper = mtmp2;
9341260Sbostic 		bill = &(ESHK(shopkeeper)->bill[0]);
9441260Sbostic 	}
9541260Sbostic }
9641260Sbostic 
97*47700Sbostic static void
setpaid()9841260Sbostic setpaid(){	/* caller has checked that shopkeeper exists */
9941260Sbostic 		/* either we paid or left the shop or he just died */
10041260Sbostic register struct obj *obj;
10141260Sbostic register struct monst *mtmp;
10241260Sbostic 	for(obj = invent; obj; obj = obj->nobj)
10341260Sbostic 		obj->unpaid = 0;
10441260Sbostic 	for(obj = fobj; obj; obj = obj->nobj)
10541260Sbostic 		obj->unpaid = 0;
10641260Sbostic 	for(obj = fcobj; obj; obj = obj->nobj)
10741260Sbostic 		obj->unpaid = 0;
10841260Sbostic 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
10941260Sbostic 		for(obj = mtmp->minvent; obj; obj = obj->nobj)
11041260Sbostic 			obj->unpaid = 0;
11141260Sbostic 	for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
11241260Sbostic 		for(obj = mtmp->minvent; obj; obj = obj->nobj)
11341260Sbostic 			obj->unpaid = 0;
11441260Sbostic 	while(obj = billobjs){
11541260Sbostic 		billobjs = obj->nobj;
11641260Sbostic 		free((char *) obj);
11741260Sbostic 	}
11841260Sbostic 	ESHK(shopkeeper)->billct = 0;
11941260Sbostic }
12041260Sbostic 
12141260Sbostic static
addupbill()12241260Sbostic addupbill(){	/* delivers result in total */
12341260Sbostic 		/* caller has checked that shopkeeper exists */
12441260Sbostic register ct = ESHK(shopkeeper)->billct;
12541260Sbostic register struct bill_x *bp = bill;
12641260Sbostic 	total = 0;
12741260Sbostic 	while(ct--){
12841260Sbostic 		total += bp->price * bp->bquan;
12941260Sbostic 		bp++;
13041260Sbostic 	}
13141260Sbostic }
13241260Sbostic 
inshop()13341260Sbostic inshop(){
13441260Sbostic register roomno = inroom(u.ux,u.uy);
13541260Sbostic 
136*47700Sbostic 	static void findshk();
137*47700Sbostic 
13841260Sbostic 	/* Did we just leave a shop? */
13941260Sbostic 	if(u.uinshop &&
14041260Sbostic 	    (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
14141260Sbostic 		if(shopkeeper) {
14241260Sbostic 		    if(ESHK(shopkeeper)->billct) {
14341260Sbostic  			if(inroom(shopkeeper->mx, shopkeeper->my)
14441260Sbostic  			    == u.uinshop - 1)	/* ab@unido */
14541260Sbostic  			    pline("Somehow you escaped the shop without paying!");
14641260Sbostic 			addupbill();
14741260Sbostic 			pline("You stole for a total worth of %ld zorkmids.",
14841260Sbostic 				total);
14941260Sbostic 			ESHK(shopkeeper)->robbed += total;
15041260Sbostic 			setpaid();
15141260Sbostic 			if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)
15241260Sbostic 			    == (rn2(3) == 0))
15341260Sbostic 			    ESHK(shopkeeper)->following = 1;
15441260Sbostic 		    }
15541260Sbostic 		    shopkeeper = 0;
15641260Sbostic 		    shlevel = 0;
15741260Sbostic 		}
15841260Sbostic  		u.uinshop = 0;
15941260Sbostic 	}
16041260Sbostic 
16141260Sbostic 	/* Did we just enter a zoo of some kind? */
16241260Sbostic 	if(roomno >= 0) {
16341260Sbostic 		register int rt = rooms[roomno].rtype;
16441260Sbostic 		register struct monst *mtmp;
16541260Sbostic 		if(rt == ZOO) {
16641260Sbostic 			pline("Welcome to David's treasure zoo!");
16741260Sbostic 		} else
16841260Sbostic 		if(rt == SWAMP) {
16941260Sbostic 			pline("It looks rather muddy down here.");
17041260Sbostic 		} else
17141260Sbostic 		if(rt == MORGUE) {
17241260Sbostic 			if(midnight())
17341260Sbostic 				pline("Go away! Go away!");
17441260Sbostic 			else
17541260Sbostic 				pline("You get an uncanny feeling ...");
17641260Sbostic 		} else
17741260Sbostic 			rt = 0;
17841260Sbostic 		if(rt != 0) {
17941260Sbostic 			rooms[roomno].rtype = 0;
18041260Sbostic 			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
18141260Sbostic 				if(rt != ZOO || !rn2(3))
18241260Sbostic 					mtmp->msleep = 0;
18341260Sbostic 		}
18441260Sbostic 	}
18541260Sbostic 
18641260Sbostic 	/* Did we just enter a shop? */
18741260Sbostic 	if(roomno >= 0 && rooms[roomno].rtype >= 8) {
18841260Sbostic 	    if(shlevel != dlevel || !shopkeeper
18941260Sbostic 				 || ESHK(shopkeeper)->shoproom != roomno)
19041260Sbostic 		findshk(roomno);
19141260Sbostic 	    if(!shopkeeper) {
19241260Sbostic 		rooms[roomno].rtype = 0;
19341260Sbostic 		u.uinshop = 0;
19441260Sbostic 	    } else if(!u.uinshop){
19541260Sbostic 		if(!ESHK(shopkeeper)->visitct ||
19641260Sbostic 		    strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){
19741260Sbostic 
19841260Sbostic 		    /* He seems to be new here */
19941260Sbostic 		    ESHK(shopkeeper)->visitct = 0;
20041260Sbostic 		    ESHK(shopkeeper)->following = 0;
20141260Sbostic 		    (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
20241260Sbostic 		    NOTANGRY(shopkeeper) = 1;
20341260Sbostic 		}
20441260Sbostic 		if(!ESHK(shopkeeper)->following) {
20541260Sbostic 		    boolean box, pick;
20641260Sbostic 
20741260Sbostic 		    pline("Hello %s! Welcome%s to %s's %s shop!",
20841260Sbostic 			plname,
20941260Sbostic 			ESHK(shopkeeper)->visitct++ ? " again" : "",
21041260Sbostic 			shkname(shopkeeper),
21141260Sbostic 			shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] );
21241260Sbostic 		    box = carrying(ICE_BOX);
21341260Sbostic 		    pick = carrying(PICK_AXE);
21441260Sbostic 		    if(box || pick) {
21541260Sbostic 			if(dochug(shopkeeper)) {
21641260Sbostic 				u.uinshop = 0;	/* he died moving */
21741260Sbostic 				return(0);
21841260Sbostic 			}
21941260Sbostic 			pline("Will you please leave your %s outside?",
22041260Sbostic 			    (box && pick) ? "box and pick-axe" :
22141260Sbostic 			    box ? "box" : "pick-axe");
22241260Sbostic 		    }
22341260Sbostic 		}
22441260Sbostic 		u.uinshop = roomno + 1;
22541260Sbostic 	    }
22641260Sbostic 	}
22741260Sbostic 	return(u.uinshop);
22841260Sbostic }
22941260Sbostic 
230*47700Sbostic static void
findshk(roomno)23141260Sbostic findshk(roomno)
23241260Sbostic register roomno;
23341260Sbostic {
23441260Sbostic register struct monst *mtmp;
23541260Sbostic 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
23641260Sbostic 	    if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
23741260Sbostic 			   && ESHK(mtmp)->shoplevel == dlevel) {
23841260Sbostic 		shopkeeper = mtmp;
23941260Sbostic 		bill = &(ESHK(shopkeeper)->bill[0]);
24041260Sbostic 		shlevel = dlevel;
24141260Sbostic 		if(ANGRY(shopkeeper) &&
24241260Sbostic 		   strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
24341260Sbostic 			NOTANGRY(shopkeeper) = 1;
24441260Sbostic 		/* billobjs = 0; -- this is wrong if we save in a shop */
24541260Sbostic 		/* (and it is harmless to have too many things in billobjs) */
24641260Sbostic 		return;
24741260Sbostic 	}
24841260Sbostic 	shopkeeper = 0;
24941260Sbostic 	shlevel = 0;
25041260Sbostic 	bill = (struct bill_x *) -1000;	/* dump core when referenced */
25141260Sbostic }
25241260Sbostic 
25341260Sbostic static struct bill_x *
onbill(obj)25441260Sbostic onbill(obj) register struct obj *obj; {
25541260Sbostic register struct bill_x *bp;
25641260Sbostic 	if(!shopkeeper) return(0);
25741260Sbostic 	for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
25841260Sbostic 		if(bp->bo_id == obj->o_id) {
25941260Sbostic 			if(!obj->unpaid) pline("onbill: paid obj on bill?");
26041260Sbostic 			return(bp);
26141260Sbostic 		}
26241260Sbostic 	if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
26341260Sbostic 	return(0);
26441260Sbostic }
26541260Sbostic 
26641260Sbostic /* called with two args on merge */
obfree(obj,merge)26741260Sbostic obfree(obj,merge) register struct obj *obj, *merge; {
26841260Sbostic register struct bill_x *bp = onbill(obj);
26941260Sbostic register struct bill_x *bpm;
27041260Sbostic 	if(bp) {
27141260Sbostic 		if(!merge){
27241260Sbostic 			bp->useup = 1;
27341260Sbostic 			obj->unpaid = 0;	/* only for doinvbill */
27441260Sbostic 			obj->nobj = billobjs;
27541260Sbostic 			billobjs = obj;
27641260Sbostic 			return;
27741260Sbostic 		}
27841260Sbostic 		bpm = onbill(merge);
27941260Sbostic 		if(!bpm){
28041260Sbostic 			/* this used to be a rename */
28141260Sbostic 			impossible("obfree: not on bill??");
28241260Sbostic 			return;
28341260Sbostic 		} else {
28441260Sbostic 			/* this was a merger */
28541260Sbostic 			bpm->bquan += bp->bquan;
28641260Sbostic 			ESHK(shopkeeper)->billct--;
28741260Sbostic 			*bp = bill[ESHK(shopkeeper)->billct];
28841260Sbostic 		}
28941260Sbostic 	}
29041260Sbostic 	free((char *) obj);
29141260Sbostic }
29241260Sbostic 
29341260Sbostic static
pay(tmp,shkp)29441260Sbostic pay(tmp,shkp)
29541260Sbostic long tmp;
29641260Sbostic register struct monst *shkp;
29741260Sbostic {
29841260Sbostic 	long robbed = ESHK(shkp)->robbed;
29941260Sbostic 
30041260Sbostic 	u.ugold -= tmp;
30141260Sbostic 	shkp->mgold += tmp;
30241260Sbostic 	flags.botl = 1;
30341260Sbostic 	if(robbed) {
30441260Sbostic 		robbed -= tmp;
30541260Sbostic 		if(robbed < 0) robbed = 0;
30641260Sbostic 		ESHK(shkp)->robbed = robbed;
30741260Sbostic 	}
30841260Sbostic }
30941260Sbostic 
dopay()31041260Sbostic dopay(){
31141260Sbostic long ltmp;
31241260Sbostic register struct bill_x *bp;
31341260Sbostic register struct monst *shkp;
31441260Sbostic int pass, tmp;
31541260Sbostic 
316*47700Sbostic 	static int dopayobj();
317*47700Sbostic 
31841260Sbostic 	multi = 0;
31941260Sbostic 	(void) inshop();
32041260Sbostic 	for(shkp = fmon; shkp; shkp = shkp->nmon)
32141260Sbostic 		if(shkp->isshk && dist(shkp->mx,shkp->my) < 3)
32241260Sbostic 			break;
32341260Sbostic 	if(!shkp && u.uinshop &&
32441260Sbostic 	   inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom)
32541260Sbostic 		shkp = shopkeeper;
32641260Sbostic 
32741260Sbostic 	if(!shkp) {
32841260Sbostic 		pline("There is nobody here to receive your payment.");
32941260Sbostic 		return(0);
33041260Sbostic 	}
33141260Sbostic 	ltmp = ESHK(shkp)->robbed;
33241260Sbostic 	if(shkp != shopkeeper && NOTANGRY(shkp)) {
33341260Sbostic 		if(!ltmp) {
33441260Sbostic 			pline("You do not owe %s anything.", monnam(shkp));
33541260Sbostic 		} else
33641260Sbostic 		if(!u.ugold) {
33741260Sbostic 			pline("You have no money.");
33841260Sbostic 		} else {
33941260Sbostic 		    long ugold = u.ugold;
34041260Sbostic 
34141260Sbostic 		    if(u.ugold > ltmp) {
34241260Sbostic 			pline("You give %s the %ld gold pieces he asked for.",
34341260Sbostic 				monnam(shkp), ltmp);
34441260Sbostic 			pay(ltmp, shkp);
34541260Sbostic 		    } else {
34641260Sbostic 			pline("You give %s all your gold.", monnam(shkp));
34741260Sbostic 			pay(u.ugold, shkp);
34841260Sbostic 		    }
34941260Sbostic 		    if(ugold < ltmp/2) {
35041260Sbostic 			pline("Unfortunately, he doesn't look satisfied.");
35141260Sbostic 		    } else {
35241260Sbostic 			ESHK(shkp)->robbed = 0;
35341260Sbostic 			ESHK(shkp)->following = 0;
35441260Sbostic 			if(ESHK(shkp)->shoplevel != dlevel) {
35541260Sbostic 			/* For convenience's sake, let him disappear */
35641260Sbostic 			    shkp->minvent = 0;		/* %% */
35741260Sbostic 			    shkp->mgold = 0;
35841260Sbostic 			    mondead(shkp);
35941260Sbostic 			}
36041260Sbostic 		    }
36141260Sbostic 		}
36241260Sbostic 		return(1);
36341260Sbostic 	}
36441260Sbostic 
36541260Sbostic 	if(!ESHK(shkp)->billct){
36641260Sbostic 		pline("You do not owe %s anything.", monnam(shkp));
36741260Sbostic 		if(!u.ugold){
36841260Sbostic 			pline("Moreover, you have no money.");
36941260Sbostic 			return(1);
37041260Sbostic 		}
37141260Sbostic 		if(ESHK(shkp)->robbed){
37241260Sbostic #define min(a,b)	((a<b)?a:b)
37341260Sbostic 		    pline("But since his shop has been robbed recently,");
37441260Sbostic 		    pline("you %srepay %s's expenses.",
37541260Sbostic 		      (u.ugold < ESHK(shkp)->robbed) ? "partially " : "",
37641260Sbostic 		      monnam(shkp));
37741260Sbostic 		    pay(min(u.ugold, ESHK(shkp)->robbed), shkp);
37841260Sbostic 		    ESHK(shkp)->robbed = 0;
37941260Sbostic 		    return(1);
38041260Sbostic 		}
38141260Sbostic 		if(ANGRY(shkp)){
38241260Sbostic 			pline("But in order to appease %s,",
38341260Sbostic 				amonnam(shkp, "angry"));
38441260Sbostic 			if(u.ugold >= 1000){
38541260Sbostic 				ltmp = 1000;
38641260Sbostic 				pline(" you give him 1000 gold pieces.");
38741260Sbostic 			} else {
38841260Sbostic 				ltmp = u.ugold;
38941260Sbostic 				pline(" you give him all your money.");
39041260Sbostic 			}
39141260Sbostic 			pay(ltmp, shkp);
39241260Sbostic 			if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
39341260Sbostic 			   || rn2(3)){
39441260Sbostic 				pline("%s calms down.", Monnam(shkp));
39541260Sbostic 				NOTANGRY(shkp) = 1;
39641260Sbostic 			} else	pline("%s is as angry as ever.",
39741260Sbostic 					Monnam(shkp));
39841260Sbostic 		}
39941260Sbostic 		return(1);
40041260Sbostic 	}
40141260Sbostic 	if(shkp != shopkeeper) {
40241260Sbostic 		impossible("dopay: not to shopkeeper?");
40341260Sbostic 		if(shopkeeper) setpaid();
40441260Sbostic 		return(0);
40541260Sbostic 	}
40641260Sbostic 	for(pass = 0; pass <= 1; pass++) {
40741260Sbostic 		tmp = 0;
40841260Sbostic 		while(tmp < ESHK(shopkeeper)->billct) {
40941260Sbostic 			bp = &bill[tmp];
41041260Sbostic 			if(!pass && !bp->useup) {
41141260Sbostic 				tmp++;
41241260Sbostic 				continue;
41341260Sbostic 			}
41441260Sbostic 			if(!dopayobj(bp)) return(1);
41541260Sbostic 			bill[tmp] = bill[--ESHK(shopkeeper)->billct];
41641260Sbostic 		}
41741260Sbostic 	}
41841260Sbostic 	pline("Thank you for shopping in %s's %s store!",
41941260Sbostic 		shkname(shopkeeper),
42041260Sbostic 		shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]);
42141260Sbostic 	NOTANGRY(shopkeeper) = 1;
42241260Sbostic 	return(1);
42341260Sbostic }
42441260Sbostic 
42541260Sbostic /* return 1 if paid successfully */
42641260Sbostic /*        0 if not enough money */
42741260Sbostic /*       -1 if object could not be found (but was paid) */
42841260Sbostic static
dopayobj(bp)42941260Sbostic dopayobj(bp) register struct bill_x *bp; {
43041260Sbostic register struct obj *obj;
43141260Sbostic long ltmp;
43241260Sbostic 
43341260Sbostic 	/* find the object on one of the lists */
43441260Sbostic 	obj = bp_to_obj(bp);
43541260Sbostic 
43641260Sbostic 	if(!obj) {
43741260Sbostic 		impossible("Shopkeeper administration out of order.");
43841260Sbostic 		setpaid();	/* be nice to the player */
43941260Sbostic 		return(0);
44041260Sbostic 	}
44141260Sbostic 
44241260Sbostic 	if(!obj->unpaid && !bp->useup){
44341260Sbostic 		impossible("Paid object on bill??");
44441260Sbostic 		return(1);
44541260Sbostic 	}
44641260Sbostic 	obj->unpaid = 0;
44741260Sbostic 	ltmp = bp->price * bp->bquan;
44841260Sbostic 	if(ANGRY(shopkeeper)) ltmp += ltmp/3;
44941260Sbostic 	if(u.ugold < ltmp){
45041260Sbostic 		pline("You don't have gold enough to pay %s.",
45141260Sbostic 			doname(obj));
45241260Sbostic 		obj->unpaid = 1;
45341260Sbostic 		return(0);
45441260Sbostic 	}
45541260Sbostic 	pay(ltmp, shopkeeper);
45641260Sbostic 	pline("You bought %s for %ld gold piece%s.",
45741260Sbostic 		doname(obj), ltmp, plur(ltmp));
45841260Sbostic 	if(bp->useup) {
45941260Sbostic 		register struct obj *otmp = billobjs;
46041260Sbostic 		if(obj == billobjs)
46141260Sbostic 			billobjs = obj->nobj;
46241260Sbostic 		else {
46341260Sbostic 			while(otmp && otmp->nobj != obj) otmp = otmp->nobj;
46441260Sbostic 			if(otmp) otmp->nobj = obj->nobj;
46541260Sbostic 			else pline("Error in shopkeeper administration.");
46641260Sbostic 		}
46741260Sbostic 		free((char *) obj);
46841260Sbostic 	}
46941260Sbostic 	return(1);
47041260Sbostic }
47141260Sbostic 
47241260Sbostic /* routine called after dying (or quitting) with nonempty bill */
paybill()47341260Sbostic paybill(){
47441260Sbostic 	if(shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct){
47541260Sbostic 		addupbill();
47641260Sbostic 		if(total > u.ugold){
47741260Sbostic 			shopkeeper->mgold += u.ugold;
47841260Sbostic 			u.ugold = 0;
47941260Sbostic 		pline("%s comes and takes all your possessions.",
48041260Sbostic 			Monnam(shopkeeper));
48141260Sbostic 		} else {
48241260Sbostic 			u.ugold -= total;
48341260Sbostic 			shopkeeper->mgold += total;
48441260Sbostic 	pline("%s comes and takes the %ld zorkmids you owed him.",
48541260Sbostic 		Monnam(shopkeeper), total);
48641260Sbostic 		}
48741260Sbostic 		setpaid();	/* in case we create bones */
48841260Sbostic 	}
48941260Sbostic }
49041260Sbostic 
49141260Sbostic /* find obj on one of the lists */
49241260Sbostic struct obj *
bp_to_obj(bp)49341260Sbostic bp_to_obj(bp)
49441260Sbostic register struct bill_x *bp;
49541260Sbostic {
49641260Sbostic 	register struct obj *obj;
49741260Sbostic 	register struct monst *mtmp;
49841260Sbostic 	register unsigned id = bp->bo_id;
49941260Sbostic 
50041260Sbostic 	if(bp->useup)
50141260Sbostic 		obj = o_on(id, billobjs);
50241260Sbostic 	else if(!(obj = o_on(id, invent)) &&
50341260Sbostic 		!(obj = o_on(id, fobj)) &&
50441260Sbostic 		!(obj = o_on(id, fcobj))) {
50541260Sbostic 		    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
50641260Sbostic 			if(obj = o_on(id, mtmp->minvent))
50741260Sbostic 			    break;
50841260Sbostic 		    for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
50941260Sbostic 			if(obj = o_on(id, mtmp->minvent))
51041260Sbostic 			    break;
51141260Sbostic 		}
51241260Sbostic 	return(obj);
51341260Sbostic }
51441260Sbostic 
515*47700Sbostic static int getprice();
516*47700Sbostic 
51741260Sbostic /* called in hack.c when we pickup an object */
addtobill(obj)51841260Sbostic addtobill(obj) register struct obj *obj; {
51941260Sbostic register struct bill_x *bp;
52041260Sbostic 	if(!inshop() ||
52141260Sbostic 	(u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
52241260Sbostic 	(u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y) ||
52341260Sbostic 		onbill(obj) /* perhaps we threw it away earlier */
52441260Sbostic 	  ) return;
52541260Sbostic 	if(ESHK(shopkeeper)->billct == BILLSZ){
52641260Sbostic 		pline("You got that for free!");
52741260Sbostic 		return;
52841260Sbostic 	}
52941260Sbostic 	bp = &bill[ESHK(shopkeeper)->billct];
53041260Sbostic 	bp->bo_id = obj->o_id;
53141260Sbostic 	bp->bquan = obj->quan;
53241260Sbostic 	bp->useup = 0;
53341260Sbostic 	bp->price = getprice(obj);
53441260Sbostic 	ESHK(shopkeeper)->billct++;
53541260Sbostic 	obj->unpaid = 1;
53641260Sbostic }
53741260Sbostic 
splitbill(obj,otmp)53841260Sbostic splitbill(obj,otmp) register struct obj *obj, *otmp; {
53941260Sbostic 	/* otmp has been split off from obj */
54041260Sbostic register struct bill_x *bp;
54141260Sbostic register int tmp;
54241260Sbostic 	bp = onbill(obj);
54341260Sbostic 	if(!bp) {
54441260Sbostic 		impossible("splitbill: not on bill?");
54541260Sbostic 		return;
54641260Sbostic 	}
54741260Sbostic 	if(bp->bquan < otmp->quan) {
54841260Sbostic 		impossible("Negative quantity on bill??");
54941260Sbostic 	}
55041260Sbostic 	if(bp->bquan == otmp->quan) {
55141260Sbostic 		impossible("Zero quantity on bill??");
55241260Sbostic 	}
55341260Sbostic 	bp->bquan -= otmp->quan;
55441260Sbostic 
55541260Sbostic 	/* addtobill(otmp); */
55641260Sbostic 	if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0;
55741260Sbostic 	else {
55841260Sbostic 		tmp = bp->price;
55941260Sbostic 		bp = &bill[ESHK(shopkeeper)->billct];
56041260Sbostic 		bp->bo_id = otmp->o_id;
56141260Sbostic 		bp->bquan = otmp->quan;
56241260Sbostic 		bp->useup = 0;
56341260Sbostic 		bp->price = tmp;
56441260Sbostic 		ESHK(shopkeeper)->billct++;
56541260Sbostic 	}
56641260Sbostic }
56741260Sbostic 
subfrombill(obj)56841260Sbostic subfrombill(obj) register struct obj *obj; {
56941260Sbostic long ltmp;
57041260Sbostic register int tmp;
57141260Sbostic register struct obj *otmp;
57241260Sbostic register struct bill_x *bp;
57341260Sbostic 	if(!inshop() || (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
57441260Sbostic 		(u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y))
57541260Sbostic 		return;
57641260Sbostic 	if((bp = onbill(obj)) != 0){
57741260Sbostic 		obj->unpaid = 0;
57841260Sbostic 		if(bp->bquan > obj->quan){
57941260Sbostic 			otmp = newobj(0);
58041260Sbostic 			*otmp = *obj;
58141260Sbostic 			bp->bo_id = otmp->o_id = flags.ident++;
58241260Sbostic 			otmp->quan = (bp->bquan -= obj->quan);
58341260Sbostic 			otmp->owt = 0;	/* superfluous */
58441260Sbostic 			otmp->onamelth = 0;
58541260Sbostic 			bp->useup = 1;
58641260Sbostic 			otmp->nobj = billobjs;
58741260Sbostic 			billobjs = otmp;
58841260Sbostic 			return;
58941260Sbostic 		}
59041260Sbostic 		ESHK(shopkeeper)->billct--;
59141260Sbostic 		*bp = bill[ESHK(shopkeeper)->billct];
59241260Sbostic 		return;
59341260Sbostic 	}
59441260Sbostic 	if(obj->unpaid){
59541260Sbostic 		pline("%s didn't notice.", Monnam(shopkeeper));
59641260Sbostic 		obj->unpaid = 0;
59741260Sbostic 		return;		/* %% */
59841260Sbostic 	}
59941260Sbostic 	/* he dropped something of his own - probably wants to sell it */
60041260Sbostic 	if(shopkeeper->msleep || shopkeeper->mfroz ||
60141260Sbostic 		inroom(shopkeeper->mx,shopkeeper->my) != ESHK(shopkeeper)->shoproom)
60241260Sbostic 		return;
60341260Sbostic 	if(ESHK(shopkeeper)->billct == BILLSZ ||
60441260Sbostic 	  ((tmp = shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype-8]) && tmp != obj->olet)
60541260Sbostic 	  || index("_0", obj->olet)) {
60641260Sbostic 		pline("%s seems not interested.", Monnam(shopkeeper));
60741260Sbostic 		return;
60841260Sbostic 	}
60941260Sbostic 	ltmp = getprice(obj) * obj->quan;
61041260Sbostic 	if(ANGRY(shopkeeper)) {
61141260Sbostic 		ltmp /= 3;
61241260Sbostic 		NOTANGRY(shopkeeper) = 1;
61341260Sbostic 	} else	ltmp /= 2;
61441260Sbostic 	if(ESHK(shopkeeper)->robbed){
61541260Sbostic 		if((ESHK(shopkeeper)->robbed -= ltmp) < 0)
61641260Sbostic 			ESHK(shopkeeper)->robbed = 0;
61741260Sbostic pline("Thank you for your contribution to restock this recently plundered shop.");
61841260Sbostic 		return;
61941260Sbostic 	}
62041260Sbostic 	if(ltmp > shopkeeper->mgold)
62141260Sbostic 		ltmp = shopkeeper->mgold;
62241260Sbostic 	pay(-ltmp, shopkeeper);
62341260Sbostic 	if(!ltmp)
62441260Sbostic 	pline("%s gladly accepts %s but cannot pay you at present.",
62541260Sbostic 		Monnam(shopkeeper), doname(obj));
62641260Sbostic 	else
62741260Sbostic 	pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp,
62841260Sbostic 		plur(ltmp));
62941260Sbostic }
63041260Sbostic 
doinvbill(mode)63141260Sbostic doinvbill(mode)
63241260Sbostic int mode;		/* 0: deliver count 1: paged */
63341260Sbostic {
63441260Sbostic 	register struct bill_x *bp;
63541260Sbostic 	register struct obj *obj;
63641260Sbostic 	long totused, thisused;
63741260Sbostic 	char buf[BUFSZ];
63841260Sbostic 
63941260Sbostic 	if(mode == 0) {
64041260Sbostic 	    register int cnt = 0;
64141260Sbostic 
64241260Sbostic 	    if(shopkeeper)
64341260Sbostic 		for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)
64441260Sbostic 		    if(bp->useup ||
64541260Sbostic 		      ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
64641260Sbostic 			cnt++;
64741260Sbostic 	    return(cnt);
64841260Sbostic 	}
64941260Sbostic 
65041260Sbostic 	if(!shopkeeper) {
65141260Sbostic 		impossible("doinvbill: no shopkeeper?");
65241260Sbostic 		return(0);
65341260Sbostic 	}
65441260Sbostic 
65541260Sbostic 	set_pager(0);
65641260Sbostic 	if(page_line("Unpaid articles already used up:") || page_line(""))
65741260Sbostic 	    goto quit;
65841260Sbostic 
65941260Sbostic 	totused = 0;
66041260Sbostic 	for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {
66141260Sbostic 	    obj = bp_to_obj(bp);
66241260Sbostic 	    if(!obj) {
66341260Sbostic 		impossible("Bad shopkeeper administration.");
66441260Sbostic 		goto quit;
66541260Sbostic 	    }
66641260Sbostic 	    if(bp->useup || bp->bquan > obj->quan) {
66741260Sbostic 		register int cnt, oquan, uquan;
66841260Sbostic 
66941260Sbostic 		oquan = obj->quan;
67041260Sbostic 		uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
67141260Sbostic 		thisused = bp->price * uquan;
67241260Sbostic 		totused += thisused;
67341260Sbostic 		obj->quan = uquan;		/* cheat doname */
67441260Sbostic 		(void) sprintf(buf, "x -  %s", doname(obj));
67541260Sbostic 		obj->quan = oquan;		/* restore value */
67641260Sbostic 		for(cnt = 0; buf[cnt]; cnt++);
67741260Sbostic 		while(cnt < 50)
67841260Sbostic 			buf[cnt++] = ' ';
67941260Sbostic 		(void) sprintf(&buf[cnt], " %5ld zorkmids", thisused);
68041260Sbostic 		if(page_line(buf))
68141260Sbostic 			goto quit;
68241260Sbostic 	    }
68341260Sbostic 	}
68441260Sbostic 	(void) sprintf(buf, "Total:%50ld zorkmids", totused);
68541260Sbostic 	if(page_line("") || page_line(buf))
68641260Sbostic 		goto quit;
68741260Sbostic 	set_pager(1);
68841260Sbostic 	return(0);
68941260Sbostic quit:
69041260Sbostic 	set_pager(2);
69141260Sbostic 	return(0);
69241260Sbostic }
69341260Sbostic 
69441260Sbostic static
getprice(obj)69541260Sbostic getprice(obj) register struct obj *obj; {
69641260Sbostic register int tmp, ac;
697*47700Sbostic 	static int realhunger();
698*47700Sbostic 
69941260Sbostic 	switch(obj->olet){
70041260Sbostic 	case AMULET_SYM:
70141260Sbostic 		tmp = 10*rnd(500);
70241260Sbostic 		break;
70341260Sbostic 	case TOOL_SYM:
70441260Sbostic 		tmp = 10*rnd((obj->otyp == EXPENSIVE_CAMERA) ? 150 : 30);
70541260Sbostic 		break;
70641260Sbostic 	case RING_SYM:
70741260Sbostic 		tmp = 10*rnd(100);
70841260Sbostic 		break;
70941260Sbostic 	case WAND_SYM:
71041260Sbostic 		tmp = 10*rnd(100);
71141260Sbostic 		break;
71241260Sbostic 	case SCROLL_SYM:
71341260Sbostic 		tmp = 10*rnd(50);
71441260Sbostic #ifdef MAIL
71541260Sbostic 		if(obj->otyp == SCR_MAIL)
71641260Sbostic 			tmp = rnd(5);
71741260Sbostic #endif MAIL
71841260Sbostic 		break;
71941260Sbostic 	case POTION_SYM:
72041260Sbostic 		tmp = 10*rnd(50);
72141260Sbostic 		break;
72241260Sbostic 	case FOOD_SYM:
72341260Sbostic 		tmp = 10*rnd(5 + (2000/realhunger()));
72441260Sbostic 		break;
72541260Sbostic 	case GEM_SYM:
72641260Sbostic 		tmp = 10*rnd(20);
72741260Sbostic 		break;
72841260Sbostic 	case ARMOR_SYM:
72941260Sbostic 		ac = ARM_BONUS(obj);
73041260Sbostic 		if(ac <= -10)		/* probably impossible */
73141260Sbostic 			ac = -9;
73241260Sbostic 		tmp = 100 + ac*ac*rnd(10+ac);
73341260Sbostic 		break;
73441260Sbostic 	case WEAPON_SYM:
73541260Sbostic 		if(obj->otyp < BOOMERANG)
73641260Sbostic 			tmp = 5*rnd(10);
73741260Sbostic 		else if(obj->otyp == LONG_SWORD ||
73841260Sbostic 			obj->otyp == TWO_HANDED_SWORD)
73941260Sbostic 			tmp = 10*rnd(150);
74041260Sbostic 		else	tmp = 10*rnd(75);
74141260Sbostic 		break;
74241260Sbostic 	case CHAIN_SYM:
74341260Sbostic 		pline("Strange ..., carrying a chain?");
74441260Sbostic 	case BALL_SYM:
74541260Sbostic 		tmp = 10;
74641260Sbostic 		break;
74741260Sbostic 	default:
74841260Sbostic 		tmp = 10000;
74941260Sbostic 	}
75041260Sbostic 	return(tmp);
75141260Sbostic }
75241260Sbostic 
75341260Sbostic static
realhunger()75441260Sbostic realhunger(){	/* not completely foolproof */
75541260Sbostic register tmp = u.uhunger;
75641260Sbostic register struct obj *otmp = invent;
75741260Sbostic 	while(otmp){
75841260Sbostic 		if(otmp->olet == FOOD_SYM && !otmp->unpaid)
75941260Sbostic 			tmp += objects[otmp->otyp].nutrition;
76041260Sbostic 		otmp = otmp->nobj;
76141260Sbostic 	}
76241260Sbostic 	return((tmp <= 0) ? 1 : tmp);
76341260Sbostic }
76441260Sbostic 
shkcatch(obj)76541260Sbostic shkcatch(obj)
76641260Sbostic register struct obj *obj;
76741260Sbostic {
76841260Sbostic 	register struct monst *shkp = shopkeeper;
76941260Sbostic 
77041260Sbostic 	if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&
77141260Sbostic 	    u.dx && u.dy &&
77241260Sbostic 	    inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop &&
77341260Sbostic 	    shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&
77441260Sbostic 	    u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {
77541260Sbostic 		pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));
77641260Sbostic 		obj->nobj = shkp->minvent;
77741260Sbostic 		shkp->minvent = obj;
77841260Sbostic 		return(1);
77941260Sbostic 	}
78041260Sbostic 	return(0);
78141260Sbostic }
78241260Sbostic 
78341260Sbostic /*
78441260Sbostic  * shk_move: return 1: he moved  0: he didnt  -1: let m_move do it
78541260Sbostic  */
shk_move(shkp)78641260Sbostic shk_move(shkp)
78741260Sbostic register struct monst *shkp;
78841260Sbostic {
78941260Sbostic 	register struct monst *mtmp;
79041260Sbostic 	register struct permonst *mdat = shkp->data;
79141260Sbostic 	register xchar gx,gy,omx,omy,nx,ny,nix,niy;
79241260Sbostic 	register schar appr,i;
79341260Sbostic 	register int udist;
79441260Sbostic 	int z;
79541260Sbostic 	schar shkroom,chi,chcnt,cnt;
79641260Sbostic 	boolean uondoor, satdoor, avoid, badinv;
79741260Sbostic 	coord poss[9];
79841260Sbostic 	int info[9];
79941260Sbostic 	struct obj *ib = 0;
80041260Sbostic 
80141260Sbostic 	omx = shkp->mx;
80241260Sbostic 	omy = shkp->my;
80341260Sbostic 
80441260Sbostic 	if((udist = dist(omx,omy)) < 3) {
80541260Sbostic 		if(ANGRY(shkp)) {
80641260Sbostic 			(void) hitu(shkp, d(mdat->damn, mdat->damd)+1);
80741260Sbostic 			return(0);
80841260Sbostic 		}
80941260Sbostic 		if(ESHK(shkp)->following) {
81041260Sbostic 			if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)){
81141260Sbostic 				pline("Hello %s! I was looking for %s.",
81241260Sbostic 					plname, ESHK(shkp)->customer);
81341260Sbostic 				ESHK(shkp)->following = 0;
81441260Sbostic 				return(0);
81541260Sbostic 			}
81641260Sbostic 			if(!ESHK(shkp)->robbed) {	/* impossible? */
81741260Sbostic 				ESHK(shkp)->following = 0;
81841260Sbostic 				return(0);
81941260Sbostic 			}
82041260Sbostic 			if(moves > followmsg+4) {
82141260Sbostic 				pline("Hello %s! Didn't you forget to pay?",
82241260Sbostic 					plname);
82341260Sbostic 				followmsg = moves;
82441260Sbostic 			}
82541260Sbostic 			if(udist < 2)
82641260Sbostic 				return(0);
82741260Sbostic 		}
82841260Sbostic 	}
82941260Sbostic 
83041260Sbostic 	shkroom = inroom(omx,omy);
83141260Sbostic 	appr = 1;
83241260Sbostic 	gx = ESHK(shkp)->shk.x;
83341260Sbostic 	gy = ESHK(shkp)->shk.y;
83441260Sbostic 	satdoor = (gx == omx && gy == omy);
83541260Sbostic 	if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
83641260Sbostic 		gx = u.ux;
83741260Sbostic 		gy = u.uy;
83841260Sbostic 		if(shkroom < 0 || shkroom != inroom(u.ux,u.uy))
83941260Sbostic 		    if(udist > 4)
84041260Sbostic 			return(-1);	/* leave it to m_move */
84141260Sbostic 	} else if(ANGRY(shkp)) {
84241260Sbostic 		long saveBlind = Blind;
84341260Sbostic 		Blind = 0;
84441260Sbostic 		if(shkp->mcansee && !Invis && cansee(omx,omy)) {
84541260Sbostic 			gx = u.ux;
84641260Sbostic 			gy = u.uy;
84741260Sbostic 		}
84841260Sbostic 		Blind = saveBlind;
84941260Sbostic 		avoid = FALSE;
85041260Sbostic 	} else {
85141260Sbostic #define	GDIST(x,y)	((x-gx)*(x-gx)+(y-gy)*(y-gy))
85241260Sbostic 		if(Invis)
85341260Sbostic 		  avoid = FALSE;
85441260Sbostic 		else {
85541260Sbostic 		  uondoor = (u.ux == ESHK(shkp)->shd.x &&
85641260Sbostic 				u.uy == ESHK(shkp)->shd.y);
85741260Sbostic 		  if(uondoor) {
85841260Sbostic 		    if(ESHK(shkp)->billct)
85941260Sbostic 			pline("Hello %s! Will you please pay before leaving?",
86041260Sbostic 				plname);
86141260Sbostic 		    badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
86241260Sbostic 		    if(satdoor && badinv)
86341260Sbostic 			return(0);
86441260Sbostic 		    avoid = !badinv;
86541260Sbostic 		  } else {
86641260Sbostic 		    avoid = (u.uinshop && dist(gx,gy) > 8);
86741260Sbostic 		    badinv = FALSE;
86841260Sbostic 		  }
86941260Sbostic 
87041260Sbostic 		  if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
87141260Sbostic 		  	&& GDIST(omx,omy) < 3){
87241260Sbostic 		  	if(!badinv && !online(omx,omy))
87341260Sbostic 				return(0);
87441260Sbostic 		  	if(satdoor)
87541260Sbostic 		  		appr = gx = gy = 0;
87641260Sbostic 		  }
87741260Sbostic 		}
87841260Sbostic 	}
87941260Sbostic 	if(omx == gx && omy == gy)
88041260Sbostic 		return(0);
88141260Sbostic 	if(shkp->mconf) {
88241260Sbostic 		avoid = FALSE;
88341260Sbostic 		appr = 0;
88441260Sbostic 	}
88541260Sbostic 	nix = omx;
88641260Sbostic 	niy = omy;
88741260Sbostic 	cnt = mfndpos(shkp,poss,info,ALLOW_SSM);
88841260Sbostic 	if(avoid && uondoor) {		/* perhaps we cannot avoid him */
88941260Sbostic 		for(i=0; i<cnt; i++)
89041260Sbostic 			if(!(info[i] & NOTONL)) goto notonl_ok;
89141260Sbostic 		avoid = FALSE;
89241260Sbostic 	notonl_ok:
89341260Sbostic 		;
89441260Sbostic 	}
89541260Sbostic 	chi = -1;
89641260Sbostic 	chcnt = 0;
89741260Sbostic 	for(i=0; i<cnt; i++){
89841260Sbostic 		nx = poss[i].x;
89941260Sbostic 		ny = poss[i].y;
90041260Sbostic 	   	if(levl[nx][ny].typ == ROOM
90141260Sbostic 		|| shkroom != ESHK(shkp)->shoproom
90241260Sbostic 		|| ESHK(shkp)->following) {
90341260Sbostic #ifdef STUPID
90441260Sbostic 		    /* cater for stupid compilers */
90541260Sbostic 		    register int zz;
90641260Sbostic #endif STUPID
90741260Sbostic 		    if(uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
90841260Sbostic 			nix = nx; niy = ny; chi = i; break;
90941260Sbostic 		    }
91041260Sbostic 		    if(avoid && (info[i] & NOTONL))
91141260Sbostic 			continue;
91241260Sbostic 		    if((!appr && !rn2(++chcnt)) ||
91341260Sbostic #ifdef STUPID
91441260Sbostic 			(appr && (zz = GDIST(nix,niy)) && zz > GDIST(nx,ny))
91541260Sbostic #else
91641260Sbostic 			(appr && GDIST(nx,ny) < GDIST(nix,niy))
91741260Sbostic #endif STUPID
91841260Sbostic 			) {
91941260Sbostic 			    nix = nx;
92041260Sbostic 			    niy = ny;
92141260Sbostic 			    chi = i;
92241260Sbostic 		    }
92341260Sbostic 		}
92441260Sbostic 	}
92541260Sbostic 	if(nix != omx || niy != omy){
92641260Sbostic 		if(info[chi] & ALLOW_M){
92741260Sbostic 			mtmp = m_at(nix,niy);
92841260Sbostic 			if(hitmm(shkp,mtmp) == 1 && rn2(3) &&
92941260Sbostic 			   hitmm(mtmp,shkp) == 2) return(2);
93041260Sbostic 			return(0);
93141260Sbostic 		} else if(info[chi] & ALLOW_U){
93241260Sbostic 			(void) hitu(shkp, d(mdat->damn, mdat->damd)+1);
93341260Sbostic 			return(0);
93441260Sbostic 		}
93541260Sbostic 		shkp->mx = nix;
93641260Sbostic 		shkp->my = niy;
93741260Sbostic 		pmon(shkp);
93841260Sbostic 		if(ib) {
93941260Sbostic 			freeobj(ib);
94041260Sbostic 			mpickobj(shkp, ib);
94141260Sbostic 		}
94241260Sbostic 		return(1);
94341260Sbostic 	}
94441260Sbostic 	return(0);
94541260Sbostic }
94641260Sbostic 
94741260Sbostic /* He is digging in the shop. */
shopdig(fall)94841260Sbostic shopdig(fall)
94941260Sbostic register int fall;
95041260Sbostic {
95141260Sbostic     if(!fall) {
95241260Sbostic 	if(u.utraptype == TT_PIT)
95341260Sbostic 	    pline("\"Be careful, sir, or you might fall through the floor.\"");
95441260Sbostic 	else
95541260Sbostic 	    pline("\"Please, do not damage the floor here.\"");
95641260Sbostic     } else if(dist(shopkeeper->mx, shopkeeper->my) < 3) {
95741260Sbostic 	register struct obj *obj, *obj2;
95841260Sbostic 
95941260Sbostic 	pline("%s grabs your backpack!", shkname(shopkeeper));
96041260Sbostic 	for(obj = invent; obj; obj = obj2) {
96141260Sbostic 		obj2 = obj->nobj;
96241260Sbostic 		if(obj->owornmask) continue;
96341260Sbostic 		freeinv(obj);
96441260Sbostic 		obj->nobj = shopkeeper->minvent;
96541260Sbostic 		shopkeeper->minvent = obj;
96641260Sbostic 		if(obj->unpaid)
96741260Sbostic 			subfrombill(obj);
96841260Sbostic 	}
96941260Sbostic     }
97041260Sbostic }
97141260Sbostic #endif QUEST
97241260Sbostic 
online(x,y)97341260Sbostic online(x,y) {
97441260Sbostic 	return(x==u.ux || y==u.uy ||
97541260Sbostic 		(x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));
97641260Sbostic }
97741260Sbostic 
97841260Sbostic /* Does this monster follow me downstairs? */
follower(mtmp)97941260Sbostic follower(mtmp)
98041260Sbostic register struct monst *mtmp;
98141260Sbostic {
98241260Sbostic 	return( mtmp->mtame || index("1TVWZi&, ", mtmp->data->mlet)
98341260Sbostic #ifndef QUEST
98441260Sbostic 		|| (mtmp->isshk && ESHK(mtmp)->following)
98541260Sbostic #endif QUEST
98641260Sbostic 		);
98741260Sbostic }
988