Wikia

Wikihack

Source:Shk.c

2,032pages on
this wiki
Talk0

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

Top of file Edit

1.    /*	SCCS Id: @(#)shk.c	3.4	2003/12/04	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    #include "hack.h"
6.    #include "eshk.h"
7.    
8.    /*#define DEBUG*/
9.    
10.   #define PAY_SOME    2
11.   #define PAY_BUY     1
12.   #define PAY_CANT    0	/* too poor */
13.   #define PAY_SKIP  (-1)
14.   #define PAY_BROKE (-2)
15.   
16.   #ifdef KOPS
17.   STATIC_DCL void FDECL(makekops, (coord *));
18.   STATIC_DCL void FDECL(call_kops, (struct monst *,BOOLEAN_P));
19.   # ifdef OVLB
20.   STATIC_DCL void FDECL(kops_gone, (BOOLEAN_P));
21.   # endif /* OVLB */
22.   #endif /* KOPS */
23.   
24.   #define IS_SHOP(x)	(rooms[x].rtype >= SHOPBASE)
25.   
26.   extern const struct shclass shtypes[];	/* defined in shknam.c */
27.   extern struct obj *thrownobj;		/* defined in dothrow.c */
28.   
29.   STATIC_VAR NEARDATA long int followmsg;	/* last time of follow message */
30.   
31.   STATIC_DCL void FDECL(setpaid, (struct monst *));
32.   STATIC_DCL long FDECL(addupbill, (struct monst *));
33.   STATIC_DCL void FDECL(pacify_shk, (struct monst *));
34.   STATIC_DCL struct bill_x *FDECL(onbill, (struct obj *, struct monst *, BOOLEAN_P));
35.   STATIC_DCL struct monst *FDECL(next_shkp, (struct monst *, BOOLEAN_P));
36.   STATIC_DCL long FDECL(shop_debt, (struct eshk *));
37.   STATIC_DCL char *FDECL(shk_owns, (char *,struct obj *));
38.   STATIC_DCL char *FDECL(mon_owns, (char *,struct obj *));
39.   STATIC_DCL void FDECL(clear_unpaid,(struct obj *));
40.   STATIC_DCL long FDECL(check_credit, (long, struct monst *));
41.   STATIC_DCL void FDECL(pay, (long, struct monst *));
42.   STATIC_DCL long FDECL(get_cost, (struct obj *, struct monst *));
43.   STATIC_DCL long FDECL(set_cost, (struct obj *, struct monst *));
44.   STATIC_DCL const char *FDECL(shk_embellish, (struct obj *, long));
45.   STATIC_DCL long FDECL(cost_per_charge, (struct monst *,struct obj *,BOOLEAN_P));
46.   STATIC_DCL long FDECL(cheapest_item, (struct monst *));
47.   STATIC_DCL int FDECL(dopayobj, (struct monst *, struct bill_x *,
48.   			    struct obj **, int, BOOLEAN_P));
49.   STATIC_DCL long FDECL(stolen_container, (struct obj *, struct monst *, long,
50.   				     BOOLEAN_P));
51.   STATIC_DCL long FDECL(getprice, (struct obj *,BOOLEAN_P));
52.   STATIC_DCL void FDECL(shk_names_obj,
53.   		 (struct monst *,struct obj *,const char *,long,const char *));
54.   STATIC_DCL struct obj *FDECL(bp_to_obj, (struct bill_x *));
55.   STATIC_DCL boolean FDECL(inherits, (struct monst *,int,int));
56.   STATIC_DCL void FDECL(set_repo_loc, (struct eshk *));
57.   STATIC_DCL boolean NDECL(angry_shk_exists);
58.   STATIC_DCL void FDECL(rile_shk, (struct monst *));
59.   STATIC_DCL void FDECL(rouse_shk, (struct monst *,BOOLEAN_P));
60.   STATIC_DCL void FDECL(remove_damage, (struct monst *, BOOLEAN_P));
61.   STATIC_DCL void FDECL(sub_one_frombill, (struct obj *, struct monst *));
62.   STATIC_DCL void FDECL(add_one_tobill, (struct obj *, BOOLEAN_P));
63.   STATIC_DCL void FDECL(dropped_container, (struct obj *, struct monst *,
64.   				      BOOLEAN_P));
65.   STATIC_DCL void FDECL(add_to_billobjs, (struct obj *));
66.   STATIC_DCL void FDECL(bill_box_content, (struct obj *, BOOLEAN_P, BOOLEAN_P,
67.   				     struct monst *));
68.   #ifdef OVL1
69.   static boolean FDECL(rob_shop, (struct monst *));
70.   #endif
71.   

money2mon Edit

72.   #ifdef OVLB
73.   /*
74.   	invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
75.   		obj->quan <= bp->bquan
76.    */
77.   
78.   
79.   #ifdef GOLDOBJ
80.   /*
81.       Transfer money from inventory to monster when paying
82.       shopkeepers, priests, oracle, succubus, & other demons.
83.       Simple with only gold coins.
84.       This routine will handle money changing when multiple
85.       coin types is implemented, only appropriate
86.       monsters will pay change.  (Peaceful shopkeepers, priests
87.       & the oracle try to maintain goodwill while selling
88.       their wares or services.  Angry monsters and all demons
89.       will keep anything they get their hands on.
90.       Returns the amount actually paid, so we can know
91.       if the monster kept the change.
92.    */
93.   long
94.   money2mon(mon, amount)
95.   struct monst *mon;
96.   long amount;
97.   {
98.       struct obj *ygold = findgold(invent);
99.   
100.      if (amount <= 0) {
101.  	impossible("%s payment in money2mon!", amount ? "negative" : "zero");
102.  	return 0L;
103.      }
104.      if (!ygold || ygold->quan < amount) {
105.  	impossible("Paying without %s money?", ygold ? "enough" : "");
106.  	return 0L;
107.      }
108.  
109.      if (ygold->quan > amount)
110.  	ygold = splitobj(ygold, amount);
111.      else if (ygold->owornmask)
112.  	remove_worn_item(ygold, FALSE);		/* quiver */
113.      freeinv(ygold);
114.      add_to_minv(mon, ygold);
115.      flags.botl = 1;
116.      return amount;
117.  }
118.  
119.  

money2u Edit

120.  /*
121.      Transfer money from monster to inventory.
122.      Used when the shopkeeper pay for items, and when
123.      the priest gives you money for an ale.
124.   */
125.  void
126.  money2u(mon, amount)
127.  struct monst *mon;
128.  long amount;
129.  {
130.      struct obj *mongold = findgold(mon->minvent);
131.  
132.      if (amount <= 0) {
133.  	impossible("%s payment in money2u!", amount ? "negative" : "zero");
134.  	return;
135.      }
136.      if (!mongold || mongold->quan < amount) {
137.  	impossible("%s paying without %s money?", a_monnam(mon),
138.  		   mongold ? "enough" : "");
139.  	return;
140.      }
141.  
142.      if (mongold->quan > amount) mongold = splitobj(mongold, amount);
143.      obj_extract_self(mongold);
144.  
145.      if (!merge_choice(invent, mongold) && inv_cnt() >= 52) {
146.  	You("have no room for the money!");
147.  	dropy(mongold);
148.      } else {
149.  	addinv(mongold);
150.  	flags.botl = 1;
151.      }
152.  }
153.  
154.  #endif /* GOLDOBJ */
155.  

next_shkp Edit

156.  STATIC_OVL struct monst *
157.  next_shkp(shkp, withbill)
158.  register struct monst *shkp;
159.  register boolean withbill;
160.  {
161.  	for (; shkp; shkp = shkp->nmon) {
162.  	    if (DEADMONSTER(shkp)) continue;
163.  	    if (shkp->isshk && (ESHK(shkp)->billct || !withbill)) break;
164.  	}
165.  
166.  	if (shkp) {
167.  	    if (NOTANGRY(shkp)) {
168.  		if (ESHK(shkp)->surcharge) pacify_shk(shkp);
169.  	    } else {
170.  		if (!ESHK(shkp)->surcharge) rile_shk(shkp);
171.  	    }
172.  	}
173.  	return(shkp);
174.  }
175.  

shkname Edit

176.  char *
177.  shkname(mtmp)				/* called in do_name.c */
178.  register struct monst *mtmp;
179.  {
180.  	return(ESHK(mtmp)->shknam);
181.  }
182.  

shkgone Edit

183.  void
184.  shkgone(mtmp)				/* called in mon.c */
185.  struct monst *mtmp;
186.  {
187.  	struct eshk *eshk = ESHK(mtmp);
188.  	struct mkroom *sroom = &rooms[eshk->shoproom - ROOMOFFSET];
189.  	struct obj *otmp;
190.  	char *p;
191.  	int sx, sy;
192.  
193.  	/* [BUG: some of this should be done on the shop level */
194.  	/*       even when the shk dies on a different level.] */
195.  	if (on_level(&eshk->shoplevel, &u.uz)) {
196.  	    remove_damage(mtmp, TRUE);
197.  	    sroom->resident = (struct monst *)0;
198.  	    if (!search_special(ANY_SHOP))
199.  		level.flags.has_shop = 0;
200.  
201.  	    /* items on shop floor revert to ordinary objects */
202.  	    for (sx = sroom->lx; sx <= sroom->hx; sx++)
203.  	      for (sy = sroom->ly; sy <= sroom->hy; sy++)
204.  		for (otmp = level.objects[sx][sy]; otmp; otmp = otmp->nexthere)
205.  		    otmp->no_charge = 0;
206.  
207.  	    /* Make sure bill is set only when the
208.  	       dead shk is the resident shk. */
209.  	    if ((p = index(u.ushops, eshk->shoproom)) != 0) {
210.  		setpaid(mtmp);
211.  		eshk->bill_p = (struct bill_x *)0;
212.  		/* remove eshk->shoproom from u.ushops */
213.  		do { *p = *(p + 1); } while (*++p);
214.  	    }
215.  	}
216.  }
217.  

set_residency Edit

218.  void
219.  set_residency(shkp, zero_out)
220.  register struct monst *shkp;
221.  register boolean zero_out;
222.  {
223.  	if (on_level(&(ESHK(shkp)->shoplevel), &u.uz))
224.  	    rooms[ESHK(shkp)->shoproom - ROOMOFFSET].resident =
225.  		(zero_out)? (struct monst *)0 : shkp;
226.  }
227.  

replshk Edit

228.  void
229.  replshk(mtmp,mtmp2)
230.  register struct monst *mtmp, *mtmp2;
231.  {
232.  	rooms[ESHK(mtmp2)->shoproom - ROOMOFFSET].resident = mtmp2;
233.  	if (inhishop(mtmp) && *u.ushops == ESHK(mtmp)->shoproom) {
234.  		ESHK(mtmp2)->bill_p = &(ESHK(mtmp2)->bill[0]);
235.  	}
236.  }
237.  

restshk Edit

238.  /* do shopkeeper specific structure munging -dlc */
239.  void
240.  restshk(shkp, ghostly)
241.  struct monst *shkp;
242.  boolean ghostly;
243.  {
244.      if (u.uz.dlevel) {
245.  	struct eshk *eshkp = ESHK(shkp);
246.  
247.  	if (eshkp->bill_p != (struct bill_x *) -1000)
248.  	    eshkp->bill_p = &eshkp->bill[0];
249.  	/* shoplevel can change as dungeons move around */
250.  	/* savebones guarantees that non-homed shk's will be gone */
251.  	if (ghostly) {
252.  	    assign_level(&eshkp->shoplevel, &u.uz);
253.  	    if (ANGRY(shkp) && strncmpi(eshkp->customer, plname, PL_NSIZ))
254.  		pacify_shk(shkp);
255.  	}
256.      }
257.  }
258.  
259.  #endif /* OVLB */

clear_unpaid Edit

260.  #ifdef OVL3
261.  
262.  /* Clear the unpaid bit on all of the objects in the list. */
263.  STATIC_OVL void
264.  clear_unpaid(list)
265.  register struct obj *list;
266.  {
267.      while (list) {
268.  	if (Has_contents(list)) clear_unpaid(list->cobj);
269.  	list->unpaid = 0;
270.  	list = list->nobj;
271.      }
272.  }
273.  #endif /*OVL3*/

setpaid Edit

274.  #ifdef OVLB
275.  
276.  /* either you paid or left the shop or the shopkeeper died */
277.  STATIC_OVL void
278.  setpaid(shkp)
279.  register struct monst *shkp;
280.  {
281.  	register struct obj *obj;
282.  	register struct monst *mtmp;
283.  
284.  	/* FIXME: object handling should be limited to
285.  	   items which are on this particular shk's bill */
286.  
287.  	clear_unpaid(invent);
288.  	clear_unpaid(fobj);
289.  	clear_unpaid(level.buriedobjlist);
290.  	if (thrownobj) thrownobj->unpaid = 0;
291.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
292.  		clear_unpaid(mtmp->minvent);
293.  	for(mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon)
294.  		clear_unpaid(mtmp->minvent);
295.  
296.  	while ((obj = billobjs) != 0) {
297.  		obj_extract_self(obj);
298.  		dealloc_obj(obj);
299.  	}
300.  	if(shkp) {
301.  		ESHK(shkp)->billct = 0;
302.  		ESHK(shkp)->credit = 0L;
303.  		ESHK(shkp)->debit = 0L;
304.  		ESHK(shkp)->loan = 0L;
305.  	}
306.  }
307.  

addupbill Edit

308.  STATIC_OVL long
309.  addupbill(shkp)
310.  register struct monst *shkp;
311.  {
312.  	register int ct = ESHK(shkp)->billct;
313.  	register struct bill_x *bp = ESHK(shkp)->bill_p;
314.  	register long total = 0L;
315.  
316.  	while(ct--){
317.  		total += bp->price * bp->bquan;
318.  		bp++;
319.  	}
320.  	return(total);
321.  }
322.  
323.  #endif /* OVLB */

call_kops Edit

324.  #ifdef OVL1
325.  
326.  #ifdef KOPS
327.  STATIC_OVL void
328.  call_kops(shkp, nearshop)
329.  register struct monst *shkp;
330.  register boolean nearshop;
331.  {
332.  	/* Keystone Kops srt@ucla */
333.  	register boolean nokops;
334.  
335.  	if(!shkp) return;
336.  
337.  	if (flags.soundok)
338.  	    pline("An alarm sounds!");
339.  
340.  	nokops = ((mvitals[PM_KEYSTONE_KOP].mvflags & G_GONE) &&
341.  		  (mvitals[PM_KOP_SERGEANT].mvflags & G_GONE) &&
342.  		  (mvitals[PM_KOP_LIEUTENANT].mvflags & G_GONE) &&
343.  		  (mvitals[PM_KOP_KAPTAIN].mvflags & G_GONE));
344.  
345.  	if(!angry_guards(!flags.soundok) && nokops) {
346.  	    if(flags.verbose && flags.soundok)
347.  		pline("But no one seems to respond to it.");
348.  	    return;
349.  	}
350.  
351.  	if(nokops) return;
352.  
353.  	{
354.  	    coord mm;
355.  
356.  	    if (nearshop) {
357.  		/* Create swarm around you, if you merely "stepped out" */
358.  		if (flags.verbose)
359.  		    pline_The("Keystone Kops appear!");
360.  		mm.x = u.ux;
361.  		mm.y = u.uy;
362.  		makekops(&mm);
363.  		return;
364.  	    }
365.  	    if (flags.verbose)
366.  		 pline_The("Keystone Kops are after you!");
367.  	    /* Create swarm near down staircase (hinders return to level) */
368.  	    mm.x = xdnstair;
369.  	    mm.y = ydnstair;
370.  	    makekops(&mm);
371.  	    /* Create swarm near shopkeeper (hinders return to shop) */
372.  	    mm.x = shkp->mx;
373.  	    mm.y = shkp->my;
374.  	    makekops(&mm);
375.  	}
376.  }
377.  #endif	/* KOPS */
378.  

inside_shop Edit

379.  /* x,y is strictly inside shop */
380.  char
381.  inside_shop(x, y)
382.  register xchar x, y;
383.  {
384.  	register char rno;
385.  
386.  	rno = levl[x][y].roomno;
387.  	if ((rno < ROOMOFFSET) || levl[x][y].edge || !IS_SHOP(rno-ROOMOFFSET))
388.  	    return(NO_ROOM);
389.  	else
390.  	    return(rno);
391.  }
392.  

u_left_shop Edit

393.  void
394.  u_left_shop(leavestring, newlev)
395.  char *leavestring;
396.  boolean newlev;
397.  {
398.  	struct monst *shkp;
399.  	struct eshk *eshkp;
400.  
401.  	/*
402.  	 * IF player
403.  	 * ((didn't leave outright) AND
404.  	 *  ((he is now strictly-inside the shop) OR
405.  	 *   (he wasn't strictly-inside last turn anyway)))
406.  	 * THEN (there's nothing to do, so just return)
407.  	 */
408.  	if(!*leavestring &&
409.  	   (!levl[u.ux][u.uy].edge || levl[u.ux0][u.uy0].edge))
410.  	    return;
411.  
412.  	shkp = shop_keeper(*u.ushops0);
413.  	if (!shkp || !inhishop(shkp))
414.  	    return;	/* shk died, teleported, changed levels... */
415.  
416.  	eshkp = ESHK(shkp);
417.  	if (!eshkp->billct && !eshkp->debit)	/* bill is settled */
418.  	    return;
419.  
420.  	if (!*leavestring && shkp->mcanmove && !shkp->msleeping) {
421.  	    /*
422.  	     * Player just stepped onto shop-boundary (known from above logic).
423.  	     * Try to intimidate him into paying his bill
424.  	     */
425.  	    verbalize(NOTANGRY(shkp) ?
426.  		      "%s!  Please pay before leaving." :
427.  		      "%s!  Don't you leave without paying!",
428.  		      plname);
429.  	    return;
430.  	}
431.  
432.  	if (rob_shop(shkp)) {
433.  #ifdef KOPS
434.  	    call_kops(shkp, (!newlev && levl[u.ux0][u.uy0].edge));
435.  #else
436.  	    (void) angry_guards(FALSE);
437.  #endif
438.  	}
439.  }
440.  

remote_burglary Edit

441.  /* robbery from outside the shop via telekinesis or grappling hook */
442.  void
443.  remote_burglary(x, y)
444.  xchar x, y;
445.  {
446.  	struct monst *shkp;
447.  	struct eshk *eshkp;
448.  
449.  	shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
450.  	if (!shkp || !inhishop(shkp))
451.  	    return;	/* shk died, teleported, changed levels... */
452.  
453.  	eshkp = ESHK(shkp);
454.  	if (!eshkp->billct && !eshkp->debit)	/* bill is settled */
455.  	    return;
456.  
457.  	if (rob_shop(shkp)) {
458.  #ifdef KOPS
459.  	    /*[might want to set 2nd arg based on distance from shop doorway]*/
460.  	    call_kops(shkp, FALSE);
461.  #else
462.  	    (void) angry_guards(FALSE);
463.  #endif
464.  	}
465.  }
466.  

rob_shop Edit

467.  /* shop merchandise has been taken; pay for it with any credit available;  
468.     return false if the debt is fully covered by credit, true otherwise */
469.  static boolean
470.  rob_shop(shkp)
471.  struct monst *shkp;
472.  {
473.  	struct eshk *eshkp;
474.  	long total;
475.  
476.  	eshkp = ESHK(shkp);
477.  	rouse_shk(shkp, TRUE);
478.  	total = (addupbill(shkp) + eshkp->debit);
479.  	if (eshkp->credit >= total) {
480.  	    Your("credit of %ld %s is used to cover your shopping bill.",
481.  		 eshkp->credit, currency(eshkp->credit));
482.  	    total = 0L;		/* credit gets cleared by setpaid() */
483.  	} else {
484.  	    You("escaped the shop without paying!");
485.  	    total -= eshkp->credit;
486.  	}
487.  	setpaid(shkp);
488.  	if (!total) return FALSE;
489.  
490.  	/* by this point, we know an actual robbery has taken place */
491.  	eshkp->robbed += total;
492.  	You("stole %ld %s worth of merchandise.",
493.  	    total, currency(total));
494.  	if (!Role_if(PM_ROGUE))	/* stealing is unlawful */
495.  	    adjalign(-sgn(u.ualign.type));
496.  
497.  	hot_pursuit(shkp);
498.  	return TRUE;
499.  }
500.  

u_entered_shop Edit

