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