1*aed906e4Smestre /* $OpenBSD: hack.shk.c,v 1.13 2016/01/09 18:33:15 mestre Exp $ */
2d0b779f3Sniklas
3df930be7Sderaadt /*
4d25013f2Scamield * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5d25013f2Scamield * Amsterdam
6d25013f2Scamield * All rights reserved.
7d25013f2Scamield *
8d25013f2Scamield * Redistribution and use in source and binary forms, with or without
9d25013f2Scamield * modification, are permitted provided that the following conditions are
10d25013f2Scamield * met:
11d25013f2Scamield *
12d25013f2Scamield * - Redistributions of source code must retain the above copyright notice,
13d25013f2Scamield * this list of conditions and the following disclaimer.
14d25013f2Scamield *
15d25013f2Scamield * - Redistributions in binary form must reproduce the above copyright
16d25013f2Scamield * notice, this list of conditions and the following disclaimer in the
17d25013f2Scamield * documentation and/or other materials provided with the distribution.
18d25013f2Scamield *
19d25013f2Scamield * - Neither the name of the Stichting Centrum voor Wiskunde en
20d25013f2Scamield * Informatica, nor the names of its contributors may be used to endorse or
21d25013f2Scamield * promote products derived from this software without specific prior
22d25013f2Scamield * written permission.
23d25013f2Scamield *
24d25013f2Scamield * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25d25013f2Scamield * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26d25013f2Scamield * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27d25013f2Scamield * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28d25013f2Scamield * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31d25013f2Scamield * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32d25013f2Scamield * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33d25013f2Scamield * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34d25013f2Scamield * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35d25013f2Scamield */
36d25013f2Scamield
37d25013f2Scamield /*
38d25013f2Scamield * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39d25013f2Scamield * All rights reserved.
40d25013f2Scamield *
41d25013f2Scamield * Redistribution and use in source and binary forms, with or without
42d25013f2Scamield * modification, are permitted provided that the following conditions
43d25013f2Scamield * are met:
44d25013f2Scamield * 1. Redistributions of source code must retain the above copyright
45d25013f2Scamield * notice, this list of conditions and the following disclaimer.
46d25013f2Scamield * 2. Redistributions in binary form must reproduce the above copyright
47d25013f2Scamield * notice, this list of conditions and the following disclaimer in the
48d25013f2Scamield * documentation and/or other materials provided with the distribution.
49d25013f2Scamield * 3. The name of the author may not be used to endorse or promote products
50d25013f2Scamield * derived from this software without specific prior written permission.
51d25013f2Scamield *
52d25013f2Scamield * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53d25013f2Scamield * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54d25013f2Scamield * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55d25013f2Scamield * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58d25013f2Scamield * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59d25013f2Scamield * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60d25013f2Scamield * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61d25013f2Scamield * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62df930be7Sderaadt */
63df930be7Sderaadt
644a5fbbc4Spjanzen #include <stdio.h>
654a5fbbc4Spjanzen #include <stdlib.h>
66*aed906e4Smestre
67df930be7Sderaadt #include "hack.h"
684a5fbbc4Spjanzen
69df930be7Sderaadt #ifdef QUEST
70df930be7Sderaadt int shlevel = 0;
71df930be7Sderaadt struct monst *shopkeeper = 0;
72df930be7Sderaadt struct obj *billobjs = 0;
734a5fbbc4Spjanzen
744a5fbbc4Spjanzen void
obfree(struct obj * obj,struct obj * merge)754a5fbbc4Spjanzen obfree(struct obj *obj, struct obj *merge)
764a5fbbc4Spjanzen {
77ebf3d589Sguenther free(obj);
78df930be7Sderaadt }
794a5fbbc4Spjanzen
804a5fbbc4Spjanzen int
inshop(void)81*aed906e4Smestre inshop(void)
824a5fbbc4Spjanzen {
834a5fbbc4Spjanzen return(0);
844a5fbbc4Spjanzen }
854a5fbbc4Spjanzen
864a5fbbc4Spjanzen void
shopdig(int a)874a5fbbc4Spjanzen shopdig(int a)
884a5fbbc4Spjanzen {}
894a5fbbc4Spjanzen
904a5fbbc4Spjanzen void
addtobill(struct obj * ign)914a5fbbc4Spjanzen addtobill(struct obj *ign)
924a5fbbc4Spjanzen {}
934a5fbbc4Spjanzen
944a5fbbc4Spjanzen void
subfrombill(struct obj * ign)954a5fbbc4Spjanzen subfrombill(struct obj *ign)
964a5fbbc4Spjanzen {}
974a5fbbc4Spjanzen
984a5fbbc4Spjanzen void
splitbill(struct obj * ign,struct obj * ign2)994a5fbbc4Spjanzen splitbill(struct obj *ign, struct obj *ign2)
1004a5fbbc4Spjanzen {}
1014a5fbbc4Spjanzen
1024a5fbbc4Spjanzen int
dopay(void)103*aed906e4Smestre dopay(void)
1044a5fbbc4Spjanzen {
1054a5fbbc4Spjanzen return(0);
1064a5fbbc4Spjanzen }
1074a5fbbc4Spjanzen
1084a5fbbc4Spjanzen void
paybill(void)109*aed906e4Smestre paybill(void)
1104a5fbbc4Spjanzen {}
1114a5fbbc4Spjanzen
1124a5fbbc4Spjanzen int
doinvbill(int a)1134a5fbbc4Spjanzen doinvbill(int a)
1144a5fbbc4Spjanzen {
1154a5fbbc4Spjanzen return(0);
1164a5fbbc4Spjanzen }
1174a5fbbc4Spjanzen
1184a5fbbc4Spjanzen void
shkdead(struct monst * ign)1194a5fbbc4Spjanzen shkdead(struct monst *ign)
1204a5fbbc4Spjanzen {}
1214a5fbbc4Spjanzen
1224a5fbbc4Spjanzen int
shkcatch(struct obj * ign)1234a5fbbc4Spjanzen shkcatch(struct obj *ign)
1244a5fbbc4Spjanzen {
1254a5fbbc4Spjanzen return(0);
1264a5fbbc4Spjanzen }
1274a5fbbc4Spjanzen
1284a5fbbc4Spjanzen int
shk_move(struct monst * ign)1294a5fbbc4Spjanzen shk_move(struct monst *ign)
1304a5fbbc4Spjanzen {
1314a5fbbc4Spjanzen return(0);
1324a5fbbc4Spjanzen }
1334a5fbbc4Spjanzen
1344a5fbbc4Spjanzen void
replshk(struct monst * mtmp,struct monst * mtmp2)1354a5fbbc4Spjanzen replshk(struct monst *mtmp, struct monst *mtmp2)
1364a5fbbc4Spjanzen {}
1374a5fbbc4Spjanzen
1384a5fbbc4Spjanzen char *
shkname(struct monst * ign)1394a5fbbc4Spjanzen shkname(struct monst *ign)
1404a5fbbc4Spjanzen {
1414a5fbbc4Spjanzen return("");
1424a5fbbc4Spjanzen }
143df930be7Sderaadt
14454da88e4Spjanzen #else /* QUEST */
145df930be7Sderaadt #include "hack.mfndpos.h"
146df930be7Sderaadt #include "def.eshk.h"
147df930be7Sderaadt
148df930be7Sderaadt #define ESHK(mon) ((struct eshk *)(&(mon->mextra[0])))
149df930be7Sderaadt #define NOTANGRY(mon) mon->mpeaceful
150df930be7Sderaadt #define ANGRY(mon) !NOTANGRY(mon)
151df930be7Sderaadt
1524a5fbbc4Spjanzen extern char plname[];
153df930be7Sderaadt
154df930be7Sderaadt /* Descriptor of current shopkeeper. Note that the bill need not be
1554a5fbbc4Spjanzen * per-shopkeeper, since it is valid only when in a shop.
1564a5fbbc4Spjanzen */
157df930be7Sderaadt static struct monst *shopkeeper = 0;
158df930be7Sderaadt static struct bill_x *bill;
159df930be7Sderaadt static int shlevel = 0; /* level of this shopkeeper */
160df930be7Sderaadt struct obj *billobjs; /* objects on bill with bp->useup */
161df930be7Sderaadt /* only accessed here and by save & restore */
162df930be7Sderaadt static long int total; /* filled by addupbill() */
163df930be7Sderaadt static long int followmsg; /* last time of follow message */
164df930be7Sderaadt
165df930be7Sderaadt /*
1664a5fbbc4Spjanzen * invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
1674a5fbbc4Spjanzen * obj->quan <= bp->bquan
168df930be7Sderaadt */
169df930be7Sderaadt
170df930be7Sderaadt
171df930be7Sderaadt char shtypes[] = { /* 8 shoptypes: 7 specialized, 1 mixed */
172df930be7Sderaadt RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM,
173df930be7Sderaadt POTION_SYM, ARMOR_SYM, 0
174df930be7Sderaadt };
175df930be7Sderaadt
176df930be7Sderaadt static char *shopnam[] = {
177df930be7Sderaadt "engagement ring", "walking cane", "antique weapon",
178df930be7Sderaadt "delicatessen", "second hand book", "liquor",
179df930be7Sderaadt "used armor", "assorted antiques"
180df930be7Sderaadt };
181df930be7Sderaadt
1824a5fbbc4Spjanzen static void setpaid(void);
1834a5fbbc4Spjanzen static void addupbill(void);
1844a5fbbc4Spjanzen static void findshk(int);
1854a5fbbc4Spjanzen static struct bill_x *onbill(struct obj *);
1864a5fbbc4Spjanzen static void pay(long, struct monst *);
1874a5fbbc4Spjanzen static int dopayobj(struct bill_x *);
1884a5fbbc4Spjanzen static struct obj *bp_to_obj(struct bill_x *);
1894a5fbbc4Spjanzen static int getprice(struct obj *);
190*aed906e4Smestre static int realhunger(void);
1914a5fbbc4Spjanzen
1924a5fbbc4Spjanzen /* called in do_name.c */
193df930be7Sderaadt char *
shkname(struct monst * mtmp)1944a5fbbc4Spjanzen shkname(struct monst *mtmp)
195df930be7Sderaadt {
196df930be7Sderaadt return(ESHK(mtmp)->shknam);
197df930be7Sderaadt }
198df930be7Sderaadt
1994a5fbbc4Spjanzen void
shkdead(struct monst * mtmp)2004a5fbbc4Spjanzen shkdead(struct monst *mtmp) /* called in mon.c */
201df930be7Sderaadt {
2024a5fbbc4Spjanzen struct eshk *eshk = ESHK(mtmp);
203df930be7Sderaadt
204df930be7Sderaadt if(eshk->shoplevel == dlevel)
205df930be7Sderaadt rooms[eshk->shoproom].rtype = 0;
206df930be7Sderaadt if(mtmp == shopkeeper) {
207df930be7Sderaadt setpaid();
208df930be7Sderaadt shopkeeper = 0;
209df930be7Sderaadt bill = (struct bill_x *) -1000; /* dump core when referenced */
210df930be7Sderaadt }
211df930be7Sderaadt }
212df930be7Sderaadt
2134a5fbbc4Spjanzen void
replshk(struct monst * mtmp,struct monst * mtmp2)2144a5fbbc4Spjanzen replshk(struct monst *mtmp, struct monst *mtmp2)
215df930be7Sderaadt {
216df930be7Sderaadt if(mtmp == shopkeeper) {
217df930be7Sderaadt shopkeeper = mtmp2;
218df930be7Sderaadt bill = &(ESHK(shopkeeper)->bill[0]);
219df930be7Sderaadt }
220df930be7Sderaadt }
221df930be7Sderaadt
2224a5fbbc4Spjanzen /* caller has checked that shopkeeper exists */
223df930be7Sderaadt /* either we paid or left the shop or he just died */
2244a5fbbc4Spjanzen static void
setpaid(void)225*aed906e4Smestre setpaid(void)
2264a5fbbc4Spjanzen {
2274a5fbbc4Spjanzen struct obj *obj;
2284a5fbbc4Spjanzen struct monst *mtmp;
2294a5fbbc4Spjanzen
230df930be7Sderaadt for(obj = invent; obj; obj = obj->nobj)
231df930be7Sderaadt obj->unpaid = 0;
232df930be7Sderaadt for(obj = fobj; obj; obj = obj->nobj)
233df930be7Sderaadt obj->unpaid = 0;
234df930be7Sderaadt for(obj = fcobj; obj; obj = obj->nobj)
235df930be7Sderaadt obj->unpaid = 0;
236df930be7Sderaadt for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
237df930be7Sderaadt for(obj = mtmp->minvent; obj; obj = obj->nobj)
238df930be7Sderaadt obj->unpaid = 0;
239df930be7Sderaadt for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
240df930be7Sderaadt for(obj = mtmp->minvent; obj; obj = obj->nobj)
241df930be7Sderaadt obj->unpaid = 0;
2424a5fbbc4Spjanzen while ((obj = billobjs)) {
243df930be7Sderaadt billobjs = obj->nobj;
244ebf3d589Sguenther free(obj);
245df930be7Sderaadt }
246df930be7Sderaadt ESHK(shopkeeper)->billct = 0;
247df930be7Sderaadt }
248df930be7Sderaadt
2494a5fbbc4Spjanzen /* delivers result in total */
250df930be7Sderaadt /* caller has checked that shopkeeper exists */
2514a5fbbc4Spjanzen static void
addupbill(void)252*aed906e4Smestre addupbill(void)
2534a5fbbc4Spjanzen {
2544a5fbbc4Spjanzen int ct = ESHK(shopkeeper)->billct;
2554a5fbbc4Spjanzen struct bill_x *bp = bill;
2564a5fbbc4Spjanzen
257df930be7Sderaadt total = 0;
258df930be7Sderaadt while(ct--){
259df930be7Sderaadt total += bp->price * bp->bquan;
260df930be7Sderaadt bp++;
261df930be7Sderaadt }
262df930be7Sderaadt }
263df930be7Sderaadt
2644a5fbbc4Spjanzen int
inshop(void)265*aed906e4Smestre inshop(void)
2664a5fbbc4Spjanzen {
2674a5fbbc4Spjanzen int roomno = inroom(u.ux,u.uy);
268df930be7Sderaadt
269df930be7Sderaadt /* Did we just leave a shop? */
270df930be7Sderaadt if(u.uinshop &&
271df930be7Sderaadt (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
272df930be7Sderaadt if(shopkeeper) {
273df930be7Sderaadt if(ESHK(shopkeeper)->billct) {
274df930be7Sderaadt if(inroom(shopkeeper->mx, shopkeeper->my)
275df930be7Sderaadt == u.uinshop - 1) /* ab@unido */
276df930be7Sderaadt pline("Somehow you escaped the shop without paying!");
277df930be7Sderaadt addupbill();
278df930be7Sderaadt pline("You stole for a total worth of %ld zorkmids.",
279df930be7Sderaadt total);
280df930be7Sderaadt ESHK(shopkeeper)->robbed += total;
281df930be7Sderaadt setpaid();
282df930be7Sderaadt if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL)
283df930be7Sderaadt == (rn2(3) == 0))
284df930be7Sderaadt ESHK(shopkeeper)->following = 1;
285df930be7Sderaadt }
286df930be7Sderaadt shopkeeper = 0;
287df930be7Sderaadt shlevel = 0;
288df930be7Sderaadt }
289df930be7Sderaadt u.uinshop = 0;
290df930be7Sderaadt }
291df930be7Sderaadt
292df930be7Sderaadt /* Did we just enter a zoo of some kind? */
293df930be7Sderaadt if(roomno >= 0) {
2944a5fbbc4Spjanzen int rt = rooms[roomno].rtype;
2954a5fbbc4Spjanzen struct monst *mtmp;
296df930be7Sderaadt if(rt == ZOO) {
297df930be7Sderaadt pline("Welcome to David's treasure zoo!");
298df930be7Sderaadt } else
299df930be7Sderaadt if(rt == SWAMP) {
300df930be7Sderaadt pline("It looks rather muddy down here.");
301df930be7Sderaadt } else
302df930be7Sderaadt if(rt == MORGUE) {
303df930be7Sderaadt if(midnight())
304df930be7Sderaadt pline("Go away! Go away!");
305df930be7Sderaadt else
306df930be7Sderaadt pline("You get an uncanny feeling ...");
307df930be7Sderaadt } else
308df930be7Sderaadt rt = 0;
309df930be7Sderaadt if(rt != 0) {
310df930be7Sderaadt rooms[roomno].rtype = 0;
311df930be7Sderaadt for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
312df930be7Sderaadt if(rt != ZOO || !rn2(3))
313df930be7Sderaadt mtmp->msleep = 0;
314df930be7Sderaadt }
315df930be7Sderaadt }
316df930be7Sderaadt
317df930be7Sderaadt /* Did we just enter a shop? */
318df930be7Sderaadt if(roomno >= 0 && rooms[roomno].rtype >= 8) {
319df930be7Sderaadt if(shlevel != dlevel || !shopkeeper
320df930be7Sderaadt || ESHK(shopkeeper)->shoproom != roomno)
321df930be7Sderaadt findshk(roomno);
322df930be7Sderaadt if(!shopkeeper) {
323df930be7Sderaadt rooms[roomno].rtype = 0;
324df930be7Sderaadt u.uinshop = 0;
325df930be7Sderaadt } else if(!u.uinshop){
326df930be7Sderaadt if(!ESHK(shopkeeper)->visitct ||
327df930be7Sderaadt strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){
328df930be7Sderaadt
329df930be7Sderaadt /* He seems to be new here */
330df930be7Sderaadt ESHK(shopkeeper)->visitct = 0;
331df930be7Sderaadt ESHK(shopkeeper)->following = 0;
332479daa62Savsm (void) strlcpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
333df930be7Sderaadt NOTANGRY(shopkeeper) = 1;
334df930be7Sderaadt }
335df930be7Sderaadt if(!ESHK(shopkeeper)->following) {
336df930be7Sderaadt boolean box, pick;
337df930be7Sderaadt
338df930be7Sderaadt pline("Hello %s! Welcome%s to %s's %s shop!",
339df930be7Sderaadt plname,
340df930be7Sderaadt ESHK(shopkeeper)->visitct++ ? " again" : "",
341df930be7Sderaadt shkname(shopkeeper),
342df930be7Sderaadt shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] );
343df930be7Sderaadt box = carrying(ICE_BOX);
344df930be7Sderaadt pick = carrying(PICK_AXE);
345df930be7Sderaadt if(box || pick) {
346df930be7Sderaadt if(dochug(shopkeeper)) {
347df930be7Sderaadt u.uinshop = 0; /* he died moving */
348df930be7Sderaadt return(0);
349df930be7Sderaadt }
350df930be7Sderaadt pline("Will you please leave your %s outside?",
351df930be7Sderaadt (box && pick) ? "box and pick-axe" :
352df930be7Sderaadt box ? "box" : "pick-axe");
353df930be7Sderaadt }
354df930be7Sderaadt }
355df930be7Sderaadt u.uinshop = roomno + 1;
356df930be7Sderaadt }
357df930be7Sderaadt }
358df930be7Sderaadt return(u.uinshop);
359df930be7Sderaadt }
360df930be7Sderaadt
361df930be7Sderaadt static void
findshk(int roomno)3624a5fbbc4Spjanzen findshk(int roomno)
363df930be7Sderaadt {
3644a5fbbc4Spjanzen struct monst *mtmp;
3654a5fbbc4Spjanzen
366df930be7Sderaadt for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
367df930be7Sderaadt if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
368df930be7Sderaadt && ESHK(mtmp)->shoplevel == dlevel) {
369df930be7Sderaadt shopkeeper = mtmp;
370df930be7Sderaadt bill = &(ESHK(shopkeeper)->bill[0]);
371df930be7Sderaadt shlevel = dlevel;
372df930be7Sderaadt if(ANGRY(shopkeeper) &&
373df930be7Sderaadt strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
374df930be7Sderaadt NOTANGRY(shopkeeper) = 1;
375df930be7Sderaadt /* billobjs = 0; -- this is wrong if we save in a shop */
376df930be7Sderaadt /* (and it is harmless to have too many things in billobjs) */
377df930be7Sderaadt return;
378df930be7Sderaadt }
379df930be7Sderaadt shopkeeper = 0;
380df930be7Sderaadt shlevel = 0;
381df930be7Sderaadt bill = (struct bill_x *) -1000; /* dump core when referenced */
382df930be7Sderaadt }
383df930be7Sderaadt
384df930be7Sderaadt static struct bill_x *
onbill(struct obj * obj)3854a5fbbc4Spjanzen onbill(struct obj *obj)
3864a5fbbc4Spjanzen {
3874a5fbbc4Spjanzen struct bill_x *bp;
3884a5fbbc4Spjanzen
3894a5fbbc4Spjanzen if(!shopkeeper) return(NULL);
390df930be7Sderaadt for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
391df930be7Sderaadt if(bp->bo_id == obj->o_id) {
392df930be7Sderaadt if(!obj->unpaid) pline("onbill: paid obj on bill?");
393df930be7Sderaadt return(bp);
394df930be7Sderaadt }
395df930be7Sderaadt if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
3964a5fbbc4Spjanzen return(NULL);
397df930be7Sderaadt }
398df930be7Sderaadt
399df930be7Sderaadt /* called with two args on merge */
4004a5fbbc4Spjanzen void
obfree(struct obj * obj,struct obj * merge)4014a5fbbc4Spjanzen obfree(struct obj *obj, struct obj *merge)
4024a5fbbc4Spjanzen {
4034a5fbbc4Spjanzen struct bill_x *bp = onbill(obj);
4044a5fbbc4Spjanzen struct bill_x *bpm;
4054a5fbbc4Spjanzen
406df930be7Sderaadt if(bp) {
407df930be7Sderaadt if(!merge){
408df930be7Sderaadt bp->useup = 1;
409df930be7Sderaadt obj->unpaid = 0; /* only for doinvbill */
410df930be7Sderaadt obj->nobj = billobjs;
411df930be7Sderaadt billobjs = obj;
412df930be7Sderaadt return;
413df930be7Sderaadt }
414df930be7Sderaadt bpm = onbill(merge);
415df930be7Sderaadt if(!bpm){
416df930be7Sderaadt /* this used to be a rename */
417df930be7Sderaadt impossible("obfree: not on bill??");
418df930be7Sderaadt return;
419df930be7Sderaadt } else {
420df930be7Sderaadt /* this was a merger */
421df930be7Sderaadt bpm->bquan += bp->bquan;
422df930be7Sderaadt ESHK(shopkeeper)->billct--;
423df930be7Sderaadt *bp = bill[ESHK(shopkeeper)->billct];
424df930be7Sderaadt }
425df930be7Sderaadt }
426ebf3d589Sguenther free(obj);
427df930be7Sderaadt }
428df930be7Sderaadt
4294a5fbbc4Spjanzen static void
pay(long tmp,struct monst * shkp)4304a5fbbc4Spjanzen pay(long tmp, struct monst *shkp)
431df930be7Sderaadt {
432df930be7Sderaadt long robbed = ESHK(shkp)->robbed;
433df930be7Sderaadt
434df930be7Sderaadt u.ugold -= tmp;
435df930be7Sderaadt shkp->mgold += tmp;
436df930be7Sderaadt flags.botl = 1;
437df930be7Sderaadt if(robbed) {
438df930be7Sderaadt robbed -= tmp;
439df930be7Sderaadt if(robbed < 0) robbed = 0;
440df930be7Sderaadt ESHK(shkp)->robbed = robbed;
441df930be7Sderaadt }
442df930be7Sderaadt }
443df930be7Sderaadt
4444a5fbbc4Spjanzen int
dopay(void)445*aed906e4Smestre dopay(void)
4464a5fbbc4Spjanzen {
447df930be7Sderaadt long ltmp;
4484a5fbbc4Spjanzen struct bill_x *bp;
4494a5fbbc4Spjanzen struct monst *shkp;
450df930be7Sderaadt int pass, tmp;
451df930be7Sderaadt
452df930be7Sderaadt multi = 0;
453df930be7Sderaadt (void) inshop();
454df930be7Sderaadt for(shkp = fmon; shkp; shkp = shkp->nmon)
455df930be7Sderaadt if(shkp->isshk && dist(shkp->mx,shkp->my) < 3)
456df930be7Sderaadt break;
457df930be7Sderaadt if(!shkp && u.uinshop &&
458df930be7Sderaadt inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom)
459df930be7Sderaadt shkp = shopkeeper;
460df930be7Sderaadt
461df930be7Sderaadt if(!shkp) {
462df930be7Sderaadt pline("There is nobody here to receive your payment.");
463df930be7Sderaadt return(0);
464df930be7Sderaadt }
465df930be7Sderaadt ltmp = ESHK(shkp)->robbed;
466df930be7Sderaadt if(shkp != shopkeeper && NOTANGRY(shkp)) {
467df930be7Sderaadt if(!ltmp) {
468df930be7Sderaadt pline("You do not owe %s anything.", monnam(shkp));
469df930be7Sderaadt } else
470df930be7Sderaadt if(!u.ugold) {
471df930be7Sderaadt pline("You have no money.");
472df930be7Sderaadt } else {
473df930be7Sderaadt long ugold = u.ugold;
474df930be7Sderaadt
475df930be7Sderaadt if(u.ugold > ltmp) {
476df930be7Sderaadt pline("You give %s the %ld gold pieces he asked for.",
477df930be7Sderaadt monnam(shkp), ltmp);
478df930be7Sderaadt pay(ltmp, shkp);
479df930be7Sderaadt } else {
480df930be7Sderaadt pline("You give %s all your gold.", monnam(shkp));
481df930be7Sderaadt pay(u.ugold, shkp);
482df930be7Sderaadt }
483df930be7Sderaadt if(ugold < ltmp/2) {
484df930be7Sderaadt pline("Unfortunately, he doesn't look satisfied.");
485df930be7Sderaadt } else {
486df930be7Sderaadt ESHK(shkp)->robbed = 0;
487df930be7Sderaadt ESHK(shkp)->following = 0;
488df930be7Sderaadt if(ESHK(shkp)->shoplevel != dlevel) {
489df930be7Sderaadt /* For convenience's sake, let him disappear */
490df930be7Sderaadt shkp->minvent = 0; /* %% */
491df930be7Sderaadt shkp->mgold = 0;
492df930be7Sderaadt mondead(shkp);
493df930be7Sderaadt }
494df930be7Sderaadt }
495df930be7Sderaadt }
496df930be7Sderaadt return(1);
497df930be7Sderaadt }
498df930be7Sderaadt
499df930be7Sderaadt if(!ESHK(shkp)->billct){
500df930be7Sderaadt pline("You do not owe %s anything.", monnam(shkp));
501df930be7Sderaadt if(!u.ugold){
502df930be7Sderaadt pline("Moreover, you have no money.");
503df930be7Sderaadt return(1);
504df930be7Sderaadt }
505df930be7Sderaadt if(ESHK(shkp)->robbed){
506df930be7Sderaadt #define min(a,b) ((a<b)?a:b)
507df930be7Sderaadt pline("But since his shop has been robbed recently,");
508df930be7Sderaadt pline("you %srepay %s's expenses.",
509df930be7Sderaadt (u.ugold < ESHK(shkp)->robbed) ? "partially " : "",
510df930be7Sderaadt monnam(shkp));
511df930be7Sderaadt pay(min(u.ugold, ESHK(shkp)->robbed), shkp);
512df930be7Sderaadt ESHK(shkp)->robbed = 0;
513df930be7Sderaadt return(1);
514df930be7Sderaadt }
515df930be7Sderaadt if(ANGRY(shkp)){
516df930be7Sderaadt pline("But in order to appease %s,",
517df930be7Sderaadt amonnam(shkp, "angry"));
518df930be7Sderaadt if(u.ugold >= 1000){
519df930be7Sderaadt ltmp = 1000;
520df930be7Sderaadt pline(" you give him 1000 gold pieces.");
521df930be7Sderaadt } else {
522df930be7Sderaadt ltmp = u.ugold;
523df930be7Sderaadt pline(" you give him all your money.");
524df930be7Sderaadt }
525df930be7Sderaadt pay(ltmp, shkp);
526df930be7Sderaadt if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
527df930be7Sderaadt || rn2(3)){
528df930be7Sderaadt pline("%s calms down.", Monnam(shkp));
529df930be7Sderaadt NOTANGRY(shkp) = 1;
530df930be7Sderaadt } else pline("%s is as angry as ever.",
531df930be7Sderaadt Monnam(shkp));
532df930be7Sderaadt }
533df930be7Sderaadt return(1);
534df930be7Sderaadt }
535df930be7Sderaadt if(shkp != shopkeeper) {
536df930be7Sderaadt impossible("dopay: not to shopkeeper?");
537df930be7Sderaadt if(shopkeeper) setpaid();
538df930be7Sderaadt return(0);
539df930be7Sderaadt }
540df930be7Sderaadt for(pass = 0; pass <= 1; pass++) {
541df930be7Sderaadt tmp = 0;
542df930be7Sderaadt while(tmp < ESHK(shopkeeper)->billct) {
543df930be7Sderaadt bp = &bill[tmp];
544df930be7Sderaadt if(!pass && !bp->useup) {
545df930be7Sderaadt tmp++;
546df930be7Sderaadt continue;
547df930be7Sderaadt }
548df930be7Sderaadt if(!dopayobj(bp)) return(1);
549df930be7Sderaadt bill[tmp] = bill[--ESHK(shopkeeper)->billct];
550df930be7Sderaadt }
551df930be7Sderaadt }
552df930be7Sderaadt pline("Thank you for shopping in %s's %s store!",
553df930be7Sderaadt shkname(shopkeeper),
554df930be7Sderaadt shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]);
555df930be7Sderaadt NOTANGRY(shopkeeper) = 1;
556df930be7Sderaadt return(1);
557df930be7Sderaadt }
558df930be7Sderaadt
559df930be7Sderaadt /* return 1 if paid successfully */
560df930be7Sderaadt /* 0 if not enough money */
561df930be7Sderaadt /* -1 if object could not be found (but was paid) */
5624a5fbbc4Spjanzen static int
dopayobj(struct bill_x * bp)5634a5fbbc4Spjanzen dopayobj(struct bill_x *bp)
5644a5fbbc4Spjanzen {
5654a5fbbc4Spjanzen struct obj *obj;
566df930be7Sderaadt long ltmp;
567df930be7Sderaadt
568df930be7Sderaadt /* find the object on one of the lists */
569df930be7Sderaadt obj = bp_to_obj(bp);
570df930be7Sderaadt
571df930be7Sderaadt if(!obj) {
572df930be7Sderaadt impossible("Shopkeeper administration out of order.");
573df930be7Sderaadt setpaid(); /* be nice to the player */
574df930be7Sderaadt return(0);
575df930be7Sderaadt }
576df930be7Sderaadt
577df930be7Sderaadt if(!obj->unpaid && !bp->useup){
578df930be7Sderaadt impossible("Paid object on bill??");
579df930be7Sderaadt return(1);
580df930be7Sderaadt }
581df930be7Sderaadt obj->unpaid = 0;
582df930be7Sderaadt ltmp = bp->price * bp->bquan;
583df930be7Sderaadt if(ANGRY(shopkeeper)) ltmp += ltmp/3;
584df930be7Sderaadt if(u.ugold < ltmp){
585df930be7Sderaadt pline("You don't have gold enough to pay %s.",
586df930be7Sderaadt doname(obj));
587df930be7Sderaadt obj->unpaid = 1;
588df930be7Sderaadt return(0);
589df930be7Sderaadt }
590df930be7Sderaadt pay(ltmp, shopkeeper);
591df930be7Sderaadt pline("You bought %s for %ld gold piece%s.",
592df930be7Sderaadt doname(obj), ltmp, plur(ltmp));
593df930be7Sderaadt if(bp->useup) {
5944a5fbbc4Spjanzen struct obj *otmp = billobjs;
595df930be7Sderaadt if(obj == billobjs)
596df930be7Sderaadt billobjs = obj->nobj;
597df930be7Sderaadt else {
598df930be7Sderaadt while(otmp && otmp->nobj != obj) otmp = otmp->nobj;
599df930be7Sderaadt if(otmp) otmp->nobj = obj->nobj;
600df930be7Sderaadt else pline("Error in shopkeeper administration.");
601df930be7Sderaadt }
602ebf3d589Sguenther free(obj);
603df930be7Sderaadt }
604df930be7Sderaadt return(1);
605df930be7Sderaadt }
606df930be7Sderaadt
607df930be7Sderaadt /* routine called after dying (or quitting) with nonempty bill */
6084a5fbbc4Spjanzen void
paybill(void)609*aed906e4Smestre paybill(void)
6104a5fbbc4Spjanzen {
611df930be7Sderaadt if(shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct){
612df930be7Sderaadt addupbill();
613df930be7Sderaadt if(total > u.ugold){
614df930be7Sderaadt shopkeeper->mgold += u.ugold;
615df930be7Sderaadt u.ugold = 0;
616df930be7Sderaadt pline("%s comes and takes all your possessions.",
617df930be7Sderaadt Monnam(shopkeeper));
618df930be7Sderaadt } else {
619df930be7Sderaadt u.ugold -= total;
620df930be7Sderaadt shopkeeper->mgold += total;
621df930be7Sderaadt pline("%s comes and takes the %ld zorkmids you owed him.",
622df930be7Sderaadt Monnam(shopkeeper), total);
623df930be7Sderaadt }
624df930be7Sderaadt setpaid(); /* in case we create bones */
625df930be7Sderaadt }
626df930be7Sderaadt }
627df930be7Sderaadt
628df930be7Sderaadt /* find obj on one of the lists */
6294a5fbbc4Spjanzen static struct obj *
bp_to_obj(struct bill_x * bp)6304a5fbbc4Spjanzen bp_to_obj(struct bill_x *bp)
631df930be7Sderaadt {
6324a5fbbc4Spjanzen struct obj *obj;
6334a5fbbc4Spjanzen struct monst *mtmp;
6344a5fbbc4Spjanzen unsigned id = bp->bo_id;
635df930be7Sderaadt
636df930be7Sderaadt if(bp->useup)
637df930be7Sderaadt obj = o_on(id, billobjs);
638df930be7Sderaadt else if(!(obj = o_on(id, invent)) &&
639df930be7Sderaadt !(obj = o_on(id, fobj)) &&
640df930be7Sderaadt !(obj = o_on(id, fcobj))) {
641df930be7Sderaadt for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
6424a5fbbc4Spjanzen if ((obj = o_on(id, mtmp->minvent)))
643df930be7Sderaadt break;
644df930be7Sderaadt for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
6454a5fbbc4Spjanzen if ((obj = o_on(id, mtmp->minvent)))
646df930be7Sderaadt break;
647df930be7Sderaadt }
648df930be7Sderaadt return(obj);
649df930be7Sderaadt }
650df930be7Sderaadt
651df930be7Sderaadt /* called in hack.c when we pickup an object */
6524a5fbbc4Spjanzen void
addtobill(struct obj * obj)6534a5fbbc4Spjanzen addtobill(struct obj *obj)
6544a5fbbc4Spjanzen {
6554a5fbbc4Spjanzen struct bill_x *bp;
6564a5fbbc4Spjanzen
657df930be7Sderaadt if(!inshop() ||
658df930be7Sderaadt (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
659df930be7Sderaadt (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y) ||
660df930be7Sderaadt onbill(obj) /* perhaps we threw it away earlier */
661df930be7Sderaadt ) return;
662df930be7Sderaadt if(ESHK(shopkeeper)->billct == BILLSZ){
663df930be7Sderaadt pline("You got that for free!");
664df930be7Sderaadt return;
665df930be7Sderaadt }
666df930be7Sderaadt bp = &bill[ESHK(shopkeeper)->billct];
667df930be7Sderaadt bp->bo_id = obj->o_id;
668df930be7Sderaadt bp->bquan = obj->quan;
669df930be7Sderaadt bp->useup = 0;
670df930be7Sderaadt bp->price = getprice(obj);
671df930be7Sderaadt ESHK(shopkeeper)->billct++;
672df930be7Sderaadt obj->unpaid = 1;
673df930be7Sderaadt }
674df930be7Sderaadt
6754a5fbbc4Spjanzen void
splitbill(struct obj * obj,struct obj * otmp)6764a5fbbc4Spjanzen splitbill(struct obj *obj, struct obj *otmp)
6774a5fbbc4Spjanzen {
678df930be7Sderaadt /* otmp has been split off from obj */
6794a5fbbc4Spjanzen struct bill_x *bp;
6804a5fbbc4Spjanzen int tmp;
681df930be7Sderaadt bp = onbill(obj);
682df930be7Sderaadt if(!bp) {
683df930be7Sderaadt impossible("splitbill: not on bill?");
684df930be7Sderaadt return;
685df930be7Sderaadt }
686df930be7Sderaadt if(bp->bquan < otmp->quan) {
687df930be7Sderaadt impossible("Negative quantity on bill??");
688df930be7Sderaadt }
689df930be7Sderaadt if(bp->bquan == otmp->quan) {
690df930be7Sderaadt impossible("Zero quantity on bill??");
691df930be7Sderaadt }
692df930be7Sderaadt bp->bquan -= otmp->quan;
693df930be7Sderaadt
694df930be7Sderaadt /* addtobill(otmp); */
695df930be7Sderaadt if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0;
696df930be7Sderaadt else {
697df930be7Sderaadt tmp = bp->price;
698df930be7Sderaadt bp = &bill[ESHK(shopkeeper)->billct];
699df930be7Sderaadt bp->bo_id = otmp->o_id;
700df930be7Sderaadt bp->bquan = otmp->quan;
701df930be7Sderaadt bp->useup = 0;
702df930be7Sderaadt bp->price = tmp;
703df930be7Sderaadt ESHK(shopkeeper)->billct++;
704df930be7Sderaadt }
705df930be7Sderaadt }
706df930be7Sderaadt
7074a5fbbc4Spjanzen void
subfrombill(struct obj * obj)7084a5fbbc4Spjanzen subfrombill(struct obj *obj)
7094a5fbbc4Spjanzen {
710df930be7Sderaadt long ltmp;
7114a5fbbc4Spjanzen int tmp;
7124a5fbbc4Spjanzen struct obj *otmp;
7134a5fbbc4Spjanzen struct bill_x *bp;
7144a5fbbc4Spjanzen
715df930be7Sderaadt if(!inshop() || (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) ||
716df930be7Sderaadt (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y))
717df930be7Sderaadt return;
718df930be7Sderaadt if((bp = onbill(obj)) != 0){
719df930be7Sderaadt obj->unpaid = 0;
720df930be7Sderaadt if(bp->bquan > obj->quan){
721df930be7Sderaadt otmp = newobj(0);
722df930be7Sderaadt *otmp = *obj;
723df930be7Sderaadt bp->bo_id = otmp->o_id = flags.ident++;
724df930be7Sderaadt otmp->quan = (bp->bquan -= obj->quan);
725df930be7Sderaadt otmp->owt = 0; /* superfluous */
726df930be7Sderaadt otmp->onamelth = 0;
727df930be7Sderaadt bp->useup = 1;
728df930be7Sderaadt otmp->nobj = billobjs;
729df930be7Sderaadt billobjs = otmp;
730df930be7Sderaadt return;
731df930be7Sderaadt }
732df930be7Sderaadt ESHK(shopkeeper)->billct--;
733df930be7Sderaadt *bp = bill[ESHK(shopkeeper)->billct];
734df930be7Sderaadt return;
735df930be7Sderaadt }
736df930be7Sderaadt if(obj->unpaid){
737df930be7Sderaadt pline("%s didn't notice.", Monnam(shopkeeper));
738df930be7Sderaadt obj->unpaid = 0;
739df930be7Sderaadt return; /* %% */
740df930be7Sderaadt }
741df930be7Sderaadt /* he dropped something of his own - probably wants to sell it */
742df930be7Sderaadt if(shopkeeper->msleep || shopkeeper->mfroz ||
743df930be7Sderaadt inroom(shopkeeper->mx,shopkeeper->my) != ESHK(shopkeeper)->shoproom)
744df930be7Sderaadt return;
745df930be7Sderaadt if(ESHK(shopkeeper)->billct == BILLSZ ||
746df930be7Sderaadt ((tmp = shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype-8]) && tmp != obj->olet)
747180acc8fSmillert || strchr("_0", obj->olet)) {
748df930be7Sderaadt pline("%s seems not interested.", Monnam(shopkeeper));
749df930be7Sderaadt return;
750df930be7Sderaadt }
751df930be7Sderaadt ltmp = getprice(obj) * obj->quan;
752df930be7Sderaadt if(ANGRY(shopkeeper)) {
753df930be7Sderaadt ltmp /= 3;
754df930be7Sderaadt NOTANGRY(shopkeeper) = 1;
755df930be7Sderaadt } else ltmp /= 2;
756df930be7Sderaadt if(ESHK(shopkeeper)->robbed){
757df930be7Sderaadt if((ESHK(shopkeeper)->robbed -= ltmp) < 0)
758df930be7Sderaadt ESHK(shopkeeper)->robbed = 0;
759df930be7Sderaadt pline("Thank you for your contribution to restock this recently plundered shop.");
760df930be7Sderaadt return;
761df930be7Sderaadt }
762df930be7Sderaadt if(ltmp > shopkeeper->mgold)
763df930be7Sderaadt ltmp = shopkeeper->mgold;
764df930be7Sderaadt pay(-ltmp, shopkeeper);
765df930be7Sderaadt if(!ltmp)
766df930be7Sderaadt pline("%s gladly accepts %s but cannot pay you at present.",
767df930be7Sderaadt Monnam(shopkeeper), doname(obj));
768df930be7Sderaadt else
769df930be7Sderaadt pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp,
770df930be7Sderaadt plur(ltmp));
771df930be7Sderaadt }
772df930be7Sderaadt
773*aed906e4Smestre /* int mode; 0: deliver count 1: paged */
7744a5fbbc4Spjanzen int
doinvbill(int mode)7754a5fbbc4Spjanzen doinvbill(int mode)
776df930be7Sderaadt {
7774a5fbbc4Spjanzen struct bill_x *bp;
7784a5fbbc4Spjanzen struct obj *obj;
779df930be7Sderaadt long totused, thisused;
780df930be7Sderaadt char buf[BUFSZ];
781df930be7Sderaadt
782df930be7Sderaadt if(mode == 0) {
7834a5fbbc4Spjanzen int cnt = 0;
784df930be7Sderaadt
785df930be7Sderaadt if(shopkeeper)
786df930be7Sderaadt for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)
787df930be7Sderaadt if(bp->useup ||
788df930be7Sderaadt ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
789df930be7Sderaadt cnt++;
790df930be7Sderaadt return(cnt);
791df930be7Sderaadt }
792df930be7Sderaadt
793df930be7Sderaadt if(!shopkeeper) {
794df930be7Sderaadt impossible("doinvbill: no shopkeeper?");
795df930be7Sderaadt return(0);
796df930be7Sderaadt }
797df930be7Sderaadt
798df930be7Sderaadt set_pager(0);
799df930be7Sderaadt if(page_line("Unpaid articles already used up:") || page_line(""))
800df930be7Sderaadt goto quit;
801df930be7Sderaadt
802df930be7Sderaadt totused = 0;
803df930be7Sderaadt for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {
804df930be7Sderaadt obj = bp_to_obj(bp);
805df930be7Sderaadt if(!obj) {
806df930be7Sderaadt impossible("Bad shopkeeper administration.");
807df930be7Sderaadt goto quit;
808df930be7Sderaadt }
809df930be7Sderaadt if(bp->useup || bp->bquan > obj->quan) {
8104a5fbbc4Spjanzen int cnt, oquan, uquan;
811df930be7Sderaadt
812df930be7Sderaadt oquan = obj->quan;
813df930be7Sderaadt uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
814df930be7Sderaadt thisused = bp->price * uquan;
815df930be7Sderaadt totused += thisused;
816df930be7Sderaadt obj->quan = uquan; /* cheat doname */
81742ceebb3Sderaadt (void) snprintf(buf, sizeof buf, "x - %s", doname(obj));
818df930be7Sderaadt obj->quan = oquan; /* restore value */
819df930be7Sderaadt for(cnt = 0; buf[cnt]; cnt++);
820df930be7Sderaadt while(cnt < 50)
821df930be7Sderaadt buf[cnt++] = ' ';
82242ceebb3Sderaadt (void) snprintf(&buf[cnt], sizeof buf - cnt,
82342ceebb3Sderaadt " %5ld zorkmids", thisused);
824df930be7Sderaadt if(page_line(buf))
825df930be7Sderaadt goto quit;
826df930be7Sderaadt }
827df930be7Sderaadt }
82842ceebb3Sderaadt (void) snprintf(buf, sizeof buf, "Total:%50ld zorkmids", totused);
829df930be7Sderaadt if(page_line("") || page_line(buf))
830df930be7Sderaadt goto quit;
831df930be7Sderaadt set_pager(1);
832df930be7Sderaadt return(0);
833df930be7Sderaadt quit:
834df930be7Sderaadt set_pager(2);
835df930be7Sderaadt return(0);
836df930be7Sderaadt }
837df930be7Sderaadt
8384a5fbbc4Spjanzen static int
getprice(struct obj * obj)8394a5fbbc4Spjanzen getprice(struct obj *obj)
8404a5fbbc4Spjanzen {
8414a5fbbc4Spjanzen int tmp, ac;
842df930be7Sderaadt
843df930be7Sderaadt switch(obj->olet){
844df930be7Sderaadt case AMULET_SYM:
845df930be7Sderaadt tmp = 10*rnd(500);
846df930be7Sderaadt break;
847df930be7Sderaadt case TOOL_SYM:
848df930be7Sderaadt tmp = 10*rnd((obj->otyp == EXPENSIVE_CAMERA) ? 150 : 30);
849df930be7Sderaadt break;
850df930be7Sderaadt case RING_SYM:
851df930be7Sderaadt tmp = 10*rnd(100);
852df930be7Sderaadt break;
853df930be7Sderaadt case WAND_SYM:
854df930be7Sderaadt tmp = 10*rnd(100);
855df930be7Sderaadt break;
856df930be7Sderaadt case SCROLL_SYM:
857df930be7Sderaadt tmp = 10*rnd(50);
858df930be7Sderaadt #ifdef MAIL
859df930be7Sderaadt if(obj->otyp == SCR_MAIL)
860df930be7Sderaadt tmp = rnd(5);
86154da88e4Spjanzen #endif /* MAIL */
862df930be7Sderaadt break;
863df930be7Sderaadt case POTION_SYM:
864df930be7Sderaadt tmp = 10*rnd(50);
865df930be7Sderaadt break;
866df930be7Sderaadt case FOOD_SYM:
867df930be7Sderaadt tmp = 10*rnd(5 + (2000/realhunger()));
868df930be7Sderaadt break;
869df930be7Sderaadt case GEM_SYM:
870df930be7Sderaadt tmp = 10*rnd(20);
871df930be7Sderaadt break;
872df930be7Sderaadt case ARMOR_SYM:
873df930be7Sderaadt ac = ARM_BONUS(obj);
874df930be7Sderaadt if(ac <= -10) /* probably impossible */
875df930be7Sderaadt ac = -9;
876df930be7Sderaadt tmp = 100 + ac*ac*rnd(10+ac);
877df930be7Sderaadt break;
878df930be7Sderaadt case WEAPON_SYM:
879df930be7Sderaadt if(obj->otyp < BOOMERANG)
880df930be7Sderaadt tmp = 5*rnd(10);
881df930be7Sderaadt else if(obj->otyp == LONG_SWORD ||
882df930be7Sderaadt obj->otyp == TWO_HANDED_SWORD)
883df930be7Sderaadt tmp = 10*rnd(150);
884df930be7Sderaadt else tmp = 10*rnd(75);
885df930be7Sderaadt break;
886df930be7Sderaadt case CHAIN_SYM:
887df930be7Sderaadt pline("Strange ..., carrying a chain?");
888df930be7Sderaadt case BALL_SYM:
889df930be7Sderaadt tmp = 10;
890df930be7Sderaadt break;
891df930be7Sderaadt default:
892df930be7Sderaadt tmp = 10000;
893df930be7Sderaadt }
894df930be7Sderaadt return(tmp);
895df930be7Sderaadt }
896df930be7Sderaadt
8974a5fbbc4Spjanzen /* not completely foolproof */
8984a5fbbc4Spjanzen static int
realhunger(void)899*aed906e4Smestre realhunger(void)
9004a5fbbc4Spjanzen {
9014a5fbbc4Spjanzen int tmp = u.uhunger;
9024a5fbbc4Spjanzen struct obj *otmp = invent;
9034a5fbbc4Spjanzen
904df930be7Sderaadt while(otmp){
905df930be7Sderaadt if(otmp->olet == FOOD_SYM && !otmp->unpaid)
906df930be7Sderaadt tmp += objects[otmp->otyp].nutrition;
907df930be7Sderaadt otmp = otmp->nobj;
908df930be7Sderaadt }
909df930be7Sderaadt return((tmp <= 0) ? 1 : tmp);
910df930be7Sderaadt }
911df930be7Sderaadt
9124a5fbbc4Spjanzen int
shkcatch(struct obj * obj)9134a5fbbc4Spjanzen shkcatch(struct obj *obj)
914df930be7Sderaadt {
9154a5fbbc4Spjanzen struct monst *shkp = shopkeeper;
916df930be7Sderaadt
917df930be7Sderaadt if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&
918df930be7Sderaadt u.dx && u.dy &&
919df930be7Sderaadt inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop &&
920df930be7Sderaadt shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&
921df930be7Sderaadt u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {
922df930be7Sderaadt pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));
923df930be7Sderaadt obj->nobj = shkp->minvent;
924df930be7Sderaadt shkp->minvent = obj;
925df930be7Sderaadt return(1);
926df930be7Sderaadt }
927df930be7Sderaadt return(0);
928df930be7Sderaadt }
929df930be7Sderaadt
930df930be7Sderaadt /*
931df930be7Sderaadt * shk_move: return 1: he moved 0: he didnt -1: let m_move do it
932df930be7Sderaadt */
9334a5fbbc4Spjanzen int
shk_move(struct monst * shkp)9344a5fbbc4Spjanzen shk_move(struct monst *shkp)
935df930be7Sderaadt {
9364a5fbbc4Spjanzen struct monst *mtmp;
9374a5fbbc4Spjanzen struct permonst *mdat = shkp->data;
9384a5fbbc4Spjanzen xchar gx,gy,omx,omy,nx,ny,nix,niy;
9394a5fbbc4Spjanzen schar appr,i;
9404a5fbbc4Spjanzen int udist;
941df930be7Sderaadt int z;
942df930be7Sderaadt schar shkroom,chi,chcnt,cnt;
943df930be7Sderaadt boolean uondoor, satdoor, avoid, badinv;
944df930be7Sderaadt coord poss[9];
945df930be7Sderaadt int info[9];
946df930be7Sderaadt struct obj *ib = 0;
947df930be7Sderaadt
948df930be7Sderaadt omx = shkp->mx;
949df930be7Sderaadt omy = shkp->my;
950df930be7Sderaadt
951df930be7Sderaadt if((udist = dist(omx,omy)) < 3) {
952df930be7Sderaadt if(ANGRY(shkp)) {
953df930be7Sderaadt (void) hitu(shkp, d(mdat->damn, mdat->damd)+1);
954df930be7Sderaadt return(0);
955df930be7Sderaadt }
956df930be7Sderaadt if(ESHK(shkp)->following) {
957df930be7Sderaadt if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)){
958df930be7Sderaadt pline("Hello %s! I was looking for %s.",
959df930be7Sderaadt plname, ESHK(shkp)->customer);
960df930be7Sderaadt ESHK(shkp)->following = 0;
961df930be7Sderaadt return(0);
962df930be7Sderaadt }
963df930be7Sderaadt if(!ESHK(shkp)->robbed) { /* impossible? */
964df930be7Sderaadt ESHK(shkp)->following = 0;
965df930be7Sderaadt return(0);
966df930be7Sderaadt }
967df930be7Sderaadt if(moves > followmsg+4) {
968df930be7Sderaadt pline("Hello %s! Didn't you forget to pay?",
969df930be7Sderaadt plname);
970df930be7Sderaadt followmsg = moves;
971df930be7Sderaadt }
972df930be7Sderaadt if(udist < 2)
973df930be7Sderaadt return(0);
974df930be7Sderaadt }
975df930be7Sderaadt }
976df930be7Sderaadt
977df930be7Sderaadt shkroom = inroom(omx,omy);
978df930be7Sderaadt appr = 1;
979df930be7Sderaadt gx = ESHK(shkp)->shk.x;
980df930be7Sderaadt gy = ESHK(shkp)->shk.y;
981df930be7Sderaadt satdoor = (gx == omx && gy == omy);
982df930be7Sderaadt if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
983df930be7Sderaadt gx = u.ux;
984df930be7Sderaadt gy = u.uy;
985df930be7Sderaadt if(shkroom < 0 || shkroom != inroom(u.ux,u.uy))
986df930be7Sderaadt if(udist > 4)
987df930be7Sderaadt return(-1); /* leave it to m_move */
988df930be7Sderaadt } else if(ANGRY(shkp)) {
989df930be7Sderaadt long saveBlind = Blind;
990df930be7Sderaadt Blind = 0;
991df930be7Sderaadt if(shkp->mcansee && !Invis && cansee(omx,omy)) {
992df930be7Sderaadt gx = u.ux;
993df930be7Sderaadt gy = u.uy;
994df930be7Sderaadt }
995df930be7Sderaadt Blind = saveBlind;
996df930be7Sderaadt avoid = FALSE;
997df930be7Sderaadt } else {
998df930be7Sderaadt #define GDIST(x,y) ((x-gx)*(x-gx)+(y-gy)*(y-gy))
999df930be7Sderaadt if(Invis)
1000df930be7Sderaadt avoid = FALSE;
1001df930be7Sderaadt else {
1002df930be7Sderaadt uondoor = (u.ux == ESHK(shkp)->shd.x &&
1003df930be7Sderaadt u.uy == ESHK(shkp)->shd.y);
1004df930be7Sderaadt if(uondoor) {
1005df930be7Sderaadt if(ESHK(shkp)->billct)
1006df930be7Sderaadt pline("Hello %s! Will you please pay before leaving?",
1007df930be7Sderaadt plname);
1008df930be7Sderaadt badinv = (carrying(PICK_AXE) || carrying(ICE_BOX));
1009df930be7Sderaadt if(satdoor && badinv)
1010df930be7Sderaadt return(0);
1011df930be7Sderaadt avoid = !badinv;
1012df930be7Sderaadt } else {
1013df930be7Sderaadt avoid = (u.uinshop && dist(gx,gy) > 8);
1014df930be7Sderaadt badinv = FALSE;
1015df930be7Sderaadt }
1016df930be7Sderaadt
1017df930be7Sderaadt if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
1018df930be7Sderaadt && GDIST(omx,omy) < 3){
1019df930be7Sderaadt if(!badinv && !online(omx,omy))
1020df930be7Sderaadt return(0);
1021df930be7Sderaadt if(satdoor)
1022df930be7Sderaadt appr = gx = gy = 0;
1023df930be7Sderaadt }
1024df930be7Sderaadt }
1025df930be7Sderaadt }
1026df930be7Sderaadt if(omx == gx && omy == gy)
1027df930be7Sderaadt return(0);
1028df930be7Sderaadt if(shkp->mconf) {
1029df930be7Sderaadt avoid = FALSE;
1030df930be7Sderaadt appr = 0;
1031df930be7Sderaadt }
1032df930be7Sderaadt nix = omx;
1033df930be7Sderaadt niy = omy;
1034df930be7Sderaadt cnt = mfndpos(shkp,poss,info,ALLOW_SSM);
1035df930be7Sderaadt if(avoid && uondoor) { /* perhaps we cannot avoid him */
1036df930be7Sderaadt for(i=0; i<cnt; i++)
10374a5fbbc4Spjanzen if(!(info[(int)i] & NOTONL)) goto notonl_ok;
1038df930be7Sderaadt avoid = FALSE;
1039df930be7Sderaadt notonl_ok:
1040df930be7Sderaadt ;
1041df930be7Sderaadt }
1042df930be7Sderaadt chi = -1;
1043df930be7Sderaadt chcnt = 0;
1044df930be7Sderaadt for(i=0; i<cnt; i++){
10454a5fbbc4Spjanzen nx = poss[(int)i].x;
10464a5fbbc4Spjanzen ny = poss[(int)i].y;
10474a5fbbc4Spjanzen if(levl[(int)nx][(int)ny].typ == ROOM
1048df930be7Sderaadt || shkroom != ESHK(shkp)->shoproom
1049df930be7Sderaadt || ESHK(shkp)->following) {
1050df930be7Sderaadt #ifdef STUPID
1051df930be7Sderaadt /* cater for stupid compilers */
10524a5fbbc4Spjanzen int zz;
105354da88e4Spjanzen #endif /* STUPID */
1054df930be7Sderaadt if(uondoor && (ib = sobj_at(ICE_BOX, nx, ny))) {
1055df930be7Sderaadt nix = nx; niy = ny; chi = i; break;
1056df930be7Sderaadt }
10574a5fbbc4Spjanzen if(avoid && (info[(int)i] & NOTONL))
1058df930be7Sderaadt continue;
1059df930be7Sderaadt if((!appr && !rn2(++chcnt)) ||
1060df930be7Sderaadt #ifdef STUPID
1061df930be7Sderaadt (appr && (zz = GDIST(nix,niy)) && zz > GDIST(nx,ny))
1062df930be7Sderaadt #else
1063df930be7Sderaadt (appr && GDIST(nx,ny) < GDIST(nix,niy))
106454da88e4Spjanzen #endif /* STUPID */
1065df930be7Sderaadt ) {
1066df930be7Sderaadt nix = nx;
1067df930be7Sderaadt niy = ny;
1068df930be7Sderaadt chi = i;
1069df930be7Sderaadt }
1070df930be7Sderaadt }
1071df930be7Sderaadt }
1072df930be7Sderaadt if(nix != omx || niy != omy){
10734a5fbbc4Spjanzen if(info[(int)chi] & ALLOW_M){
1074df930be7Sderaadt mtmp = m_at(nix,niy);
1075df930be7Sderaadt if(hitmm(shkp,mtmp) == 1 && rn2(3) &&
1076df930be7Sderaadt hitmm(mtmp,shkp) == 2) return(2);
1077df930be7Sderaadt return(0);
10784a5fbbc4Spjanzen } else if(info[(int)chi] & ALLOW_U){
1079df930be7Sderaadt (void) hitu(shkp, d(mdat->damn, mdat->damd)+1);
1080df930be7Sderaadt return(0);
1081df930be7Sderaadt }
1082df930be7Sderaadt shkp->mx = nix;
1083df930be7Sderaadt shkp->my = niy;
1084df930be7Sderaadt pmon(shkp);
1085df930be7Sderaadt if(ib) {
1086df930be7Sderaadt freeobj(ib);
1087df930be7Sderaadt mpickobj(shkp, ib);
1088df930be7Sderaadt }
1089df930be7Sderaadt return(1);
1090df930be7Sderaadt }
1091df930be7Sderaadt return(0);
1092df930be7Sderaadt }
1093df930be7Sderaadt
1094df930be7Sderaadt /* He is digging in the shop. */
10954a5fbbc4Spjanzen void
shopdig(int fall)10964a5fbbc4Spjanzen shopdig(int fall)
1097df930be7Sderaadt {
1098df930be7Sderaadt if(!fall) {
1099df930be7Sderaadt if(u.utraptype == TT_PIT)
1100df930be7Sderaadt pline("\"Be careful, sir, or you might fall through the floor.\"");
1101df930be7Sderaadt else
1102df930be7Sderaadt pline("\"Please, do not damage the floor here.\"");
1103df930be7Sderaadt } else if(dist(shopkeeper->mx, shopkeeper->my) < 3) {
11044a5fbbc4Spjanzen struct obj *obj, *obj2;
1105df930be7Sderaadt
1106df930be7Sderaadt pline("%s grabs your backpack!", shkname(shopkeeper));
1107df930be7Sderaadt for(obj = invent; obj; obj = obj2) {
1108df930be7Sderaadt obj2 = obj->nobj;
1109df930be7Sderaadt if(obj->owornmask) continue;
1110df930be7Sderaadt freeinv(obj);
1111df930be7Sderaadt obj->nobj = shopkeeper->minvent;
1112df930be7Sderaadt shopkeeper->minvent = obj;
1113df930be7Sderaadt if(obj->unpaid)
1114df930be7Sderaadt subfrombill(obj);
1115df930be7Sderaadt }
1116df930be7Sderaadt }
1117df930be7Sderaadt }
111854da88e4Spjanzen #endif /* QUEST */
1119df930be7Sderaadt
11204a5fbbc4Spjanzen int
online(int x,int y)11214a5fbbc4Spjanzen online(int x, int y)
11224a5fbbc4Spjanzen {
1123df930be7Sderaadt return(x==u.ux || y==u.uy ||
1124df930be7Sderaadt (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));
1125df930be7Sderaadt }
1126df930be7Sderaadt
1127df930be7Sderaadt /* Does this monster follow me downstairs? */
11284a5fbbc4Spjanzen int
follower(struct monst * mtmp)11294a5fbbc4Spjanzen follower(struct monst *mtmp)
1130df930be7Sderaadt {
1131180acc8fSmillert return( mtmp->mtame || strchr("1TVWZi&, ", mtmp->data->mlet)
1132df930be7Sderaadt #ifndef QUEST
1133df930be7Sderaadt || (mtmp->isshk && ESHK(mtmp)->following)
113454da88e4Spjanzen #endif /* QUEST */
1135df930be7Sderaadt );
1136df930be7Sderaadt }
1137