501.  void
502.  u_entered_shop(enterstring)
503.  register char *enterstring;
504.  {
505.  
506.  	register int rt;
507.  	register struct monst *shkp;
508.  	register struct eshk *eshkp;
509.  	static const char no_shk[] = "This shop appears to be deserted.";
510.  	static char empty_shops[5];
511.  
512.  	if(!*enterstring)
513.  		return;
514.  
515.  	if(!(shkp = shop_keeper(*enterstring))) {
516.  	    if (!index(empty_shops, *enterstring) &&
517.  		in_rooms(u.ux, u.uy, SHOPBASE) !=
518.  				  in_rooms(u.ux0, u.uy0, SHOPBASE))
519.  		pline(no_shk);
520.  	    Strcpy(empty_shops, u.ushops);
521.  	    u.ushops[0] = '\0';
522.  	    return;
523.  	}
524.  
525.  	eshkp = ESHK(shkp);
526.  
527.  	if (!inhishop(shkp)) {
528.  	    /* dump core when referenced */
529.  	    eshkp->bill_p = (struct bill_x *) -1000;
530.  	    if (!index(empty_shops, *enterstring))
531.  		pline(no_shk);
532.  	    Strcpy(empty_shops, u.ushops);
533.  	    u.ushops[0] = '\0';
534.  	    return;
535.  	}
536.  
537.  	eshkp->bill_p = &(eshkp->bill[0]);
538.  
539.  	if ((!eshkp->visitct || *eshkp->customer) &&
540.  	    strncmpi(eshkp->customer, plname, PL_NSIZ)) {
541.  	    /* You seem to be new here */
542.  	    eshkp->visitct = 0;
543.  	    eshkp->following = 0;
544.  	    (void) strncpy(eshkp->customer,plname,PL_NSIZ);
545.  	    pacify_shk(shkp);
546.  	}
547.  
548.  	if (shkp->msleeping || !shkp->mcanmove || eshkp->following)
549.  	    return;	/* no dialog */
550.  
551.  	if (Invis) {
552.  	    pline("%s senses your presence.", shkname(shkp));
553.  	    verbalize("Invisible customers are not welcome!");
554.  	    return;
555.  	}
556.  
557.  	rt = rooms[*enterstring - ROOMOFFSET].rtype;
558.  
559.  	if (ANGRY(shkp)) {
560.  	    verbalize("So, %s, you dare return to %s %s?!",
561.  		      plname,
562.  		      s_suffix(shkname(shkp)),
563.  		      shtypes[rt - SHOPBASE].name);
564.  	} else if (eshkp->robbed) {
565.  	    pline("%s mutters imprecations against shoplifters.", shkname(shkp));
566.  	} else {
567.  	    verbalize("%s, %s!  Welcome%s to %s %s!",
568.  		      Hello(shkp), plname,
569.  		      eshkp->visitct++ ? " again" : "",
570.  		      s_suffix(shkname(shkp)),
571.  		      shtypes[rt - SHOPBASE].name);
572.  	}
573.  	/* can't do anything about blocking if teleported in */
574.  	if (!inside_shop(u.ux, u.uy)) {
575.  	    boolean should_block;
576.  	    int cnt;
577.  	    const char *tool;
578.  	    struct obj *pick = carrying(PICK_AXE),
579.  		       *mattock = carrying(DWARVISH_MATTOCK);
580.  
581.  	    if (pick || mattock) {
582.  		cnt = 1;	/* so far */
583.  		if (pick && mattock) {	/* carrying both types */
584.  		    tool = "digging tool";
585.  		    cnt = 2;	/* `more than 1' is all that matters */
586.  		} else if (pick) {
587.  		    tool = "pick-axe";
588.  		    /* hack: `pick' already points somewhere into inventory */
589.  		    while ((pick = pick->nobj) != 0)
590.  			if (pick->otyp == PICK_AXE) ++cnt;
591.  		} else {	/* assert(mattock != 0) */
592.  		    tool = "mattock";
593.  		    while ((mattock = mattock->nobj) != 0)
594.  			if (mattock->otyp == DWARVISH_MATTOCK) ++cnt;
595.  		    /* [ALI] Shopkeeper identifies mattock(s) */
596.  		    if (!Blind) makeknown(DWARVISH_MATTOCK);
597.  		}
598.  		verbalize(NOTANGRY(shkp) ?
599.  			  "Will you please leave your %s%s outside?" :
600.  			  "Leave the %s%s outside.",
601.  			  tool, plur(cnt));
602.  		should_block = TRUE;
603.  #ifdef STEED
604.  	    } else if (u.usteed) {
605.  		verbalize(NOTANGRY(shkp) ?
606.  			  "Will you please leave %s outside?" :
607.  			  "Leave %s outside.", y_monnam(u.usteed));
608.  		should_block = TRUE;
609.  #endif
610.  	    } else {
611.  		should_block = (Fast && (sobj_at(PICK_AXE, u.ux, u.uy) ||
612.  				      sobj_at(DWARVISH_MATTOCK, u.ux, u.uy)));
613.  	    }
614.  	    if (should_block) (void) dochug(shkp);  /* shk gets extra move */
615.  	}
616.  	return;
617.  }
618.  

same_price Edit

619.  /*
620.     Decide whether two unpaid items are mergable; caller is responsible for
621.     making sure they're unpaid and the same type of object; we check the price
622.     quoted by the shopkeeper and also that they both belong to the same shk.
623.   */
624.  boolean
625.  same_price(obj1, obj2)
626.  struct obj *obj1, *obj2;
627.  {
628.  	register struct monst *shkp1, *shkp2;
629.  	register struct bill_x *bp1 = 0, *bp2 = 0;
630.  	register boolean are_mergable = FALSE;
631.  
632.  	/* look up the first object by finding shk whose bill it's on */
633.  	for (shkp1 = next_shkp(fmon, TRUE); shkp1;
634.  		shkp1 = next_shkp(shkp1->nmon, TRUE))
635.  	    if ((bp1 = onbill(obj1, shkp1, TRUE)) != 0) break;
636.  	/* second object is probably owned by same shk; if not, look harder */
637.  	if (shkp1 && (bp2 = onbill(obj2, shkp1, TRUE)) != 0) {
638.  	    shkp2 = shkp1;
639.  	} else {
640.  	    for (shkp2 = next_shkp(fmon, TRUE); shkp2;
641.  		    shkp2 = next_shkp(shkp2->nmon, TRUE))
642.  		if ((bp2 = onbill(obj2, shkp2, TRUE)) != 0) break;
643.  	}
644.  
645.  	if (!bp1 || !bp2) impossible("same_price: object wasn't on any bill!");
646.  	else are_mergable = (shkp1 == shkp2 && bp1->price == bp2->price);
647.  	return are_mergable;
648.  }
649.  

shop_debt Edit

650.  /*
651.   * Figure out how much is owed to a given shopkeeper.
652.   * At present, we ignore any amount robbed from the shop, to avoid
653.   * turning the `$' command into a way to discover that the current
654.   * level is bones data which has a shk on the warpath.
655.   */
656.  STATIC_OVL long
657.  shop_debt(eshkp)
658.  struct eshk *eshkp;
659.  {
660.  	struct bill_x *bp;
661.  	int ct;
662.  	long debt = eshkp->debit;
663.  
664.  	for (bp = eshkp->bill_p, ct = eshkp->billct; ct > 0; bp++, ct--)
665.  	    debt += bp->price * bp->bquan;
666.  	return debt;
667.  }
668.  

shopper_financial_report Edit

669.  /* called in response to the `$' command */
670.  void
671.  shopper_financial_report()
672.  {
673.  	struct monst *shkp, *this_shkp = shop_keeper(inside_shop(u.ux, u.uy));
674.  	struct eshk *eshkp;
675.  	long amt;
676.  	int pass;
677.  
678.  	if (this_shkp &&
679.  	    !(ESHK(this_shkp)->credit || shop_debt(ESHK(this_shkp)))) {
680.  	    You("have no credit or debt in here.");
681.  	    this_shkp = 0;	/* skip first pass */
682.  	}
683.  
684.  	/* pass 0: report for the shop we're currently in, if any;
685.  	   pass 1: report for all other shops on this level. */
686.  	for (pass = this_shkp ? 0 : 1; pass <= 1; pass++)
687.  	    for (shkp = next_shkp(fmon, FALSE);
688.  		    shkp; shkp = next_shkp(shkp->nmon, FALSE)) {
689.  		if ((shkp != this_shkp) ^ pass) continue;
690.  		eshkp = ESHK(shkp);
691.  		if ((amt = eshkp->credit) != 0)
692.  		    You("have %ld %s credit at %s %s.",
693.  			amt, currency(amt), s_suffix(shkname(shkp)),
694.  			shtypes[eshkp->shoptype - SHOPBASE].name);
695.  		else if (shkp == this_shkp)
696.  		    You("have no credit in here.");
697.  		if ((amt = shop_debt(eshkp)) != 0)
698.  		    You("owe %s %ld %s.",
699.  			shkname(shkp), amt, currency(amt));
700.  		else if (shkp == this_shkp)
701.  		    You("don't owe any money here.");
702.  	    }
703.  }
704.  
705.  #endif /* OVL1 */

inhishop Edit

706.  #ifdef OVLB
707.  
708.  int
709.  inhishop(mtmp)
710.  register struct monst *mtmp;
711.  {
712.  	return(index(in_rooms(mtmp->mx, mtmp->my, SHOPBASE),
713.  		     ESHK(mtmp)->shoproom) &&
714.  		on_level(&(ESHK(mtmp)->shoplevel), &u.uz));
715.  }
716.  

shop_keeper Edit

717.  struct monst *
718.  shop_keeper(rmno)
719.  register char rmno;
720.  {
721.  	struct monst *shkp = rmno >= ROOMOFFSET ?
722.  				rooms[rmno - ROOMOFFSET].resident : 0;
723.  
724.  	if (shkp) {
725.  	    if (NOTANGRY(shkp)) {
726.  		if (ESHK(shkp)->surcharge) pacify_shk(shkp);
727.  	    } else {
728.  		if (!ESHK(shkp)->surcharge) rile_shk(shkp);
729.  	    }
730.  	}
731.  	return shkp;
732.  }
733.  

tended_shop Edit

734.  boolean
735.  tended_shop(sroom)
736.  register struct mkroom *sroom;
737.  {
738.  	register struct monst *mtmp = sroom->resident;
739.  
740.  	if (!mtmp)
741.  		return(FALSE);
742.  	else
743.  		return((boolean)(inhishop(mtmp)));
744.  }
745.  

onbill Edit

746.  STATIC_OVL struct bill_x *
747.  onbill(obj, shkp, silent)
748.  register struct obj *obj;
749.  register struct monst *shkp;
750.  register boolean silent;
751.  {
752.  	if (shkp) {
753.  		register struct bill_x *bp = ESHK(shkp)->bill_p;
754.  		register int ct = ESHK(shkp)->billct;
755.  
756.  		while (--ct >= 0)
757.  		    if (bp->bo_id == obj->o_id) {
758.  			if (!obj->unpaid) pline("onbill: paid obj on bill?");
759.  			return bp;
760.  		    } else bp++;
761.  	}
762.  	if(obj->unpaid & !silent) pline("onbill: unpaid obj not on bill?");
763.  	return (struct bill_x *)0;
764.  }
765.  

delete_contents Edit

766.  /* Delete the contents of the given object. */
767.  void
768.  delete_contents(obj)
769.  register struct obj *obj;
770.  {
771.  	register struct obj *curr;
772.  
773.  	while ((curr = obj->cobj) != 0) {
774.  	    obj_extract_self(curr);
775.  	    obfree(curr, (struct obj *)0);
776.  	}
777.  }
778.  

obfree Edit

779.  /* called with two args on merge */
780.  void
781.  obfree(obj, merge)
782.  register struct obj *obj, *merge;
783.  {
784.  	register struct bill_x *bp;
785.  	register struct bill_x *bpm;
786.  	register struct monst *shkp;
787.  
788.  	if (obj->otyp == LEASH && obj->leashmon) o_unleash(obj);
789.  	if (obj->oclass == FOOD_CLASS) food_disappears(obj);
790.  	if (obj->oclass == SPBOOK_CLASS) book_disappears(obj);
791.  	if (Has_contents(obj)) delete_contents(obj);
792.  
793.  	shkp = 0;
794.  	if (obj->unpaid) {
795.  	    /* look for a shopkeeper who owns this object */
796.  	    for (shkp = next_shkp(fmon, TRUE); shkp;
797.  		    shkp = next_shkp(shkp->nmon, TRUE))
798.  		if (onbill(obj, shkp, TRUE)) break;
799.  	}
800.  	/* sanity check, more or less */
801.  	if (!shkp) shkp = shop_keeper(*u.ushops);
802.  		/*
803.  		 * Note:  `shkp = shop_keeper(*u.ushops)' used to be
804.  		 *	  unconditional.  But obfree() is used all over
805.  		 *	  the place, so making its behavior be dependent
806.  		 *	  upon player location doesn't make much sense.
807.  		 */
808.  
809.  	if ((bp = onbill(obj, shkp, FALSE)) != 0) {
810.  		if(!merge){
811.  			bp->useup = 1;
812.  			obj->unpaid = 0;	/* only for doinvbill */
813.  			add_to_billobjs(obj);
814.  			return;
815.  		}
816.  		bpm = onbill(merge, shkp, FALSE);
817.  		if(!bpm){
818.  			/* this used to be a rename */
819.  			impossible("obfree: not on bill??");
820.  			return;
821.  		} else {
822.  			/* this was a merger */
823.  			bpm->bquan += bp->bquan;
824.  			ESHK(shkp)->billct--;
825.  #ifdef DUMB
826.  			{
827.  			/* DRS/NS 2.2.6 messes up -- Peter Kendell */
828.  				int indx = ESHK(shkp)->billct;
829.  				*bp = ESHK(shkp)->bill_p[indx];
830.  			}
831.  #else
832.  			*bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
833.  #endif
834.  		}
835.  	}
836.  	dealloc_obj(obj);
837.  }
838.  #endif /* OVLB */

check_credit Edit

839.  #ifdef OVL3
840.  
841.  STATIC_OVL long
842.  check_credit(tmp, shkp)
843.  long tmp;
844.  register struct monst *shkp;
845.  {
846.  	long credit = ESHK(shkp)->credit;
847.  
848.  	if(credit == 0L) return(tmp);
849.  	if(credit >= tmp) {
850.  		pline_The("price is deducted from your credit.");
851.  		ESHK(shkp)->credit -=tmp;
852.  		tmp = 0L;
853.  	} else {
854.  		pline_The("price is partially covered by your credit.");
855.  		ESHK(shkp)->credit = 0L;
856.  		tmp -= credit;
857.  	}
858.  	return(tmp);
859.  }
860.  

pay Edit

861.  STATIC_OVL void
862.  pay(tmp,shkp)
863.  long tmp;
864.  register struct monst *shkp;
865.  {
866.  	long robbed = ESHK(shkp)->robbed;
867.  	long balance = ((tmp <= 0L) ? tmp : check_credit(tmp, shkp));
868.  
869.  #ifndef GOLDOBJ
870.  	u.ugold -= balance;
871.  	shkp->mgold += balance;
872.  #else
873.  	if (balance > 0) money2mon(shkp, balance);
874.  	else if (balance < 0) money2u(shkp, -balance);
875.  #endif
876.  	flags.botl = 1;
877.  	if(robbed) {
878.  		robbed -= tmp;
879.  		if(robbed < 0) robbed = 0L;
880.  		ESHK(shkp)->robbed = robbed;
881.  	}
882.  }
883.  #endif /*OVL3*/

home_shk Edit

884.  #ifdef OVLB
885.  
886.  /* return shkp to home position */
887.  void
888.  home_shk(shkp, killkops)
889.  register struct monst *shkp;
890.  register boolean killkops;
891.  {
892.  	register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y;
893.  
894.  	(void) mnearto(shkp, x, y, TRUE);
895.  	level.flags.has_shop = 1;
896.  	if (killkops) {
897.  #ifdef KOPS
898.  		kops_gone(TRUE);
899.  #else
900.  		You_feel("vaguely apprehensive.");
901.  #endif
902.  		pacify_guards();
903.  	}
904.  	after_shk_move(shkp);
905.  }
906.  

angry_shk_exists Edit

907.  STATIC_OVL boolean
908.  angry_shk_exists()
909.  {
910.  	register struct monst *shkp;
911.  
912.  	for (shkp = next_shkp(fmon, FALSE);
913.  		shkp; shkp = next_shkp(shkp->nmon, FALSE))
914.  	    if (ANGRY(shkp)) return(TRUE);
915.  	return(FALSE);
916.  }
917.  

pacify_shk Edit

918.  /* remove previously applied surcharge from all billed items */
919.  STATIC_OVL void
920.  pacify_shk(shkp)
921.  register struct monst *shkp;
922.  {
923.  	NOTANGRY(shkp) = TRUE;	/* make peaceful */
924.  	if (ESHK(shkp)->surcharge) {
925.  		register struct bill_x *bp = ESHK(shkp)->bill_p;
926.  		register int ct = ESHK(shkp)->billct;
927.  
928.  		ESHK(shkp)->surcharge = FALSE;
929.  		while (ct-- > 0) {
930.  			register long reduction = (bp->price + 3L) / 4L;
931.  			bp->price -= reduction;		/* undo 33% increase */
932.  			bp++;
933.  		}
934.  	}
935.  }
936.  

rile_shk Edit

937.  /* add aggravation surcharge to all billed items */
938.  STATIC_OVL void
939.  rile_shk(shkp)
940.  register struct monst *shkp;
941.  {
942.  	NOTANGRY(shkp) = FALSE;	/* make angry */
943.  	if (!ESHK(shkp)->surcharge) {
944.  		register struct bill_x *bp = ESHK(shkp)->bill_p;
945.  		register int ct = ESHK(shkp)->billct;
946.  
947.  		ESHK(shkp)->surcharge = TRUE;
948.  		while (ct-- > 0) {
949.  			register long surcharge = (bp->price + 2L) / 3L;
950.  			bp->price += surcharge;
951.  			bp++;
952.  		}
953.  	}
954.  }
955.  

rouse_shk Edit

956.  /* wakeup and/or unparalyze shopkeeper */
957.  STATIC_OVL void
958.  rouse_shk(shkp, verbosely)
959.  struct monst *shkp;
960.  boolean verbosely;
961.  {
962.  	if (!shkp->mcanmove || shkp->msleeping) {
963.  	    /* greed induced recovery... */
964.  	    if (verbosely && canspotmon(shkp))
965.  		pline("%s %s.", Monnam(shkp),
966.  		      shkp->msleeping ? "wakes up" : "can move again");
967.  	    shkp->msleeping = 0;
968.  	    shkp->mfrozen = 0;
969.  	    shkp->mcanmove = 1;
970.  	}
971.  }
972.  

make_happy_shk Edit

973.  void
974.  make_happy_shk(shkp, silentkops)
975.  register struct monst *shkp;
976.  register boolean silentkops;
977.  {
978.  	boolean wasmad = ANGRY(shkp);
979.  	struct eshk *eshkp = ESHK(shkp);
980.  
981.  	pacify_shk(shkp);
982.  	eshkp->following = 0;
983.  	eshkp->robbed = 0L;
984.  	if (!Role_if(PM_ROGUE))
985.  		adjalign(sgn(u.ualign.type));
986.  	if(!inhishop(shkp)) {
987.  		char shk_nam[BUFSZ];
988.  		boolean vanished = canseemon(shkp);
989.  
990.  		Strcpy(shk_nam, mon_nam(shkp));
991.  		if (on_level(&eshkp->shoplevel, &u.uz)) {
992.  			home_shk(shkp, FALSE);
993.  			/* didn't disappear if shk can still be seen */
994.  			if (canseemon(shkp)) vanished = FALSE;
995.  		} else {
996.  			/* if sensed, does disappear regardless whether seen */
997.  			if (sensemon(shkp)) vanished = TRUE;
998.  			/* can't act as porter for the Amulet, even if shk
999.  			   happens to be going farther down rather than up */
1000. 			mdrop_special_objs(shkp);
1001. 			/* arrive near shop's door */
1002. 			migrate_to_level(shkp, ledger_no(&eshkp->shoplevel),
1003. 					 MIGR_APPROX_XY, &eshkp->shd);
1004. 		}
1005. 		if (vanished)
1006. 		    pline("Satisfied, %s suddenly disappears!", shk_nam);
1007. 	} else if(wasmad)
1008. 		pline("%s calms down.", Monnam(shkp));
1009. 
1010. 	if(!angry_shk_exists()) {
1011. #ifdef KOPS
1012. 		kops_gone(silentkops);
1013. #endif
1014. 		pacify_guards();
1015. 	}
1016. }
1017. 

hot_pursuit Edit

1018. void
1019. hot_pursuit(shkp)
1020. register struct monst *shkp;
1021. {
1022. 	if(!shkp->isshk) return;
1023. 
1024. 	rile_shk(shkp);
1025. 	(void) strncpy(ESHK(shkp)->customer, plname, PL_NSIZ);
1026. 	ESHK(shkp)->following = 1;
1027. }
1028. 

make_angry_shk Edit

1029. /* used when the shkp is teleported or falls (ox == 0) out of his shop,
1030.  * or when the player is not on a costly_spot and he
1031.  * damages something inside the shop.  these conditions
1032.  * must be checked by the calling function.
1033.  */
1034. void
1035. make_angry_shk(shkp, ox, oy)
1036. register struct monst *shkp;
1037. register xchar ox,oy;
1038. {
1039. 	xchar sx, sy;
1040. 	struct eshk *eshkp = ESHK(shkp);
1041. 
1042. 	/* all pending shop transactions are now "past due" */
1043. 	if (eshkp->billct || eshkp->debit || eshkp->loan || eshkp->credit) {
1044. 	    eshkp->robbed += (addupbill(shkp) + eshkp->debit + eshkp->loan);
1045. 	    eshkp->robbed -= eshkp->credit;
1046. 	    if (eshkp->robbed < 0L) eshkp->robbed = 0L;
1047. 	    /* billct, debit, loan, and credit will be cleared by setpaid */
1048. 	    setpaid(shkp);
1049. 	}
1050. 
1051. 	/* If you just used a wand of teleportation to send the shk away, you
1052. 	   might not be able to see her any more.  Monnam would yield "it",
1053. 	   which makes this message look pretty silly, so temporarily restore
1054. 	   her original location during the call to Monnam. */
1055. 	sx = shkp->mx,  sy = shkp->my;
1056. 	if (isok(ox, oy) && cansee(ox, oy) && !cansee(sx, sy))
1057. 		shkp->mx = ox,  shkp->my = oy;
1058. 	pline("%s %s!", Monnam(shkp),
1059. 	      !ANGRY(shkp) ? "gets angry" : "is furious");
1060. 	shkp->mx = sx,  shkp->my = sy;
1061. 	hot_pursuit(shkp);
1062. }
1063. 
1064. STATIC_VAR const char no_money[] = "Moreover, you%s have no money.";
1065. STATIC_VAR const char not_enough_money[] =
1066. 			    "Besides, you don't have enough to interest %s.";
1067. 
1068. #else
1069. STATIC_VAR const char no_money[];
1070. STATIC_VAR const char not_enough_money[];
1071. #endif /*OVLB*/
1072. 
1073. #ifdef OVL3
1074. 

