File: | src/games/hack/hack.shk.c |
Warning: | line 1035, column 5 Branch condition evaluates to a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: hack.shk.c,v 1.13 2016/01/09 18:33:15 mestre Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, | |||
5 | * Amsterdam | |||
6 | * All rights reserved. | |||
7 | * | |||
8 | * Redistribution and use in source and binary forms, with or without | |||
9 | * modification, are permitted provided that the following conditions are | |||
10 | * met: | |||
11 | * | |||
12 | * - Redistributions of source code must retain the above copyright notice, | |||
13 | * this list of conditions and the following disclaimer. | |||
14 | * | |||
15 | * - Redistributions in binary form must reproduce the above copyright | |||
16 | * notice, this list of conditions and the following disclaimer in the | |||
17 | * documentation and/or other materials provided with the distribution. | |||
18 | * | |||
19 | * - Neither the name of the Stichting Centrum voor Wiskunde en | |||
20 | * Informatica, nor the names of its contributors may be used to endorse or | |||
21 | * promote products derived from this software without specific prior | |||
22 | * written permission. | |||
23 | * | |||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |||
25 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
26 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |||
27 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER | |||
28 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
29 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
30 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |||
31 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |||
32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
33 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||
34 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
35 | */ | |||
36 | ||||
37 | /* | |||
38 | * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> | |||
39 | * All rights reserved. | |||
40 | * | |||
41 | * Redistribution and use in source and binary forms, with or without | |||
42 | * modification, are permitted provided that the following conditions | |||
43 | * are met: | |||
44 | * 1. Redistributions of source code must retain the above copyright | |||
45 | * notice, this list of conditions and the following disclaimer. | |||
46 | * 2. Redistributions in binary form must reproduce the above copyright | |||
47 | * notice, this list of conditions and the following disclaimer in the | |||
48 | * documentation and/or other materials provided with the distribution. | |||
49 | * 3. The name of the author may not be used to endorse or promote products | |||
50 | * derived from this software without specific prior written permission. | |||
51 | * | |||
52 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
53 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||
54 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |||
55 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
56 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
57 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
58 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
59 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
60 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
61 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
62 | */ | |||
63 | ||||
64 | #include <stdio.h> | |||
65 | #include <stdlib.h> | |||
66 | ||||
67 | #include "hack.h" | |||
68 | ||||
69 | #ifdef QUEST | |||
70 | int shlevel = 0; | |||
71 | struct monst *shopkeeper = 0; | |||
72 | struct obj *billobjs = 0; | |||
73 | ||||
74 | void | |||
75 | obfree(struct obj *obj, struct obj *merge) | |||
76 | { | |||
77 | free(obj); | |||
78 | } | |||
79 | ||||
80 | int | |||
81 | inshop(void) | |||
82 | { | |||
83 | return(0); | |||
84 | } | |||
85 | ||||
86 | void | |||
87 | shopdig(int a) | |||
88 | {} | |||
89 | ||||
90 | void | |||
91 | addtobill(struct obj *ign) | |||
92 | {} | |||
93 | ||||
94 | void | |||
95 | subfrombill(struct obj *ign) | |||
96 | {} | |||
97 | ||||
98 | void | |||
99 | splitbill(struct obj *ign, struct obj *ign2) | |||
100 | {} | |||
101 | ||||
102 | int | |||
103 | dopay(void) | |||
104 | { | |||
105 | return(0); | |||
106 | } | |||
107 | ||||
108 | void | |||
109 | paybill(void) | |||
110 | {} | |||
111 | ||||
112 | int | |||
113 | doinvbill(int a) | |||
114 | { | |||
115 | return(0); | |||
116 | } | |||
117 | ||||
118 | void | |||
119 | shkdead(struct monst *ign) | |||
120 | {} | |||
121 | ||||
122 | int | |||
123 | shkcatch(struct obj *ign) | |||
124 | { | |||
125 | return(0); | |||
126 | } | |||
127 | ||||
128 | int | |||
129 | shk_move(struct monst *ign) | |||
130 | { | |||
131 | return(0); | |||
132 | } | |||
133 | ||||
134 | void | |||
135 | replshk(struct monst *mtmp, struct monst *mtmp2) | |||
136 | {} | |||
137 | ||||
138 | char * | |||
139 | shkname(struct monst *ign) | |||
140 | { | |||
141 | return(""); | |||
142 | } | |||
143 | ||||
144 | #else /* QUEST */ | |||
145 | #include "hack.mfndpos.h" | |||
146 | #include "def.eshk.h" | |||
147 | ||||
148 | #define ESHK(mon)((struct eshk *)(&(mon->mextra[0]))) ((struct eshk *)(&(mon->mextra[0]))) | |||
149 | #define NOTANGRY(mon)mon->mpeaceful mon->mpeaceful | |||
150 | #define ANGRY(mon)!mon->mpeaceful !NOTANGRY(mon)mon->mpeaceful | |||
151 | ||||
152 | extern char plname[]; | |||
153 | ||||
154 | /* Descriptor of current shopkeeper. Note that the bill need not be | |||
155 | * per-shopkeeper, since it is valid only when in a shop. | |||
156 | */ | |||
157 | static struct monst *shopkeeper = 0; | |||
158 | static struct bill_x *bill; | |||
159 | static int shlevel = 0; /* level of this shopkeeper */ | |||
160 | struct obj *billobjs; /* objects on bill with bp->useup */ | |||
161 | /* only accessed here and by save & restore */ | |||
162 | static long int total; /* filled by addupbill() */ | |||
163 | static long int followmsg; /* last time of follow message */ | |||
164 | ||||
165 | /* | |||
166 | * invariants: obj->unpaid iff onbill(obj) [unless bp->useup] | |||
167 | * obj->quan <= bp->bquan | |||
168 | */ | |||
169 | ||||
170 | ||||
171 | char shtypes[] = { /* 8 shoptypes: 7 specialized, 1 mixed */ | |||
172 | RING_SYM'=', WAND_SYM'/', WEAPON_SYM')', FOOD_SYM'%', SCROLL_SYM'?', | |||
173 | POTION_SYM'!', ARMOR_SYM'[', 0 | |||
174 | }; | |||
175 | ||||
176 | static char *shopnam[] = { | |||
177 | "engagement ring", "walking cane", "antique weapon", | |||
178 | "delicatessen", "second hand book", "liquor", | |||
179 | "used armor", "assorted antiques" | |||
180 | }; | |||
181 | ||||
182 | static void setpaid(void); | |||
183 | static void addupbill(void); | |||
184 | static void findshk(int); | |||
185 | static struct bill_x *onbill(struct obj *); | |||
186 | static void pay(long, struct monst *); | |||
187 | static int dopayobj(struct bill_x *); | |||
188 | static struct obj *bp_to_obj(struct bill_x *); | |||
189 | static int getprice(struct obj *); | |||
190 | static int realhunger(void); | |||
191 | ||||
192 | /* called in do_name.c */ | |||
193 | char * | |||
194 | shkname(struct monst *mtmp) | |||
195 | { | |||
196 | return(ESHK(mtmp)((struct eshk *)(&(mtmp->mextra[0])))->shknam); | |||
197 | } | |||
198 | ||||
199 | void | |||
200 | shkdead(struct monst *mtmp) /* called in mon.c */ | |||
201 | { | |||
202 | struct eshk *eshk = ESHK(mtmp)((struct eshk *)(&(mtmp->mextra[0]))); | |||
203 | ||||
204 | if(eshk->shoplevel == dlevel) | |||
205 | rooms[eshk->shoproom].rtype = 0; | |||
206 | if(mtmp == shopkeeper) { | |||
207 | setpaid(); | |||
208 | shopkeeper = 0; | |||
209 | bill = (struct bill_x *) -1000; /* dump core when referenced */ | |||
210 | } | |||
211 | } | |||
212 | ||||
213 | void | |||
214 | replshk(struct monst *mtmp, struct monst *mtmp2) | |||
215 | { | |||
216 | if(mtmp == shopkeeper) { | |||
217 | shopkeeper = mtmp2; | |||
218 | bill = &(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->bill[0]); | |||
219 | } | |||
220 | } | |||
221 | ||||
222 | /* caller has checked that shopkeeper exists */ | |||
223 | /* either we paid or left the shop or he just died */ | |||
224 | static void | |||
225 | setpaid(void) | |||
226 | { | |||
227 | struct obj *obj; | |||
228 | struct monst *mtmp; | |||
229 | ||||
230 | for(obj = invent; obj; obj = obj->nobj) | |||
231 | obj->unpaid = 0; | |||
232 | for(obj = fobj; obj; obj = obj->nobj) | |||
233 | obj->unpaid = 0; | |||
234 | for(obj = fcobj; obj; obj = obj->nobj) | |||
235 | obj->unpaid = 0; | |||
236 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) | |||
237 | for(obj = mtmp->minvent; obj; obj = obj->nobj) | |||
238 | obj->unpaid = 0; | |||
239 | for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon) | |||
240 | for(obj = mtmp->minvent; obj; obj = obj->nobj) | |||
241 | obj->unpaid = 0; | |||
242 | while ((obj = billobjs)) { | |||
243 | billobjs = obj->nobj; | |||
244 | free(obj); | |||
245 | } | |||
246 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct = 0; | |||
247 | } | |||
248 | ||||
249 | /* delivers result in total */ | |||
250 | /* caller has checked that shopkeeper exists */ | |||
251 | static void | |||
252 | addupbill(void) | |||
253 | { | |||
254 | int ct = ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct; | |||
255 | struct bill_x *bp = bill; | |||
256 | ||||
257 | total = 0; | |||
258 | while(ct--){ | |||
259 | total += bp->price * bp->bquan; | |||
260 | bp++; | |||
261 | } | |||
262 | } | |||
263 | ||||
264 | int | |||
265 | inshop(void) | |||
266 | { | |||
267 | int roomno = inroom(u.ux,u.uy); | |||
268 | ||||
269 | /* Did we just leave a shop? */ | |||
270 | if(u.uinshop && | |||
271 | (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) { | |||
272 | if(shopkeeper) { | |||
273 | if(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct) { | |||
274 | if(inroom(shopkeeper->mx, shopkeeper->my) | |||
275 | == u.uinshop - 1) /* ab@unido */ | |||
276 | pline("Somehow you escaped the shop without paying!"); | |||
277 | addupbill(); | |||
278 | pline("You stole for a total worth of %ld zorkmids.", | |||
279 | total); | |||
280 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->robbed += total; | |||
281 | setpaid(); | |||
282 | if((rooms[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shoproom].rtype == GENERAL15) | |||
283 | == (rn2(3) == 0)) | |||
284 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->following = 1; | |||
285 | } | |||
286 | shopkeeper = 0; | |||
287 | shlevel = 0; | |||
288 | } | |||
289 | u.uinshop = 0; | |||
290 | } | |||
291 | ||||
292 | /* Did we just enter a zoo of some kind? */ | |||
293 | if(roomno >= 0) { | |||
294 | int rt = rooms[roomno].rtype; | |||
295 | struct monst *mtmp; | |||
296 | if(rt == ZOO7) { | |||
297 | pline("Welcome to David's treasure zoo!"); | |||
298 | } else | |||
299 | if(rt == SWAMP3) { | |||
300 | pline("It looks rather muddy down here."); | |||
301 | } else | |||
302 | if(rt == MORGUE6) { | |||
303 | if(midnight()) | |||
304 | pline("Go away! Go away!"); | |||
305 | else | |||
306 | pline("You get an uncanny feeling ..."); | |||
307 | } else | |||
308 | rt = 0; | |||
309 | if(rt != 0) { | |||
310 | rooms[roomno].rtype = 0; | |||
311 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) | |||
312 | if(rt != ZOO7 || !rn2(3)) | |||
313 | mtmp->msleep = 0; | |||
314 | } | |||
315 | } | |||
316 | ||||
317 | /* Did we just enter a shop? */ | |||
318 | if(roomno >= 0 && rooms[roomno].rtype >= 8) { | |||
319 | if(shlevel != dlevel || !shopkeeper | |||
320 | || ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shoproom != roomno) | |||
321 | findshk(roomno); | |||
322 | if(!shopkeeper) { | |||
323 | rooms[roomno].rtype = 0; | |||
324 | u.uinshop = 0; | |||
325 | } else if(!u.uinshop){ | |||
326 | if(!ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->visitct || | |||
327 | strncmp(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->customer, plname, PL_NSIZ32)){ | |||
328 | ||||
329 | /* He seems to be new here */ | |||
330 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->visitct = 0; | |||
331 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->following = 0; | |||
332 | (void) strlcpy(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->customer,plname,PL_NSIZ32); | |||
333 | NOTANGRY(shopkeeper)shopkeeper->mpeaceful = 1; | |||
334 | } | |||
335 | if(!ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->following) { | |||
336 | boolean box, pick; | |||
337 | ||||
338 | pline("Hello %s! Welcome%s to %s's %s shop!", | |||
339 | plname, | |||
340 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->visitct++ ? " again" : "", | |||
341 | shkname(shopkeeper), | |||
342 | shopnam[rooms[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shoproom].rtype - 8] ); | |||
343 | box = carrying(ICE_BOX92); | |||
344 | pick = carrying(PICK_AXE93); | |||
345 | if(box || pick) { | |||
346 | if(dochug(shopkeeper)) { | |||
347 | u.uinshop = 0; /* he died moving */ | |||
348 | return(0); | |||
349 | } | |||
350 | pline("Will you please leave your %s outside?", | |||
351 | (box && pick) ? "box and pick-axe" : | |||
352 | box ? "box" : "pick-axe"); | |||
353 | } | |||
354 | } | |||
355 | u.uinshop = roomno + 1; | |||
356 | } | |||
357 | } | |||
358 | return(u.uinshop); | |||
359 | } | |||
360 | ||||
361 | static void | |||
362 | findshk(int roomno) | |||
363 | { | |||
364 | struct monst *mtmp; | |||
365 | ||||
366 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) | |||
367 | if(mtmp->isshk && ESHK(mtmp)((struct eshk *)(&(mtmp->mextra[0])))->shoproom == roomno | |||
368 | && ESHK(mtmp)((struct eshk *)(&(mtmp->mextra[0])))->shoplevel == dlevel) { | |||
369 | shopkeeper = mtmp; | |||
370 | bill = &(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->bill[0]); | |||
371 | shlevel = dlevel; | |||
372 | if(ANGRY(shopkeeper)!shopkeeper->mpeaceful && | |||
373 | strncmp(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->customer,plname,PL_NSIZ32)) | |||
374 | NOTANGRY(shopkeeper)shopkeeper->mpeaceful = 1; | |||
375 | /* billobjs = 0; -- this is wrong if we save in a shop */ | |||
376 | /* (and it is harmless to have too many things in billobjs) */ | |||
377 | return; | |||
378 | } | |||
379 | shopkeeper = 0; | |||
380 | shlevel = 0; | |||
381 | bill = (struct bill_x *) -1000; /* dump core when referenced */ | |||
382 | } | |||
383 | ||||
384 | static struct bill_x * | |||
385 | onbill(struct obj *obj) | |||
386 | { | |||
387 | struct bill_x *bp; | |||
388 | ||||
389 | if(!shopkeeper) return(NULL((void *)0)); | |||
390 | for(bp = bill; bp < &bill[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct]; bp++) | |||
391 | if(bp->bo_id == obj->o_id) { | |||
392 | if(!obj->unpaid) pline("onbill: paid obj on bill?"); | |||
393 | return(bp); | |||
394 | } | |||
395 | if(obj->unpaid) pline("onbill: unpaid obj not on bill?"); | |||
396 | return(NULL((void *)0)); | |||
397 | } | |||
398 | ||||
399 | /* called with two args on merge */ | |||
400 | void | |||
401 | obfree(struct obj *obj, struct obj *merge) | |||
402 | { | |||
403 | struct bill_x *bp = onbill(obj); | |||
404 | struct bill_x *bpm; | |||
405 | ||||
406 | if(bp) { | |||
407 | if(!merge){ | |||
408 | bp->useup = 1; | |||
409 | obj->unpaid = 0; /* only for doinvbill */ | |||
410 | obj->nobj = billobjs; | |||
411 | billobjs = obj; | |||
412 | return; | |||
413 | } | |||
414 | bpm = onbill(merge); | |||
415 | if(!bpm){ | |||
416 | /* this used to be a rename */ | |||
417 | impossible("obfree: not on bill??"); | |||
418 | return; | |||
419 | } else { | |||
420 | /* this was a merger */ | |||
421 | bpm->bquan += bp->bquan; | |||
422 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct--; | |||
423 | *bp = bill[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct]; | |||
424 | } | |||
425 | } | |||
426 | free(obj); | |||
427 | } | |||
428 | ||||
429 | static void | |||
430 | pay(long tmp, struct monst *shkp) | |||
431 | { | |||
432 | long robbed = ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed; | |||
433 | ||||
434 | u.ugold -= tmp; | |||
435 | shkp->mgold += tmp; | |||
436 | flags.botl = 1; | |||
437 | if(robbed) { | |||
438 | robbed -= tmp; | |||
439 | if(robbed < 0) robbed = 0; | |||
440 | ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed = robbed; | |||
441 | } | |||
442 | } | |||
443 | ||||
444 | int | |||
445 | dopay(void) | |||
446 | { | |||
447 | long ltmp; | |||
448 | struct bill_x *bp; | |||
449 | struct monst *shkp; | |||
450 | int pass, tmp; | |||
451 | ||||
452 | multi = 0; | |||
453 | (void) inshop(); | |||
454 | for(shkp = fmon; shkp; shkp = shkp->nmon) | |||
455 | if(shkp->isshk && dist(shkp->mx,shkp->my) < 3) | |||
456 | break; | |||
457 | if(!shkp && u.uinshop && | |||
458 | inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shoproom) | |||
459 | shkp = shopkeeper; | |||
460 | ||||
461 | if(!shkp) { | |||
462 | pline("There is nobody here to receive your payment."); | |||
463 | return(0); | |||
464 | } | |||
465 | ltmp = ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed; | |||
466 | if(shkp != shopkeeper && NOTANGRY(shkp)shkp->mpeaceful) { | |||
467 | if(!ltmp) { | |||
468 | pline("You do not owe %s anything.", monnam(shkp)); | |||
469 | } else | |||
470 | if(!u.ugold) { | |||
471 | pline("You have no money."); | |||
472 | } else { | |||
473 | long ugold = u.ugold; | |||
474 | ||||
475 | if(u.ugold > ltmp) { | |||
476 | pline("You give %s the %ld gold pieces he asked for.", | |||
477 | monnam(shkp), ltmp); | |||
478 | pay(ltmp, shkp); | |||
479 | } else { | |||
480 | pline("You give %s all your gold.", monnam(shkp)); | |||
481 | pay(u.ugold, shkp); | |||
482 | } | |||
483 | if(ugold < ltmp/2) { | |||
484 | pline("Unfortunately, he doesn't look satisfied."); | |||
485 | } else { | |||
486 | ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed = 0; | |||
487 | ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->following = 0; | |||
488 | if(ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shoplevel != dlevel) { | |||
489 | /* For convenience's sake, let him disappear */ | |||
490 | shkp->minvent = 0; /* %% */ | |||
491 | shkp->mgold = 0; | |||
492 | mondead(shkp); | |||
493 | } | |||
494 | } | |||
495 | } | |||
496 | return(1); | |||
497 | } | |||
498 | ||||
499 | if(!ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->billct){ | |||
500 | pline("You do not owe %s anything.", monnam(shkp)); | |||
501 | if(!u.ugold){ | |||
502 | pline("Moreover, you have no money."); | |||
503 | return(1); | |||
504 | } | |||
505 | if(ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed){ | |||
506 | #define min(a,b)((a<b)?a:b) ((a<b)?a:b) | |||
507 | pline("But since his shop has been robbed recently,"); | |||
508 | pline("you %srepay %s's expenses.", | |||
509 | (u.ugold < ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed) ? "partially " : "", | |||
510 | monnam(shkp)); | |||
511 | pay(min(u.ugold, ESHK(shkp)->robbed)((u.ugold<((struct eshk *)(&(shkp->mextra[0])))-> robbed)?u.ugold:((struct eshk *)(&(shkp->mextra[0])))-> robbed), shkp); | |||
512 | ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed = 0; | |||
513 | return(1); | |||
514 | } | |||
515 | if(ANGRY(shkp)!shkp->mpeaceful){ | |||
516 | pline("But in order to appease %s,", | |||
517 | amonnam(shkp, "angry")); | |||
518 | if(u.ugold >= 1000){ | |||
519 | ltmp = 1000; | |||
520 | pline(" you give him 1000 gold pieces."); | |||
521 | } else { | |||
522 | ltmp = u.ugold; | |||
523 | pline(" you give him all your money."); | |||
524 | } | |||
525 | pay(ltmp, shkp); | |||
526 | if(strncmp(ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->customer, plname, PL_NSIZ32) | |||
527 | || rn2(3)){ | |||
528 | pline("%s calms down.", Monnam(shkp)); | |||
529 | NOTANGRY(shkp)shkp->mpeaceful = 1; | |||
530 | } else pline("%s is as angry as ever.", | |||
531 | Monnam(shkp)); | |||
532 | } | |||
533 | return(1); | |||
534 | } | |||
535 | if(shkp != shopkeeper) { | |||
536 | impossible("dopay: not to shopkeeper?"); | |||
537 | if(shopkeeper) setpaid(); | |||
538 | return(0); | |||
539 | } | |||
540 | for(pass = 0; pass <= 1; pass++) { | |||
541 | tmp = 0; | |||
542 | while(tmp < ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct) { | |||
543 | bp = &bill[tmp]; | |||
544 | if(!pass && !bp->useup) { | |||
545 | tmp++; | |||
546 | continue; | |||
547 | } | |||
548 | if(!dopayobj(bp)) return(1); | |||
549 | bill[tmp] = bill[--ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct]; | |||
550 | } | |||
551 | } | |||
552 | pline("Thank you for shopping in %s's %s store!", | |||
553 | shkname(shopkeeper), | |||
554 | shopnam[rooms[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shoproom].rtype - 8]); | |||
555 | NOTANGRY(shopkeeper)shopkeeper->mpeaceful = 1; | |||
556 | return(1); | |||
557 | } | |||
558 | ||||
559 | /* return 1 if paid successfully */ | |||
560 | /* 0 if not enough money */ | |||
561 | /* -1 if object could not be found (but was paid) */ | |||
562 | static int | |||
563 | dopayobj(struct bill_x *bp) | |||
564 | { | |||
565 | struct obj *obj; | |||
566 | long ltmp; | |||
567 | ||||
568 | /* find the object on one of the lists */ | |||
569 | obj = bp_to_obj(bp); | |||
570 | ||||
571 | if(!obj) { | |||
572 | impossible("Shopkeeper administration out of order."); | |||
573 | setpaid(); /* be nice to the player */ | |||
574 | return(0); | |||
575 | } | |||
576 | ||||
577 | if(!obj->unpaid && !bp->useup){ | |||
578 | impossible("Paid object on bill??"); | |||
579 | return(1); | |||
580 | } | |||
581 | obj->unpaid = 0; | |||
582 | ltmp = bp->price * bp->bquan; | |||
583 | if(ANGRY(shopkeeper)!shopkeeper->mpeaceful) ltmp += ltmp/3; | |||
584 | if(u.ugold < ltmp){ | |||
585 | pline("You don't have gold enough to pay %s.", | |||
586 | doname(obj)); | |||
587 | obj->unpaid = 1; | |||
588 | return(0); | |||
589 | } | |||
590 | pay(ltmp, shopkeeper); | |||
591 | pline("You bought %s for %ld gold piece%s.", | |||
592 | doname(obj), ltmp, plur(ltmp)(((ltmp) == 1) ? "" : "s")); | |||
593 | if(bp->useup) { | |||
594 | struct obj *otmp = billobjs; | |||
595 | if(obj == billobjs) | |||
596 | billobjs = obj->nobj; | |||
597 | else { | |||
598 | while(otmp && otmp->nobj != obj) otmp = otmp->nobj; | |||
599 | if(otmp) otmp->nobj = obj->nobj; | |||
600 | else pline("Error in shopkeeper administration."); | |||
601 | } | |||
602 | free(obj); | |||
603 | } | |||
604 | return(1); | |||
605 | } | |||
606 | ||||
607 | /* routine called after dying (or quitting) with nonempty bill */ | |||
608 | void | |||
609 | paybill(void) | |||
610 | { | |||
611 | if(shlevel == dlevel && shopkeeper && ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct){ | |||
612 | addupbill(); | |||
613 | if(total > u.ugold){ | |||
614 | shopkeeper->mgold += u.ugold; | |||
615 | u.ugold = 0; | |||
616 | pline("%s comes and takes all your possessions.", | |||
617 | Monnam(shopkeeper)); | |||
618 | } else { | |||
619 | u.ugold -= total; | |||
620 | shopkeeper->mgold += total; | |||
621 | pline("%s comes and takes the %ld zorkmids you owed him.", | |||
622 | Monnam(shopkeeper), total); | |||
623 | } | |||
624 | setpaid(); /* in case we create bones */ | |||
625 | } | |||
626 | } | |||
627 | ||||
628 | /* find obj on one of the lists */ | |||
629 | static struct obj * | |||
630 | bp_to_obj(struct bill_x *bp) | |||
631 | { | |||
632 | struct obj *obj; | |||
633 | struct monst *mtmp; | |||
634 | unsigned id = bp->bo_id; | |||
635 | ||||
636 | if(bp->useup) | |||
637 | obj = o_on(id, billobjs); | |||
638 | else if(!(obj = o_on(id, invent)) && | |||
639 | !(obj = o_on(id, fobj)) && | |||
640 | !(obj = o_on(id, fcobj))) { | |||
641 | for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) | |||
642 | if ((obj = o_on(id, mtmp->minvent))) | |||
643 | break; | |||
644 | for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon) | |||
645 | if ((obj = o_on(id, mtmp->minvent))) | |||
646 | break; | |||
647 | } | |||
648 | return(obj); | |||
649 | } | |||
650 | ||||
651 | /* called in hack.c when we pickup an object */ | |||
652 | void | |||
653 | addtobill(struct obj *obj) | |||
654 | { | |||
655 | struct bill_x *bp; | |||
656 | ||||
657 | if(!inshop() || | |||
658 | (u.ux == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shk.x && u.uy == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shk.y) || | |||
659 | (u.ux == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shd.x && u.uy == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shd.y) || | |||
660 | onbill(obj) /* perhaps we threw it away earlier */ | |||
661 | ) return; | |||
662 | if(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct == BILLSZ200){ | |||
663 | pline("You got that for free!"); | |||
664 | return; | |||
665 | } | |||
666 | bp = &bill[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct]; | |||
667 | bp->bo_id = obj->o_id; | |||
668 | bp->bquan = obj->quan; | |||
669 | bp->useup = 0; | |||
670 | bp->price = getprice(obj); | |||
671 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct++; | |||
672 | obj->unpaid = 1; | |||
673 | } | |||
674 | ||||
675 | void | |||
676 | splitbill(struct obj *obj, struct obj *otmp) | |||
677 | { | |||
678 | /* otmp has been split off from obj */ | |||
679 | struct bill_x *bp; | |||
680 | int tmp; | |||
681 | bp = onbill(obj); | |||
682 | if(!bp) { | |||
683 | impossible("splitbill: not on bill?"); | |||
684 | return; | |||
685 | } | |||
686 | if(bp->bquan < otmp->quan) { | |||
687 | impossible("Negative quantity on bill??"); | |||
688 | } | |||
689 | if(bp->bquan == otmp->quan) { | |||
690 | impossible("Zero quantity on bill??"); | |||
691 | } | |||
692 | bp->bquan -= otmp->quan; | |||
693 | ||||
694 | /* addtobill(otmp); */ | |||
695 | if(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct == BILLSZ200) otmp->unpaid = 0; | |||
696 | else { | |||
697 | tmp = bp->price; | |||
698 | bp = &bill[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct]; | |||
699 | bp->bo_id = otmp->o_id; | |||
700 | bp->bquan = otmp->quan; | |||
701 | bp->useup = 0; | |||
702 | bp->price = tmp; | |||
703 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct++; | |||
704 | } | |||
705 | } | |||
706 | ||||
707 | void | |||
708 | subfrombill(struct obj *obj) | |||
709 | { | |||
710 | long ltmp; | |||
711 | int tmp; | |||
712 | struct obj *otmp; | |||
713 | struct bill_x *bp; | |||
714 | ||||
715 | if(!inshop() || (u.ux == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shk.x && u.uy == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shk.y) || | |||
716 | (u.ux == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shd.x && u.uy == ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shd.y)) | |||
717 | return; | |||
718 | if((bp = onbill(obj)) != 0){ | |||
719 | obj->unpaid = 0; | |||
720 | if(bp->bquan > obj->quan){ | |||
721 | otmp = newobj(0)(struct obj *) alloc((unsigned)(0) + sizeof(struct obj)); | |||
722 | *otmp = *obj; | |||
723 | bp->bo_id = otmp->o_id = flags.ident++; | |||
724 | otmp->quan = (bp->bquan -= obj->quan); | |||
725 | otmp->owt = 0; /* superfluous */ | |||
726 | otmp->onamelth = 0; | |||
727 | bp->useup = 1; | |||
728 | otmp->nobj = billobjs; | |||
729 | billobjs = otmp; | |||
730 | return; | |||
731 | } | |||
732 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct--; | |||
733 | *bp = bill[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct]; | |||
734 | return; | |||
735 | } | |||
736 | if(obj->unpaid){ | |||
737 | pline("%s didn't notice.", Monnam(shopkeeper)); | |||
738 | obj->unpaid = 0; | |||
739 | return; /* %% */ | |||
740 | } | |||
741 | /* he dropped something of his own - probably wants to sell it */ | |||
742 | if(shopkeeper->msleep || shopkeeper->mfroz || | |||
743 | inroom(shopkeeper->mx,shopkeeper->my) != ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shoproom) | |||
744 | return; | |||
745 | if(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct == BILLSZ200 || | |||
746 | ((tmp = shtypes[rooms[ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->shoproom].rtype-8]) && tmp != obj->olet) | |||
747 | || strchr("_0", obj->olet)) { | |||
748 | pline("%s seems not interested.", Monnam(shopkeeper)); | |||
749 | return; | |||
750 | } | |||
751 | ltmp = getprice(obj) * obj->quan; | |||
752 | if(ANGRY(shopkeeper)!shopkeeper->mpeaceful) { | |||
753 | ltmp /= 3; | |||
754 | NOTANGRY(shopkeeper)shopkeeper->mpeaceful = 1; | |||
755 | } else ltmp /= 2; | |||
756 | if(ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->robbed){ | |||
757 | if((ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->robbed -= ltmp) < 0) | |||
758 | ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->robbed = 0; | |||
759 | pline("Thank you for your contribution to restock this recently plundered shop."); | |||
760 | return; | |||
761 | } | |||
762 | if(ltmp > shopkeeper->mgold) | |||
763 | ltmp = shopkeeper->mgold; | |||
764 | pay(-ltmp, shopkeeper); | |||
765 | if(!ltmp) | |||
766 | pline("%s gladly accepts %s but cannot pay you at present.", | |||
767 | Monnam(shopkeeper), doname(obj)); | |||
768 | else | |||
769 | pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp, | |||
770 | plur(ltmp)(((ltmp) == 1) ? "" : "s")); | |||
771 | } | |||
772 | ||||
773 | /* int mode; 0: deliver count 1: paged */ | |||
774 | int | |||
775 | doinvbill(int mode) | |||
776 | { | |||
777 | struct bill_x *bp; | |||
778 | struct obj *obj; | |||
779 | long totused, thisused; | |||
780 | char buf[BUFSZ256]; | |||
781 | ||||
782 | if(mode == 0) { | |||
783 | int cnt = 0; | |||
784 | ||||
785 | if(shopkeeper) | |||
786 | for(bp = bill; bp - bill < ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct; bp++) | |||
787 | if(bp->useup || | |||
788 | ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan)) | |||
789 | cnt++; | |||
790 | return(cnt); | |||
791 | } | |||
792 | ||||
793 | if(!shopkeeper) { | |||
794 | impossible("doinvbill: no shopkeeper?"); | |||
795 | return(0); | |||
796 | } | |||
797 | ||||
798 | set_pager(0); | |||
799 | if(page_line("Unpaid articles already used up:") || page_line("")) | |||
800 | goto quit; | |||
801 | ||||
802 | totused = 0; | |||
803 | for(bp = bill; bp - bill < ESHK(shopkeeper)((struct eshk *)(&(shopkeeper->mextra[0])))->billct; bp++) { | |||
804 | obj = bp_to_obj(bp); | |||
805 | if(!obj) { | |||
806 | impossible("Bad shopkeeper administration."); | |||
807 | goto quit; | |||
808 | } | |||
809 | if(bp->useup || bp->bquan > obj->quan) { | |||
810 | int cnt, oquan, uquan; | |||
811 | ||||
812 | oquan = obj->quan; | |||
813 | uquan = (bp->useup ? bp->bquan : bp->bquan - oquan); | |||
814 | thisused = bp->price * uquan; | |||
815 | totused += thisused; | |||
816 | obj->quan = uquan; /* cheat doname */ | |||
817 | (void) snprintf(buf, sizeof buf, "x - %s", doname(obj)); | |||
818 | obj->quan = oquan; /* restore value */ | |||
819 | for(cnt = 0; buf[cnt]; cnt++); | |||
820 | while(cnt < 50) | |||
821 | buf[cnt++] = ' '; | |||
822 | (void) snprintf(&buf[cnt], sizeof buf - cnt, | |||
823 | " %5ld zorkmids", thisused); | |||
824 | if(page_line(buf)) | |||
825 | goto quit; | |||
826 | } | |||
827 | } | |||
828 | (void) snprintf(buf, sizeof buf, "Total:%50ld zorkmids", totused); | |||
829 | if(page_line("") || page_line(buf)) | |||
830 | goto quit; | |||
831 | set_pager(1); | |||
832 | return(0); | |||
833 | quit: | |||
834 | set_pager(2); | |||
835 | return(0); | |||
836 | } | |||
837 | ||||
838 | static int | |||
839 | getprice(struct obj *obj) | |||
840 | { | |||
841 | int tmp, ac; | |||
842 | ||||
843 | switch(obj->olet){ | |||
844 | case AMULET_SYM'"': | |||
845 | tmp = 10*rnd(500); | |||
846 | break; | |||
847 | case TOOL_SYM'(': | |||
848 | tmp = 10*rnd((obj->otyp == EXPENSIVE_CAMERA91) ? 150 : 30); | |||
849 | break; | |||
850 | case RING_SYM'=': | |||
851 | tmp = 10*rnd(100); | |||
852 | break; | |||
853 | case WAND_SYM'/': | |||
854 | tmp = 10*rnd(100); | |||
855 | break; | |||
856 | case SCROLL_SYM'?': | |||
857 | tmp = 10*rnd(50); | |||
858 | #ifdef MAIL | |||
859 | if(obj->otyp == SCR_MAIL130) | |||
860 | tmp = rnd(5); | |||
861 | #endif /* MAIL */ | |||
862 | break; | |||
863 | case POTION_SYM'!': | |||
864 | tmp = 10*rnd(50); | |||
865 | break; | |||
866 | case FOOD_SYM'%': | |||
867 | tmp = 10*rnd(5 + (2000/realhunger())); | |||
868 | break; | |||
869 | case GEM_SYM'*': | |||
870 | tmp = 10*rnd(20); | |||
871 | break; | |||
872 | case ARMOR_SYM'[': | |||
873 | ac = ARM_BONUS(obj)((10 - objects[obj->otyp].oc_oc1) + obj->spe); | |||
874 | if(ac <= -10) /* probably impossible */ | |||
875 | ac = -9; | |||
876 | tmp = 100 + ac*ac*rnd(10+ac); | |||
877 | break; | |||
878 | case WEAPON_SYM')': | |||
879 | if(obj->otyp < BOOMERANG76) | |||
880 | tmp = 5*rnd(10); | |||
881 | else if(obj->otyp == LONG_SWORD80 || | |||
882 | obj->otyp == TWO_HANDED_SWORD81) | |||
883 | tmp = 10*rnd(150); | |||
884 | else tmp = 10*rnd(75); | |||
885 | break; | |||
886 | case CHAIN_SYM'_': | |||
887 | pline("Strange ..., carrying a chain?"); | |||
888 | case BALL_SYM'0': | |||
889 | tmp = 10; | |||
890 | break; | |||
891 | default: | |||
892 | tmp = 10000; | |||
893 | } | |||
894 | return(tmp); | |||
895 | } | |||
896 | ||||
897 | /* not completely foolproof */ | |||
898 | static int | |||
899 | realhunger(void) | |||
900 | { | |||
901 | int tmp = u.uhunger; | |||
902 | struct obj *otmp = invent; | |||
903 | ||||
904 | while(otmp){ | |||
905 | if(otmp->olet == FOOD_SYM'%' && !otmp->unpaid) | |||
906 | tmp += objects[otmp->otyp].nutritionoc_oi; | |||
907 | otmp = otmp->nobj; | |||
908 | } | |||
909 | return((tmp <= 0) ? 1 : tmp); | |||
910 | } | |||
911 | ||||
912 | int | |||
913 | shkcatch(struct obj *obj) | |||
914 | { | |||
915 | struct monst *shkp = shopkeeper; | |||
916 | ||||
917 | if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep && | |||
918 | u.dx && u.dy && | |||
919 | inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop && | |||
920 | shkp->mx == ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shk.x && shkp->my == ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shk.y && | |||
921 | u.ux == ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shd.x && u.uy == ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shd.y) { | |||
922 | pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj)); | |||
923 | obj->nobj = shkp->minvent; | |||
924 | shkp->minvent = obj; | |||
925 | return(1); | |||
926 | } | |||
927 | return(0); | |||
928 | } | |||
929 | ||||
930 | /* | |||
931 | * shk_move: return 1: he moved 0: he didnt -1: let m_move do it | |||
932 | */ | |||
933 | int | |||
934 | shk_move(struct monst *shkp) | |||
935 | { | |||
936 | struct monst *mtmp; | |||
937 | struct permonst *mdat = shkp->data; | |||
938 | xchar gx,gy,omx,omy,nx,ny,nix,niy; | |||
939 | schar appr,i; | |||
940 | int udist; | |||
941 | int z; | |||
942 | schar shkroom,chi,chcnt,cnt; | |||
943 | boolean uondoor, satdoor, avoid, badinv; | |||
| ||||
944 | coord poss[9]; | |||
945 | int info[9]; | |||
946 | struct obj *ib = 0; | |||
947 | ||||
948 | omx = shkp->mx; | |||
949 | omy = shkp->my; | |||
950 | ||||
951 | if((udist = dist(omx,omy)) < 3) { | |||
952 | if(ANGRY(shkp)!shkp->mpeaceful) { | |||
953 | (void) hitu(shkp, d(mdat->damn, mdat->damd)+1); | |||
954 | return(0); | |||
955 | } | |||
956 | if(ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->following) { | |||
957 | if(strncmp(ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->customer, plname, PL_NSIZ32)){ | |||
958 | pline("Hello %s! I was looking for %s.", | |||
959 | plname, ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->customer); | |||
960 | ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->following = 0; | |||
961 | return(0); | |||
962 | } | |||
963 | if(!ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed) { /* impossible? */ | |||
964 | ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->following = 0; | |||
965 | return(0); | |||
966 | } | |||
967 | if(moves > followmsg+4) { | |||
968 | pline("Hello %s! Didn't you forget to pay?", | |||
969 | plname); | |||
970 | followmsg = moves; | |||
971 | } | |||
972 | if(udist < 2) | |||
973 | return(0); | |||
974 | } | |||
975 | } | |||
976 | ||||
977 | shkroom = inroom(omx,omy); | |||
978 | appr = 1; | |||
979 | gx = ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shk.x; | |||
980 | gy = ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shk.y; | |||
981 | satdoor = (gx == omx && gy == omy); | |||
982 | if(ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->following || ((z = holetime()) >= 0 && z*z <= udist)){ | |||
983 | gx = u.ux; | |||
984 | gy = u.uy; | |||
985 | if(shkroom < 0 || shkroom != inroom(u.ux,u.uy)) | |||
986 | if(udist > 4) | |||
987 | return(-1); /* leave it to m_move */ | |||
988 | } else if(ANGRY(shkp)!shkp->mpeaceful) { | |||
989 | long saveBlind = Blindu.uprops[(19 +7)].p_flgs; | |||
990 | Blindu.uprops[(19 +7)].p_flgs = 0; | |||
991 | if(shkp->mcansee && !Invisu.uprops[(19 +3)].p_flgs && cansee(omx,omy)) { | |||
992 | gx = u.ux; | |||
993 | gy = u.uy; | |||
994 | } | |||
995 | Blindu.uprops[(19 +7)].p_flgs = saveBlind; | |||
996 | avoid = FALSE0; | |||
997 | } else { | |||
998 | #define GDIST(x,y)((x-gx)*(x-gx)+(y-gy)*(y-gy)) ((x-gx)*(x-gx)+(y-gy)*(y-gy)) | |||
999 | if(Invisu.uprops[(19 +3)].p_flgs) | |||
1000 | avoid = FALSE0; | |||
1001 | else { | |||
1002 | uondoor = (u.ux == ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shd.x && | |||
1003 | u.uy == ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shd.y); | |||
1004 | if(uondoor) { | |||
1005 | if(ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->billct) | |||
1006 | pline("Hello %s! Will you please pay before leaving?", | |||
1007 | plname); | |||
1008 | badinv = (carrying(PICK_AXE93) || carrying(ICE_BOX92)); | |||
1009 | if(satdoor && badinv) | |||
1010 | return(0); | |||
1011 | avoid = !badinv; | |||
1012 | } else { | |||
1013 | avoid = (u.uinshop && dist(gx,gy) > 8); | |||
1014 | badinv = FALSE0; | |||
1015 | } | |||
1016 | ||||
1017 | if(((!ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->robbed && !ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->billct) || avoid) | |||
1018 | && GDIST(omx,omy)((omx-gx)*(omx-gx)+(omy-gy)*(omy-gy)) < 3){ | |||
1019 | if(!badinv && !online(omx,omy)) | |||
1020 | return(0); | |||
1021 | if(satdoor) | |||
1022 | appr = gx = gy = 0; | |||
1023 | } | |||
1024 | } | |||
1025 | } | |||
1026 | if(omx == gx && omy == gy) | |||
1027 | return(0); | |||
1028 | if(shkp->mconf) { | |||
1029 | avoid = FALSE0; | |||
1030 | appr = 0; | |||
1031 | } | |||
1032 | nix = omx; | |||
1033 | niy = omy; | |||
1034 | cnt = mfndpos(shkp,poss,info,ALLOW_SSM010000); | |||
1035 | if(avoid && uondoor) { /* perhaps we cannot avoid him */ | |||
| ||||
1036 | for(i=0; i<cnt; i++) | |||
1037 | if(!(info[(int)i] & NOTONL040000)) goto notonl_ok; | |||
1038 | avoid = FALSE0; | |||
1039 | notonl_ok: | |||
1040 | ; | |||
1041 | } | |||
1042 | chi = -1; | |||
1043 | chcnt = 0; | |||
1044 | for(i=0; i<cnt; i++){ | |||
1045 | nx = poss[(int)i].x; | |||
1046 | ny = poss[(int)i].y; | |||
1047 | if(levl[(int)nx][(int)ny].typ == ROOM9 | |||
1048 | || shkroom != ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->shoproom | |||
1049 | || ESHK(shkp)((struct eshk *)(&(shkp->mextra[0])))->following) { | |||
1050 | #ifdef STUPID | |||
1051 | /* cater for stupid compilers */ | |||
1052 | int zz; | |||
1053 | #endif /* STUPID */ | |||
1054 | if(uondoor && (ib = sobj_at(ICE_BOX92, nx, ny))) { | |||
1055 | nix = nx; niy = ny; chi = i; break; | |||
1056 | } | |||
1057 | if(avoid && (info[(int)i] & NOTONL040000)) | |||
1058 | continue; | |||
1059 | if((!appr && !rn2(++chcnt)) || | |||
1060 | #ifdef STUPID | |||
1061 | (appr && (zz = GDIST(nix,niy)((nix-gx)*(nix-gx)+(niy-gy)*(niy-gy))) && zz > GDIST(nx,ny)((nx-gx)*(nx-gx)+(ny-gy)*(ny-gy))) | |||
1062 | #else | |||
1063 | (appr && GDIST(nx,ny)((nx-gx)*(nx-gx)+(ny-gy)*(ny-gy)) < GDIST(nix,niy)((nix-gx)*(nix-gx)+(niy-gy)*(niy-gy))) | |||
1064 | #endif /* STUPID */ | |||
1065 | ) { | |||
1066 | nix = nx; | |||
1067 | niy = ny; | |||
1068 | chi = i; | |||
1069 | } | |||
1070 | } | |||
1071 | } | |||
1072 | if(nix != omx || niy != omy){ | |||
1073 | if(info[(int)chi] & ALLOW_M02000){ | |||
1074 | mtmp = m_at(nix,niy); | |||
1075 | if(hitmm(shkp,mtmp) == 1 && rn2(3) && | |||
1076 | hitmm(mtmp,shkp) == 2) return(2); | |||
1077 | return(0); | |||
1078 | } else if(info[(int)chi] & ALLOW_U01000){ | |||
1079 | (void) hitu(shkp, d(mdat->damn, mdat->damd)+1); | |||
1080 | return(0); | |||
1081 | } | |||
1082 | shkp->mx = nix; | |||
1083 | shkp->my = niy; | |||
1084 | pmon(shkp); | |||
1085 | if(ib) { | |||
1086 | freeobj(ib); | |||
1087 | mpickobj(shkp, ib); | |||
1088 | } | |||
1089 | return(1); | |||
1090 | } | |||
1091 | return(0); | |||
1092 | } | |||
1093 | ||||
1094 | /* He is digging in the shop. */ | |||
1095 | void | |||
1096 | shopdig(int fall) | |||
1097 | { | |||
1098 | if(!fall) { | |||
1099 | if(u.utraptype == TT_PIT1) | |||
1100 | pline("\"Be careful, sir, or you might fall through the floor.\""); | |||
1101 | else | |||
1102 | pline("\"Please, do not damage the floor here.\""); | |||
1103 | } else if(dist(shopkeeper->mx, shopkeeper->my) < 3) { | |||
1104 | struct obj *obj, *obj2; | |||
1105 | ||||
1106 | pline("%s grabs your backpack!", shkname(shopkeeper)); | |||
1107 | for(obj = invent; obj; obj = obj2) { | |||
1108 | obj2 = obj->nobj; | |||
1109 | if(obj->owornmask) continue; | |||
1110 | freeinv(obj); | |||
1111 | obj->nobj = shopkeeper->minvent; | |||
1112 | shopkeeper->minvent = obj; | |||
1113 | if(obj->unpaid) | |||
1114 | subfrombill(obj); | |||
1115 | } | |||
1116 | } | |||
1117 | } | |||
1118 | #endif /* QUEST */ | |||
1119 | ||||
1120 | int | |||
1121 | online(int x, int y) | |||
1122 | { | |||
1123 | return(x==u.ux || y==u.uy || | |||
1124 | (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy)); | |||
1125 | } | |||
1126 | ||||
1127 | /* Does this monster follow me downstairs? */ | |||
1128 | int | |||
1129 | follower(struct monst *mtmp) | |||
1130 | { | |||
1131 | return( mtmp->mtame || strchr("1TVWZi&, ", mtmp->data->mlet) | |||
1132 | #ifndef QUEST | |||
1133 | || (mtmp->isshk && ESHK(mtmp)((struct eshk *)(&(mtmp->mextra[0])))->following) | |||
1134 | #endif /* QUEST */ | |||
1135 | ); | |||
1136 | } |