Fandom

Wikihack

Source:NetHack 3.0.0/shk.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Below is the full text to shk.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.0/shk.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)shk.c	3.0	89/02/10
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    /* block some unused #defines to avoid overloading some cpp's */
6.    #define MONATTK_H
7.    #include "hack.h"
8.    
9.    #include "eshk.h"
10.   
11.   #ifdef KOPS
12.   static int makekops();
13.   static void kops_gone();
14.   #endif /* KOPS */
15.   
16.   #define	NOTANGRY(mon)	mon->mpeaceful
17.   #define	ANGRY(mon)	!NOTANGRY(mon)
18.   
19.   /* Descriptor of current shopkeeper. Note that the bill need not be
20.      per-shopkeeper, since it is valid only when in a shop. */
21.   static struct monst *shopkeeper = 0;
22.   static struct bill_x *bill;
23.   static int shlevel = 0;	/* level of this shopkeeper */
24.   /* struct obj *billobjs;	/* objects on bill with bp->useup */
25.   				/* only accessed here and by save & restore */
26.   static long int total;		/* filled by addupbill() */
27.   static long int followmsg;	/* last time of follow message */
28.   static void setpaid(), findshk P((int));
29.   static int dopayobj P((struct bill_x *)), getprice P((struct obj *));
30.   static struct obj *bp_to_obj P((struct bill_x *));
31.   
32.   /*
33.   	invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
34.   		obj->quan <= bp->bquan
35.    */
36.   
37.   char *
38.   shkname(mtmp)				/* called in do_name.c */
39.   register struct monst *mtmp;
40.   {
41.   	return(ESHK(mtmp)->shknam);
42.   }
43.   
44.   void
45.   shkdead(mtmp)				/* called in mon.c */
46.   register struct monst *mtmp;
47.   {
48.   	register struct eshk *eshk = ESHK(mtmp);
49.   
50.   	if(eshk->shoplevel == dlevel)
51.   		rooms[eshk->shoproom].rtype = OROOM;
52.   	if(mtmp == shopkeeper) {
53.   		setpaid();
54.   		shopkeeper = 0;
55.   		bill = (struct bill_x *) -1000;	/* dump core when referenced */
56.   	}
57.   }
58.   
59.   void
60.   replshk(mtmp,mtmp2)
61.   register struct monst *mtmp, *mtmp2;
62.   {
63.   	if(mtmp == shopkeeper) {
64.   		shopkeeper = mtmp2;
65.   		bill = &(ESHK(shopkeeper)->bill[0]);
66.   	}
67.   }
68.   
69.   static void
70.   setpaid(){	/* caller has checked that shopkeeper exists */
71.   		/* either we paid or left the shop or he just died */
72.   	register struct obj *obj;
73.   	register struct monst *mtmp;
74.   	for(obj = invent; obj; obj = obj->nobj)
75.   		obj->unpaid = 0;
76.   	for(obj = fobj; obj; obj = obj->nobj)
77.   		obj->unpaid = 0;
78.   	for(obj = fcobj; obj; obj = obj->nobj)
79.   		obj->unpaid = 0;
80.   	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
81.   		for(obj = mtmp->minvent; obj; obj = obj->nobj)
82.   			obj->unpaid = 0;
83.   	for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
84.   		for(obj = mtmp->minvent; obj; obj = obj->nobj)
85.   			obj->unpaid = 0;
86.   	while(obj = billobjs){
87.   		billobjs = obj->nobj;
88.   		free((genericptr_t) obj);
89.   	}
90.   	if(shopkeeper) {
91.   		ESHK(shopkeeper)->billct = 0;
92.   		ESHK(shopkeeper)->credit = 0L;
93.   		ESHK(shopkeeper)->debit = 0L;
94.   	}
95.   }
96.   
97.   static void
98.   addupbill(){	/* delivers result in total */
99.   		/* caller has checked that shopkeeper exists */
100.  	register int ct = ESHK(shopkeeper)->billct;
101.  	register struct bill_x *bp = bill;
102.  	total = 0;
103.  	while(ct--){
104.  		total += bp->price * bp->bquan;
105.  		bp++;
106.  	}
107.  }
108.  
109.  int
110.  inshop() {
111.  	register int roomno = inroom(u.ux,u.uy);
112.  
113.  	/* Did we just leave a shop? */
114.  	if(u.uinshop &&
115.  	    (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
116.  
117.  	/* This is part of the bugfix for shopkeepers not having their
118.  	 * bill paid.  As reported by ab@unido -dgk
119.  	 * I made this standard due to the KOPS code below. -mrs
120.  	 */
121.  		if(shopkeeper) {
122.  		    if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->debit) {
123.  			if(inroom(shopkeeper->mx, shopkeeper->my)
124.  			    == u.uinshop - 1)	/* ab@unido */
125.  			    You("escaped the shop without paying!");
126.  			addupbill();
127.  			total += ESHK(shopkeeper)->debit;
128.  			You("stole %ld zorkmids worth of merchandise.",
129.  				total);
130.  			ESHK(shopkeeper)->robbed += total;
131.  			ESHK(shopkeeper)->credit = 0L;
132.  			ESHK(shopkeeper)->debit = 0L;
133.  			if (pl_character[0] != 'R') /* stealing is unlawful */
134.  				adjalign(-sgn(u.ualigntyp));
135.  			setpaid();
136.  			if((rooms[ESHK(shopkeeper)->shoproom].rtype == SHOPBASE)
137.  			    == (rn2(3) == 0))
138.  			    ESHK(shopkeeper)->following = 1;
139.  #ifdef KOPS
140.  		    {   /* Keystone Kops srt@ucla */
141.  			coord mm;
142.  
143.  			if (flags.soundok)
144.  			    pline("An alarm sounds throughout the dungeon!");
145.  			if(flags.verbose) {
146.  			    if((mons[PM_KEYSTONE_KOP].geno & G_GENOD) &&
147.   			       (mons[PM_KOP_SERGEANT].geno & G_GENOD) &&
148.   			       (mons[PM_KOP_LIEUTENANT].geno & G_GENOD) &&
149.  			       (mons[PM_KOP_KAPTAIN].geno & G_GENOD)) {
150.  				if (flags.soundok)
151.  				    pline("But no one seems to respond to it.");
152.  			    } else
153.  				pline("The Keystone Kops are after you!");
154.  			}
155.  			/* Create a swarm near the staircase */
156.  			mm.x = xdnstair;
157.  			mm.y = ydnstair;
158.  			(void) makekops(&mm);
159.  			/* Create a swarm near the shopkeeper */
160.  			mm.x = shopkeeper->mx;
161.  			mm.y = shopkeeper->my;
162.  			(void) makekops(&mm);
163.  		    }
164.  #endif
165.  		    }
166.  		    shopkeeper = 0;
167.  		    shlevel = 0;
168.  		}
169.  		u.uinshop = 0;
170.  	}
171.  
172.  	/* Did we just enter a zoo of some kind? */
173.  	/* This counts everything except shops and vaults
174.  	   -- vault.c insists that a vault remain a VAULT */
175.  	if(roomno >= 0) {
176.  		register int rt = rooms[roomno].rtype;
177.  		register struct monst *mtmp;
178.  
179.  		switch (rt) {
180.  		case ZOO:
181.  		    pline("Welcome to David's treasure zoo!");
182.  		    break;
183.  		case SWAMP:
184.  		    pline("It looks rather muddy down here.");
185.  		    break;
186.  #ifdef THRONES
187.  		case COURT:
188.  		    You("enter an opulent throne room!");
189.  		    break;
190.  #endif
191.  		case MORGUE:
192.  		    if(midnight())
193.  			pline("Run away!  Run away!");
194.  		    else
195.  			You("have an uncanny feeling...");
196.  		    break;
197.  		case BEEHIVE:
198.  		    You("enter a giant beehive!");
199.  		    break;
200.  #ifdef ARMY
201.  		case BARRACKS:
202.  		    if(!((mons[PM_SOLDIER].geno & G_GENOD) &&
203.  		         (mons[PM_SERGEANT].geno & G_GENOD) &&
204.  		         (mons[PM_LIEUTENANT].geno & G_GENOD) &&
205.  		         (mons[PM_CAPTAIN].geno & G_GENOD)))
206.  		    	You("enter a military barracks!");
207.  		    else You("enter an abandoned barracks.");
208.  		    break;
209.  #endif
210.  #ifdef ORACLE
211.  		case DELPHI:
212.  		    if(!(mons[PM_ORACLE].geno & G_GENOD))
213.  		        pline("\"Hello, %s, welcome to Delphi!\"", plname);
214.  		    break;
215.  #endif
216.  		default:
217.  		    rt = 0;
218.  		}
219.  
220.  		if(rt != 0) {
221.  		    rooms[roomno].rtype = OROOM;
222.  		    if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO)
223.  			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
224.  			    /* was if(rt != ZOO || !rn2(3)) -- why should ZOO
225.  			       be different from COURT or MORGUE? */
226.  			    if(!Stealth && !rn2(3))
227.  				mtmp->msleep = 0;
228.  		}
229.  	}
230.  #if defined(ALTARS) && defined(THEOLOGY)
231.  	if(roomno >= 0 && rooms[roomno].rtype == TEMPLE) {
232.  	    intemple();
233.  	}
234.  #endif
235.  	/* Did we just enter a shop? */
236.  	if(roomno >= 0 && rooms[roomno].rtype >= SHOPBASE) {
237.  	    register int rt = rooms[roomno].rtype;
238.  
239.  	    if(shlevel != dlevel || !shopkeeper
240.  				 || ESHK(shopkeeper)->shoproom != roomno)
241.  		findshk(roomno);
242.  	    if(!shopkeeper) {
243.  		rooms[roomno].rtype = OROOM;
244.  		u.uinshop = 0;
245.  	    } else if(!u.uinshop){
246.  		if(!ESHK(shopkeeper)->visitct ||
247.  		   strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)) {
248.  		    /* He seems to be new here */
249.  		    ESHK(shopkeeper)->visitct = 0;
250.  		    ESHK(shopkeeper)->following = 0;
251.  		    (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
252.  		    NOTANGRY(shopkeeper) = 1;
253.  		}
254.  		if(!ESHK(shopkeeper)->following && inhishop(shopkeeper)) {
255.  		    if(ANGRY(shopkeeper))
256.  			pline("\"So, %s, you dare return to %s's %s?!\"",
257.  			    plname,
258.  			    shkname(shopkeeper),
259.  			    shtypes[rt - SHOPBASE].name);
260.  		    else
261.  		    if(ESHK(shopkeeper)->robbed)
262.  			pline("\"Beware, %s!  I am upset about missing stock!\"",
263.  			    plname);
264.  		    else
265.  			pline("\"Hello, %s!  Welcome%s to %s's %s!\"",
266.  			    plname,
267.  			    ESHK(shopkeeper)->visitct++ ? " again" : "",
268.  			    shkname(shopkeeper),
269.  			    shtypes[rt - SHOPBASE].name);
270.  		    if(carrying(PICK_AXE) != (struct obj *)0) {
271.  			pline(NOTANGRY(shopkeeper) ?
272.  			   "\"Will you please leave your pick-axe outside?\"" :
273.  			   "\"Leave the pick-axe outside.\"");
274.  			if(dochug(shopkeeper)) {
275.  			    u.uinshop = 0;	/* he died moving */
276.  			    return(0);
277.  			}
278.  		    }
279.  		}
280.  		u.uinshop = (unsigned int)(roomno + 1);
281.  	    }
282.  	}
283.  	return (int)u.uinshop;
284.  }
285.  
286.  int
287.  inhishop(mtmp)
288.  register struct monst *mtmp;
289.  {
290.  	return((ESHK(mtmp)->shoproom == inroom(mtmp->mx, mtmp->my) &&
291.  		ESHK(mtmp)->shoplevel == dlevel));
292.  }
293.  
294.  static void
295.  findshk(roomno)
296.  register int roomno;
297.  {
298.  	register struct monst *mtmp;
299.  
300.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
301.  	    if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
302.  			   && ESHK(mtmp)->shoplevel == dlevel) {
303.  		shopkeeper = mtmp;
304.  		bill = &(ESHK(shopkeeper)->bill[0]);
305.  		shlevel = dlevel;
306.  		if(ANGRY(shopkeeper) &&
307.  		   strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
308.  			NOTANGRY(shopkeeper) = 1;
309.  		/* billobjs = 0; -- this is wrong if we save in a shop */
310.  		/* (and it is harmless to have too many things in billobjs) */
311.  		return;
312.  	}
313.  	shopkeeper = 0;
314.  	shlevel = 0;
315.  	bill = (struct bill_x *) -1000;	/* dump core when referenced */
316.  }
317.  
318.  static struct bill_x *
319.  onbill(obj)
320.  register struct obj *obj;
321.  {
322.  	register struct bill_x *bp;
323.  	if(!shopkeeper) return (struct bill_x *)0;
324.  	for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
325.  		if(bp->bo_id == obj->o_id) {
326.  			if(!obj->unpaid) pline("onbill: paid obj on bill?");
327.  			return(bp);
328.  		}
329.  	if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
330.  	return (struct bill_x *)0;
331.  }
332.  
333.  /* called with two args on merge */
334.  void
335.  obfree(obj, merge)
336.  register struct obj *obj, *merge;
337.  {
338.  	register struct bill_x *bp = onbill(obj);
339.  	register struct bill_x *bpm;
340.  	if(bp) {
341.  		if(!merge){
342.  			bp->useup = 1;
343.  			obj->unpaid = 0;	/* only for doinvbill */
344.  			obj->nobj = billobjs;
345.  			billobjs = obj;
346.  			return;
347.  		}
348.  		bpm = onbill(merge);
349.  		if(!bpm){
350.  			/* this used to be a rename */
351.  			impossible("obfree: not on bill??");
352.  			return;
353.  		} else {
354.  			/* this was a merger */
355.  			bpm->bquan += bp->bquan;
356.  			ESHK(shopkeeper)->billct--;
357.  			*bp = bill[ESHK(shopkeeper)->billct];
358.  		}
359.  	}
360.  	free((genericptr_t) obj);
361.  }
362.  
363.  static long
364.  check_credit(tmp, shkp)
365.  long tmp;
366.  register struct monst *shkp;
367.  {
368.  	long credit = ESHK(shkp)->credit;
369.  
370.  	if(credit == 0L) return(tmp);
371.  	if(credit >= tmp) {
372.  		pline("The price is deducted from your credit.");
373.  		ESHK(shkp)->credit -=tmp;
374.  		tmp = 0L;
375.  	} else {
376.  		pline("The price is partially covered by your credit.");
377.  		ESHK(shkp)->credit = 0L;
378.  		tmp -= credit;
379.  	}
380.  	return(tmp);
381.  }
382.  
383.  static void
384.  pay(tmp,shkp)
385.  long tmp;
386.  register struct monst *shkp;
387.  {
388.  	long robbed = ESHK(shkp)->robbed;
389.  	long balance = ((tmp <= 0) ? tmp : check_credit(tmp, shkp));
390.  
391.  	u.ugold -= balance;
392.  	shkp->mgold += balance;
393.  	flags.botl = 1;
394.  	if(robbed) {
395.  		robbed -= tmp;
396.  		if(robbed < 0) robbed = 0;
397.  		ESHK(shkp)->robbed = robbed;
398.  	}
399.  }
400.  
401.  /* return shkp to home position */
402.  void
403.  home_shk(shkp)
404.  register struct monst *shkp;
405.  {
406.  	register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y;
407.  	if(levl[x][y].mmask)
408.  		mnearto(m_at(x,y), x, y, FALSE);
409.  	levl[shkp->mx][shkp->my].mmask = 0;
410.  	shkp->mx = x;
411.  	shkp->my = y;
412.  	levl[shkp->mx][shkp->my].mmask = 1;
413.  	unpmon(shkp);
414.  }
415.  
416.  void
417.  make_happy_shk(shkp)
418.  struct monst *shkp;
419.  {
420.  	register boolean wasmad = ANGRY(shkp);
421.  
422.  	NOTANGRY(shkp) = 1;
423.  	ESHK(shkp)->following = 0;
424.  	ESHK(shkp)->robbed = 0;
425.  	if (pl_character[0] != 'R')
426.  		adjalign(sgn(u.ualigntyp));
427.  	if(!inhishop(shkp)) {
428.  		pline("Satisfied, %s suddenly disappears!", mon_nam(shkp));
429.  		if(ESHK(shkp)->shoplevel == dlevel)
430.  			home_shk(shkp);
431.  		else
432.  			fall_down(shkp, ESHK(shkp)->shoplevel);
433.  	} else if(wasmad)
434.  		pline("%s calms down.", Monnam(shkp));
435.  #ifdef KOPS
436.  	kops_gone();
437.  #endif
438.  }
439.  
440.  static const char no_money[] = "Moreover, you have no money.";
441.  
442.  int
443.  dopay()
444.  {
445.  	long ltmp;
446.  	register struct bill_x *bp;
447.  	register struct monst *shkp;
448.  	int pass, tmp;
449.  
450.  	multi = 0;
451.  	(void) inshop();
452.  	for(shkp = fmon; shkp; shkp = shkp->nmon)
453.  		if(shkp->isshk && dist(shkp->mx,shkp->my) < 3)
454.  			break;
455.  	if(!shkp && u.uinshop && inhishop(shopkeeper))
456.  		shkp = shopkeeper;
457.  
458.  	if(!shkp) {
459.  		pline("There is nobody here to receive your payment.");
460.  		return(0);
461.  	}
462.  	ltmp = ESHK(shkp)->robbed;
463.  	if(shkp != shopkeeper && NOTANGRY(shkp)) {
464.  		if(!ltmp)
465.  		    You("do not owe %s anything.", mon_nam(shkp));
466.  		else if(!u.ugold)
467.  		    You("have no money.");
468.  		else {
469.  		    long ugold = u.ugold;
470.  
471.  		    if(ugold  > ltmp) {
472.  			You("give %s the %ld gold pieces %s asked for.",
473.  			    mon_nam(shkp), ltmp,
474.  			    ESHK(shkp)->ismale ? "he" : "she");
475.  			pay(ltmp, shkp);
476.  		    } else {
477.  			You("give %s all your gold.", mon_nam(shkp));
478.  			pay(u.ugold, shkp);
479.  		    }
480.  		    if(ugold < ltmp/2)
481.  			pline("Unfortunately, %s doesn't look satisfied.",
482.  			    ESHK(shkp)->ismale ? "he" : "she");
483.  		    else
484.  			make_happy_shk(shkp);
485.  		}
486.  		return(1);
487.  	}
488.  
489.  	/* ltmp is still ESHK(shkp)->robbed here */
490.  	if(!ESHK(shkp)->billct) {
491.  		if(!ltmp && NOTANGRY(shkp)) {
492.  		    You("do not owe %s anything.", mon_nam(shkp));
493.  		    if(!u.ugold) pline(no_money);
494.  		} else if(ltmp) {
495.  		    pline("%s is after blood, not money!", mon_nam(shkp));
496.  		    if(u.ugold < ltmp/2) {
497.  			if(!u.ugold) pline(no_money);
498.  			else pline("Besides, you don't have enough to interest %s.",
499.  				ESHK(shkp)->ismale ? "him" : "her");
500.  			return(1);
501.  		    }
502.  		    pline("But since %s shop has been robbed recently,",
503.  			ESHK(shkp)->ismale ? "his" : "her");
504.  		    pline("you %scompensate %s for %s losses.",
505.  			(u.ugold < ltmp) ? "partially " : "",
506.  			mon_nam(shkp),
507.  			ESHK(shkp)->ismale ? "his" : "her");
508.  		    pay(u.ugold < ltmp ? u.ugold : ltmp, shkp);
509.  		    make_happy_shk(shkp);
510.  		} else {
511.  		    /* shopkeeper is angry, but has not been robbed --
512.  		     * door broken, attacked, etc. */
513.  		    pline("%s is after your hide, not your money!",
514.  					mon_nam(shkp));
515.  		    if(u.ugold < 1000) {
516.  			if(!u.ugold) pline(no_money);
517.  			else
518.  		pline("Besides, you don't have enough to interest %s.",
519.  				ESHK(shkp)->ismale ? "him" : "her");
520.  			return(1);
521.  		    }
522.  		    You("try to appease %s by giving %s 1000 gold pieces.",
523.  				a_monnam(shkp, "angry"),
524.  				ESHK(shkp)->ismale ? "him" : "her");
525.  		    pay(1000L,shkp);
526.  		    if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
527.  		    		|| rn2(3))
528.  			make_happy_shk(shkp);
529.  		    else
530.  			pline("But %s is as angry as ever.", Monnam(shkp));
531.  		}
532.  		return(1);
533.  	}
534.  	if(shkp != shopkeeper) {
535.  		impossible("dopay: not to shopkeeper?");
536.  		if(shopkeeper) setpaid();
537.  		return(0);
538.  	}
539.  	/* pay debt, if any, first */
540.  	if(ESHK(shopkeeper)->debit) {
541.  	        You("owe %s %ld zorkmids for the use of merchandise.",
542.  			shkname(shopkeeper), ESHK(shopkeeper)->debit);
543.  	        if(u.ugold + ESHK(shopkeeper)->credit < 
544.  					ESHK(shopkeeper)->debit) {
545.  		    pline("But you don't have enough gold%s.",
546.  			ESHK(shopkeeper)->credit ? " or credit" : "");
547.  		    return(1);
548.  	        } else {
549.  		    long dtmp = ESHK(shopkeeper)->debit;
550.  
551.  		    if(ESHK(shopkeeper)->credit >= dtmp) {
552.  			ESHK(shopkeeper)->credit -= dtmp;
553.  			ESHK(shopkeeper)->debit = 0L;
554.  	                Your("debt is covered by your credit.");
555.  		    } else if(!ESHK(shopkeeper)->credit) {
556.  			u.ugold -= dtmp;
557.  			shopkeeper->mgold += dtmp;
558.  			ESHK(shopkeeper)->debit = 0L;
559.  			You("pay that debt.");
560.  			flags.botl = 1;
561.  		    } else {
562.  			dtmp -= ESHK(shopkeeper)->credit;
563.  			ESHK(shopkeeper)->credit = 0L;
564.  			u.ugold -= dtmp;
565.  			shopkeeper->mgold += dtmp;
566.  			ESHK(shopkeeper)->debit = 0L;
567.  			pline("That debt is partially offset by your credit.");
568.  			You("pay the remainder.");
569.  			flags.botl = 1;
570.  		    }
571.  		}
572.  	}
573.  	for(pass = 0; pass <= 1; pass++) {
574.  		tmp = 0;
575.  		while(tmp < ESHK(shopkeeper)->billct) {
576.  		    bp = &bill[tmp];
577.  		    if(!pass && !bp->useup) {
578.  			tmp++;
579.  			continue;
580.  		    }
581.  		    if(!dopayobj(bp)) return(1);
582.  #ifdef MSDOS
583.  		    *bp = bill[--ESHK(shopkeeper)->billct];
584.  #else
585.  		    bill[tmp] = bill[--ESHK(shopkeeper)->billct];
586.  #endif /* MSDOS /**/
587.  		}
588.  	}
589.  	pline("\"Thank you for shopping in %s's %s!\"",
590.  		shkname(shopkeeper),
591.  		shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - SHOPBASE].name);
592.  	NOTANGRY(shopkeeper) = 1;
593.  	return(1);
594.  }
595.  
596.  /* return 1 if paid successfully */
597.  /*        0 if not enough money */
598.  /*       -1 if object could not be found (but was paid) */
599.  static int
600.  dopayobj(bp)
601.  register struct bill_x *bp;
602.  {
603.  	register struct obj *obj;
604.  	long ltmp;
605.  
606.  	/* find the object on one of the lists */
607.  	obj = bp_to_obj(bp);
608.  
609.  	if(!obj) {
610.  		impossible("Shopkeeper administration out of order.");
611.  		setpaid();	/* be nice to the player */
612.  		return(0);
613.  	}
614.  
615.  	if(!obj->unpaid && !bp->useup){
616.  		impossible("Paid object on bill??");
617.  		return(1);
618.  	}
619.  	obj->unpaid = 0;
620.  	ltmp = bp->price * bp->bquan;
621.  	if(ANGRY(shopkeeper)) ltmp += ltmp/3;
622.  	if(u.ugold + ESHK(shopkeeper)->credit < ltmp){
623.  		You("don't have gold%s enough to pay for %s.",
624.  			(ESHK(shopkeeper)->credit > 0L) ? " or credit" : "",
625.  			doname(obj));
626.  		obj->unpaid = 1;
627.  		return(0);
628.  	}
629.  	pay(ltmp, shopkeeper);
630.  	You("bought %s for %ld gold piece%s.",
631.  		doname(obj), ltmp, plur(ltmp));
632.  	if(bp->useup) {
633.  		register struct obj *otmp = billobjs;
634.  		if(obj == billobjs)
635.  			billobjs = obj->nobj;
636.  		else {
637.  			while(otmp && otmp->nobj != obj) otmp = otmp->nobj;
638.  			if(otmp) otmp->nobj = obj->nobj;
639.  			else pline("Error in shopkeeper administration.");
640.  		}
641.  		free((genericptr_t) obj);
642.  	}
643.  	return(1);
644.  }
645.  
646.  /* routine called after dying (or quitting) with nonempty bill or upset shk */
647.  boolean
648.  paybill(){
649.  	register struct monst *mtmp;
650.  	register int loss = 0;
651.  	register struct obj *otmp;
652.  	register xchar ox, oy;
653.  	register boolean take = FALSE;
654.  	register boolean taken = FALSE;
655.  
656.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
657.  	    if(mtmp->isshk) {
658.  		/* for bones: we don't want a shopless shk around */
659.  		if(ESHK(mtmp)->shoplevel != dlevel) mongone(mtmp);
660.  		else shopkeeper = mtmp;
661.  	    }
662.  
663.  	if(!shopkeeper) return(FALSE);
664.  
665.  	/* get one case out of the way: you die in the shop, the */
666.  	/* shopkeeper is peaceful, nothing stolen, nothing owed. */
667.  	if(in_shop(u.ux,u.uy) && !IS_DOOR(levl[u.ux][u.uy].typ) &&
668.  	    !ESHK(shopkeeper)->billct && !ESHK(shopkeeper)->robbed &&
669.  	    inhishop(shopkeeper) && NOTANGRY(shopkeeper) &&
670.  	    !ESHK(shopkeeper)->following) {
671.  		pline("%s gratefully inherits all your possessions.",
672.  				Monnam(shopkeeper));
673.  		goto clear;
674.  	}
675.  
676.  	if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->robbed) {
677.  		addupbill();
678.  		loss = ((total >= ESHK(shopkeeper)->robbed) ? total :
679.  				ESHK(shopkeeper)->robbed);
680.  		take = TRUE;
681.  	}
682.  
683.  	if(ESHK(shopkeeper)->following || ANGRY(shopkeeper) || take) {
684.  		if((loss > u.ugold) || !loss) {
685.  			pline("%s comes and takes all your possessions.",
686.  					Monnam(shopkeeper));
687.  			taken = TRUE;
688.  			shopkeeper->mgold += u.ugold;
689.  			u.ugold = 0;
690.  			/* in case bones: make it be for real... */
691.  			if(!in_shop(u.ux, u.uy) || IS_DOOR(levl[u.ux][u.uy].typ)) {
692.  			    /* shk.x,shk.y is the position immediately in
693.  			     * front of the door -- move in one more space
694.  			     */
695.  			    ox = ESHK(shopkeeper)->shk.x;
696.  			    oy = ESHK(shopkeeper)->shk.y;
697.  			    ox += sgn(ox - ESHK(shopkeeper)->shd.x);
698.  			    oy += sgn(oy - ESHK(shopkeeper)->shd.y);
699.  			} else {
700.  			    ox = u.ux;
701.  			    oy = u.uy;
702.  			}
703.  
704.  			if (invent) {
705.  			    levl[ox][oy].omask = 1;
706.  			    for(otmp = invent; otmp; otmp = otmp->nobj) {
707.  				otmp->ox = ox;
708.  				otmp->oy = oy;
709.  				otmp->age = 0;
710.  			    }
711.  
712.  			    /* add to main object list at end so invent is
713.  			       still good */
714.  			    if (fobj) {
715.  				otmp = fobj;
716.  				while(otmp->nobj)
717.  				    otmp = otmp->nobj;
718.  				otmp->nobj = invent;
719.  			    } else
720.  				fobj = invent;
721.  			}
722.  		} else {
723.  			u.ugold -= loss;
724.  			shopkeeper->mgold += loss;
725.  			pline("%s comes and takes %ld zorkmids %sowed %s.",
726.  			       Monnam(shopkeeper),
727.  			       loss,
728.  			       strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ) ? "" : "you ",
729.  			       ESHK(shopkeeper)->ismale ? "him" : "her");
730.  		}
731.  
732.  		/* in case we create bones */
733.  		if(!inhishop(shopkeeper))
734.  			home_shk(shopkeeper);
735.  	}
736.  clear:
737.  	setpaid();
738.  	return(taken);
739.  }
740.  
741.  /* find obj on one of the lists */
742.  static struct obj *
743.  bp_to_obj(bp)
744.  register struct bill_x *bp;
745.  {
746.  	register struct obj *obj;
747.  	register struct monst *mtmp;
748.  	register unsigned int id = bp->bo_id;
749.  
750.  	if(bp->useup)
751.  		obj = o_on(id, billobjs);
752.  	else if(!(obj = o_on(id, invent)) &&
753.  		!(obj = o_on(id, fobj)) &&
754.  		!(obj = o_on(id, fcobj))) {
755.  		    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
756.  			if(obj = o_on(id, mtmp->minvent))
757.  			    break;
758.  		    for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
759.  			if(obj = o_on(id, mtmp->minvent))
760.  			    break;
761.  		}
762.  	return(obj);
763.  }
764.  
765.  static long
766.  get_cost(obj)
767.  register struct obj *obj;
768.  {
769.  	register long tmp;
770.  
771.  	tmp = getprice(obj);
772.  	if (!tmp) tmp = 5;
773.  	if (ANGRY(shopkeeper) || 
774.  		(pl_character[0] == 'T' && u.ulevel < (MAXULEV/2))
775.  #ifdef SHIRT
776.  	    || (uarmu && !uarm) /* wearing just a Hawaiian shirt */
777.  #endif
778.  	   )
779.  		tmp += tmp/3;
780.  	if (ACURR(A_CHA) > 18)		tmp /= 2;
781.  	else if (ACURR(A_CHA) > 17)	tmp = (tmp * 2)/3;
782.  	else if (ACURR(A_CHA) > 15)	tmp = (tmp * 3)/4;
783.  	else if (ACURR(A_CHA) < 11)	tmp = (tmp * 4)/3;
784.  	else if (ACURR(A_CHA) < 8)	tmp = (tmp * 3)/2;
785.  	else if (ACURR(A_CHA) < 6)	tmp *= 2;
786.  	return(tmp);
787.  }
788.  
789.  
790.  /* called in hack.c when we pickup an object */
791.  void
792.  addtobill(obj, ininv)
793.  register struct obj *obj;
794.  register boolean ininv;
795.  {
796.  	register struct bill_x *bp;
797.  	char	buf[40];
798.  	if(!shopkeeper || !inhishop(shopkeeper)) return;
799.  
800.  	if(!costly_spot(obj->ox,obj->oy) ||	/* either pickup or kick */
801.  		onbill(obj) /* perhaps we threw it away earlier */
802.  	      ) return;
803.  	if(ESHK(shopkeeper)->billct == BILLSZ) {
804.  		You("got that for free!");
805.  		return;
806.  	}
807.  	/* To recognize objects the shopkeeper is not interested in. -dgk
808.  	 */
809.  	if (obj->no_charge) {
810.  		obj->no_charge = 0;
811.  		return;
812.  	}
813.  	bp = &bill[ESHK(shopkeeper)->billct];
814.  	bp->bo_id = obj->o_id;
815.  	bp->bquan = obj->quan;
816.  	bp->useup = 0;
817.  	bp->price = get_cost(obj);
818.  	Strcpy(buf, "\"For you, ");
819.  	if (ANGRY(shopkeeper)) Strcat(buf, "scum ");
820.  	else {
821.  	    switch(rnd(4)
822.  #ifdef HARD
823.  		   + u.udemigod
824.  #endif
825.  				) {
826.  		case 1:	Strcat(buf, "good");
827.  			break;
828.  		case 2:	Strcat(buf, "honored");
829.  			break;
830.  		case 3:	Strcat(buf, "most gracious");
831.  			break;
832.  		case 4:	Strcat(buf, "esteemed");
833.  			break;
834.  		case 5: if (u.ualigntyp == U_CHAOTIC) Strcat(buf, "un");
835.  			Strcat(buf, "holy");
836.  			break;
837.  	    }
838.  #ifdef POLYSELF
839.  	    if(!is_human(uasmon)) Strcat(buf, " creature");
840.  	    else
841.  #endif
842.  		Strcat(buf, (flags.female) ? " lady" : " sir");
843.  	}
844.  	obj->dknown = 1; /* after all, the shk is telling you what it is */
845.  	if(ininv) {
846.  		obj->quan = 1; /* fool xname() into giving singular */
847.  		pline("%s; only %d %s %s.\"", buf, bp->price,
848.  			(bp->bquan > 1) ? "per" : "for this", xname(obj));
849.  		obj->quan = bp->bquan;
850.  	} else pline("The %s will cost you %d zorkmids%s.",
851.  			xname(obj), bp->price,
852.  			(bp->bquan > 1) ? " each" : "");
853.  	ESHK(shopkeeper)->billct++;
854.  	obj->unpaid = 1;
855.  }
856.  
857.  void
858.  splitbill(obj, otmp)
859.  register struct obj *obj, *otmp;
860.  {
861.  	/* otmp has been split off from obj */
862.  	register struct bill_x *bp;
863.  	register int tmp;
864.  	bp = onbill(obj);
865.  	if(!bp) {
866.  		impossible("splitbill: not on bill?");
867.  		return;
868.  	}
869.  	if(bp->bquan < otmp->quan) {
870.  		impossible("Negative quantity on bill??");
871.  	}
872.  	if(bp->bquan == otmp->quan) {
873.  		impossible("Zero quantity on bill??");
874.  	}
875.  	bp->bquan -= otmp->quan;
876.  
877.  	if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0;
878.  	else {
879.  		tmp = bp->price;
880.  		bp = &bill[ESHK(shopkeeper)->billct];
881.  		bp->bo_id = otmp->o_id;
882.  		bp->bquan = otmp->quan;
883.  		bp->useup = 0;
884.  		bp->price = tmp;
885.  		ESHK(shopkeeper)->billct++;
886.  	}
887.  }
888.  
889.  void
890.  subfrombill(obj)
891.  register struct obj *obj;
892.  {
893.  	long ltmp;
894.  	/* register int tmp;	/* use of tmp commented out below */
895.  	register struct obj *otmp;
896.  	register struct bill_x *bp;
897.  	if(!costly_spot(u.ux,u.uy))
898.  		return;
899.  	if((bp = onbill(obj)) != 0) {
900.  		obj->unpaid = 0;
901.  		if(bp->bquan > obj->quan){
902.  			otmp = newobj(0);
903.  			*otmp = *obj;
904.  			bp->bo_id = otmp->o_id = flags.ident++;
905.  			otmp->quan = (bp->bquan -= obj->quan);
906.  			otmp->owt = 0;	/* superfluous */
907.  			otmp->onamelth = 0;
908.  			bp->useup = 1;
909.  			otmp->nobj = billobjs;
910.  			billobjs = otmp;
911.  			return;
912.  		}
913.  		ESHK(shopkeeper)->billct--;
914.  		*bp = bill[ESHK(shopkeeper)->billct];
915.  		return;
916.  	}
917.  	if(obj->unpaid) {
918.  		if(inhishop(shopkeeper))
919.  		    pline("%s didn't notice.", Monnam(shopkeeper));
920.  		obj->unpaid = 0;
921.  		return;		/* %% */
922.  	}
923.  	/* he dropped something of his own - probably wants to sell it */
924.  	if(shopkeeper->msleep || shopkeeper->mfroz || !inhishop(shopkeeper))
925.  		return;
926.  	ltmp = getprice(obj) * obj->quan;
927.  	if(ESHK(shopkeeper)->billct == BILLSZ
928.  	   || !saleable(rooms[ESHK(shopkeeper)->shoproom].rtype-SHOPBASE, obj)
929.  	   || otmp->olet == BALL_SYM || ltmp == 0L) {
930.  		pline("%s seems not interested.", Monnam(shopkeeper));
931.  		obj->no_charge = 1;
932.  		return;
933.  	}
934.  	if (ANGRY(shopkeeper) || (pl_character[0] == 'T' && u.ulevel < (MAXULEV/2))
935.  #ifdef SHIRT
936.  	    || (uarmu && !uarm) /* wearing just a Hawaiian shirt */
937.  #endif
938.  	   ) {
939.  		ltmp /= 3;
940.  		NOTANGRY(shopkeeper) = 1;
941.  	} else	ltmp /= 2;
942.  	if(ESHK(shopkeeper)->robbed) {
943.  		if((ESHK(shopkeeper)->robbed -= ltmp) < 0)
944.  			ESHK(shopkeeper)->robbed = 0;
945.  pline("\"Thank you for your contribution to restock this recently plundered shop.\"");
946.  		return;
947.  	}
948.  	if(ltmp > shopkeeper->mgold)
949.  		ltmp = shopkeeper->mgold;
950.  	pay(-ltmp, shopkeeper);
951.  	if(!ltmp) {
952.  		pline("%s gladly accepts %s but cannot pay you at present.",
953.  			Monnam(shopkeeper), doname(obj));
954.  			obj->no_charge = 1;
955.  	} else
956.  	You("sold %s for %ld gold piece%s.", doname(obj), ltmp,
957.  		plur(ltmp));
958.  }
959.  
960.  int
961.  doinvbill(mode)
962.  int mode;		/* 0: deliver count 1: paged */
963.  {
964.  	register struct bill_x *bp;
965.  	register struct obj *obj;
966.  	long totused, thisused;
967.  	char buf[BUFSZ];
968.  
969.  	if(mode == 0) {
970.  	    register int cnt = 0;
971.  
972.  	    if(shopkeeper)
973.  		for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)
974.  		    if(bp->useup ||
975.  		      ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
976.  			cnt++;
977.  	    return(cnt);
978.  	}
979.  
980.  	if(!shopkeeper) {
981.  		impossible("doinvbill: no shopkeeper?");
982.  		return(0);
983.  	}
984.  
985.  	set_pager(0);
986.  	if(page_line("Unpaid articles already used up:") || page_line(""))
987.  	    goto quit;
988.  
989.  	totused = 0;
990.  	for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {
991.  	    obj = bp_to_obj(bp);
992.  	    if(!obj) {
993.  		impossible("Bad shopkeeper administration.");
994.  		goto quit;
995.  	    }
996.  	    if(bp->useup || bp->bquan > obj->quan) {
997.  		register int cnt, oquan, uquan;
998.  
999.  		oquan = obj->quan;
1000. 		uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
1001. 		thisused = bp->price * uquan;
1002. 		totused += thisused;
1003. 		obj->quan = uquan;		/* cheat doname */
1004. 		Sprintf(buf, "x -  %s", doname(obj));
1005. 		obj->quan = oquan;		/* restore value */
1006. 		for(cnt = 0; buf[cnt]; cnt++);
1007. 		while(cnt < 50)
1008. 			buf[cnt++] = ' ';
1009. 		Sprintf(&buf[cnt], " %5ld zorkmids", thisused);
1010. 		if(page_line(buf))
1011. 			goto quit;
1012. 	    }
1013. 	}
1014. 	Sprintf(buf, "Total:%50ld zorkmids", totused);
1015. 	if(page_line("") || page_line(buf))
1016. 		goto quit;
1017. 	set_pager(1);
1018. 	return(0);
1019. quit:
1020. 	set_pager(2);
1021. 	return(0);
1022. }
1023. 
1024. #define HUNGRY	2
1025. static int
1026. getprice(obj)
1027. register struct obj *obj;
1028. {
1029. 	register int tmp = objects[obj->otyp].oc_cost;
1030. 
1031. 	switch(obj->olet) {
1032. 	case AMULET_SYM:
1033. 		if(obj->otyp == AMULET_OF_YENDOR) {
1034. 			/* don't let the player get rich selling fakes */
1035. 			tmp = (obj->spe < 0 ? 0 : 3500);
1036. 		}
1037. 		break;
1038. 	case FOOD_SYM:
1039. 		/* simpler hunger check, (2-4)*cost */
1040. 		if (u.uhs >= HUNGRY) tmp *= u.uhs;
1041. 		break;
1042. 	case WAND_SYM:
1043. 		if (obj->spe == -1) tmp = 0;
1044. 		break;
1045. 	case POTION_SYM:
1046. 		if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
1047. 			tmp = 0;
1048. 		break;
1049. 	case ARMOR_SYM:
1050. 		if (u.uac > 0) tmp += u.uac * 2;
1051. 	case WEAPON_SYM:
1052. 		if (obj->spe > 0) tmp += 10 * obj->spe;
1053. 		break;
1054. 	case CHAIN_SYM:
1055. 		pline("Strange... carrying a chain?");
1056. 		break;
1057. 	}
1058. 	return(tmp);
1059. }
1060. 
1061. int
1062. shkcatch(obj)
1063. register struct obj *obj;
1064. {
1065. 	register struct monst *shkp = shopkeeper;
1066. 
1067. 	if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&
1068. 	    u.dx && u.dy &&
1069. 	    inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop &&
1070. 	    shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&
1071. 	    u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {
1072. 		pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));
1073. 		obj->nobj = shkp->minvent;
1074. 		shkp->minvent = obj;
1075. 		return(1);
1076. 	}
1077. 	return(0);
1078. }
1079. 
1080. /*
1081.  * shk_move: return 1: he moved  0: he didn't  -1: let m_move do it  -2: died
1082.  */
1083. int
1084. shk_move(shkp)
1085. register struct monst *shkp;
1086. {
1087. 	register xchar gx,gy,omx,omy;
1088. 	register int udist;
1089. 	register schar appr;
1090. 	int z;
1091. 	schar shkroom;
1092. 	boolean uondoor, satdoor, avoid, badinv;
1093. 
1094. 	omx = shkp->mx;
1095. 	omy = shkp->my;
1096. 
1097. 	if((udist = dist(omx,omy)) < 3) {
1098. 		if(ANGRY(shkp)) {
1099. 			if(Displaced)
1100. 			  Your("displaced image doesn't fool %s!",
1101. 				Monnam(shkp));
1102. 			(void) mattacku(shkp);
1103. 			return(0);
1104. 		}
1105. 		if(ESHK(shkp)->following) {
1106. 			if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)) {
1107. 			    pline("\"Hello, %s!  I was looking for %s.\"",
1108. 				    plname, ESHK(shkp)->customer);
1109. 				    ESHK(shkp)->following = 0;
1110. 			    return(0);
1111. 			}
1112. 			if(moves > followmsg+4) {
1113. 			    pline("\"Hello, %s!  Didn't you forget to pay?\"",
1114. 				    plname);
1115. 			    followmsg = moves;
1116. #ifdef HARD
1117. 			    if (!rn2(4)) {
1118. 	    pline ("%s doesn't like customers who don't pay.", Monnam(shkp));
1119. 				NOTANGRY(shkp) = 0;
1120. 			    }
1121. #endif
1122. 			}
1123. 			if(udist < 2)
1124. 			    return(0);
1125. 		}
1126. 	}
1127. 
1128. 	shkroom = inroom(omx,omy);
1129. 	appr = 1;
1130. 	gx = ESHK(shkp)->shk.x;
1131. 	gy = ESHK(shkp)->shk.y;
1132. 	satdoor = (gx == omx && gy == omy);
1133. 	if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
1134. 		gx = u.ux;
1135. 		gy = u.uy;
1136. 		if(shkroom < 0 || shkroom != inroom(u.ux,u.uy))
1137. 		    if(udist > 4)
1138. 			return(-1);	/* leave it to m_move */
1139. 	} else if(ANGRY(shkp)) {
1140. 		long saveBlind = Blinded;
1141. 		struct obj *saveUblindf = ublindf;
1142. 		Blinded = 0;
1143. 		ublindf = (struct obj *)0;
1144. 		if(shkp->mcansee && !Invis && cansee(omx,omy)) {
1145. 			gx = u.ux;
1146. 			gy = u.uy;
1147. 		}
1148. 		Blinded = saveBlind;
1149. 		ublindf = saveUblindf;
1150. 		avoid = FALSE;
1151. 	} else {
1152. #define	GDIST(x,y)	(dist2(x,y,gx,gy))
1153. 		if(Invis)
1154. 		    avoid = FALSE;
1155. 		else {
1156. 		    uondoor = (u.ux == ESHK(shkp)->shd.x &&
1157. 				u.uy == ESHK(shkp)->shd.y);
1158. 		    if(uondoor) {
1159. 			if(ESHK(shkp)->billct && inhishop(shkp))
1160. 			    pline(NOTANGRY(shkp) ?
1161. 				"\"Hello, %s!  Will you please pay before leaving?\"" :
1162. 				"\"Hey, %s!  Don't leave without paying!\"",
1163. 				plname);
1164. 			badinv = (!!carrying(PICK_AXE));
1165. 			if(satdoor && badinv)
1166. 			    return(0);
1167. 			avoid = !badinv;
1168. 		    } else {
1169. 			avoid = (u.uinshop && dist(gx,gy) > 8);
1170. 			badinv = FALSE;
1171. 		    }
1172. 
1173. 		    if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
1174. 			&& GDIST(omx,omy) < 3) {
1175. 			if(!badinv && !online(omx,omy))
1176. 			    return(0);
1177. 			if(satdoor)
1178. 			    appr = gx = gy = 0;
1179. 		    }
1180. 		}
1181. 	}
1182. 	
1183. 	return(move_special(shkp,shkroom,appr,uondoor,avoid,omx,omy,gx,gy));
1184. }
1185. 
1186. int
1187. online(x,y)		/*	New version to speed things up.
1188. 			 *	Compiler dependant, may not always work.
1189. 			 */
1190. register xchar x, y;
1191. {
1192. 	return((x-=u.ux) == 0 || (y-=u.uy) == 0 || x == y || (x+=y) == 0);
1193. }
1194. 
1195. /*			Original version, just in case...
1196.  *online(x,y) {
1197.  *	return(x==u.ux || y==u.uy || (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));
1198.  *}
1199.  */
1200. 
1201. /* for use in levl_follower (mondata.c) */
1202. boolean
1203. is_fshk(mtmp)
1204. register struct monst *mtmp;
1205. {
1206. 	return(mtmp->isshk && ESHK(mtmp)->following);
1207. }
1208. 
1209. /* He is digging in the shop. */
1210. void
1211. shopdig(fall)
1212. register int fall;
1213. {
1214.     if(!shopkeeper) return;
1215.     if(!inhishop(shopkeeper)) {
1216. 	if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp));
1217. 	return;
1218.     }
1219. 
1220.     if(!fall) {
1221. 	if(u.utraptype == TT_PIT)
1222. 	    pline("\"Be careful, %s, or you might fall through the floor.\"",
1223. 		flags.female ? "madam" : "sir");
1224. 	else
1225. 	    pline("\"%s, do not damage the floor here!\"",
1226. 			flags.female ? "Madam" : "Sir");
1227. 	if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp));
1228.     } else if(um_dist(shopkeeper->mx, shopkeeper->my, 2)) {
1229. 	register struct obj *obj, *obj2;
1230. 
1231. 	if(dist(shopkeeper->mx, shopkeeper->my) > 2) {
1232. 		mnexto(shopkeeper);
1233. 		/* for some reason he can't come next to you */
1234. 		if(dist(shopkeeper->mx, shopkeeper->my) > 2) {
1235. 		    pline("%s curses you in anger and frustration!",
1236. 					shkname(shopkeeper));
1237. 		    NOTANGRY(shopkeeper) = 0;
1238. 		    return;
1239. 		} else pline("%s leaps, and grabs your backpack!",
1240. 					shkname(shopkeeper));
1241. 	} else pline("%s grabs your backpack!", shkname(shopkeeper));
1242. 
1243. 	for(obj = invent; obj; obj = obj2) {
1244. 		obj2 = obj->nobj;
1245. 		if(obj->owornmask) continue;
1246. 		freeinv(obj);
1247. 		obj->nobj = shopkeeper->minvent;
1248. 		shopkeeper->minvent = obj;
1249. 		if(obj->unpaid)
1250. 			subfrombill(obj);
1251. 	}
1252.     }
1253. }
1254. 
1255. #ifdef KOPS
1256. static int
1257. makekops(mm)		/* returns the number of (all types of) Kops  made */
1258. coord *mm;
1259. {
1260. 	register int cnt = dlevel + rnd(5);
1261. 	register int scnt = (cnt / 3) + 1;	/* at least one sarge */
1262. 	register int lcnt = (cnt / 6);		/* maybe a lieutenant */
1263. 	register int kcnt = (cnt / 9);		/* and maybe a kaptain */
1264. 
1265. 	while(cnt--) {
1266. 	    enexto(mm, mm->x, mm->y);
1267. 	    (void) makemon(&mons[PM_KEYSTONE_KOP], mm->x, mm->y);
1268. 	}
1269. 	while(scnt--) {
1270. 	    enexto(mm, mm->x, mm->y);
1271. 	    (void) makemon(&mons[PM_KOP_SERGEANT], mm->x, mm->y);
1272. 	}
1273. 	while(lcnt--) {
1274. 	    enexto(mm, mm->x, mm->y);
1275. 	    (void) makemon(&mons[PM_KOP_LIEUTENANT], mm->x, mm->y);
1276. 	}
1277. 	while(kcnt--) {
1278. 	    enexto(mm, mm->x, mm->y);
1279. 	    (void) makemon(&mons[PM_KOP_KAPTAIN], mm->x, mm->y);
1280. 	}
1281. 	return(cnt + scnt + lcnt + kcnt);
1282. }
1283. #endif
1284. 
1285. boolean
1286. in_shop(x,y)
1287. register int x, y;
1288. {
1289. 	register int roomno = inroom(x, y);
1290. 
1291. 	if (roomno < 0) return(FALSE);
1292. 	return (IS_SHOP(rooms[roomno]));
1293. }
1294. 
1295. void
1296. pay_for_door(x,y,dmgstr)
1297. register int x, y;
1298. register char *dmgstr;
1299. {
1300. 	register struct monst *mtmp;
1301. 	register int ox, oy;
1302. 	register int roomno = inroom(x, y);
1303. 	register int damage = (ACURR(A_STR) > 18) ? 400 : 20 * ACURR(A_STR);
1304. 
1305. 	/* make sure this function is not used in the wrong place */
1306. 	if(!(IS_DOOR(levl[x][y].typ) && in_shop(x, y))) return;
1307. 
1308. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1309. 	    if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
1310. 			   && ESHK(mtmp)->shoplevel == dlevel) {
1311. 		shopkeeper = mtmp;
1312. 	}
1313. 
1314. 	if(!shopkeeper) return;
1315. 
1316. 	/* not the best introduction to the shk... */
1317. 	(void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
1318. 
1319. 	/* if he is already on the war path, be sure it's all out */
1320. 	if(ANGRY(shopkeeper) || ESHK(shopkeeper)->following) {
1321. 		NOTANGRY(shopkeeper) = 0;
1322. 		ESHK(shopkeeper)->following = 1;
1323. 		return;
1324. 	}
1325. 
1326. 	ox = shopkeeper->mx;
1327. 	oy = shopkeeper->my;
1328. 
1329. 	/* if he's not in his shop.. */
1330. 	if(!in_shop(ox, oy)) return;
1331. 
1332. 	/* if a !shopkeeper shows up at the door, move him */
1333. 	if(levl[x][y].mmask && (mtmp = m_at(x, y)) != shopkeeper) {
1334. 		if(flags.soundok) {
1335. 		    You("hear an angry voice: \"Out of my way, scum!\"");
1336. 		    (void) fflush(stdout);
1337. #if defined(SYSV) || defined(ULTRIX)
1338. 		    (void)
1339. #endif
1340. #ifdef UNIX
1341. 			sleep(1);
1342. #endif
1343. 		}
1344. 		mnearto(mtmp, x, y, FALSE);
1345. 	}
1346. 
1347. 	/* make shk show up at the door */
1348. 	levl[shopkeeper->mx][shopkeeper->my].mmask = 0;
1349. 	levl[x][y].mmask = 1;
1350. 	shopkeeper->mx = x;
1351. 	shopkeeper->my = y;
1352. 	pmon(shopkeeper);
1353. 
1354. 	if(um_dist(x, y, 1)) goto chase;
1355. 
1356. 	if(u.ugold < damage || !rn2(50)) {
1357. chase:
1358. 		if(um_dist(x, y, 1))
1359. 		    pline("%s shouts: \"Who dared %s my door?\"",
1360. 				shkname(shopkeeper), dmgstr);
1361. 		else pline("\"How dare you %s my door?\"", dmgstr);
1362. 		NOTANGRY(shopkeeper) = 0;
1363. 		ESHK(shopkeeper)->following = 1;
1364. 		return;
1365. 	}
1366. 
1367. 	pline("\"Cad!  You did %d zorkmids worth of damage!\"  Pay? ", damage);
1368. 	if(yn() != 'n') {
1369. 		u.ugold -= damage;
1370. 		shopkeeper->mgold += damage;
1371. 		flags.botl = 1;
1372. 		pline("Mollified, %s accepts your restitution.",
1373. 			shkname(shopkeeper));
1374. 
1375. 		/* clear ox oy of another monster, if one got there somehow */
1376. 		if(levl[ox][oy].mmask) mnearto(m_at(ox,oy),ox,oy,FALSE);
1377. 
1378. 		/* move shk back to his orig loc */
1379. 		levl[shopkeeper->mx][shopkeeper->my].mmask = 0;
1380. 		levl[ox][oy].mmask = 1;
1381. 		shopkeeper->mx = ox;
1382. 		shopkeeper->my = oy;
1383. 		unpmon(shopkeeper);
1384. 		NOTANGRY(shopkeeper) = 1;
1385. 	}
1386. 	else {
1387. 		pline("\"Oh, yes!  You'll pay!\"");
1388. 		ESHK(shopkeeper)->following = 1;
1389. 		NOTANGRY(shopkeeper) = 0;
1390. 		adjalign(-sgn(u.ualigntyp));
1391. 	}
1392. }
1393. 
1394. /* called in dokick.c when we kick an object in a store */
1395. boolean
1396. costly_spot(x, y)
1397. register int x, y;
1398. {
1399. 	register struct monst *shkp = shopkeeper;
1400. 	
1401. 	if(!shkp) return(FALSE);
1402. 
1403. 	return(in_shop(x, y) && levl[x][y].typ != DOOR &&
1404. 		!(x == ESHK(shkp)->shk.x && y == ESHK(shkp)->shk.y));
1405. }
1406. 
1407. #ifdef KOPS
1408. static void
1409. kops_gone()
1410. {
1411. 	register int cnt = 0;
1412. 	register struct monst *mtmp, *mtmp2;
1413. 
1414. 	/* turn off automatic resurrection of kops */
1415. 	allow_kops = FALSE;
1416. 
1417. 	for(mtmp = fmon; mtmp; mtmp = mtmp2) {
1418. 		mtmp2 = mtmp->nmon;
1419. 		if(mtmp->data->mlet == S_KOP) {
1420. 			mongone(mtmp);
1421. 			cnt++;
1422. 		}
1423. 	}
1424. 	if(cnt) pline("The Kops (disappointed) disappear into thin air.");
1425. 	allow_kops = TRUE;
1426. }
1427. #endif
1428. 
1429. static long
1430. cost_per_charge(otmp)
1431. register struct obj *otmp;
1432. {
1433. 	register long tmp = get_cost(otmp);
1434. 
1435. 	/* The idea is to make the exhaustive use of */
1436. 	/* an unpaid item more expansive than buying */
1437. 	/* outright.				     */
1438. 	if(otmp->otyp == MAGIC_LAMP) {			 /* 1 */
1439. 		tmp += (tmp/3L);
1440. 	} else if(otmp->otyp == MAGIC_MARKER) {  	 /* 70 - 100 */
1441. 		/* no way to determine in advance   */
1442. 		/* how many charges will be wasted. */
1443. 		/* so, arbitrarily, one half of the */
1444. 		/* price per use.		    */
1445. 		tmp = (tmp/2L);
1446. 	} else if(otmp->otyp == BAG_OF_TRICKS) { 	 /* 1 - 20 */
1447. 		tmp = (tmp/5L);
1448. 	} else if(otmp->otyp == CRYSTAL_BALL ||  	 /* 1 - 5 */
1449. 		  otmp->otyp == LAMP ||	                 /* 1-10 */
1450. #ifdef MUSIC
1451. 		 (otmp->otyp >= MAGIC_FLUTE &&
1452. 		  otmp->otyp <= DRUM_OF_EARTHQUAKE) || 	 /* 5 - 9 */
1453. #endif
1454. 	  	  otmp->olet == WAND_SYM) {		 /* 3 - 11 */
1455. 		if(otmp->spe == 1) tmp += (tmp/3L);
1456. 		else tmp = (tmp/4L);
1457. 	}
1458. 	else return(0L);
1459. 	return(tmp);
1460. }
1461. 
1462. /* for using charges of unpaid objects */
1463. void
1464. check_unpaid(otmp)
1465. register struct obj *otmp;
1466. {
1467. 	if(!in_shop(u.ux, u.uy)) return;
1468. 	
1469. 	if(otmp->spe <= 0) return;
1470. 
1471. 	if(otmp->unpaid) {
1472. 		ESHK(shopkeeper)->debit += cost_per_charge(otmp);
1473. 	}
1474. }

Also on Fandom

Random Wiki