cheapest_item Edit

1075. STATIC_OVL long
1076. cheapest_item(shkp)   /* delivers the cheapest item on the list */
1077. register struct monst *shkp;
1078. {
1079. 	register int ct = ESHK(shkp)->billct;
1080. 	register struct bill_x *bp = ESHK(shkp)->bill_p;
1081. 	register long gmin = (bp->price * bp->bquan);
1082. 
1083. 	while(ct--){
1084. 		if(bp->price * bp->bquan < gmin)
1085. 			gmin = bp->price * bp->bquan;
1086. 		bp++;
1087. 	}
1088. 	return(gmin);
1089. }
1090. #endif /*OVL3*/

dopay Edit

1091. #ifdef OVL0
1092. 
1093. int
1094. dopay()
1095. {
1096. 	register struct eshk *eshkp;
1097. 	register struct monst *shkp;
1098. 	struct monst *nxtm, *resident;
1099. 	long ltmp;
1100. #ifdef GOLDOBJ
1101. 	long umoney;
1102. #endif
1103. 	int pass, tmp, sk = 0, seensk = 0;
1104. 	boolean paid = FALSE, stashed_gold = (hidden_gold() > 0L);
1105. 
1106. 	multi = 0;
1107. 
1108. 	/* find how many shk's there are, how many are in */
1109. 	/* sight, and are you in a shop room with one.    */
1110. 	nxtm = resident = 0;
1111. 	for (shkp = next_shkp(fmon, FALSE);
1112. 		shkp; shkp = next_shkp(shkp->nmon, FALSE)) {
1113. 	    sk++;
1114. 	    if (ANGRY(shkp) && distu(shkp->mx, shkp->my) <= 2) nxtm = shkp;
1115. 	    if (canspotmon(shkp)) seensk++;
1116. 	    if (inhishop(shkp) && (*u.ushops == ESHK(shkp)->shoproom))
1117. 		resident = shkp;
1118. 	}
1119. 
1120. 	if (nxtm) {			/* Player should always appease an */
1121. 	     shkp = nxtm;		/* irate shk standing next to them. */
1122. 	     goto proceed;
1123. 	}
1124. 
1125. 	if ((!sk && (!Blind || Blind_telepat)) || (!Blind && !seensk)) {
1126.       There("appears to be no shopkeeper here to receive your payment.");
1127. 		return(0);
1128. 	}
1129. 
1130. 	if(!seensk) {
1131. 		You_cant("see...");
1132. 		return(0);
1133. 	}
1134. 
1135. 	/* the usual case.  allow paying at a distance when */
1136. 	/* inside a tended shop.  should we change that?    */
1137. 	if(sk == 1 && resident) {
1138. 		shkp = resident;
1139. 		goto proceed;
1140. 	}
1141. 
1142. 	if (seensk == 1) {
1143. 		for (shkp = next_shkp(fmon, FALSE);
1144. 			shkp; shkp = next_shkp(shkp->nmon, FALSE))
1145. 		    if (canspotmon(shkp)) break;
1146. 		if (shkp != resident && distu(shkp->mx, shkp->my) > 2) {
1147. 		    pline("%s is not near enough to receive your payment.",
1148. 					     Monnam(shkp));
1149. 		    return(0);
1150. 		}
1151. 	} else {
1152. 		struct monst *mtmp;
1153. 		coord cc;
1154. 		int cx, cy;
1155. 
1156. 		pline("Pay whom?");
1157. 		cc.x = u.ux;
1158. 		cc.y = u.uy;
1159. 		if (getpos(&cc, TRUE, "the creature you want to pay") < 0)
1160. 		    return 0;	/* player pressed ESC */
1161. 		cx = cc.x;
1162. 		cy = cc.y;
1163. 		if(cx < 0) {
1164. 		     pline("Try again...");
1165. 		     return(0);
1166. 		}
1167. 		if(u.ux == cx && u.uy == cy) {
1168. 		     You("are generous to yourself.");
1169. 		     return(0);
1170. 		}
1171. 		mtmp = m_at(cx, cy);
1172. 		if(!mtmp) {
1173. 		     There("is no one there to receive your payment.");
1174. 		     return(0);
1175. 		}
1176. 		if(!mtmp->isshk) {
1177. 		     pline("%s is not interested in your payment.",
1178. 				    Monnam(mtmp));
1179. 		     return(0);
1180. 		}
1181. 		if (mtmp != resident && distu(mtmp->mx, mtmp->my) > 2) {
1182. 		     pline("%s is too far to receive your payment.",
1183. 				    Monnam(mtmp));
1184. 		     return(0);
1185. 		}
1186. 		shkp = mtmp;
1187. 	}
1188. 
1189. 	if(!shkp) {
1190. #ifdef DEBUG
1191. 		pline("dopay: null shkp.");
1192. #endif
1193. 		return(0);
1194. 	}
1195. proceed:
1196. 	eshkp = ESHK(shkp);
1197. 	ltmp = eshkp->robbed;
1198. 
1199. 	/* wake sleeping shk when someone who owes money offers payment */
1200. 	if (ltmp || eshkp->billct || eshkp->debit) 
1201. 	    rouse_shk(shkp, TRUE);
1202. 
1203. 	if (!shkp->mcanmove || shkp->msleeping) { /* still asleep/paralyzed */
1204. 		pline("%s %s.", Monnam(shkp),
1205. 		      rn2(2) ? "seems to be napping" : "doesn't respond");
1206. 		return 0;
1207. 	}
1208. 
1209. 	if(shkp != resident && NOTANGRY(shkp)) {
1210. #ifdef GOLDOBJ
1211.                 umoney = money_cnt(invent);
1212. #endif
1213. 		if(!ltmp)
1214. 		    You("do not owe %s anything.", mon_nam(shkp));
1215. #ifndef GOLDOBJ
1216. 		else if(!u.ugold) {
1217. #else
1218. 		else if(!umoney) {
1219. #endif
1220. 		    You("%shave no money.", stashed_gold ? "seem to " : "");
1221. 		    if(stashed_gold)
1222. 			pline("But you have some gold stashed away.");
1223. 		} else {
1224. #ifndef GOLDOBJ
1225. 		    long ugold = u.ugold;
1226. 		    if(ugold > ltmp) {
1227. #else
1228. 		    if(umoney > ltmp) {
1229. #endif
1230. 			You("give %s the %ld gold piece%s %s asked for.",
1231. 			    mon_nam(shkp), ltmp, plur(ltmp), mhe(shkp));
1232. 			pay(ltmp, shkp);
1233. 		    } else {
1234. 			You("give %s all your%s gold.", mon_nam(shkp),
1235. 					stashed_gold ? " openly kept" : "");
1236. #ifndef GOLDOBJ
1237. 			pay(u.ugold, shkp);
1238. #else
1239. 			pay(umoney, shkp);
1240. #endif
1241. 			if (stashed_gold) pline("But you have hidden gold!");
1242. 		    }
1243. #ifndef GOLDOBJ
1244. 		    if((ugold < ltmp/2L) || (ugold < ltmp && stashed_gold))
1245. #else
1246. 		    if((umoney < ltmp/2L) || (umoney < ltmp && stashed_gold))
1247. #endif
1248. 			pline("Unfortunately, %s doesn't look satisfied.",
1249. 			      mhe(shkp));
1250. 		    else
1251. 			make_happy_shk(shkp, FALSE);
1252. 		}
1253. 		return(1);
1254. 	}
1255. 
1256. 	/* ltmp is still eshkp->robbed here */
1257. 	if (!eshkp->billct && !eshkp->debit) {
1258. #ifdef GOLDOBJ
1259.                 umoney = money_cnt(invent);
1260. #endif
1261. 		if(!ltmp && NOTANGRY(shkp)) {
1262. 		    You("do not owe %s anything.", mon_nam(shkp));
1263. #ifndef GOLDOBJ
1264. 		    if (!u.ugold)
1265. #else
1266. 		    if (!umoney)
1267. #endif
1268. 			pline(no_money, stashed_gold ? " seem to" : "");
1269. 		} else if(ltmp) {
1270. 		    pline("%s is after blood, not money!", Monnam(shkp));
1271. #ifndef GOLDOBJ
1272. 		    if(u.ugold < ltmp/2L ||
1273. 				(u.ugold < ltmp && stashed_gold)) {
1274. 			if (!u.ugold)
1275. #else
1276. 		    if(umoney < ltmp/2L ||
1277. 				(umoney < ltmp && stashed_gold)) {
1278. 			if (!umoney)
1279. #endif
1280. 			    pline(no_money, stashed_gold ? " seem to" : "");
1281. 			else pline(not_enough_money, mhim(shkp));
1282. 			return(1);
1283. 		    }
1284. 		    pline("But since %s shop has been robbed recently,",
1285. 			  mhis(shkp));
1286. 		    pline("you %scompensate %s for %s losses.",
1287. #ifndef GOLDOBJ
1288. 			  (u.ugold < ltmp) ? 
1289. #else
1290. 			  (umoney < ltmp) ? 
1291. #endif
1292. 			  "partially " : "",
1293. 			  mon_nam(shkp), mhis(shkp));
1294. #ifndef GOLDOBJ
1295. 		    pay(u.ugold < ltmp ? u.ugold : ltmp, shkp);
1296. #else
1297. 		    pay(umoney < ltmp ? umoney : ltmp, shkp);
1298. #endif
1299. 		    make_happy_shk(shkp, FALSE);
1300. 		} else {
1301. 		    /* shopkeeper is angry, but has not been robbed --
1302. 		     * door broken, attacked, etc. */
1303. 		    pline("%s is after your hide, not your money!",
1304. 			  Monnam(shkp));
1305. #ifndef GOLDOBJ
1306. 		    if(u.ugold < 1000L) {
1307. 			if (!u.ugold)
1308. #else
1309. 		    if(umoney < 1000L) {
1310. 			if (!umoney)
1311. #endif
1312. 			    pline(no_money, stashed_gold ? " seem to" : "");
1313. 			else pline(not_enough_money, mhim(shkp));
1314. 			return(1);
1315. 		    }
1316. 		    You("try to appease %s by giving %s 1000 gold pieces.",
1317. 			x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE),
1318. 			mhim(shkp));
1319. 		    pay(1000L,shkp);
1320. 		    if (strncmp(eshkp->customer, plname, PL_NSIZ) || rn2(3))
1321. 			make_happy_shk(shkp, FALSE);
1322. 		    else
1323. 			pline("But %s is as angry as ever.", mon_nam(shkp));
1324. 		}
1325. 		return(1);
1326. 	}
1327. 	if(shkp != resident) {
1328. 		impossible("dopay: not to shopkeeper?");
1329. 		if(resident) setpaid(resident);
1330. 		return(0);
1331. 	}        
1332. 	/* pay debt, if any, first */
1333. 	if(eshkp->debit) {
1334. 		long dtmp = eshkp->debit;
1335. 		long loan = eshkp->loan;
1336. 		char sbuf[BUFSZ];
1337. #ifdef GOLDOBJ
1338.                 umoney = money_cnt(invent);
1339. #endif
1340. 		Sprintf(sbuf, "You owe %s %ld %s ",
1341. 					   shkname(shkp), dtmp, currency(dtmp));
1342. 		if(loan) {
1343. 		    if(loan == dtmp)
1344. 			Strcat(sbuf, "you picked up in the store.");
1345. 		    else Strcat(sbuf,
1346. 			   "for gold picked up and the use of merchandise.");
1347. 		} else Strcat(sbuf, "for the use of merchandise.");
1348. 		pline(sbuf);
1349. #ifndef GOLDOBJ
1350. 		if (u.ugold + eshkp->credit < dtmp) {
1351. #else
1352. 		if (umoney + eshkp->credit < dtmp) {
1353. #endif
1354. 		    pline("But you don't%s have enough gold%s.",
1355. 			stashed_gold ? " seem to" : "",
1356. 			eshkp->credit ? " or credit" : "");
1357. 		    return(1);
1358. 		} else {
1359. 		    if (eshkp->credit >= dtmp) {
1360. 			eshkp->credit -= dtmp;
1361. 			eshkp->debit = 0L;
1362. 			eshkp->loan = 0L;
1363. 			Your("debt is covered by your credit.");
1364. 		    } else if (!eshkp->credit) {
1365. #ifndef GOLDOBJ
1366. 			u.ugold -= dtmp;
1367.  			shkp->mgold += dtmp;
1368. #else
1369.                         money2mon(shkp, dtmp);
1370. #endif
1371. 			eshkp->debit = 0L;
1372. 			eshkp->loan = 0L;
1373. 			You("pay that debt.");
1374. 			flags.botl = 1;
1375. 		    } else {
1376. 			dtmp -= eshkp->credit;
1377. 			eshkp->credit = 0L;
1378. #ifndef GOLDOBJ
1379. 			u.ugold -= dtmp;
1380. 			shkp->mgold += dtmp;
1381. #else
1382.                         money2mon(shkp, dtmp);
1383. #endif
1384. 			eshkp->debit = 0L;
1385. 			eshkp->loan = 0L;
1386. 			pline("That debt is partially offset by your credit.");
1387. 			You("pay the remainder.");
1388. 			flags.botl = 1;
1389. 		    }
1390. 		    paid = TRUE;
1391. 		}
1392. 	}
1393. 	/* now check items on bill */
1394. 	if (eshkp->billct) {
1395. 	    register boolean itemize;
1396. #ifndef GOLDOBJ
1397. 	    if (!u.ugold && !eshkp->credit) {
1398. #else
1399.             umoney = money_cnt(invent);
1400. 	    if (!umoney && !eshkp->credit) {
1401. #endif
1402. 		You("%shave no money or credit%s.",
1403. 				    stashed_gold ? "seem to " : "",
1404. 				    paid ? " left" : "");
1405. 		return(0);
1406. 	    }
1407. #ifndef GOLDOBJ
1408. 	    if ((u.ugold + eshkp->credit) < cheapest_item(shkp)) {
1409. #else
1410. 	    if ((umoney + eshkp->credit) < cheapest_item(shkp)) {
1411. #endif
1412. 		You("don't have enough money to buy%s the item%s you picked.",
1413. 		    eshkp->billct > 1 ? " any of" : "", plur(eshkp->billct));
1414. 		if(stashed_gold)
1415. 		    pline("Maybe you have some gold stashed away?");
1416. 		return(0);
1417. 	    }
1418. 
1419. 	    /* this isn't quite right; it itemizes without asking if the
1420. 	     * single item on the bill is partly used up and partly unpaid */
1421. 	    itemize = (eshkp->billct > 1 ? yn("Itemized billing?") == 'y' : 1);
1422. 
1423. 	    for (pass = 0; pass <= 1; pass++) {
1424. 		tmp = 0;
1425. 		while (tmp < eshkp->billct) {
1426. 		    struct obj *otmp;
1427. 		    register struct bill_x *bp = &(eshkp->bill_p[tmp]);
1428. 
1429. 		    /* find the object on one of the lists */
1430. 		    if ((otmp = bp_to_obj(bp)) != 0) {
1431. 			/* if completely used up, object quantity is stale;
1432. 			   restoring it to its original value here avoids
1433. 			   making the partly-used-up code more complicated */
1434. 			if (bp->useup) otmp->quan = bp->bquan;
1435. 		    } else {
1436. 			impossible("Shopkeeper administration out of order.");
1437. 			setpaid(shkp);	/* be nice to the player */
1438. 			return 1;
1439. 		    }
1440. 		    if (pass == bp->useup && otmp->quan == bp->bquan) {
1441. 			/* pay for used-up items on first pass and others
1442. 			 * on second, so player will be stuck in the store
1443. 			 * less often; things which are partly used up
1444. 			 * are processed on both passes */
1445. 			tmp++;
1446. 		    } else {
1447. 			switch (dopayobj(shkp, bp, &otmp, pass, itemize)) {
1448. 			  case PAY_CANT:
1449. 				return 1;	/*break*/
1450. 			  case PAY_BROKE:
1451. 				paid = TRUE;
1452. 				goto thanks;	/*break*/
1453. 			  case PAY_SKIP:
1454. 				tmp++;
1455. 				continue;	/*break*/
1456. 			  case PAY_SOME:
1457. 				paid = TRUE;
1458. 				if (itemize) bot();
1459. 				continue;	/*break*/
1460. 			  case PAY_BUY:
1461. 				paid = TRUE;
1462. 				break;
1463. 			}
1464. 			if (itemize) bot();
1465. 			*bp = eshkp->bill_p[--eshkp->billct];
1466. 		    }
1467. 		}
1468. 	    }
1469. 	thanks:
1470. 	    if (!itemize)
1471. 	        update_inventory(); /* Done in dopayobj() if itemize. */
1472. 	}
1473. 	if(!ANGRY(shkp) && paid)
1474. 	    verbalize("Thank you for shopping in %s %s!",
1475. 		s_suffix(shkname(shkp)),
1476. 		shtypes[eshkp->shoptype - SHOPBASE].name);
1477. 	return(1);
1478. }
1479. #endif /*OVL0*/

dopayobj Edit

1480. #ifdef OVL3
1481. 
1482. /* return 2 if used-up portion paid */
1483. /*	  1 if paid successfully    */
1484. /*	  0 if not enough money     */
1485. /*	 -1 if skip this object     */
1486. /*	 -2 if no money/credit left */
1487. STATIC_OVL int
1488. dopayobj(shkp, bp, obj_p, which, itemize)
1489. register struct monst *shkp;
1490. register struct bill_x *bp;
1491. struct obj **obj_p;
1492. int	which;		/* 0 => used-up item, 1 => other (unpaid or lost) */
1493. boolean itemize;
1494. {
1495. 	register struct obj *obj = *obj_p;
1496. 	long ltmp, quan, save_quan;
1497. #ifdef GOLDOBJ
1498. 	long umoney = money_cnt(invent);
1499. #endif
1500. 	int buy;
1501. 	boolean stashed_gold = (hidden_gold() > 0L),
1502. 		consumed = (which == 0);
1503. 
1504. 	if(!obj->unpaid && !bp->useup){
1505. 		impossible("Paid object on bill??");
1506. 		return PAY_BUY;
1507. 	}
1508. #ifndef GOLDOBJ
1509. 	if(itemize && u.ugold + ESHK(shkp)->credit == 0L){
1510. #else
1511. 	if(itemize && umoney + ESHK(shkp)->credit == 0L){
1512. #endif
1513. 		You("%shave no money or credit left.",
1514. 			     stashed_gold ? "seem to " : "");
1515. 		return PAY_BROKE;
1516. 	}
1517. 	/* we may need to temporarily adjust the object, if part of the
1518. 	   original quantity has been used up but part remains unpaid  */
1519. 	save_quan = obj->quan;
1520. 	if (consumed) {
1521. 	    /* either completely used up (simple), or split needed */
1522. 	    quan = bp->bquan;
1523. 	    if (quan > obj->quan)	/* difference is amount used up */
1524. 		quan -= obj->quan;
1525. 	} else {
1526. 	    /* dealing with ordinary unpaid item */
1527. 	    quan = obj->quan;
1528. 	}
1529. 	obj->quan = quan;	/* to be used by doname() */
1530. 	obj->unpaid = 0;	/* ditto */
1531. 	ltmp = bp->price * quan;
1532. 	buy = PAY_BUY;		/* flag; if changed then return early */
1533. 
1534. 	if (itemize) {
1535. 	    char qbuf[BUFSZ];
1536. 	    Sprintf(qbuf,"%s for %ld %s.  Pay?", quan == 1L ?
1537. 		    Doname2(obj) : doname(obj), ltmp, currency(ltmp));
1538. 	    if (yn(qbuf) == 'n') {
1539. 		buy = PAY_SKIP;		/* don't want to buy */
1540. 	    } else if (quan < bp->bquan && !consumed) { /* partly used goods */
1541. 		obj->quan = bp->bquan - save_quan;	/* used up amount */
1542. 		verbalize("%s for the other %s before buying %s.",
1543. 			  ANGRY(shkp) ? "Pay" : "Please pay", xname(obj),
1544. 			  save_quan > 1L ? "these" : "this one");
1545. 		buy = PAY_SKIP;		/* shk won't sell */
1546. 	    }
1547. 	}
1548. #ifndef GOLDOBJ
1549. 	if (buy == PAY_BUY && u.ugold + ESHK(shkp)->credit < ltmp) {
1550. #else
1551. 	if (buy == PAY_BUY && umoney + ESHK(shkp)->credit < ltmp) {
1552. #endif
1553. 	    You("don't%s have gold%s enough to pay for %s.",
1554. 		stashed_gold ? " seem to" : "",
1555. 		(ESHK(shkp)->credit > 0L) ? " or credit" : "",
1556. 		doname(obj));
1557. 	    buy = itemize ? PAY_SKIP : PAY_CANT;
1558. 	}
1559. 
1560. 	if (buy != PAY_BUY) {
1561. 	    /* restore unpaid object to original state */
1562. 	    obj->quan = save_quan;
1563. 	    obj->unpaid = 1;
1564. 	    return buy;
1565. 	}
1566. 
1567. 	pay(ltmp, shkp);
1568. 	shk_names_obj(shkp, obj, consumed ?
1569. 			"paid for %s at a cost of %ld gold piece%s.%s" :
1570. 			"bought %s for %ld gold piece%s.%s", ltmp, "");
1571. 	obj->quan = save_quan;		/* restore original count */
1572. 	/* quan => amount just bought, save_quan => remaining unpaid count */
1573. 	if (consumed) {
1574. 	    if (quan != bp->bquan) {
1575. 		/* eliminate used-up portion; remainder is still unpaid */
1576. 		bp->bquan = obj->quan;
1577. 		obj->unpaid = 1;
1578. 		bp->useup = 0;
1579. 		buy = PAY_SOME;
1580. 	    } else {	/* completely used-up, so get rid of it */
1581. 		obj_extract_self(obj);
1582. 	     /* assert( obj == *obj_p ); */
1583. 		dealloc_obj(obj);
1584. 		*obj_p = 0;	/* destroy pointer to freed object */
1585. 	    }
1586. 	} else if (itemize)
1587. 	    update_inventory();	/* Done just once in dopay() if !itemize. */
1588. 	return buy;
1589. }
1590. #endif /*OVL3*/

paybill Edit

1591. #ifdef OVLB
1592. 
1593. static coord repo_location;	/* repossession context */
1594. 
1595. /* routine called after dying (or quitting) */
1596. boolean
1597. paybill(croaked)
1598. int croaked;	/* -1: escaped dungeon; 0: quit; 1: died */
1599. {
1600. 	register struct monst *mtmp, *mtmp2, *resident= (struct monst *)0;
1601. 	register boolean taken = FALSE;
1602. 	register int numsk = 0;
1603. 
1604. 	/* if we escaped from the dungeon, shopkeepers can't reach us;
1605. 	   shops don't occur on level 1, but this could happen if hero
1606. 	   level teleports out of the dungeon and manages not to die */
1607. 	if (croaked < 0) return FALSE;
1608. 
1609. 	/* this is where inventory will end up if any shk takes it */
1610. 	repo_location.x = repo_location.y = 0;
1611. 
1612. 	/* give shopkeeper first crack */
1613. 	if ((mtmp = shop_keeper(*u.ushops)) && inhishop(mtmp)) {
1614. 	    numsk++;
1615. 	    resident = mtmp;
1616. 	    taken = inherits(resident, numsk, croaked);
1617. 	}
1618. 	for (mtmp = next_shkp(fmon, FALSE);
1619. 		mtmp; mtmp = next_shkp(mtmp2, FALSE)) {
1620. 	    mtmp2 = mtmp->nmon;
1621. 	    if (mtmp != resident) {
1622. 		/* for bones: we don't want a shopless shk around */
1623. 		if(!on_level(&(ESHK(mtmp)->shoplevel), &u.uz))
1624. 			mongone(mtmp);
1625. 		else {
1626. 		    numsk++;
1627. 		    taken |= inherits(mtmp, numsk, croaked);
1628. 		}
1629. 	    }
1630. 	}
1631. 	if(numsk == 0) return(FALSE);
1632. 	return(taken);
1633. }
1634. 

inherits Edit

1635. STATIC_OVL boolean
1636. inherits(shkp, numsk, croaked)
1637. struct monst *shkp;
1638. int numsk;
1639. int croaked;
1640. {
1641. 	long loss = 0L;
1642. #ifdef GOLDOBJ
1643. 	long umoney;
1644. #endif
1645. 	struct eshk *eshkp = ESHK(shkp);
1646. 	boolean take = FALSE, taken = FALSE;
1647. 	int roomno = *u.ushops;
1648. 	char takes[BUFSZ];
1649. 
1650. 	/* the simplifying principle is that first-come */
1651. 	/* already took everything you had.		*/
1652. 	if (numsk > 1) {
1653. 	    if (cansee(shkp->mx, shkp->my && croaked))
1654. 		pline("%s %slooks at your corpse%s and %s.",
1655. 		      Monnam(shkp),
1656. 		      (!shkp->mcanmove || shkp->msleeping) ? "wakes up, " : "",
1657. 		      !rn2(2) ? (shkp->female ? ", shakes her head," :
1658. 			   ", shakes his head,") : "",
1659. 		      !inhishop(shkp) ? "disappears" : "sighs");
1660. 	    rouse_shk(shkp, FALSE);	/* wake shk for bones */    
1661. 	    taken = (roomno == eshkp->shoproom);
1662. 	    goto skip;
1663. 	}
1664. 
1665. 	/* get one case out of the way: you die in the shop, the */
1666. 	/* shopkeeper is peaceful, nothing stolen, nothing owed. */
1667. 	if(roomno == eshkp->shoproom && inhishop(shkp) &&
1668. 	    !eshkp->billct && !eshkp->robbed && !eshkp->debit &&
1669. 	     NOTANGRY(shkp) && !eshkp->following) {
1670. 		if (invent)
1671. 			pline("%s gratefully inherits all your possessions.",
1672. 				shkname(shkp));
1673. 		set_repo_loc(eshkp);
1674. 		goto clear;
1675. 	}
1676. 
1677. 	if (eshkp->billct || eshkp->debit || eshkp->robbed) {
1678. 		if (roomno == eshkp->shoproom && inhishop(shkp))
1679. 		    loss = addupbill(shkp) + eshkp->debit;
1680. 		if (loss < eshkp->robbed) loss = eshkp->robbed;
1681. 		take = TRUE;
1682. 	}
1683. 
1684. 	if (eshkp->following || ANGRY(shkp) || take) {
1685. #ifndef GOLDOBJ
1686. 		if (!invent && !u.ugold) goto skip;
1687. #else
1688. 		if (!invent) goto skip;
1689.                 umoney = money_cnt(invent);
1690. #endif
1691. 		takes[0] = '\0';
1692. 		if (!shkp->mcanmove || shkp->msleeping)
1693. 			Strcat(takes, "wakes up and ");
1694. 		if (distu(shkp->mx, shkp->my) > 2)
1695. 			Strcat(takes, "comes and ");
1696. 		Strcat(takes, "takes");
1697. 
1698. #ifndef GOLDOBJ
1699. 		if (loss > u.ugold || !loss || roomno == eshkp->shoproom) {
1700. 			eshkp->robbed -= u.ugold;
1701. 			if (eshkp->robbed < 0L) eshkp->robbed = 0L;
1702. 			shkp->mgold += u.ugold;
1703. 			u.ugold = 0L;
1704. #else
1705. 		if (loss > umoney || !loss || roomno == eshkp->shoproom) {
1706. 			eshkp->robbed -= umoney;
1707. 			if (eshkp->robbed < 0L) eshkp->robbed = 0L;
1708.                         if (umoney > 0) money2mon(shkp, umoney);
1709. #endif
1710. 			flags.botl = 1;
1711. 			pline("%s %s all your possessions.",
1712. 			      shkname(shkp), takes);
1713. 			taken = TRUE;
1714. 			/* where to put player's invent (after disclosure) */
1715. 			set_repo_loc(eshkp);
1716. 		} else {
1717. #ifndef GOLDOBJ
1718. 			shkp->mgold += loss;
1719. 			u.ugold -= loss;
1720. #else
1721.                         money2mon(shkp, loss);
1722. #endif
1723. 			flags.botl = 1;
1724. 			pline("%s %s the %ld %s %sowed %s.",
1725. 			      Monnam(shkp), takes,
1726. 			      loss, currency(loss),
1727. 			      strncmp(eshkp->customer, plname, PL_NSIZ) ?
1728. 					"" : "you ",
1729. 			      shkp->female ? "her" : "him");
1730. 			/* shopkeeper has now been paid in full */
1731. 			pacify_shk(shkp);
1732. 			eshkp->following = 0;
1733. 			eshkp->robbed = 0L;
1734. 		}
1735. skip:
1736. 		/* in case we create bones */
1737. 		rouse_shk(shkp, FALSE);	/* wake up */
1738. 		if (!inhishop(shkp))
1739. 			home_shk(shkp, FALSE);
1740. 	}
1741. clear:
1742. 	setpaid(shkp);
1743. 	return(taken);
1744. }
1745. 

set_repo_loc Edit

1746. STATIC_OVL void
1747. set_repo_loc(eshkp)
1748. struct eshk *eshkp;
1749. {
1750. 	register xchar ox, oy;
1751. 
1752. 	/* if you're not in this shk's shop room, or if you're in its doorway
1753. 	    or entry spot, then your gear gets dumped all the way inside */
1754. 	if (*u.ushops != eshkp->shoproom ||
1755. 		IS_DOOR(levl[u.ux][u.uy].typ) ||
1756. 		(u.ux == eshkp->shk.x && u.uy == eshkp->shk.y)) {
1757. 	    /* shk.x,shk.y is the position immediately in
1758. 	     * front of the door -- move in one more space
1759. 	     */
1760. 	    ox = eshkp->shk.x;
1761. 	    oy = eshkp->shk.y;
1762. 	    ox += sgn(ox - eshkp->shd.x);
1763. 	    oy += sgn(oy - eshkp->shd.y);
1764. 	} else {		/* already inside this shk's shop */
1765. 	    ox = u.ux;
1766. 	    oy = u.uy;
1767. 	}
1768. 	/* finish_paybill will deposit invent here */
1769. 	repo_location.x = ox;
1770. 	repo_location.y = oy;
1771. }
1772. 

finish_paybill Edit

1773. /* called at game exit, after inventory disclosure but before making bones */
1774. void
1775. finish_paybill()
1776. {
1777. 	register struct obj *otmp;
1778. 	int ox = repo_location.x,
1779. 	    oy = repo_location.y;
1780. 
1781. #if 0		/* don't bother */
1782. 	if (ox == 0 && oy == 0) impossible("finish_paybill: no location");
1783. #endif
1784. 	/* normally done by savebones(), but that's too late in this case */
1785. 	unleash_all();
1786. 	/* transfer all of the character's inventory to the shop floor */
1787. 	while ((otmp = invent) != 0) {
1788. 	    otmp->owornmask = 0L;	/* perhaps we should call setnotworn? */
1789. 	    otmp->lamplit = 0;		/* avoid "goes out" msg from freeinv */
1790. 	    if (rn2(5)) curse(otmp);	/* normal bones treatment for invent */
1791. 	    obj_extract_self(otmp);
1792. 	    place_object(otmp, ox, oy);
1793. 	}
1794. }
1795. 

bp_to_obj Edit

1796. /* find obj on one of the lists */
1797. STATIC_OVL struct obj *
1798. bp_to_obj(bp)
1799. register struct bill_x *bp;
1800. {
1801. 	register struct obj *obj;
1802. 	register unsigned int id = bp->bo_id;
1803. 
1804. 	if(bp->useup)
1805. 		obj = o_on(id, billobjs);
1806. 	else
1807. 		obj = find_oid(id);
1808. 	return obj;
1809. }
1810. 

find_oid Edit

1811. /*
1812.  * Look for o_id on all lists but billobj.  Return obj or NULL if not found.
1813.  * Its OK for restore_timers() to call this function, there should not
1814.  * be any timeouts on the billobjs chain.
1815.  */
1816. struct obj *
1817. find_oid(id)
1818. unsigned id;
1819. {
1820. 	struct obj *obj;
1821. 	struct monst *mon, *mmtmp[3];
1822. 	int i;
1823. 
1824. 	/* first check various obj lists directly */
1825. 	if ((obj = o_on(id, invent)) != 0) return obj;
1826. 	if ((obj = o_on(id, fobj)) != 0) return obj;
1827. 	if ((obj = o_on(id, level.buriedobjlist)) != 0) return obj;
1828. 	if ((obj = o_on(id, migrating_objs)) != 0) return obj;
1829. 
1830. 	/* not found yet; check inventory for members of various monst lists */
1831. 	mmtmp[0] = fmon;
1832. 	mmtmp[1] = migrating_mons;
1833. 	mmtmp[2] = mydogs;		/* for use during level changes */
1834. 	for (i = 0; i < 3; i++)
1835. 	    for (mon = mmtmp[i]; mon; mon = mon->nmon)
1836. 		if ((obj = o_on(id, mon->minvent)) != 0) return obj;
1837. 
1838. 	/* not found at all */
1839. 	return (struct obj *)0;
1840. }
1841. #endif /*OVLB*/

get_cost Edit

1842. #ifdef OVL3
1843. 
1844. /* calculate the value that the shk will charge for [one of] an object */
1845. STATIC_OVL long
1846. get_cost(obj, shkp)
1847. register struct obj *obj;
1848. register struct monst *shkp;	/* if angry, impose a surcharge */
1849. {
1850. 	register long tmp = getprice(obj, FALSE);
1851. 
1852. 	if (!tmp) tmp = 5L;
1853. 	/* shopkeeper may notice if the player isn't very knowledgeable -
1854. 	   especially when gem prices are concerned */
1855. 	if (!obj->dknown || !objects[obj->otyp].oc_name_known) {
1856. 		if (obj->oclass == GEM_CLASS &&
1857. 			objects[obj->otyp].oc_material == GLASS) {
1858. 		    int i;
1859. 		    /* get a value that's 'random' from game to game, but the
1860. 		       same within the same game */
1861. 		    boolean pseudorand =
1862. 			(((int)u.ubirthday % obj->otyp) >= obj->otyp/2);
1863. 
1864. 		    /* all gems are priced high - real or not */
1865. 		    switch(obj->otyp - LAST_GEM) {
1866. 			case 1: /* white */
1867. 			    i = pseudorand ? DIAMOND : OPAL;
1868. 			    break;
1869. 			case 2: /* blue */
1870. 			    i = pseudorand ? SAPPHIRE : AQUAMARINE;
1871. 			    break;
1872. 			case 3: /* red */
1873. 			    i = pseudorand ? RUBY : JASPER;
1874. 			    break;
1875. 			case 4: /* yellowish brown */
1876. 			    i = pseudorand ? AMBER : TOPAZ;
1877. 			    break;
1878. 			case 5: /* orange */
1879. 			    i = pseudorand ? JACINTH : AGATE;
1880. 			    break;
1881. 			case 6: /* yellow */
1882. 			    i = pseudorand ? CITRINE : CHRYSOBERYL;
1883. 			    break;
1884. 			case 7: /* black */
1885. 			    i = pseudorand ? BLACK_OPAL : JET;
1886. 			    break;
1887. 			case 8: /* green */
1888. 			    i = pseudorand ? EMERALD : JADE;
1889. 			    break;
1890. 			case 9: /* violet */
1891. 			    i = pseudorand ? AMETHYST : FLUORITE;
1892. 			    break;
1893. 			default: impossible("bad glass gem %d?", obj->otyp);
1894. 			    i = STRANGE_OBJECT;
1895. 			    break;
1896. 		    }
1897. 		    tmp = (long) objects[i].oc_cost;
1898. 		} else if (!(obj->o_id % 4)) /* arbitrarily impose surcharge */
1899. 		    tmp += tmp / 3L;
1900. 	}
1901. #ifdef TOURIST
1902. 	if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2))
1903. 	    || (uarmu && !uarm && !uarmc))	/* touristy shirt visible */
1904. 		tmp += tmp / 3L;
1905. 	else
1906. #endif
1907. 	if (uarmh && uarmh->otyp == DUNCE_CAP)
1908. 		tmp += tmp / 3L;
1909. 
1910. 	if (ACURR(A_CHA) > 18)		tmp /= 2L;
1911. 	else if (ACURR(A_CHA) > 17)	tmp -= tmp / 3L;
1912. 	else if (ACURR(A_CHA) > 15)	tmp -= tmp / 4L;
1913. 	else if (ACURR(A_CHA) < 6)	tmp *= 2L;
1914. 	else if (ACURR(A_CHA) < 8)	tmp += tmp / 2L;
1915. 	else if (ACURR(A_CHA) < 11)	tmp += tmp / 3L;
1916. 	if (tmp <= 0L) tmp = 1L;
1917. 	else if (obj->oartifact) tmp *= 4L;
1918. 	/* anger surcharge should match rile_shk's */
1919. 	if (shkp && ESHK(shkp)->surcharge) tmp += (tmp + 2L) / 3L;
1920. 	return tmp;
1921. }
1922. #endif /*OVL3*/

contained_cost Edit

1923. #ifdef OVLB
1924. 
1925. /* returns the price of a container's content.  the price
1926.  * of the "top" container is added in the calling functions.
1927.  * a different price quoted for selling as vs. buying.
1928.  */
1929. long
1930. contained_cost(obj, shkp, price, usell, unpaid_only)
1931. register struct obj *obj;
1932. register struct monst *shkp;
1933. long price;
1934. register boolean usell;
1935. register boolean unpaid_only;
1936. {
1937. 	register struct obj *otmp;
1938. 
1939. 	/* the price of contained objects */
1940. 	for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
1941. 	    if (otmp->oclass == COIN_CLASS) continue;
1942. 	    /* the "top" container is evaluated by caller */
1943. 	    if (usell) {
1944. 		if (saleable(shkp, otmp) &&
1945. 			!otmp->unpaid && otmp->oclass != BALL_CLASS &&
1946. 			!(otmp->oclass == FOOD_CLASS && otmp->oeaten) &&
1947. 			!(Is_candle(otmp) && otmp->age <
1948. 				20L * (long)objects[otmp->otyp].oc_cost))
1949. 		    price += set_cost(otmp, shkp);
1950. 	    } else if (!otmp->no_charge &&
1951. 		      (!unpaid_only || (unpaid_only && otmp->unpaid))) {
1952. 		    price += get_cost(otmp, shkp) * otmp->quan;
1953. 	    }
1954. 
1955. 	    if (Has_contents(otmp))
1956. 		    price += contained_cost(otmp, shkp, price, usell, unpaid_only);
1957. 	}
1958. 
1959. 	return(price);
1960. }
1961. 

contained_gold Edit

1962. long
1963. contained_gold(obj)
1964. register struct obj *obj;
1965. {
1966. 	register struct obj *otmp;
1967. 	register long value = 0L;
1968. 
1969. 	/* accumulate contained gold */
1970. 	for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
1971. 	    if (otmp->oclass == COIN_CLASS)
1972. 		value += otmp->quan;
1973. 	    else if (Has_contents(otmp))
1974. 		value += contained_gold(otmp);
1975. 
1976. 	return(value);
1977. }
1978. 

dropped_container Edit

1979. STATIC_OVL void
1980. dropped_container(obj, shkp, sale)
1981. register struct obj *obj;
1982. register struct monst *shkp;
1983. register boolean sale;
1984. {
1985. 	register struct obj *otmp;
1986. 
1987. 	/* the "top" container is treated in the calling fn */
1988. 	for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
1989. 	    if (otmp->oclass == COIN_CLASS) continue;
1990. 
1991. 	    if (!otmp->unpaid && !(sale && saleable(shkp, otmp)))
1992. 		otmp->no_charge = 1;
1993. 
1994. 	    if (Has_contents(otmp))
1995. 		dropped_container(otmp, shkp, sale);
1996. 	}
1997. }
1998. 

picked_container Edit

1999. void
2000. picked_container(obj)
2001. register struct obj *obj;
2002. {
2003. 	register struct obj *otmp;
2004. 
2005. 	/* the "top" container is treated in the calling fn */
2006. 	for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2007. 	    if (otmp->oclass == COIN_CLASS) continue;
2008. 
2009. 	    if (otmp->no_charge)
2010. 		otmp->no_charge = 0;
2011. 
2012. 	    if (Has_contents(otmp))
2013. 		picked_container(otmp);
2014. 	}
2015. }
2016. #endif /*OVLB*/

set_cost Edit

2017. #ifdef OVL3
2018. 
2019. /* calculate how much the shk will pay when buying [all of] an object */
2020. STATIC_OVL long
2021. set_cost(obj, shkp)
2022. register struct obj *obj;
2023. register struct monst *shkp;
2024. {
2025. 	long tmp = getprice(obj, TRUE) * obj->quan;
2026. 
2027. #ifdef TOURIST
2028. 	if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2))
2029. 	    || (uarmu && !uarm && !uarmc))	/* touristy shirt visible */
2030. 		tmp /= 3L;
2031. 	else
2032. #endif
2033. 	if (uarmh && uarmh->otyp == DUNCE_CAP)
2034. 		tmp /= 3L;
2035. 	else
2036. 		tmp /= 2L;
2037. 
2038. 	/* shopkeeper may notice if the player isn't very knowledgeable -
2039. 	   especially when gem prices are concerned */
2040. 	if (!obj->dknown || !objects[obj->otyp].oc_name_known) {
2041. 		if (obj->oclass == GEM_CLASS) {
2042. 			/* different shop keepers give different prices */
2043. 			if (objects[obj->otyp].oc_material == GEMSTONE ||
2044. 			    objects[obj->otyp].oc_material == GLASS) {
2045. 				tmp = (obj->otyp % (6 - shkp->m_id % 3));
2046. 				tmp = (tmp + 3) * obj->quan;
2047. 			}
2048. 		} else if (tmp > 1L && !rn2(4))
2049. 			tmp -= tmp / 4L;
2050. 	}
2051. 	return tmp;
2052. }
2053. 
2054. #endif /*OVL3*/

unpaid_cost Edit

2055. #ifdef OVLB
2056. 
2057. /* called from doinv(invent.c) for inventory of unpaid objects */
2058. long
2059. unpaid_cost(unp_obj)
2060. register struct obj *unp_obj;	/* known to be unpaid */
2061. {
2062. 	register struct bill_x *bp = (struct bill_x *)0;
2063. 	register struct monst *shkp;
2064. 
2065. 	for(shkp = next_shkp(fmon, TRUE); shkp;
2066. 					shkp = next_shkp(shkp->nmon, TRUE))
2067. 	    if ((bp = onbill(unp_obj, shkp, TRUE)) != 0) break;
2068. 
2069. 	/* onbill() gave no message if unexpected problem occurred */
2070. 	if(!bp) impossible("unpaid_cost: object wasn't on any bill!");
2071. 
2072. 	return bp ? unp_obj->quan * bp->price : 0L;
2073. }
2074. 

add_one_tobill Edit

2075. STATIC_OVL void
2076. add_one_tobill(obj, dummy)
2077. register struct obj *obj;
2078. register boolean dummy;
2079. {
2080. 	register struct monst *shkp;
2081. 	register struct bill_x *bp;
2082. 	register int bct;
2083. 	register char roomno = *u.ushops;
2084. 
2085. 	if (!roomno) return;
2086. 	if (!(shkp = shop_keeper(roomno))) return;
2087. 	if (!inhishop(shkp)) return;
2088. 
2089. 	if (onbill(obj, shkp, FALSE) || /* perhaps thrown away earlier */
2090. 		    (obj->oclass == FOOD_CLASS && obj->oeaten))
2091. 		return;
2092. 
2093. 	if (ESHK(shkp)->billct == BILLSZ) {
2094. 		You("got that for free!");
2095. 		return;
2096. 	}
2097. 
2098. 	/* To recognize objects the shopkeeper is not interested in. -dgk
2099. 	 */
2100. 	if (obj->no_charge) {
2101. 		obj->no_charge = 0;
2102. 		return;
2103. 	}
2104. 
2105. 	bct = ESHK(shkp)->billct;
2106. 	bp = &(ESHK(shkp)->bill_p[bct]);
2107. 	bp->bo_id = obj->o_id;
2108. 	bp->bquan = obj->quan;
2109. 	if(dummy) {		  /* a dummy object must be inserted into  */
2110. 	    bp->useup = 1;	  /* the billobjs chain here.  crucial for */
2111. 	    add_to_billobjs(obj); /* eating floorfood in shop.  see eat.c  */
2112. 	} else	bp->useup = 0;
2113. 	bp->price = get_cost(obj, shkp);
2114. 	ESHK(shkp)->billct++;
2115. 	obj->unpaid = 1;
2116. }
2117. 

add_to_billobjs Edit

2118. STATIC_OVL void
2119. add_to_billobjs(obj)
2120.     struct obj *obj;
2121. {
2122.     if (obj->where != OBJ_FREE)
2123. 	panic("add_to_billobjs: obj not free");
2124.     if (obj->timed)
2125. 	obj_stop_timers(obj);
2126. 
2127.     obj->nobj = billobjs;
2128.     billobjs = obj;
2129.     obj->where = OBJ_ONBILL;
2130. }
2131. 

bill_box_content Edit

2132. /* recursive billing of objects within containers. */
2133. STATIC_OVL void
2134. bill_box_content(obj, ininv, dummy, shkp)
2135. register struct obj *obj;
2136. register boolean ininv, dummy;
2137. register struct monst *shkp;
2138. {
2139. 	register struct obj *otmp;
2140. 
2141. 	for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2142. 		if (otmp->oclass == COIN_CLASS) continue;
2143. 
2144. 		/* the "top" box is added in addtobill() */
2145. 		if (!otmp->no_charge)
2146. 		    add_one_tobill(otmp, dummy);
2147. 		if (Has_contents(otmp))
2148. 		    bill_box_content(otmp, ininv, dummy, shkp);
2149. 	}
2150. 
2151. }
2152. 

shk_names_obj Edit

2153. /* shopkeeper tells you what you bought or sold, sometimes partly IDing it */
2154. STATIC_OVL void
2155. shk_names_obj(shkp, obj, fmt, amt, arg)
2156. struct monst *shkp;
2157. struct obj *obj;
2158. const char *fmt;	/* "%s %ld %s %s", doname(obj), amt, plur(amt), arg */
2159. long amt;
2160. const char *arg;
2161. {
2162. 	char *obj_name, fmtbuf[BUFSZ];
2163. 	boolean was_unknown = !obj->dknown;
2164. 
2165. 	obj->dknown = TRUE;
2166. 	/* Use real name for ordinary weapons/armor, and spell-less
2167. 	 * scrolls/books (that is, blank and mail), but only if the
2168. 	 * object is within the shk's area of interest/expertise.
2169. 	 */
2170. 	if (!objects[obj->otyp].oc_magic && saleable(shkp, obj) &&
2171. 	    (obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS ||
2172. 	     obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS ||
2173. 	     obj->otyp == MIRROR)) {
2174. 	    was_unknown |= !objects[obj->otyp].oc_name_known;
2175. 	    makeknown(obj->otyp);
2176. 	}
2177. 	obj_name = doname(obj);
2178. 	/* Use an alternate message when extra information is being provided */
2179. 	if (was_unknown) {
2180. 	    Sprintf(fmtbuf, "%%s; you %s", fmt);
2181. 	    obj_name[0] = highc(obj_name[0]);
2182. 	    pline(fmtbuf, obj_name, (obj->quan > 1) ? "them" : "it",
2183. 		  amt, plur(amt), arg);
2184. 	} else {
2185. 	    You(fmt, obj_name, amt, plur(amt), arg);
2186. 	}
2187. }
2188. 

addtobill Edit

2189. void
2190. addtobill(obj, ininv, dummy, silent)
2191. register struct obj *obj;
2192. register boolean ininv, dummy, silent;
2193. {
2194. 	register struct monst *shkp;
2195. 	register char roomno = *u.ushops;
2196. 	long ltmp = 0L, cltmp = 0L, gltmp = 0L;
2197. 	register boolean container = Has_contents(obj);
2198. 
2199. 	if(!*u.ushops) return;
2200. 
2201. 	if(!(shkp = shop_keeper(roomno))) return;
2202. 
2203. 	if(!inhishop(shkp)) return;
2204. 
2205. 	if(/* perhaps we threw it away earlier */
2206. 		 onbill(obj, shkp, FALSE) ||
2207. 		 (obj->oclass == FOOD_CLASS && obj->oeaten)
2208. 	      ) return;
2209. 
2210. 	if(ESHK(shkp)->billct == BILLSZ) {
2211. 		You("got that for free!");
2212. 		return;
2213. 	}
2214. 
2215. 	if(obj->oclass == COIN_CLASS) {
2216. 		costly_gold(obj->ox, obj->oy, obj->quan);
2217. 		return;
2218. 	}
2219. 
2220. 	if(!obj->no_charge)
2221. 	    ltmp = get_cost(obj, shkp);
2222. 
2223. 	if (obj->no_charge && !container) {
2224. 		obj->no_charge = 0;
2225. 		return;
2226. 	}
2227. 
2228. 	if(container) {
2229. 	    if(obj->cobj == (struct obj *)0) {
2230. 		if(obj->no_charge) {
2231. 		    obj->no_charge = 0;
2232. 		    return;
2233. 		} else {
2234. 		    add_one_tobill(obj, dummy);
2235. 		    goto speak;
2236. 		}
2237. 	    } else {
2238. 		cltmp += contained_cost(obj, shkp, cltmp, FALSE, FALSE);
2239. 		gltmp += contained_gold(obj);
2240. 	    }
2241. 
2242. 	    if(ltmp) add_one_tobill(obj, dummy);
2243. 	    if(cltmp) bill_box_content(obj, ininv, dummy, shkp);
2244. 	    picked_container(obj); /* reset contained obj->no_charge */
2245. 
2246. 	    ltmp += cltmp;
2247. 
2248. 	    if(gltmp) {
2249. 		costly_gold(obj->ox, obj->oy, gltmp);
2250. 		if(!ltmp) return;
2251. 	    }
2252. 
2253. 	    if(obj->no_charge)
2254. 		obj->no_charge = 0;
2255. 
2256. 	} else /* i.e., !container */
2257. 	    add_one_tobill(obj, dummy);
2258. speak:
2259. 	if (shkp->mcanmove && !shkp->msleeping && !silent) {
2260. 	    char buf[BUFSZ];
2261. 
2262. 	    if(!ltmp) {
2263. 		pline("%s has no interest in %s.", Monnam(shkp),
2264. 					     the(xname(obj)));
2265. 		return;
2266. 	    }
2267. 	    Strcpy(buf, "\"For you, ");
2268. 	    if (ANGRY(shkp)) Strcat(buf, "scum ");
2269. 	    else {
2270. 		static const char *honored[5] = {
2271. 		  "good", "honored", "most gracious", "esteemed",
2272. 		  "most renowned and sacred"
2273. 		};
2274. 		Strcat(buf, honored[rn2(4) + u.uevent.udemigod]);
2275. 		if (!is_human(youmonst.data)) Strcat(buf, " creature");
2276. 		else
2277. 		    Strcat(buf, (flags.female) ? " lady" : " sir");
2278. 	    }
2279. 	    if(ininv) {
2280. 		long quan = obj->quan;
2281. 		obj->quan = 1L; /* fool xname() into giving singular */
2282. 		pline("%s; only %ld %s %s.\"", buf, ltmp,
2283. 			(quan > 1L) ? "per" : "for this", xname(obj));
2284. 		obj->quan = quan;
2285. 	    } else
2286. 		pline("%s will cost you %ld %s%s.",
2287. 			The(xname(obj)), ltmp, currency(ltmp),
2288. 			(obj->quan > 1L) ? " each" : "");
2289. 	} else if(!silent) {
2290. 	    if(ltmp) pline_The("list price of %s is %ld %s%s.",
2291. 				   the(xname(obj)), ltmp, currency(ltmp),
2292. 				   (obj->quan > 1L) ? " each" : "");
2293. 	    else pline("%s does not notice.", Monnam(shkp));
2294. 	}
2295. }
2296. 

splitbill Edit

2297. void
2298. splitbill(obj, otmp)
2299. register struct obj *obj, *otmp;
2300. {
2301. 	/* otmp has been split off from obj */
2302. 	register struct bill_x *bp;
2303. 	register long tmp;
2304. 	register struct monst *shkp = shop_keeper(*u.ushops);
2305. 
2306. 	if(!shkp || !inhishop(shkp)) {
2307. 		impossible("splitbill: no resident shopkeeper??");
2308. 		return;
2309. 	}
2310. 	bp = onbill(obj, shkp, FALSE);
2311. 	if(!bp) {
2312. 		impossible("splitbill: not on bill?");
2313. 		return;
2314. 	}
2315. 	if(bp->bquan < otmp->quan) {
2316. 		impossible("Negative quantity on bill??");
2317. 	}
2318. 	if(bp->bquan == otmp->quan) {
2319. 		impossible("Zero quantity on bill??");
2320. 	}
2321. 	bp->bquan -= otmp->quan;
2322. 
2323. 	if(ESHK(shkp)->billct == BILLSZ) otmp->unpaid = 0;
2324. 	else {
2325. 		tmp = bp->price;
2326. 		bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
2327. 		bp->bo_id = otmp->o_id;
2328. 		bp->bquan = otmp->quan;
2329. 		bp->useup = 0;
2330. 		bp->price = tmp;
2331. 		ESHK(shkp)->billct++;
2332. 	}
2333. }
2334. 

sub_one_frombill Edit

2335. STATIC_OVL void
2336. sub_one_frombill(obj, shkp)
2337. register struct obj *obj;
2338. register struct monst *shkp;
2339. {
2340. 	register struct bill_x *bp;
2341. 
2342. 	if((bp = onbill(obj, shkp, FALSE)) != 0) {
2343. 		register struct obj *otmp;
2344. 
2345. 		obj->unpaid = 0;
2346. 		if(bp->bquan > obj->quan){
2347. 			otmp = newobj(0);
2348. 			*otmp = *obj;
2349. 			bp->bo_id = otmp->o_id = flags.ident++;
2350. 			otmp->where = OBJ_FREE;
2351. 			otmp->quan = (bp->bquan -= obj->quan);
2352. 			otmp->owt = 0;	/* superfluous */
2353. 			otmp->onamelth = 0;
2354. 			otmp->oxlth = 0;
2355. 			otmp->oattached = OATTACHED_NOTHING;
2356. 			bp->useup = 1;
2357. 			add_to_billobjs(otmp);
2358. 			return;
2359. 		}
2360. 		ESHK(shkp)->billct--;
2361. #ifdef DUMB
2362. 		{
2363. 		/* DRS/NS 2.2.6 messes up -- Peter Kendell */
2364. 			int indx = ESHK(shkp)->billct;
2365. 			*bp = ESHK(shkp)->bill_p[indx];
2366. 		}
2367. #else
2368. 		*bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
2369. #endif
2370. 		return;
2371. 	} else if (obj->unpaid) {
2372. 		impossible("sub_one_frombill: unpaid object not on bill");
2373. 		obj->unpaid = 0;
2374. 	}
2375. }
2376. 

subfrombill Edit

2377. /* recursive check of unpaid objects within nested containers. */
2378. void
2379. subfrombill(obj, shkp)
2380. register struct obj *obj;
2381. register struct monst *shkp;
2382. {
2383. 	register struct obj *otmp;
2384. 
2385. 	sub_one_frombill(obj, shkp);
2386. 
2387. 	if (Has_contents(obj))
2388. 	    for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2389. 		if(otmp->oclass == COIN_CLASS) continue;
2390. 
2391. 		if (Has_contents(otmp))
2392. 		    subfrombill(otmp, shkp);
2393. 		else
2394. 		    sub_one_frombill(otmp, shkp);
2395. 	    }
2396. }
2397. 
2398. #endif /*OVLB*/

stolen_container Edit

2399. #ifdef OVL3
2400. 
2401. STATIC_OVL long
2402. stolen_container(obj, shkp, price, ininv)
2403. register struct obj *obj;
2404. register struct monst *shkp;
2405. long price;
2406. register boolean ininv;
2407. {
2408. 	register struct obj *otmp;
2409. 
2410. 	if(ininv && obj->unpaid)
2411. 	    price += get_cost(obj, shkp);
2412. 	else {
2413. 	    if(!obj->no_charge)
2414. 		price += get_cost(obj, shkp);
2415. 	    obj->no_charge = 0;
2416. 	}
2417. 
2418. 	/* the price of contained objects, if any */
2419. 	for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
2420. 
2421. 	    if(otmp->oclass == COIN_CLASS) continue;
2422. 
2423. 	    if (!Has_contents(otmp)) {
2424. 		if(ininv) {
2425. 		    if(otmp->unpaid)
2426. 			price += otmp->quan * get_cost(otmp, shkp);
2427. 		} else {
2428. 		    if(!otmp->no_charge) {
2429. 			if(otmp->oclass != FOOD_CLASS || !otmp->oeaten)
2430. 			    price += otmp->quan * get_cost(otmp, shkp);
2431. 		    }
2432. 		    otmp->no_charge = 0;
2433. 		}
2434. 	    } else
2435. 		price += stolen_container(otmp, shkp, price, ininv);
2436. 	}
2437. 
2438. 	return(price);
2439. }
2440. #endif /*OVL3*/

stolen_value Edit

2441. #ifdef OVLB
2442. 
2443. long
2444. stolen_value(obj, x, y, peaceful, silent)
2445. register struct obj *obj;
2446. register xchar x, y;
2447. register boolean peaceful, silent;
2448. {
2449. 	register long value = 0L, gvalue = 0L;
2450. 	register struct monst *shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
2451. 
2452. 	if (!shkp || !inhishop(shkp))
2453. 	    return (0L);
2454. 
2455. 	if(obj->oclass == COIN_CLASS) {
2456. 	    gvalue += obj->quan;
2457. 	} else if (Has_contents(obj)) {
2458. 	    register boolean ininv = !!count_unpaid(obj->cobj);
2459. 
2460. 	    value += stolen_container(obj, shkp, value, ininv);
2461. 	    if(!ininv) gvalue += contained_gold(obj);
2462. 	} else if (!obj->no_charge && saleable(shkp, obj)) {
2463. 	    value += get_cost(obj, shkp);
2464. 	}
2465. 
2466. 	if(gvalue + value == 0L) return(0L);
2467. 
2468. 	value += gvalue;
2469. 
2470. 	if(peaceful) {
2471. 	    boolean credit_use = !!ESHK(shkp)->credit;
2472. 	    value = check_credit(value, shkp);
2473. 	    /* 'peaceful' affects general treatment, but doesn't affect
2474. 	     * the fact that other code expects that all charges after the
2475. 	     * shopkeeper is angry are included in robbed, not debit */
2476. 	    if (ANGRY(shkp))
2477. 		ESHK(shkp)->robbed += value;
2478. 	    else 
2479. 		ESHK(shkp)->debit += value;
2480. 
2481. 	    if(!silent) {
2482. 		const char *still = "";
2483. 
2484. 		if (credit_use) {
2485. 		    if (ESHK(shkp)->credit) {
2486. 			You("have %ld %s credit remaining.",
2487. 				 ESHK(shkp)->credit, currency(ESHK(shkp)->credit));
2488. 			return value;
2489. 		    } else if (!value) {
2490. 			You("have no credit remaining.");
2491. 			return 0;
2492. 		    }
2493. 		    still = "still ";
2494. 		}
2495. 		if(obj->oclass == COIN_CLASS)
2496. 		    You("%sowe %s %ld %s!", still,
2497. 			mon_nam(shkp), value, currency(value));
2498. 		else
2499. 		    You("%sowe %s %ld %s for %s!", still,
2500. 			mon_nam(shkp), value, currency(value),
2501. 			obj->quan > 1L ? "them" : "it");
2502. 	    }
2503. 	} else {
2504. 	    ESHK(shkp)->robbed += value;
2505. 
2506. 	    if(!silent) {
2507. 		if(cansee(shkp->mx, shkp->my)) {
2508. 		    Norep("%s booms: \"%s, you are a thief!\"",
2509. 				Monnam(shkp), plname);
2510. 		} else  Norep("You hear a scream, \"Thief!\"");
2511. 	    }
2512. 	    hot_pursuit(shkp);
2513. 	    (void) angry_guards(FALSE);
2514. 	}
2515. 	return(value);
2516. }
2517. 

sellobj_state Edit

2518. /* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */
2519. static char sell_response = 'a';
2520. static int sell_how = SELL_NORMAL;
2521. /* can't just use sell_response='y' for auto_credit because the 'a' response
2522.    shouldn't carry over from ordinary selling to credit selling */
2523. static boolean auto_credit = FALSE;
2524. 
2525. void
2526. sellobj_state(deliberate)
2527. int deliberate;
2528. {
2529. 	/* If we're deliberately dropping something, there's no automatic
2530. 	   response to the shopkeeper's "want to sell" query; however, if we
2531. 	   accidentally drop anything, the shk will buy it/them without asking.
2532. 	   This retains the old pre-query risk that slippery fingers while in
2533. 	   shops entailed:  you drop it, you've lost it.
2534. 	 */
2535. 	sell_response = (deliberate != SELL_NORMAL) ? '\0' : 'a';
2536. 	sell_how = deliberate;
2537. 	auto_credit = FALSE;
2538. }
2539. 

sellobj Edit

2540. void
2541. sellobj(obj, x, y)
2542. register struct obj *obj;
2543. xchar x, y;
2544. {
2545. 	register struct monst *shkp;
2546. 	register struct eshk *eshkp;
2547. 	long ltmp = 0L, cltmp = 0L, gltmp = 0L, offer;
2548. 	boolean saleitem, cgold = FALSE, container = Has_contents(obj);
2549. 	boolean isgold = (obj->oclass == COIN_CLASS);
2550. 	boolean only_partially_your_contents = FALSE;
2551. 
2552. 	if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) ||
2553. 	   !inhishop(shkp)) return;
2554. 	if(!costly_spot(x, y))	return;
2555. 	if(!*u.ushops) return;
2556. 
2557. 	if(obj->unpaid && !container && !isgold) {
2558. 	    sub_one_frombill(obj, shkp);
2559. 	    return;
2560. 	}
2561. 	if(container) {
2562. 		/* find the price of content before subfrombill */
2563. 		cltmp += contained_cost(obj, shkp, cltmp, TRUE, FALSE);
2564. 		/* find the value of contained gold */
2565. 		gltmp += contained_gold(obj);
2566. 		cgold = (gltmp > 0L);
2567. 	}
2568. 
2569. 	saleitem = saleable(shkp, obj);
2570. 	if(!isgold && !obj->unpaid && saleitem)
2571. 	    ltmp = set_cost(obj, shkp);
2572. 
2573. 	offer = ltmp + cltmp;
2574. 
2575. 	/* get one case out of the way: nothing to sell, and no gold */
2576. 	if(!isgold &&
2577. 	   ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) {
2578. 		register boolean unpaid = (obj->unpaid ||
2579. 				  (container && count_unpaid(obj->cobj)));
2580. 
2581. 		if(container) {
2582. 			dropped_container(obj, shkp, FALSE);
2583. 			if(!obj->unpaid && !saleitem)
2584. 			    obj->no_charge = 1;
2585. 			if(obj->unpaid || count_unpaid(obj->cobj))
2586. 			    subfrombill(obj, shkp);
2587. 		} else obj->no_charge = 1;
2588. 
2589. 		if(!unpaid && (sell_how != SELL_DONTSELL))
2590. 		    pline("%s seems uninterested.", Monnam(shkp));
2591. 		return;
2592. 	}
2593. 
2594. 	/* you dropped something of your own - probably want to sell it */
2595. 	rouse_shk(shkp, TRUE);	/* wake up sleeping or paralyzed shk */
2596. 	eshkp = ESHK(shkp);
2597. 
2598. 	if (ANGRY(shkp)) { /* they become shop-objects, no pay */
2599. 		pline("Thank you, scum!");
2600. 		subfrombill(obj, shkp);
2601. 		return;
2602. 	}
2603. 
2604. 	if(eshkp->robbed) {  /* shkp is not angry? */
2605. 		if(isgold) offer = obj->quan;
2606. 		else if(cgold) offer += cgold;
2607. 		if((eshkp->robbed -= offer < 0L))
2608. 			eshkp->robbed = 0L;
2609. 		if(offer) verbalize(
2610.   "Thank you for your contribution to restock this recently plundered shop.");
2611. 		subfrombill(obj, shkp);
2612. 		return;
2613. 	}
2614. 
2615. 	if(isgold || cgold) {
2616. 		if(!cgold) gltmp = obj->quan;
2617. 
2618. 		if(eshkp->debit >= gltmp) {
2619. 		    if(eshkp->loan) { /* you carry shop's gold */
2620. 			 if(eshkp->loan >= gltmp)
2621. 			     eshkp->loan -= gltmp;
2622. 			 else eshkp->loan = 0L;
2623. 		    }
2624. 		    eshkp->debit -= gltmp;
2625. 		    Your("debt is %spaid off.",
2626. 				eshkp->debit ? "partially " : "");
2627. 		} else {
2628. 		    long delta = gltmp - eshkp->debit;
2629. 
2630. 		    eshkp->credit += delta;
2631. 		    if(eshkp->debit) {
2632. 			eshkp->debit = 0L;
2633. 			eshkp->loan = 0L;
2634. 			Your("debt is paid off.");
2635. 		    }
2636. 		    pline("%ld %s %s added to your credit.",
2637. 				delta, currency(delta), delta > 1L ? "are" : "is");
2638. 		}
2639. 		if(offer) goto move_on;
2640. 		else {
2641. 		    if(!isgold) {
2642. 			if (container)
2643. 			    dropped_container(obj, shkp, FALSE);
2644. 			if (!obj->unpaid && !saleitem) obj->no_charge = 1;
2645. 			subfrombill(obj, shkp);
2646. 		    }
2647. 		    return;
2648. 		}
2649. 	}
2650. move_on:
2651. 	if((!saleitem && !(container && cltmp > 0L))
2652. 	   || eshkp->billct == BILLSZ
2653. 	   || obj->oclass == BALL_CLASS
2654. 	   || obj->oclass == CHAIN_CLASS || offer == 0L
2655. 	   || (obj->oclass == FOOD_CLASS && obj->oeaten)
2656. 	   || (Is_candle(obj) &&
2657. 		   obj->age < 20L * (long)objects[obj->otyp].oc_cost)) {
2658. 		pline("%s seems uninterested%s.", Monnam(shkp),
2659. 			cgold ? " in the rest" : "");
2660. 		if (container)
2661. 		    dropped_container(obj, shkp, FALSE);
2662. 		obj->no_charge = 1;
2663. 		return;
2664. 	}
2665.         
2666. #ifndef GOLDOBJ
2667. 	if(!shkp->mgold) {
2668. #else
2669. 	if(!money_cnt(shkp->minvent)) {
2670. #endif
2671. 		char c, qbuf[BUFSZ];
2672. 		long tmpcr = ((offer * 9L) / 10L) + (offer <= 1L);
2673. 
2674. 		if (sell_how == SELL_NORMAL || auto_credit) {
2675. 		    c = sell_response = 'y';
2676. 		} else if (sell_response != 'n') {
2677. 		    pline("%s cannot pay you at present.", Monnam(shkp));
2678. 		    Sprintf(qbuf,
2679. 			    "Will you accept %ld %s in credit for %s?",
2680. 			    tmpcr, currency(tmpcr), doname(obj));
2681. 		    /* won't accept 'a' response here */
2682. 		    /* KLY - 3/2000 yes, we will, it's a damn nuisance
2683.                        to have to constantly hit 'y' to sell for credit */
2684. 		    c = ynaq(qbuf);
2685. 		    if (c == 'a') {
2686. 			c = 'y';
2687. 			auto_credit = TRUE;
2688. 		    }
2689. 		} else		/* previously specified "quit" */
2690. 		    c = 'n';
2691. 
2692. 		if (c == 'y') {
2693. 		    shk_names_obj(shkp, obj, (sell_how != SELL_NORMAL) ?
2694. 			    "traded %s for %ld zorkmid%s in %scredit." :
2695. 			"relinquish %s and acquire %ld zorkmid%s in %scredit.",
2696. 			    tmpcr,
2697. 			    (eshkp->credit > 0L) ? "additional " : "");
2698. 		    eshkp->credit += tmpcr;
2699. 		    subfrombill(obj, shkp);
2700. 		} else {
2701. 		    if (c == 'q') sell_response = 'n';
2702. 		    if (container)
2703. 			dropped_container(obj, shkp, FALSE);
2704. 		    if (!obj->unpaid) obj->no_charge = 1;
2705. 		    subfrombill(obj, shkp);
2706. 		}
2707. 	} else {
2708. 		char qbuf[BUFSZ];
2709. #ifndef GOLDOBJ
2710. 		boolean short_funds = (offer > shkp->mgold);
2711. 		if (short_funds) offer = shkp->mgold;
2712. #else
2713.                 long shkmoney = money_cnt(shkp->minvent);
2714. 		boolean short_funds = (offer > shkmoney);
2715. 		if (short_funds) offer = shkmoney;
2716. #endif
2717. 		if (!sell_response) {
2718. 		    only_partially_your_contents =
2719. 			(contained_cost(obj, shkp, 0L, FALSE, FALSE) !=
2720. 			 contained_cost(obj, shkp, 0L, FALSE, TRUE));
2721. 		    Sprintf(qbuf,
2722. 			 "%s offers%s %ld gold piece%s for%s %s %s.  Sell %s?",
2723. 			    Monnam(shkp), short_funds ? " only" : "",
2724. 			    offer, plur(offer),
2725. 			    (!ltmp && cltmp && only_partially_your_contents) ?
2726. 			     " your items in" : (!ltmp && cltmp) ? " the contents of" : "",
2727. 			    obj->unpaid ? "the" : "your", cxname(obj),
2728. 			    (obj->quan == 1L &&
2729. 			    !(!ltmp && cltmp && only_partially_your_contents)) ?
2730. 			    "it" : "them");
2731. 		} else  qbuf[0] = '\0';		/* just to pacify lint */
2732. 
2733. 		switch (sell_response ? sell_response : ynaq(qbuf)) {
2734. 		 case 'q':  sell_response = 'n';
2735. 		 case 'n':  if (container)
2736. 				dropped_container(obj, shkp, FALSE);
2737. 			    if (!obj->unpaid) obj->no_charge = 1;
2738. 			    subfrombill(obj, shkp);
2739. 			    break;
2740. 		 case 'a':  sell_response = 'y';
2741. 		 case 'y':  if (container)
2742. 				dropped_container(obj, shkp, TRUE);
2743. 			    if (!obj->unpaid && !saleitem) obj->no_charge = 1;
2744. 			    subfrombill(obj, shkp);
2745. 			    pay(-offer, shkp);
2746. 			    shk_names_obj(shkp, obj, (sell_how != SELL_NORMAL) ?
2747. 				    (!ltmp && cltmp && only_partially_your_contents) ?
2748. 			    	    "sold some items inside %s for %ld gold pieces%s.%s" :
2749. 				    "sold %s for %ld gold piece%s.%s" :
2750. 	       "relinquish %s and receive %ld gold piece%s in compensation.%s",
2751. 				    offer, "");
2752. 			    break;
2753. 		 default:   impossible("invalid sell response");
2754. 		}
2755. 	}
2756. }
2757. 

doinvbill Edit

2758. int
2759. doinvbill(mode)
2760. int mode;		/* 0: deliver count 1: paged */
2761. {
2762. #ifdef	__SASC
2763. 	void sasc_bug(struct obj *, unsigned);
2764. #endif
2765. 	struct monst *shkp;
2766. 	struct eshk *eshkp;
2767. 	struct bill_x *bp, *end_bp;
2768. 	struct obj *obj;
2769. 	long totused;
2770. 	char *buf_p;
2771. 	winid datawin;
2772. 
2773. 	shkp = shop_keeper(*u.ushops);
2774. 	if (!shkp || !inhishop(shkp)) {
2775. 	    if (mode != 0) impossible("doinvbill: no shopkeeper?");
2776. 	    return 0;
2777. 	}
2778. 	eshkp = ESHK(shkp);
2779. 
2780. 	if (mode == 0) {
2781. 	    /* count expended items, so that the `I' command can decide
2782. 	       whether to include 'x' in its prompt string */
2783. 	    int cnt = !eshkp->debit ? 0 : 1;
2784. 
2785. 	    for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct];
2786. 		    bp < end_bp; bp++)
2787. 		if (bp->useup ||
2788. 			((obj = bp_to_obj(bp)) != 0 && obj->quan < bp->bquan))
2789. 		    cnt++;
2790. 	    return cnt;
2791. 	}
2792. 
2793. 	datawin = create_nhwindow(NHW_MENU);
2794. 	putstr(datawin, 0, "Unpaid articles already used up:");
2795. 	putstr(datawin, 0, "");
2796. 
2797. 	totused = 0L;
2798. 	for (bp = eshkp->bill_p, end_bp = &eshkp->bill_p[eshkp->billct];
2799. 		bp < end_bp; bp++) {
2800. 	    obj = bp_to_obj(bp);
2801. 	    if(!obj) {
2802. 		impossible("Bad shopkeeper administration.");
2803. 		goto quit;
2804. 	    }
2805. 	    if(bp->useup || bp->bquan > obj->quan) {
2806. 		long oquan, uquan, thisused;
2807. 		unsigned save_unpaid;
2808. 
2809. 		save_unpaid = obj->unpaid;
2810. 		oquan = obj->quan;
2811. 		uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
2812. 		thisused = bp->price * uquan;
2813. 		totused += thisused;
2814. 		obj->unpaid = 0;		/* ditto */
2815. 		/* Why 'x'?  To match `I x', more or less. */
2816. 		buf_p = xprname(obj, (char *)0, 'x', FALSE, thisused, uquan);
2817. #ifdef __SASC
2818. 				/* SAS/C 6.2 can't cope for some reason */
2819. 		sasc_bug(obj,save_unpaid);
2820. #else
2821. 		obj->unpaid = save_unpaid;
2822. #endif
2823. 		putstr(datawin, 0, buf_p);
2824. 	    }
2825. 	}
2826. 	if (eshkp->debit) {
2827. 	    /* additional shop debt which has no itemization available */
2828. 	    if (totused) putstr(datawin, 0, "");
2829. 	    totused += eshkp->debit;
2830. 	    buf_p = xprname((struct obj *)0,
2831. 			    "usage charges and/or other fees",
2832. 			    GOLD_SYM, FALSE, eshkp->debit, 0L);
2833. 	    putstr(datawin, 0, buf_p);
2834. 	}
2835. 	buf_p = xprname((struct obj *)0, "Total:", '*', FALSE, totused, 0L);
2836. 	putstr(datawin, 0, "");
2837. 	putstr(datawin, 0, buf_p);
2838. 	display_nhwindow(datawin, FALSE);
2839.     quit:
2840. 	destroy_nhwindow(datawin);
2841. 	return(0);
2842. }
2843. 

getprice Edit

2844. #define HUNGRY	2
2845. 
2846. STATIC_OVL long
2847. getprice(obj, shk_buying)
2848. register struct obj *obj;
2849. boolean shk_buying;
2850. {
2851. 	register long tmp = (long) objects[obj->otyp].oc_cost;
2852. 
2853. 	if (obj->oartifact) {
2854. 	    tmp = arti_cost(obj);
2855. 	    if (shk_buying) tmp /= 4;
2856. 	}
2857. 	switch(obj->oclass) {
2858. 	case FOOD_CLASS:
2859. 		/* simpler hunger check, (2-4)*cost */
2860. 		if (u.uhs >= HUNGRY && !shk_buying) tmp *= (long) u.uhs;
2861. 		if (obj->oeaten) tmp = 0L;
2862. 		break;
2863. 	case WAND_CLASS:
2864. 		if (obj->spe == -1) tmp = 0L;
2865. 		break;
2866. 	case POTION_CLASS:
2867. 		if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
2868. 			tmp = 0L;
2869. 		break;
2870. 	case ARMOR_CLASS:
2871. 	case WEAPON_CLASS:
2872. 		if (obj->spe > 0) tmp += 10L * (long) obj->spe;
2873. 		break;
2874. 	case TOOL_CLASS:
2875. 		if (Is_candle(obj) &&
2876. 			obj->age < 20L * (long)objects[obj->otyp].oc_cost)
2877. 		    tmp /= 2L;
2878. 		break;
2879. 	}
2880. 	return tmp;
2881. }
2882. 

shkcatch Edit

2883. /* shk catches thrown pick-axe */
2884. struct monst *
2885. shkcatch(obj, x, y)
2886. register struct obj *obj;
2887. register xchar x, y;
2888. {
2889. 	register struct monst *shkp;
2890. 
2891. 	if (!(shkp = shop_keeper(inside_shop(x, y))) ||
2892. 	    !inhishop(shkp)) return(0);
2893. 
2894. 	if (shkp->mcanmove && !shkp->msleeping &&
2895. 	    (*u.ushops != ESHK(shkp)->shoproom || !inside_shop(u.ux, u.uy)) &&
2896. 	    dist2(shkp->mx, shkp->my, x, y) < 3 &&
2897. 	    /* if it is the shk's pos, you hit and anger him */
2898. 	    (shkp->mx != x || shkp->my != y)) {
2899. 		if (mnearto(shkp, x, y, TRUE))
2900. 		    verbalize("Out of my way, scum!");
2901. 		if (cansee(x, y)) {
2902. 		    pline("%s nimbly%s catches %s.",
2903. 			  Monnam(shkp),
2904. 			  (x == shkp->mx && y == shkp->my) ? "" : " reaches over and",
2905. 			  the(xname(obj)));
2906. 		    if (!canspotmon(shkp))
2907. 			map_invisible(x, y);
2908. 		    delay_output();
2909. 		    mark_synch();
2910. 		}
2911. 		subfrombill(obj, shkp);
2912. 		(void) mpickobj(shkp, obj);
2913. 		return shkp;
2914. 	}
2915. 	return (struct monst *)0;
2916. }
2917. 

add_damage Edit

2918. void
2919. add_damage(x, y, cost)
2920. register xchar x, y;
2921. long cost;
2922. {
2923. 	struct damage *tmp_dam;
2924. 	char *shops;
2925. 
2926. 	if (IS_DOOR(levl[x][y].typ)) {
2927. 	    struct monst *mtmp;
2928. 
2929. 	    /* Don't schedule for repair unless it's a real shop entrance */
2930. 	    for (shops = in_rooms(x, y, SHOPBASE); *shops; shops++)
2931. 		if ((mtmp = shop_keeper(*shops)) != 0 &&
2932. 			x == ESHK(mtmp)->shd.x && y == ESHK(mtmp)->shd.y)
2933. 		    break;
2934. 	    if (!*shops) return;
2935. 	}
2936. 	for (tmp_dam = level.damagelist; tmp_dam; tmp_dam = tmp_dam->next)
2937. 	    if (tmp_dam->place.x == x && tmp_dam->place.y == y) {
2938. 		tmp_dam->cost += cost;
2939. 		return;
2940. 	    }
2941. 	tmp_dam = (struct damage *)alloc((unsigned)sizeof(struct damage));
2942. 	tmp_dam->when = monstermoves;
2943. 	tmp_dam->place.x = x;
2944. 	tmp_dam->place.y = y;
2945. 	tmp_dam->cost = cost;
2946. 	tmp_dam->typ = levl[x][y].typ;
2947. 	tmp_dam->next = level.damagelist;
2948. 	level.damagelist = tmp_dam;
2949. 	/* If player saw damage, display as a wall forever */
2950. 	if (cansee(x, y))
2951. 	    levl[x][y].seenv = SVALL;
2952. }
2953. 
2954. #endif /*OVLB*/

remove_damage Edit

2955. #ifdef OVL0
2956. 
2957. /*
2958.  * Do something about damage. Either (!croaked) try to repair it, or
2959.  * (croaked) just discard damage structs for non-shared locations, since
2960.  * they'll never get repaired. Assume that shared locations will get
2961.  * repaired eventually by the other shopkeeper(s). This might be an erroneous
2962.  * assumption (they might all be dead too), but we have no reasonable way of
2963.  * telling that.
2964.  */
2965. STATIC_OVL
2966. void
2967. remove_damage(shkp, croaked)
2968. register struct monst *shkp;
2969. register boolean croaked;
2970. {
2971. 	register struct damage *tmp_dam, *tmp2_dam;
2972. 	register boolean did_repair = FALSE, saw_door = FALSE;
2973. 	register boolean saw_floor = FALSE, stop_picking = FALSE;
2974. 	register boolean saw_untrap = FALSE;
2975. 	uchar saw_walls = 0;
2976. 
2977. 	tmp_dam = level.damagelist;
2978. 	tmp2_dam = 0;
2979. 	while (tmp_dam) {
2980. 	    register xchar x = tmp_dam->place.x, y = tmp_dam->place.y;
2981. 	    char shops[5];
2982. 	    int disposition;
2983. 
2984. 	    disposition = 0;
2985. 	    Strcpy(shops, in_rooms(x, y, SHOPBASE));
2986. 	    if (index(shops, ESHK(shkp)->shoproom)) {
2987. 		if (croaked)
2988. 		    disposition = (shops[1])? 0 : 1;
2989. 		else if (stop_picking)
2990. 		    disposition = repair_damage(shkp, tmp_dam, FALSE);
2991. 		else {
2992. 		    /* Defer the stop_occupation() until after repair msgs */
2993. 		    if (closed_door(x, y))
2994. 			stop_picking = picking_at(x, y);
2995. 		    disposition = repair_damage(shkp, tmp_dam, FALSE);
2996. 		    if (!disposition)
2997. 			stop_picking = FALSE;
2998. 		}
2999. 	    }
3000. 
3001. 	    if (!disposition) {
3002. 		tmp2_dam = tmp_dam;
3003. 		tmp_dam = tmp_dam->next;
3004. 		continue;
3005. 	    }
3006. 
3007. 	    if (disposition > 1) {
3008. 		did_repair = TRUE;
3009. 		if (cansee(x, y)) {
3010. 		    if (IS_WALL(levl[x][y].typ))
3011. 			saw_walls++;
3012. 		    else if (IS_DOOR(levl[x][y].typ))
3013. 			saw_door = TRUE;
3014. 		    else if (disposition == 3)		/* untrapped */
3015. 			saw_untrap = TRUE;
3016. 		    else
3017. 			saw_floor = TRUE;
3018. 		}
3019. 	    }
3020. 
3021. 	    tmp_dam = tmp_dam->next;
3022. 	    if (!tmp2_dam) {
3023. 		free((genericptr_t)level.damagelist);
3024. 		level.damagelist = tmp_dam;
3025. 	    } else {
3026. 		free((genericptr_t)tmp2_dam->next);
3027. 		tmp2_dam->next = tmp_dam;
3028. 	    }
3029. 	}
3030. 	if (!did_repair)
3031. 	    return;
3032. 	if (saw_walls) {
3033. 	    pline("Suddenly, %s section%s of wall close%s up!",
3034. 		  (saw_walls == 1) ? "a" : (saw_walls <= 3) ?
3035. 						  "some" : "several",
3036. 		  (saw_walls == 1) ? "" : "s", (saw_walls == 1) ? "s" : "");
3037. 	    if (saw_door)
3038. 		pline_The("shop door reappears!");
3039. 	    if (saw_floor)
3040. 		pline_The("floor is repaired!");
3041. 	} else {
3042. 	    if (saw_door)
3043. 		pline("Suddenly, the shop door reappears!");
3044. 	    else if (saw_floor)
3045. 		pline("Suddenly, the floor damage is gone!");
3046. 	    else if (saw_untrap)
3047. 	        pline("Suddenly, the trap is removed from the floor!");
3048. 	    else if (inside_shop(u.ux, u.uy) == ESHK(shkp)->shoproom)
3049. 		You_feel("more claustrophobic than before.");
3050. 	    else if (flags.soundok && !rn2(10))
3051. 		Norep("The dungeon acoustics noticeably change.");
3052. 	}
3053. 	if (stop_picking)
3054. 		stop_occupation();
3055. }
3056. 

repair_damage Edit

3057. /*
3058.  * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
3059.  * 3: untrap
3060.  */
3061. int
3062. repair_damage(shkp, tmp_dam, catchup)
3063. register struct monst *shkp;
3064. register struct damage *tmp_dam;
3065. boolean catchup;	/* restoring a level */
3066. {
3067. 	register xchar x, y, i;
3068. 	xchar litter[9];
3069. 	register struct monst *mtmp;
3070. 	register struct obj *otmp;
3071. 	register struct trap *ttmp;
3072. 
3073. 	if ((monstermoves - tmp_dam->when) < REPAIR_DELAY)
3074. 	    return(0);
3075. 	if (shkp->msleeping || !shkp->mcanmove || ESHK(shkp)->following)
3076. 	    return(0);
3077. 	x = tmp_dam->place.x;
3078. 	y = tmp_dam->place.y;
3079. 	if (!IS_ROOM(tmp_dam->typ)) {
3080. 	    if (x == u.ux && y == u.uy)
3081. 		if (!Passes_walls)
3082. 		    return(0);
3083. 	    if (x == shkp->mx && y == shkp->my)
3084. 		return(0);
3085. 	    if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data)))
3086. 		return(0);
3087. 	}
3088. 	if ((ttmp = t_at(x, y)) != 0) {
3089. 	    if (x == u.ux && y == u.uy)
3090. 		if (!Passes_walls)
3091. 		    return(0);
3092. 	    if (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP) {
3093. 		/* convert to an object */
3094. 		otmp = mksobj((ttmp->ttyp == LANDMINE) ? LAND_MINE :
3095. 				BEARTRAP, TRUE, FALSE);
3096. 		otmp->quan= 1;
3097. 		otmp->owt = weight(otmp);
3098. 		(void) mpickobj(shkp, otmp);
3099. 	    }
3100. 	    deltrap(ttmp);
3101. 	    if(IS_DOOR(tmp_dam->typ)) {
3102. 		levl[x][y].doormask = D_CLOSED; /* arbitrary */
3103. 		block_point(x, y);
3104. 	    } else if (IS_WALL(tmp_dam->typ)) {
3105. 		levl[x][y].typ = tmp_dam->typ;
3106. 		block_point(x, y);
3107. 	    }
3108. 	    newsym(x, y);
3109. 	    return(3);
3110. 	}
3111. 	if (IS_ROOM(tmp_dam->typ)) {
3112. 	    /* No messages, because player already filled trap door */
3113. 	    return(1);
3114. 	}
3115. 	if ((tmp_dam->typ == levl[x][y].typ) &&
3116. 	    (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN)))
3117. 	    /* No messages if player already replaced shop door */
3118. 	    return(1);
3119. 	levl[x][y].typ = tmp_dam->typ;
3120. 	(void) memset((genericptr_t)litter, 0, sizeof(litter));
3121. 	if ((otmp = level.objects[x][y]) != 0) {
3122. 	    /* Scatter objects haphazardly into the shop */
3123. #define NEED_UPDATE 1
3124. #define OPEN	    2
3125. #define INSHOP	    4
3126. #define horiz(i) ((i%3)-1)
3127. #define vert(i)  ((i/3)-1)
3128. 	    for (i = 0; i < 9; i++) {
3129. 		if ((i == 4) || (!ZAP_POS(levl[x+horiz(i)][y+vert(i)].typ)))
3130. 		    continue;
3131. 		litter[i] = OPEN;
3132. 		if (inside_shop(x+horiz(i),
3133. 				y+vert(i)) == ESHK(shkp)->shoproom)
3134. 		    litter[i] |= INSHOP;
3135. 	    }
3136. 	    if (Punished && !u.uswallow &&
3137. 				((uchain->ox == x && uchain->oy == y) ||
3138. 				 (uball->ox == x && uball->oy == y))) {
3139. 		/*
3140. 		 * Either the ball or chain is in the repair location.
3141. 		 *
3142. 		 * Take the easy way out and put ball&chain under hero.
3143. 		 */
3144. 		verbalize("Get your junk out of my wall!");
3145. 		unplacebc();	/* pick 'em up */
3146. 		placebc();	/* put 'em down */
3147. 	    }
3148. 	    while ((otmp = level.objects[x][y]) != 0)
3149. 		/* Don't mess w/ boulders -- just merge into wall */
3150. 		if ((otmp->otyp == BOULDER) || (otmp->otyp == ROCK)) {
3151. 		    obj_extract_self(otmp);
3152. 		    obfree(otmp, (struct obj *)0);
3153. 		} else {
3154. 		    while (!(litter[i = rn2(9)] & INSHOP));
3155. 			remove_object(otmp);
3156. 			place_object(otmp, x+horiz(i), y+vert(i));
3157. 			litter[i] |= NEED_UPDATE;
3158. 		}
3159. 	}
3160. 	if (catchup) return 1;	/* repair occurred while off level */
3161. 
3162. 	block_point(x, y);
3163. 	if(IS_DOOR(tmp_dam->typ)) {
3164. 	    levl[x][y].doormask = D_CLOSED; /* arbitrary */
3165. 	    newsym(x, y);
3166. 	} else {
3167. 	    /* don't set doormask  - it is (hopefully) the same as it was */
3168. 	    /* if not, perhaps save it with the damage array...  */
3169. 
3170. 	    if (IS_WALL(tmp_dam->typ) && cansee(x, y)) {
3171. 	    /* Player sees actual repair process, so they KNOW it's a wall */
3172. 		levl[x][y].seenv = SVALL;
3173. 		newsym(x, y);
3174. 	    }
3175. 	    /* Mark this wall as "repaired".  There currently is no code */
3176. 	    /* to do anything about repaired walls, so don't do it.	 */
3177. 	}
3178. 	for (i = 0; i < 9; i++)
3179. 	    if (litter[i] & NEED_UPDATE)
3180. 		newsym(x+horiz(i), y+vert(i));
3181. 	return(2);
3182. #undef NEED_UPDATE
3183. #undef OPEN
3184. #undef INSHOP
3185. #undef vert
3186. #undef horiz
3187. }
3188. #endif /*OVL0*/

shk_move Edit

3189. #ifdef OVL3
3190. /*
3191.  * shk_move: return 1: moved  0: didn't  -1: let m_move do it  -2: died
3192.  */
3193. int
3194. shk_move(shkp)
3195. register struct monst *shkp;
3196. {
3197. 	register xchar gx,gy,omx,omy;
3198. 	register int udist;
3199. 	register schar appr;
3200. 	register struct eshk *eshkp = ESHK(shkp);
3201. 	int z;
3202. 	boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv;
3203. 
3204. 	omx = shkp->mx;
3205. 	omy = shkp->my;
3206. 
3207. 	if (inhishop(shkp))
3208. 	    remove_damage(shkp, FALSE);
3209. 
3210. 	if((udist = distu(omx,omy)) < 3 &&
3211. 	   (shkp->data != &mons[PM_GRID_BUG] || (omx==u.ux || omy==u.uy))) {
3212. 		if(ANGRY(shkp) ||
3213. 		   (Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
3214. 			if(Displaced)
3215. 			  Your("displaced image doesn't fool %s!",
3216. 				mon_nam(shkp));
3217. 			(void) mattacku(shkp);
3218. 			return(0);
3219. 		}
3220. 		if(eshkp->following) {
3221. 			if(strncmp(eshkp->customer, plname, PL_NSIZ)) {
3222. 			    verbalize("%s, %s!  I was looking for %s.",
3223. 				    Hello(shkp), plname, eshkp->customer);
3224. 				    eshkp->following = 0;
3225. 			    return(0);
3226. 			}
3227. 			if(moves > followmsg+4) {
3228. 			    verbalize("%s, %s!  Didn't you forget to pay?",
3229. 				    Hello(shkp), plname);
3230. 			    followmsg = moves;
3231. 			    if (!rn2(9)) {
3232. 			      pline("%s doesn't like customers who don't pay.",
3233. 				    Monnam(shkp));
3234. 				rile_shk(shkp);
3235. 			    }
3236. 			}
3237. 			if(udist < 2)
3238. 			    return(0);
3239. 		}
3240. 	}
3241. 
3242. 	appr = 1;
3243. 	gx = eshkp->shk.x;
3244. 	gy = eshkp->shk.y;
3245. 	satdoor = (gx == omx && gy == omy);
3246. 	if(eshkp->following || ((z = holetime()) >= 0 && z*z <= udist)){
3247. 		/* [This distance check used to apply regardless of
3248. 		    whether the shk was following, but that resulted in
3249. 		    m_move() sometimes taking the shk out of the shop if
3250. 		    the player had fenced him in with boulders or traps.
3251. 		    Such voluntary abandonment left unpaid objects in
3252. 		    invent, triggering billing impossibilities on the
3253. 		    next level once the character fell through the hole.] */
3254. 		if (udist > 4 && eshkp->following)
3255. 		    return(-1);	/* leave it to m_move */
3256. 		gx = u.ux;
3257. 		gy = u.uy;
3258. 	} else if(ANGRY(shkp)) {
3259. 		/* Move towards the hero if the shopkeeper can see him. */
3260. 		if(shkp->mcansee && m_canseeu(shkp)) {
3261. 			gx = u.ux;
3262. 			gy = u.uy;
3263. 		}
3264. 		avoid = FALSE;
3265. 	} else {
3266. #define	GDIST(x,y)	(dist2(x,y,gx,gy))
3267. 		if (Invis
3268. #ifdef STEED
3269. 			|| u.usteed
3270. #endif
3271. 			) {
3272. 		    avoid = FALSE;
3273. 		} else {
3274. 		    uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y);
3275. 		    if(uondoor) {
3276. 			badinv = (carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK) ||
3277. 				  (Fast && (sobj_at(PICK_AXE, u.ux, u.uy) ||
3278. 				  sobj_at(DWARVISH_MATTOCK, u.ux, u.uy))));
3279. 			if(satdoor && badinv)
3280. 			    return(0);
3281. 			avoid = !badinv;
3282. 		    } else {
3283. 			avoid = (*u.ushops && distu(gx,gy) > 8);
3284. 			badinv = FALSE;
3285. 		    }
3286. 
3287. 		    if(((!eshkp->robbed && !eshkp->billct && !eshkp->debit)
3288. 			|| avoid) && GDIST(omx,omy) < 3) {
3289. 			if (!badinv && !onlineu(omx,omy))
3290. 			    return(0);
3291. 			if(satdoor)
3292. 			    appr = gx = gy = 0;
3293. 		    }
3294. 		}
3295. 	}
3296. 
3297. 	z = move_special(shkp,inhishop(shkp),appr,uondoor,avoid,omx,omy,gx,gy);
3298. 	if (z > 0) after_shk_move(shkp);
3299. 
3300. 	return z;
3301. }
3302. 

after_shk_move Edit

3303. /* called after shopkeeper moves, in case the move causes re-entry into shop */
3304. void
3305. after_shk_move(shkp)
3306. struct monst *shkp;
3307. {
3308. 	struct eshk *eshkp = ESHK(shkp);
3309. 
3310. 	if (eshkp->bill_p == (struct bill_x *) -1000 && inhishop(shkp)) {
3311. 	    /* reset bill_p, need to re-calc player's occupancy too */
3312. 	    eshkp->bill_p = &eshkp->bill[0];
3313. 	    check_special_room(FALSE);
3314. 	}
3315. }
3316. 
3317. #endif /*OVL3*/

is_fshk Edit

3318. #ifdef OVLB
3319. 
3320. /* for use in levl_follower (mondata.c) */
3321. boolean
3322. is_fshk(mtmp)
3323. register struct monst *mtmp;
3324. {
3325. 	return((boolean)(mtmp->isshk && ESHK(mtmp)->following));
3326. }
3327. 

shopdig Edit

3328. /* You are digging in the shop. */
3329. void
3330. shopdig(fall)
3331. register int fall;
3332. {
3333.     register struct monst *shkp = shop_keeper(*u.ushops);
3334.     int lang;
3335.     const char *grabs = "grabs";
3336. 
3337.     if(!shkp) return;
3338. 
3339.     /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */
3340.     lang = 0;
3341.     if (shkp->msleeping || !shkp->mcanmove || is_silent(shkp->data))
3342. 	;	/* lang stays 0 */
3343.     else if (shkp->data->msound <= MS_ANIMAL)
3344. 	lang = 1;
3345.     else if (shkp->data->msound >= MS_HUMANOID)
3346. 	lang = 2;
3347. 
3348.     if(!inhishop(shkp)) {
3349. 	if (Role_if(PM_KNIGHT)) {
3350. 	    You_feel("like a common thief.");
3351. 	    adjalign(-sgn(u.ualign.type));
3352. 	}
3353. 	return;
3354.     }
3355. 
3356.     if(!fall) {
3357. 	if (lang == 2) {
3358. 	    if(u.utraptype == TT_PIT)
3359. 		verbalize(
3360. 			"Be careful, %s, or you might fall through the floor.",
3361. 			flags.female ? "madam" : "sir");
3362. 	    else
3363. 		verbalize("%s, do not damage the floor here!",
3364. 			flags.female ? "Madam" : "Sir");
3365. 	}
3366. 	if (Role_if(PM_KNIGHT)) {
3367. 	    You_feel("like a common thief.");
3368. 	    adjalign(-sgn(u.ualign.type));
3369. 	}
3370.     } else if(!um_dist(shkp->mx, shkp->my, 5) &&
3371. 		!shkp->msleeping && shkp->mcanmove &&
3372. 		(ESHK(shkp)->billct || ESHK(shkp)->debit)) {
3373. 	    register struct obj *obj, *obj2;
3374. 	    if (nolimbs(shkp->data)) {
3375. 		grabs = "knocks off";
3376. #if 0
3377. 	       /* This is what should happen, but for balance
3378. 	        * reasons, it isn't currently.
3379. 	        */
3380. 		if (lang == 2)
3381. 		    pline("%s curses %s inability to grab your backpack!",
3382. 			  shkname(shkp), mhim(shkp));
3383. 		rile_shk(shkp);
3384. 		return;
3385. #endif
3386. 	    }
3387. 	    if (distu(shkp->mx, shkp->my) > 2) {
3388. 		mnexto(shkp);
3389. 		/* for some reason the shopkeeper can't come next to you */
3390. 		if (distu(shkp->mx, shkp->my) > 2) {
3391. 		    if (lang == 2)
3392. 			pline("%s curses you in anger and frustration!",
3393. 			      shkname(shkp));
3394. 		    rile_shk(shkp);
3395. 		    return;
3396. 		} else
3397. 		    pline("%s %s, and %s your backpack!",
3398. 			  shkname(shkp),
3399. 			  makeplural(locomotion(shkp->data,"leap")), grabs);
3400. 	    } else
3401. 		pline("%s %s your backpack!", shkname(shkp), grabs);
3402. 
3403. 	    for(obj = invent; obj; obj = obj2) {
3404. 		obj2 = obj->nobj;
3405. 		if ((obj->owornmask & ~(W_SWAPWEP|W_QUIVER)) != 0 ||
3406. 			(obj == uswapwep && u.twoweap) ||
3407. 			(obj->otyp == LEASH && obj->leashmon)) continue;
3408. 		if (obj == current_wand) continue;
3409. 		setnotworn(obj);
3410. 		freeinv(obj);
3411. 		subfrombill(obj, shkp);
3412. 		(void) add_to_minv(shkp, obj);	/* may free obj */
3413. 	    }
3414.     }
3415. }
3416. 

makekops Edit

3417. #ifdef KOPS
3418. STATIC_OVL void
3419. makekops(mm)
3420. coord *mm;
3421. {
3422. 	static const short k_mndx[4] = {
3423. 	    PM_KEYSTONE_KOP, PM_KOP_SERGEANT, PM_KOP_LIEUTENANT, PM_KOP_KAPTAIN
3424. 	};
3425. 	int k_cnt[4], cnt, mndx, k;
3426. 
3427. 	k_cnt[0] = cnt = abs(depth(&u.uz)) + rnd(5);
3428. 	k_cnt[1] = (cnt / 3) + 1;	/* at least one sarge */
3429. 	k_cnt[2] = (cnt / 6);		/* maybe a lieutenant */
3430. 	k_cnt[3] = (cnt / 9);		/* and maybe a kaptain */
3431. 
3432. 	for (k = 0; k < 4; k++) {
3433. 	    if ((cnt = k_cnt[k]) == 0) break;
3434. 	    mndx = k_mndx[k];
3435. 	    if (mvitals[mndx].mvflags & G_GONE) continue;
3436. 
3437. 	    while (cnt--)
3438. 		if (enexto(mm, mm->x, mm->y, &mons[mndx]))
3439. 		    (void) makemon(&mons[mndx], mm->x, mm->y, NO_MM_FLAGS);
3440. 	}
3441. }
3442. #endif	/* KOPS */
3443. 

pay_for_damage Edit

3444. void
3445. pay_for_damage(dmgstr, cant_mollify)
3446. const char *dmgstr;
3447. boolean cant_mollify;
3448. {
3449. 	register struct monst *shkp = (struct monst *)0;
3450. 	char shops_affected[5];
3451. 	register boolean uinshp = (*u.ushops != '\0');
3452. 	char qbuf[80];
3453. 	register xchar x, y;
3454. 	boolean dugwall = !strcmp(dmgstr, "dig into") ||	/* wand */
3455. 			  !strcmp(dmgstr, "damage");		/* pick-axe */
3456. 	struct damage *tmp_dam, *appear_here = 0;
3457. 	/* any number >= (80*80)+(24*24) would do, actually */
3458. 	long cost_of_damage = 0L;
3459. 	unsigned int nearest_shk = 7000, nearest_damage = 7000;
3460. 	int picks = 0;
3461. 
3462. 	for (tmp_dam = level.damagelist;
3463. 	     (tmp_dam && (tmp_dam->when == monstermoves));
3464. 	     tmp_dam = tmp_dam->next) {
3465. 	    char *shp;
3466. 
3467. 	    if (!tmp_dam->cost)
3468. 		continue;
3469. 	    cost_of_damage += tmp_dam->cost;
3470. 	    Strcpy(shops_affected,
3471. 		   in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
3472. 	    for (shp = shops_affected; *shp; shp++) {
3473. 		struct monst *tmp_shk;
3474. 		unsigned int shk_distance;
3475. 
3476. 		if (!(tmp_shk = shop_keeper(*shp)))
3477. 		    continue;
3478. 		if (tmp_shk == shkp) {
3479. 		    unsigned int damage_distance =
3480. 				   distu(tmp_dam->place.x, tmp_dam->place.y);
3481. 
3482. 		    if (damage_distance < nearest_damage) {
3483. 			nearest_damage = damage_distance;
3484. 			appear_here = tmp_dam;
3485. 		    }
3486. 		    continue;
3487. 		}
3488. 		if (!inhishop(tmp_shk))
3489. 		    continue;
3490. 		shk_distance = distu(tmp_shk->mx, tmp_shk->my);
3491. 		if (shk_distance > nearest_shk)
3492. 		    continue;
3493. 		if ((shk_distance == nearest_shk) && picks) {
3494. 		    if (rn2(++picks))
3495. 			continue;
3496. 		} else
3497. 		    picks = 1;
3498. 		shkp = tmp_shk;
3499. 		nearest_shk = shk_distance;
3500. 		appear_here = tmp_dam;
3501. 		nearest_damage = distu(tmp_dam->place.x, tmp_dam->place.y);
3502. 	    }
3503. 	}
3504. 
3505. 	if (!cost_of_damage || !shkp)
3506. 	    return;
3507. 
3508. 	x = appear_here->place.x;
3509. 	y = appear_here->place.y;
3510. 
3511. 	/* not the best introduction to the shk... */
3512. 	(void) strncpy(ESHK(shkp)->customer,plname,PL_NSIZ);
3513. 
3514. 	/* if the shk is already on the war path, be sure it's all out */
3515. 	if(ANGRY(shkp) || ESHK(shkp)->following) {
3516. 		hot_pursuit(shkp);
3517. 		return;
3518. 	}
3519. 
3520. 	/* if the shk is not in their shop.. */
3521. 	if(!*in_rooms(shkp->mx,shkp->my,SHOPBASE)) {
3522. 		if(!cansee(shkp->mx, shkp->my))
3523. 			return;
3524. 		goto getcad;
3525. 	}
3526. 
3527. 	if(uinshp) {
3528. 		if(um_dist(shkp->mx, shkp->my, 1) &&
3529. 			!um_dist(shkp->mx, shkp->my, 3)) {
3530. 		    pline("%s leaps towards you!", shkname(shkp));
3531. 		    mnexto(shkp);
3532. 		}
3533. 		if(um_dist(shkp->mx, shkp->my, 1)) goto getcad;
3534. 	} else {
3535. 	    /*
3536. 	     * Make shkp show up at the door.  Effect:  If there is a monster
3537. 	     * in the doorway, have the hero hear the shopkeeper yell a bit,
3538. 	     * pause, then have the shopkeeper appear at the door, having
3539. 	     * yanked the hapless critter out of the way.
3540. 	     */
3541. 	    if (MON_AT(x, y)) {
3542. 		if(flags.soundok) {
3543. 		    You_hear("an angry voice:");
3544. 		    verbalize("Out of my way, scum!");
3545. 		    wait_synch();
3546. #if defined(UNIX) || defined(VMS)
3547. # if defined(SYSV) || defined(ULTRIX) || defined(VMS)
3548. 		    (void)
3549. # endif
3550. 			sleep(1);
3551. #endif
3552. 		}
3553. 	    }
3554. 	    (void) mnearto(shkp, x, y, TRUE);
3555. 	}
3556. 
3557. 	if((um_dist(x, y, 1) && !uinshp) || cant_mollify ||
3558. #ifndef GOLDOBJ
3559. 	   (u.ugold + ESHK(shkp)->credit) < cost_of_damage
3560. #else
3561. 	   (money_cnt(invent) + ESHK(shkp)->credit) < cost_of_damage
3562. #endif
3563. 				|| !rn2(50)) {
3564. 		if(um_dist(x, y, 1) && !uinshp) {
3565. 		    pline("%s shouts:", shkname(shkp));
3566. 		    verbalize("Who dared %s my %s?", dmgstr,
3567. 					 dugwall ? "shop" : "door");
3568. 		} else {
3569. getcad:
3570. 		    verbalize("How dare you %s my %s?", dmgstr,
3571. 					 dugwall ? "shop" : "door");
3572. 		}
3573. 		hot_pursuit(shkp);
3574. 		return;
3575. 	}
3576. 
3577. 	if (Invis) Your("invisibility does not fool %s!", shkname(shkp));
3578. 	Sprintf(qbuf,"\"Cad!  You did %ld %s worth of damage!\"  Pay? ",
3579. 		 cost_of_damage, currency(cost_of_damage));
3580. 	if(yn(qbuf) != 'n') {
3581. 		cost_of_damage = check_credit(cost_of_damage, shkp);
3582. #ifndef GOLDOBJ
3583. 		u.ugold -= cost_of_damage;
3584. 		shkp->mgold += cost_of_damage;
3585. #else
3586.                 money2mon(shkp, cost_of_damage);
3587. #endif
3588. 		flags.botl = 1;
3589. 		pline("Mollified, %s accepts your restitution.",
3590. 			shkname(shkp));
3591. 		/* move shk back to his home loc */
3592. 		home_shk(shkp, FALSE);
3593. 		pacify_shk(shkp);
3594. 	} else {
3595. 		verbalize("Oh, yes!  You'll pay!");
3596. 		hot_pursuit(shkp);
3597. 		adjalign(-sgn(u.ualign.type));
3598. 	}
3599. }
3600. #endif /*OVLB*/

costly_spot Edit

3601. #ifdef OVL0
3602. /* called in dokick.c when we kick an object that might be in a store */
3603. boolean
3604. costly_spot(x, y)
3605. register xchar x, y;
3606. {
3607. 	register struct monst *shkp;
3608. 
3609. 	if (!level.flags.has_shop) return FALSE;
3610. 	shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
3611. 	if(!shkp || !inhishop(shkp)) return(FALSE);
3612. 
3613. 	return((boolean)(inside_shop(x, y) &&
3614. 		!(x == ESHK(shkp)->shk.x &&
3615. 			y == ESHK(shkp)->shk.y)));
3616. }
3617. #endif /*OVL0*/

shop_object Edit

3618. #ifdef OVLB
3619. 
3620. /* called by dotalk(sounds.c) when #chatting; returns obj if location
3621.    contains shop goods and shopkeeper is willing & able to speak */
3622. struct obj *
3623. shop_object(x, y)
3624. register xchar x, y;
3625. {
3626.     register struct obj *otmp;
3627.     register struct monst *shkp;
3628. 
3629.     if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
3630. 	return(struct obj *)0;
3631. 
3632.     for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
3633. 	if (otmp->oclass != COIN_CLASS)
3634. 	    break;
3635.     /* note: otmp might have ->no_charge set, but that's ok */
3636.     return (otmp && costly_spot(x, y) && NOTANGRY(shkp)
3637. 	    && shkp->mcanmove && !shkp->msleeping)
3638. 		? otmp : (struct obj *)0;
3639. }
3640. 

price_quote Edit

3641. /* give price quotes for all objects linked to this one (ie, on this spot) */
3642. void
3643. price_quote(first_obj)
3644. register struct obj *first_obj;
3645. {
3646.     register struct obj *otmp;
3647.     char buf[BUFSZ], price[40];
3648.     long cost;
3649.     int cnt = 0;
3650.     winid tmpwin;
3651.     struct monst *shkp = shop_keeper(inside_shop(u.ux, u.uy));
3652. 
3653.     tmpwin = create_nhwindow(NHW_MENU);
3654.     putstr(tmpwin, 0, "Fine goods for sale:");
3655.     putstr(tmpwin, 0, "");
3656.     for (otmp = first_obj; otmp; otmp = otmp->nexthere) {
3657. 	if (otmp->oclass == COIN_CLASS) continue;
3658. 	cost = (otmp->no_charge || otmp == uball || otmp == uchain) ? 0L :
3659. 		get_cost(otmp, (struct monst *)0);
3660. 	if (Has_contents(otmp))
3661. 	    cost += contained_cost(otmp, shkp, 0L, FALSE, FALSE);
3662. 	if (!cost) {
3663. 	    Strcpy(price, "no charge");
3664. 	} else {
3665. 	    Sprintf(price, "%ld %s%s", cost, currency(cost),
3666. 		    otmp->quan > 1L ? " each" : "");
3667. 	}
3668. 	Sprintf(buf, "%s, %s", doname(otmp), price);
3669. 	putstr(tmpwin, 0, buf),  cnt++;
3670.     }
3671.     if (cnt > 1) {
3672. 	display_nhwindow(tmpwin, TRUE);
3673.     } else if (cnt == 1) {
3674. 	if (first_obj->no_charge || first_obj == uball || first_obj == uchain){
3675. 	    pline("%s!", buf);	/* buf still contains the string */
3676. 	} else {
3677. 	    /* print cost in slightly different format, so can't reuse buf */
3678. 	    cost = get_cost(first_obj, (struct monst *)0);
3679. 	    if (Has_contents(first_obj))
3680. 		cost += contained_cost(first_obj, shkp, 0L, FALSE, FALSE);
3681. 	    pline("%s, price %ld %s%s%s", doname(first_obj),
3682. 		cost, currency(cost), first_obj->quan > 1L ? " each" : "",
3683. 		shk_embellish(first_obj, cost));
3684. 	}
3685.     }
3686.     destroy_nhwindow(tmpwin);
3687. }
3688. #endif /*OVLB*/

shk_embellish Edit

3689. #ifdef OVL3
3690. 
3691. STATIC_OVL const char *
3692. shk_embellish(itm, cost)
3693. register struct obj *itm;
3694. long cost;
3695. {
3696.     if (!rn2(3)) {
3697. 	register int o, choice = rn2(5);
3698. 	if (choice == 0) choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
3699. 	switch (choice) {
3700. 	    case 4:
3701. 		if (cost < 10L) break; else o = itm->oclass;
3702. 		if (o == FOOD_CLASS) return ", gourmets' delight!";
3703. 		if (objects[itm->otyp].oc_name_known
3704. 		    ? objects[itm->otyp].oc_magic
3705. 		    : (o == AMULET_CLASS || o == RING_CLASS   ||
3706. 		       o == WAND_CLASS   || o == POTION_CLASS ||
3707. 		       o == SCROLL_CLASS || o == SPBOOK_CLASS))
3708. 		    return ", painstakingly developed!";
3709. 		return ", superb craftsmanship!";
3710. 	    case 3: return ", finest quality.";
3711. 	    case 2: return ", an excellent choice.";
3712. 	    case 1: return ", a real bargain.";
3713. 	   default: break;
3714. 	}
3715.     } else if (itm->oartifact) {
3716. 	return ", one of a kind!";
3717.     }
3718.     return ".";
3719. }
3720. #endif /*OVL3*/

shk_chat Edit

3721. #ifdef OVLB
3722. 
3723. /* First 4 supplied by Ronen and Tamar, remainder by development team */
3724. const char *Izchak_speaks[]={
3725.     "%s says: 'These shopping malls give me a headache.'",
3726.     "%s says: 'Slow down.  Think clearly.'",
3727.     "%s says: 'You need to take things one at a time.'",
3728.     "%s says: 'I don't like poofy coffee... give me Columbian Supremo.'",
3729.     "%s says that getting the devteam's agreement on anything is difficult.",
3730.     "%s says that he has noticed those who serve their deity will prosper.",
3731.     "%s says: 'Don't try to steal from me - I have friends in high places!'",
3732.     "%s says: 'You may well need something from this shop in the future.'",
3733.     "%s comments about the Valley of the Dead as being a gateway."
3734. };
3735. 
3736. void
3737. shk_chat(shkp)
3738. struct monst *shkp;
3739. {
3740. 	struct eshk *eshk;
3741. #ifdef GOLDOBJ
3742. 	long shkmoney;
3743. #endif
3744. 	if (!shkp->isshk) {
3745. 		/* The monster type is shopkeeper, but this monster is
3746. 		   not actually a shk, which could happen if someone
3747. 		   wishes for a shopkeeper statue and then animates it.
3748. 		   (Note: shkname() would be "" in a case like this.) */
3749. 		pline("%s asks whether you've seen any untended shops recently.",
3750. 		      Monnam(shkp));
3751. 		/* [Perhaps we ought to check whether this conversation
3752. 		   is taking place inside an untended shop, but a shopless
3753. 		   shk can probably be expected to be rather disoriented.] */
3754. 		return;
3755. 	}
3756. 
3757. 	eshk = ESHK(shkp);
3758. 	if (ANGRY(shkp))
3759. 		pline("%s mentions how much %s dislikes %s customers.",
3760. 			shkname(shkp), mhe(shkp),
3761. 			eshk->robbed ? "non-paying" : "rude");
3762. 	else if (eshk->following) {
3763. 		if (strncmp(eshk->customer, plname, PL_NSIZ)) {
3764. 		    verbalize("%s %s!  I was looking for %s.",
3765. 			    Hello(shkp), plname, eshk->customer);
3766. 		    eshk->following = 0;
3767. 		} else {
3768. 		    verbalize("%s %s!  Didn't you forget to pay?",
3769. 			      Hello(shkp), plname);
3770. 		}
3771. 	} else if (eshk->billct) {
3772. 		register long total = addupbill(shkp) + eshk->debit;
3773. 		pline("%s says that your bill comes to %ld %s.",
3774. 		      shkname(shkp), total, currency(total));
3775. 	} else if (eshk->debit)
3776. 		pline("%s reminds you that you owe %s %ld %s.",
3777. 		      shkname(shkp), mhim(shkp),
3778. 		      eshk->debit, currency(eshk->debit));
3779. 	else if (eshk->credit)
3780. 		pline("%s encourages you to use your %ld %s of credit.",
3781. 		      shkname(shkp), eshk->credit, currency(eshk->credit));
3782. 	else if (eshk->robbed)
3783. 		pline("%s complains about a recent robbery.", shkname(shkp));
3784. #ifndef GOLDOBJ
3785. 	else if (shkp->mgold < 50)
3786. #else
3787. 	else if ((shkmoney = money_cnt(shkp->minvent)) < 50)
3788. #endif
3789. 		pline("%s complains that business is bad.", shkname(shkp));
3790. #ifndef GOLDOBJ
3791. 	else if (shkp->mgold > 4000)
3792. #else
3793. 	else if (shkmoney > 4000)
3794. #endif
3795. 		pline("%s says that business is good.", shkname(shkp));
3796. 	else if (strcmp(shkname(shkp), "Izchak") == 0)
3797. 		pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))],shkname(shkp));
3798. 	else
3799. 		pline("%s talks about the problem of shoplifters.",shkname(shkp));
3800. }
3801. 

kops_gone Edit

3802. #ifdef KOPS
3803. STATIC_OVL void
3804. kops_gone(silent)
3805. register boolean silent;
3806. {
3807. 	register int cnt = 0;
3808. 	register struct monst *mtmp, *mtmp2;
3809. 
3810. 	for (mtmp = fmon; mtmp; mtmp = mtmp2) {
3811. 	    mtmp2 = mtmp->nmon;
3812. 	    if (mtmp->data->mlet == S_KOP) {
3813. 		if (canspotmon(mtmp)) cnt++;
3814. 		mongone(mtmp);
3815. 	    }
3816. 	}
3817. 	if (cnt && !silent)
3818. 	    pline_The("Kop%s (disappointed) vanish%s into thin air.",
3819. 		      plur(cnt), cnt == 1 ? "es" : "");
3820. }
3821. #endif	/* KOPS */
3822. 
3823. #endif /*OVLB*/

cost_per_charge Edit

3824. #ifdef OVL3
3825. 
3826. STATIC_OVL long
3827. cost_per_charge(shkp, otmp, altusage)
3828. struct monst *shkp;
3829. struct obj *otmp;
3830. boolean altusage; /* some items have an "alternate" use with different cost */
3831. {
3832. 	long tmp = 0L;
3833. 
3834. 	if(!shkp || !inhishop(shkp)) return(0L); /* insurance */
3835. 	tmp = get_cost(otmp, shkp);
3836. 
3837. 	/* The idea is to make the exhaustive use of */
3838. 	/* an unpaid item more expensive than buying */
3839. 	/* it outright.				     */
3840. 	if(otmp->otyp == MAGIC_LAMP) {			 /* 1 */
3841. 		/* normal use (ie, as light source) of a magic lamp never
3842. 		   degrades its value, but not charging anything would make
3843. 		   identifcation too easy; charge an amount comparable to
3844. 		   what is charged for an ordinary lamp (don't bother with
3845. 		   angry shk surchage) */
3846. 		if (!altusage) tmp = (long) objects[OIL_LAMP].oc_cost;
3847. 		else tmp += tmp / 3L;	/* djinni is being released */
3848. 	} else if(otmp->otyp == MAGIC_MARKER) {		 /* 70 - 100 */
3849. 		/* no way to determine in advance   */
3850. 		/* how many charges will be wasted. */
3851. 		/* so, arbitrarily, one half of the */
3852. 		/* price per use.		    */
3853. 		tmp /= 2L;
3854. 	} else if(otmp->otyp == BAG_OF_TRICKS ||	 /* 1 - 20 */
3855. 		  otmp->otyp == HORN_OF_PLENTY) {
3856. 		tmp /= 5L;
3857. 	} else if(otmp->otyp == CRYSTAL_BALL ||		 /* 1 - 5 */
3858. 		  otmp->otyp == OIL_LAMP ||		 /* 1 - 10 */
3859. 		  otmp->otyp == BRASS_LANTERN ||
3860. 		 (otmp->otyp >= MAGIC_FLUTE &&
3861. 		  otmp->otyp <= DRUM_OF_EARTHQUAKE) ||	 /* 5 - 9 */
3862. 		  otmp->oclass == WAND_CLASS) {		 /* 3 - 11 */
3863. 		if (otmp->spe > 1) tmp /= 4L;
3864. 	} else if (otmp->oclass == SPBOOK_CLASS) {
3865. 		tmp -= tmp / 5L;
3866. 	} else if (otmp->otyp == CAN_OF_GREASE ||
3867. 		   otmp->otyp == TINNING_KIT
3868. #ifdef TOURIST
3869. 		   || otmp->otyp == EXPENSIVE_CAMERA
3870. #endif
3871. 		   ) {
3872. 		tmp /= 10L;
3873. 	} else if (otmp->otyp == POT_OIL) {
3874. 		tmp /= 5L;
3875. 	}
3876. 	return(tmp);
3877. }
3878. #endif /*OVL3*/

check_unpaid_usage Edit

3879. #ifdef OVLB
3880. 
3881. /* Charge the player for partial use of an unpaid object.
3882.  *
3883.  * Note that bill_dummy_object() should be used instead
3884.  * when an object is completely used.
3885.  */
3886. void
3887. check_unpaid_usage(otmp, altusage)
3888. struct obj *otmp;
3889. boolean altusage;
3890. {
3891. 	struct monst *shkp;
3892. 	const char *fmt, *arg1, *arg2;
3893. 	long tmp;
3894. 
3895. 	if (!otmp->unpaid || !*u.ushops ||
3896. 		(otmp->spe <= 0 && objects[otmp->otyp].oc_charged))
3897. 	    return;
3898. 	if (!(shkp = shop_keeper(*u.ushops)) || !inhishop(shkp))
3899. 	    return;
3900. 	if ((tmp = cost_per_charge(shkp, otmp, altusage)) == 0L)
3901. 	    return;
3902. 
3903. 	arg1 = arg2 = "";
3904. 	if (otmp->oclass == SPBOOK_CLASS) {
3905. 	    fmt = "%sYou owe%s %ld %s.";
3906. 	    arg1 = rn2(2) ? "This is no free library, cad!  " : "";
3907. 	    arg2 = ESHK(shkp)->debit > 0L ? " an additional" : "";
3908. 	} else if (otmp->otyp == POT_OIL) {
3909. 	    fmt = "%s%sThat will cost you %ld %s (Yendorian Fuel Tax).";
3910. 	} else {
3911. 	    fmt = "%s%sUsage fee, %ld %s.";
3912. 	    if (!rn2(3)) arg1 = "Hey!  ";
3913. 	    if (!rn2(3)) arg2 = "Ahem.  ";
3914. 	}
3915. 
3916. 	if (shkp->mcanmove || !shkp->msleeping)
3917. 	    verbalize(fmt, arg1, arg2, tmp, currency(tmp));
3918. 	ESHK(shkp)->debit += tmp;
3919. 	exercise(A_WIS, TRUE);		/* you just got info */
3920. }
3921. 

check_unpaid Edit

3922. /* for using charges of unpaid objects "used in the normal manner" */
3923. void
3924. check_unpaid(otmp)
3925. struct obj *otmp;
3926. {
3927. 	check_unpaid_usage(otmp, FALSE);		/* normal item use */
3928. }
3929. 

costly_gold Edit

3930. void
3931. costly_gold(x, y, amount)
3932. register xchar x, y;
3933. register long amount;
3934. {
3935. 	register long delta;
3936. 	register struct monst *shkp;
3937. 	register struct eshk *eshkp;
3938. 
3939. 	if(!costly_spot(x, y)) return;
3940. 	/* shkp now guaranteed to exist by costly_spot() */
3941. 	shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
3942. 
3943. 	eshkp = ESHK(shkp);
3944. 	if(eshkp->credit >= amount) {
3945. 	    if(eshkp->credit > amount)
3946. 		Your("credit is reduced by %ld %s.",
3947. 					amount, currency(amount));
3948. 	    else Your("credit is erased.");
3949. 	    eshkp->credit -= amount;
3950. 	} else {
3951. 	    delta = amount - eshkp->credit;
3952. 	    if(eshkp->credit)
3953. 		Your("credit is erased.");
3954. 	    if(eshkp->debit)
3955. 		Your("debt increases by %ld %s.",
3956. 					delta, currency(delta));
3957. 	    else You("owe %s %ld %s.",
3958. 				shkname(shkp), delta, currency(delta));
3959. 	    eshkp->debit += delta;
3960. 	    eshkp->loan += delta;
3961. 	    eshkp->credit = 0L;
3962. 	}
3963. }
3964. 

block_door Edit

3965. /* used in domove to block diagonal shop-exit */
3966. /* x,y should always be a door */
3967. boolean
3968. block_door(x,y)
3969. register xchar x, y;
3970. {
3971. 	register int roomno = *in_rooms(x, y, SHOPBASE);
3972. 	register struct monst *shkp;
3973. 
3974. 	if(roomno < 0 || !IS_SHOP(roomno)) return(FALSE);
3975. 	if(!IS_DOOR(levl[x][y].typ)) return(FALSE);
3976. 	if(roomno != *u.ushops) return(FALSE);
3977. 
3978. 	if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp))
3979. 		return(FALSE);
3980. 
3981. 	if(shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y
3982. 	    /* Actually, the shk should be made to block _any_
3983. 	     * door, including a door the player digs, if the
3984. 	     * shk is within a 'jumping' distance.
3985. 	     */
3986. 	    && ESHK(shkp)->shd.x == x && ESHK(shkp)->shd.y == y
3987. 	    && shkp->mcanmove && !shkp->msleeping
3988. 	    && (ESHK(shkp)->debit || ESHK(shkp)->billct ||
3989. 		ESHK(shkp)->robbed)) {
3990. 		pline("%s%s blocks your way!", shkname(shkp),
3991. 				Invis ? " senses your motion and" : "");
3992. 		return(TRUE);
3993. 	}
3994. 	return(FALSE);
3995. }
3996. 

block_entry Edit

3997. /* used in domove to block diagonal shop-entry */
3998. /* u.ux, u.uy should always be a door */
3999. boolean
4000. block_entry(x,y)
4001. register xchar x, y;
4002. {
4003. 	register xchar sx, sy;
4004. 	register int roomno;
4005. 	register struct monst *shkp;
4006. 
4007. 	if(!(IS_DOOR(levl[u.ux][u.uy].typ) &&
4008. 		levl[u.ux][u.uy].doormask == D_BROKEN)) return(FALSE);
4009. 
4010. 	roomno = *in_rooms(x, y, SHOPBASE);
4011. 	if(roomno < 0 || !IS_SHOP(roomno)) return(FALSE);
4012. 	if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp))
4013. 		return(FALSE);
4014. 
4015. 	if(ESHK(shkp)->shd.x != u.ux || ESHK(shkp)->shd.y != u.uy)
4016. 		return(FALSE);
4017. 
4018. 	sx = ESHK(shkp)->shk.x;
4019. 	sy = ESHK(shkp)->shk.y;
4020. 
4021. 	if(shkp->mx == sx && shkp->my == sy
4022. 		&& shkp->mcanmove && !shkp->msleeping
4023. 		&& (x == sx-1 || x == sx+1 || y == sy-1 || y == sy+1)
4024. 		&& (Invis || carrying(PICK_AXE) || carrying(DWARVISH_MATTOCK)
4025. #ifdef STEED
4026. 			|| u.usteed
4027. #endif
4028. 	  )) {
4029. 		pline("%s%s blocks your way!", shkname(shkp),
4030. 				Invis ? " senses your motion and" : "");
4031. 		return(TRUE);
4032. 	}
4033. 	return(FALSE);
4034. }
4035. 
4036. #endif /* OVLB */

shk_your Edit

4037. #ifdef OVL2
4038. 
4039. char *
4040. shk_your(buf, obj)
4041. char *buf;
4042. struct obj *obj;
4043. {
4044. 	if (!shk_owns(buf, obj) && !mon_owns(buf, obj))
4045. 	    Strcpy(buf, carried(obj) ? "your" : "the");
4046. 	return buf;
4047. }
4048. 

Shk_Your Edit

4049. char *
4050. Shk_Your(buf, obj)
4051. char *buf;
4052. struct obj *obj;
4053. {
4054. 	(void) shk_your(buf, obj);
4055. 	*buf = highc(*buf);
4056. 	return buf;
4057. }
4058. 

shk_owns Edit

4059. STATIC_OVL char *
4060. shk_owns(buf, obj)
4061. char *buf;
4062. struct obj *obj;
4063. {
4064. 	struct monst *shkp;
4065. 	xchar x, y;
4066. 
4067. 	if (get_obj_location(obj, &x, &y, 0) &&
4068. 	    (obj->unpaid ||
4069. 	     (obj->where==OBJ_FLOOR && !obj->no_charge && costly_spot(x,y)))) {
4070. 	    shkp = shop_keeper(inside_shop(x, y));
4071. 	    return strcpy(buf, shkp ? s_suffix(shkname(shkp)) : "the");
4072. 	}
4073. 	return (char *)0;
4074. }
4075. 

mon_owns Edit

4076. STATIC_OVL char *
4077. mon_owns(buf, obj)
4078. char *buf;
4079. struct obj *obj;
4080. {
4081. 	if (obj->where == OBJ_MINVENT)
4082. 	    return strcpy(buf, s_suffix(mon_nam(obj->ocarry)));
4083. 	return (char *)0;
4084. }
4085. 
4086. #endif /* OVL2 */

sasc_bug Edit

4087. #ifdef OVLB
4088. 
4089. #ifdef __SASC
4090. void
4091. sasc_bug(struct obj *op, unsigned x){
4092. 	op->unpaid=x;
4093. }
4094. #endif
4095. 
4096. #endif /* OVLB */
4097. 
4098. /*shk.c*/

Around Wikia's network

Random Wiki