home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume16 / nethack31 / part33 < prev    next >
Internet Message Format  |  1993-02-01  |  60KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v16i033:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part33/108
  5. Message-ID: <4321@master.CNA.TEK.COM>
  6. Date: 29 Jan 93 20:46:50 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2191
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1590
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 33
  14. Archive-name: nethack31/Part33
  15. Supersedes: nethack3p9: Volume 10, Issue 46-102
  16. Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
  17.  
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 33 (of 108)."
  27. # Contents:  src/dog.c src/shk.c2
  28. # Wrapped by billr@saab on Wed Jan 27 16:08:59 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/dog.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/dog.c'\"
  32. else
  33. echo shar: Extracting \"'src/dog.c'\" \(13007 characters\)
  34. sed "s/^X//" >'src/dog.c' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)dog.c    3.1    92/10/18    */
  36. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  37. X/* NetHack may be freely redistributed.  See license for details. */
  38. X
  39. X#include "hack.h"
  40. X#include "edog.h"
  41. X
  42. X#define domestic(mtmp)    (mtmp->data->msound == MS_BARK || \
  43. X             mtmp->data->msound == MS_MEW)
  44. X
  45. X#ifdef OVLB
  46. X
  47. Xstatic int NDECL(pet_type);
  48. X
  49. Xvoid
  50. Xinitedog(mtmp)
  51. Xregister struct monst *mtmp;
  52. X{
  53. X    mtmp->mtame = domestic(mtmp) ? 10 : 5;
  54. X    mtmp->mpeaceful = 1;
  55. X    set_malign(mtmp); /* recalc alignment now that it's tamed */
  56. X    mtmp->mleashed = 0;
  57. X    mtmp->meating = 0;
  58. X    EDOG(mtmp)->droptime = 0;
  59. X    EDOG(mtmp)->dropdist = 10000;
  60. X    EDOG(mtmp)->apport = 10;
  61. X    EDOG(mtmp)->whistletime = 0;
  62. X    EDOG(mtmp)->hungrytime = 1000 + moves;
  63. X}
  64. X
  65. Xstatic int
  66. Xpet_type()
  67. X{
  68. X    register int pettype;
  69. X
  70. X    switch (pl_character[0]) {
  71. X        /* some character classes have restricted ideas of pets */
  72. X        case 'C':
  73. X        case 'S':
  74. X            pettype = PM_LITTLE_DOG;
  75. X            break;
  76. X        case 'W':
  77. X            pettype = PM_KITTEN;
  78. X            break;
  79. X        /* otherwise, see if the player has a preference */
  80. X        default:
  81. X            if (preferred_pet == 'c')
  82. X                pettype = PM_KITTEN;
  83. X            else if (preferred_pet == 'd')
  84. X                pettype = PM_LITTLE_DOG;
  85. X            else    pettype = rn2(2) ? PM_KITTEN : PM_LITTLE_DOG;
  86. X            break;
  87. X    }
  88. X    return pettype;
  89. X}
  90. X
  91. Xvoid
  92. Xmake_familiar(otmp,x,y)
  93. Xregister struct obj *otmp;
  94. Xxchar x, y;
  95. X{
  96. X    register struct monst *mtmp;
  97. X    register struct permonst *pm;
  98. X
  99. Xtop:
  100. X    if (otmp) pm = &mons[otmp->corpsenm]; /* Figurine; otherwise spell */
  101. X    else if (rn2(3)) {
  102. X        if (!(pm = rndmonst())) {
  103. X        pline("There seems to be nothing available for a familiar.");
  104. X        return;
  105. X        }
  106. X    }
  107. X    else pm = &mons[pet_type()];
  108. X
  109. X    pm->pxlth += sizeof(struct edog);
  110. X    mtmp = makemon(pm, x, y);
  111. X    pm->pxlth -= sizeof(struct edog);
  112. X    if (!mtmp) { /* monster was genocided */
  113. X        if (otmp)
  114. X        pline("The figurine writhes and then shatters into pieces!");
  115. X        else goto top;
  116. X        /* rndmonst() returns something not genocided always, so this
  117. X         * means it was a cat or dog; loop back to try again until
  118. X         * either rndmonst() is called, or if only one of cat/dog
  119. X         * was genocided, they get the other.
  120. X         */
  121. X        return;
  122. X    }
  123. X    initedog(mtmp);
  124. X    mtmp->msleep = 0;
  125. X    if (otmp && otmp->cursed) { /* cursed figurine */
  126. X        You("get a bad feeling about this.");
  127. X        mtmp->mtame = mtmp->mpeaceful = 0;
  128. X        newsym(mtmp->mx, mtmp->my);
  129. X    }
  130. X    set_malign(mtmp); /* more alignment changes */
  131. X}
  132. X
  133. Xstruct monst *
  134. Xmakedog()
  135. X{
  136. X    register struct monst *mtmp;
  137. X    char *petname;
  138. X    int   pettype;
  139. X    static int petname_used = 0;
  140. X
  141. X    pettype = pet_type();
  142. X    if (pettype == PM_LITTLE_DOG)
  143. X        petname = dogname;
  144. X    else
  145. X        petname = catname;
  146. X
  147. X    mons[pettype].pxlth = sizeof(struct edog);
  148. X    mtmp = makemon(&mons[pettype], u.ux, u.uy);
  149. X    mons[pettype].pxlth = 0;
  150. X
  151. X    if(!mtmp) return((struct monst *) 0); /* pets were genocided */
  152. X
  153. X    if (!petname_used++ && *petname)
  154. X        mtmp = christen_monst(mtmp, petname);
  155. X
  156. X    initedog(mtmp);
  157. X    return(mtmp);
  158. X}
  159. X
  160. Xvoid
  161. Xlosedogs()
  162. X{
  163. X    register struct monst *mtmp,*mtmp0,*mtmp2;
  164. X    int num_segs;
  165. X
  166. X    while(mtmp = mydogs){
  167. X        mydogs = mtmp->nmon;
  168. X        mtmp->nmon = fmon;
  169. X        fmon = mtmp;
  170. X        if (mtmp->isshk)
  171. X            set_residency(mtmp, FALSE);
  172. X
  173. X        num_segs = mtmp->wormno;
  174. X        /* baby long worms have no tail so don't use is_longworm() */
  175. X        if ( (mtmp->data == &mons[PM_LONG_WORM]) &&
  176. X             (mtmp->wormno = get_wormno()) ) {
  177. X            initworm(mtmp, num_segs);
  178. X            /* tail segs are not yet initialized or displayed */
  179. X        } else mtmp->wormno = 0;
  180. X        mnexto(mtmp);
  181. X    }
  182. X
  183. X#if defined(LINT) || defined(GCC_WARN)
  184. X    mtmp0 = (struct monst *)0;
  185. X#endif
  186. X    for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
  187. X        mtmp2 = mtmp->nmon;
  188. X        if(mtmp->mx == u.uz.dnum && mtmp->mux == u.uz.dlevel) {
  189. X            mtmp->mx = 0;           /* save xyloc in mtmp->my */
  190. X            mtmp->mux = u.ux; mtmp->muy = u.uy; /* not really req'd */
  191. X            if(mtmp == migrating_mons)
  192. X            migrating_mons = mtmp->nmon;
  193. X            else
  194. X            mtmp0->nmon = mtmp->nmon;
  195. X            mtmp->nmon = fmon;
  196. X            fmon = mtmp;
  197. X            num_segs = mtmp->wormno;
  198. X            if ( (mtmp->data == &mons[PM_LONG_WORM]) &&
  199. X             (mtmp->wormno = get_wormno()) ) {
  200. X            initworm(mtmp, num_segs);
  201. X            /* tail segs are not yet initialized or displayed */
  202. X            } else mtmp->wormno = 0;
  203. X
  204. X            if(mtmp->mlstmv < monstermoves-1) {
  205. X            /* heal monster for time spent in limbo */
  206. X            long nmv = monstermoves - mtmp->mlstmv - 1;
  207. X
  208. X            /* might stop being afraid, blind or frozen */
  209. X            /* set to 1 and allow final decrement in movemon() */
  210. X            if(nmv >= (long)mtmp->mblinded) mtmp->mblinded = 1;
  211. X            else mtmp->mblinded -= nmv;
  212. X            if(nmv >= (long)mtmp->mfrozen) mtmp->mfrozen = 1;
  213. X            else mtmp->mfrozen -= nmv;
  214. X            if(nmv >= (long)mtmp->mfleetim) mtmp->mfleetim = 1;
  215. X            else mtmp->mfleetim -= nmv;
  216. X
  217. X            /* might be able to use special ability again */
  218. X            if(nmv > (long)mtmp->mspec_used) mtmp->mspec_used = 0;
  219. X            else mtmp->mspec_used -= nmv;
  220. X
  221. X            if(!regenerates(mtmp->data)) nmv /= 20;
  222. X            if((long)mtmp->mhp + nmv >= (long)mtmp->mhpmax)
  223. X                mtmp->mhp = mtmp->mhpmax;
  224. X            else mtmp->mhp += nmv;
  225. X            mtmp->mlstmv = monstermoves-1;
  226. X            }
  227. X
  228. X            if (mtmp->data->geno & G_GENOD) {
  229. X#ifdef KOPS
  230. X            allow_kops = FALSE;
  231. X#endif
  232. X            mondead(mtmp);    /* must put in fmon list first */
  233. X#ifdef KOPS
  234. X            allow_kops = TRUE;
  235. X#endif
  236. X            } else if (mtmp->isshk && mtmp->mpeaceful)
  237. X            home_shk(mtmp, TRUE);
  238. X            else switch(mtmp->my) {
  239. X            xchar *xlocale, *ylocale;
  240. X
  241. X            case 1: xlocale = &xupstair; ylocale = &yupstair;
  242. X                goto common;
  243. X            case 2: xlocale = &xdnstair; ylocale = &ydnstair;
  244. X                goto common;
  245. X            case 3: xlocale = &xupladder; ylocale = &yupladder;
  246. X                goto common;
  247. X            case 4: xlocale = &xdnladder; ylocale = &ydnladder;
  248. X                goto common;
  249. X            case 5: xlocale = &sstairs.sx; ylocale = &sstairs.sy;
  250. X                goto common;
  251. Xcommon:
  252. X                if (*xlocale && *ylocale) {
  253. X                (void) mnearto(mtmp, *xlocale, *ylocale, FALSE);
  254. X                    break;
  255. X                } /* else fall through */
  256. X            default: 
  257. X                rloc(mtmp);
  258. X                break;
  259. X            }
  260. X        } else
  261. X            mtmp0 = mtmp;
  262. X        if (mtmp->isshk)
  263. X            set_residency(mtmp, FALSE);
  264. X    }
  265. X}
  266. X
  267. X#endif /* OVLB */
  268. X#ifdef OVL2
  269. X
  270. Xvoid
  271. Xkeepdogs()
  272. X{
  273. X    register struct monst *mtmp;
  274. X    register struct obj *obj;
  275. X    int num_segs = 0;
  276. X
  277. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  278. X        if(((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp)) ||
  279. X        /* the wiz will level t-port from anywhere to chase
  280. X           the amulet; if you don't have it, will chase you
  281. X           only if in range. -3. */
  282. X            (u.uhave.amulet && mtmp->iswiz))
  283. X            && !mtmp->msleep && mtmp->mcanmove) {
  284. X
  285. X        /* long worms can now change levels! - Norm */
  286. X
  287. X        if (mtmp->mtame && mtmp->meating && canseemon(mtmp)) {
  288. X            pline("%s is still eating.", Monnam(mtmp));
  289. X            goto merge;
  290. X        }
  291. X        if (mon_has_amulet(mtmp)) {
  292. X            pline("%s seems very disoriented for a moment.",
  293. X                Monnam(mtmp));
  294. X        merge:
  295. X#ifdef WALKIES
  296. X            if (mtmp->mleashed) {
  297. X                pline("%s leash suddenly comes loose.",
  298. X                    humanoid(mtmp->data)
  299. X                        ? (mtmp->female ? "Her" : "His")
  300. X                        : "Its");
  301. X                m_unleash(mtmp);
  302. X            }
  303. X#endif
  304. X            continue;
  305. X        }
  306. X        if (mtmp->isshk)
  307. X            set_residency(mtmp, TRUE);
  308. X
  309. X        if (mtmp->wormno) {
  310. X            /* NOTE: worm is truncated to # segs = max wormno size */
  311. X            num_segs = min(count_wsegs(mtmp), MAX_NUM_WORMS - 1);
  312. X            wormgone(mtmp);
  313. X        }
  314. X
  315. X        /* set minvent's obj->no_charge to 0 */
  316. X        for(obj = mtmp->minvent; obj; obj = obj->nobj) {
  317. X            if(Is_container(obj))
  318. X                picked_container(obj); /* does the right thing */
  319. X            obj->no_charge = 0;
  320. X        }
  321. X
  322. X        relmon(mtmp);
  323. X        newsym(mtmp->mx,mtmp->my);
  324. X        mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
  325. X        mtmp->wormno = num_segs;
  326. X        mtmp->nmon = mydogs;
  327. X        mydogs = mtmp;
  328. X        keepdogs();    /* we destroyed the link, so use recursion */
  329. X        return;        /* (admittedly somewhat primitive) */
  330. X    }
  331. X}
  332. X
  333. X#endif /* OVL2 */
  334. X#ifdef OVLB
  335. X
  336. Xvoid
  337. Xmigrate_to_level(mtmp, tolev, xyloc) 
  338. X    register struct monst *mtmp; 
  339. X    xchar tolev;      /* destination level */
  340. X    xchar xyloc;    /* destination xy location: */
  341. X            /*     0: rnd,
  342. X             *    1: <,
  343. X             *    2: >,
  344. X             *    3: < ladder,
  345. X             *    4: > ladder,
  346. X             *    5: sstairs
  347. X             */ 
  348. X{
  349. X        register struct obj *obj;
  350. X    int num_segs = 0;    /* count of worm segments */
  351. X
  352. X    if (mtmp->isshk)
  353. X        set_residency(mtmp, TRUE);
  354. X
  355. X    if (mtmp->wormno) {
  356. X      /* **** NOTE: worm is truncated to # segs = max wormno size **** */
  357. X        num_segs = min(count_wsegs(mtmp), MAX_NUM_WORMS - 1);
  358. X        wormgone(mtmp);
  359. X    }
  360. X
  361. X    /* set minvent's obj->no_charge to 0 */
  362. X    for(obj = mtmp->minvent; obj; obj = obj->nobj) {
  363. X        if(Is_container(obj))
  364. X            picked_container(obj); /* does the right thing */
  365. X        obj->no_charge = 0;
  366. X    }
  367. X
  368. X    relmon(mtmp);
  369. X    mtmp->nmon = migrating_mons;
  370. X    migrating_mons = mtmp;
  371. X#ifdef WALKIES
  372. X    if (mtmp->mleashed)  {
  373. X        pline("The leash comes off!");
  374. X        m_unleash(mtmp);
  375. X    }
  376. X#endif
  377. X    mtmp->mtame = 0;
  378. X    newsym(mtmp->mx,mtmp->my);
  379. X    /* make sure to reset mtmp->[mx,my] to 0 when releasing, */
  380. X    /* so rloc() on next level doesn't affect MON_AT() state */
  381. X    mtmp->mx = ledger_to_dnum((xchar)tolev); 
  382. X    mtmp->mux = ledger_to_dlev((xchar)tolev); 
  383. X    mtmp->my = xyloc;
  384. X    mtmp->muy = 0;
  385. X    mtmp->wormno = num_segs;
  386. X    mtmp->mlstmv = monstermoves;
  387. X}
  388. X
  389. X#endif /* OVLB */
  390. X#ifdef OVL1
  391. X
  392. X/* return quality of food; the lower the better */
  393. X/* fungi will eat even tainted food */
  394. Xint
  395. Xdogfood(mon,obj)
  396. Xstruct monst *mon;
  397. Xregister struct obj *obj;
  398. X{
  399. X    boolean carni = carnivorous(mon->data);
  400. X    boolean herbi = herbivorous(mon->data);
  401. X    struct permonst *fptr = &mons[obj->corpsenm];
  402. X
  403. X    switch(obj->oclass) {
  404. X    case FOOD_CLASS:
  405. X        if (obj->otyp == CORPSE &&
  406. X        ((obj->corpsenm == PM_COCKATRICE && !resists_ston(mon->data))
  407. X         || is_rider(fptr)))
  408. X            return TABU;
  409. X
  410. X        if (!carni && !herbi)
  411. X            return (obj->cursed ? UNDEF : APPORT);
  412. X
  413. X        switch (obj->otyp) {
  414. X        case TRIPE_RATION:
  415. X            return (carni ? DOGFOOD : MANFOOD);
  416. X        case EGG:
  417. X            if (obj->corpsenm == PM_COCKATRICE &&
  418. X                        !resists_ston(mon->data))
  419. X            return POISON;
  420. X            return (carni ? CADAVER : MANFOOD);
  421. X        case CORPSE:
  422. X            if ((obj->age+50 <= monstermoves
  423. X                        && obj->corpsenm != PM_LIZARD
  424. X                        && mon->data->mlet != S_FUNGUS) ||
  425. X            (acidic(&mons[obj->corpsenm]) &&
  426. X                        !resists_acid(mon->data)) ||
  427. X            (poisonous(&mons[obj->corpsenm]) &&
  428. X                        !resists_poison(mon->data)))
  429. X            return POISON;
  430. X            else if (fptr->mlet == S_FUNGUS)
  431. X            return (herbi ? CADAVER : MANFOOD);
  432. X            else if (is_meaty(fptr))
  433. X                return (carni ? CADAVER : MANFOOD);
  434. X            else return (carni ? ACCFOOD : MANFOOD);
  435. X        case CLOVE_OF_GARLIC:
  436. X            return (is_undead(mon->data) ? TABU :
  437. X                (herbi ? ACCFOOD : MANFOOD));
  438. X        case TIN:
  439. X            return (metallivorous(mon->data) ? ACCFOOD : MANFOOD);
  440. X        case APPLE:
  441. X        case CARROT:
  442. X            return (herbi ? DOGFOOD : MANFOOD);
  443. X        case BANANA:
  444. X            return ((mon->data->mlet == S_YETI) ? DOGFOOD :
  445. X                (herbi ? ACCFOOD : MANFOOD));
  446. X        default:
  447. X#ifdef TUTTI_FRUTTI
  448. X            return (obj->otyp > SLIME_MOLD ?
  449. X#else
  450. X            return (obj->otyp > CLOVE_OF_GARLIC ?
  451. X#endif
  452. X                (carni ? ACCFOOD : MANFOOD) :
  453. X                (herbi ? ACCFOOD : MANFOOD));
  454. X        }
  455. X    default:
  456. X        if (hates_silver(mon->data) && 
  457. X        objects[obj->otyp].oc_material == SILVER)
  458. X        return(TABU);
  459. X        if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
  460. X        return(ACCFOOD);
  461. X        if (metallivorous(mon->data) && is_metallic(obj))
  462. X        /* Ferrous based metals are preferred. */
  463. X        return(objects[obj->otyp].oc_material == IRON ? DOGFOOD :
  464. X               ACCFOOD);
  465. X        if(!obj->cursed && obj->oclass != BALL_CLASS &&
  466. X                        obj->oclass != CHAIN_CLASS)
  467. X        return(APPORT);
  468. X        /* fall into next case */
  469. X    case ROCK_CLASS:
  470. X        return(UNDEF);
  471. X    }
  472. X}
  473. X
  474. X#endif /* OVL1 */
  475. X#ifdef OVLB
  476. X
  477. Xstruct monst *
  478. Xtamedog(mtmp, obj)
  479. Xregister struct monst *mtmp;
  480. Xregister struct obj *obj;
  481. X{
  482. X    register struct monst *mtmp2;
  483. X
  484. X    /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
  485. X    if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
  486. X#ifdef MULDGN
  487. X        || (mtmp->data->mflags3 & M3_WANTSARTI)
  488. X#endif
  489. X        )
  490. X        return((struct monst *)0);
  491. X
  492. X    /* worst case, at least he'll be peaceful. */
  493. X    mtmp->mpeaceful = 1;
  494. X    set_malign(mtmp);
  495. X    if(flags.moonphase == FULL_MOON && night() && rn2(6) && obj
  496. X                        && mtmp->data->mlet == S_DOG)
  497. X        return((struct monst *)0);
  498. X
  499. X    /* If we cannot tame him, at least he's no longer afraid. */
  500. X    mtmp->mflee = 0;
  501. X    mtmp->mfleetim = 0;
  502. X    if(mtmp->mtame || !mtmp->mcanmove ||
  503. X       /* monsters with conflicting structures cannot be tamed */
  504. X       mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion ||
  505. X#ifdef POLYSELF
  506. X       is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(uasmon))
  507. X#else
  508. X       is_human(mtmp->data) || is_demon(mtmp->data)
  509. X#endif
  510. X       || (mtmp->data->mflags3 &
  511. X           (M3_WANTSAMUL|M3_WANTSBELL|M3_WANTSBOOK|M3_WANTSCAND))
  512. X       )
  513. X        return((struct monst *)0);
  514. X    if(obj) {
  515. X        if(dogfood(mtmp, obj) >= MANFOOD) return((struct monst *)0);
  516. X        if(cansee(mtmp->mx,mtmp->my))
  517. X            pline("%s devours the %s.", Monnam(mtmp), xname(obj));
  518. X        obfree(obj, (struct obj *)0);
  519. X    }
  520. X    if (u.uswallow && mtmp == u.ustuck)
  521. X        expels(mtmp, mtmp->data, TRUE);
  522. X    mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
  523. X    *mtmp2 = *mtmp;
  524. X    mtmp2->mxlth = sizeof(struct edog);
  525. X    if(mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp));
  526. X    initedog(mtmp2);
  527. X    replmon(mtmp,mtmp2);
  528. X    newsym(mtmp2->mx, mtmp2->my);
  529. X    return(mtmp2);
  530. X}
  531. X
  532. X#endif /* OVLB */
  533. X
  534. X/*dog.c*/
  535. END_OF_FILE
  536. if test 13007 -ne `wc -c <'src/dog.c'`; then
  537.     echo shar: \"'src/dog.c'\" unpacked with wrong size!
  538. fi
  539. # end of 'src/dog.c'
  540. fi
  541. if test -f 'src/shk.c2' -a "${1}" != "-c" ; then 
  542.   echo shar: Will not clobber existing file \"'src/shk.c2'\"
  543. else
  544. echo shar: Extracting \"'src/shk.c2'\" \(41942 characters\)
  545. sed "s/^X//" >'src/shk.c2' <<'END_OF_FILE'
  546. Xstatic void
  547. Xadd_one_tobill(obj, dummy)
  548. Xregister struct obj *obj;
  549. Xregister boolean dummy;
  550. X{
  551. X    register struct monst *shkp;
  552. X    register struct bill_x *bp;
  553. X    register int bct;
  554. X    register char roomno = *u.ushops;
  555. X
  556. X    if(!*u.ushops) return;
  557. X
  558. X    if(!(shkp = shop_keeper(roomno))) return;
  559. X
  560. X    if(!inhishop(shkp)) return;
  561. X
  562. X    if(onbill(obj, shkp, FALSE) || /* perhaps thrown away earlier */
  563. X            (obj->oclass == FOOD_CLASS && obj->oeaten))
  564. X        return;
  565. X
  566. X    if(ESHK(shkp)->billct == BILLSZ) {
  567. X        You("got that for free!");
  568. X        return;
  569. X    }
  570. X
  571. X    /* To recognize objects the shopkeeper is not interested in. -dgk
  572. X     */
  573. X    if (obj->no_charge) {
  574. X        obj->no_charge = 0;
  575. X        return;
  576. X    }
  577. X
  578. X    bct = ESHK(shkp)->billct;
  579. X    bp = &(ESHK(shkp)->bill_p[bct]);
  580. X    bp->bo_id = obj->o_id;
  581. X    bp->bquan = obj->quan;
  582. X    if(dummy) {          /* a dummy object must be inserted into  */
  583. X        bp->useup = 1;      /* the billobjs chain here.  crucial for */
  584. X        obj->nobj = billobjs; /* eating floorfood in shop.  see eat.c  */
  585. X        billobjs = obj;
  586. X    } else    bp->useup = 0;
  587. X    bp->price = get_cost(obj, shkp);
  588. X    ESHK(shkp)->billct++;
  589. X    obj->unpaid = 1;
  590. X}
  591. X
  592. X/* recursive billing of objects within containers. */
  593. Xstatic void
  594. Xbill_box_content(obj, ininv, dummy, shkp)
  595. Xregister struct obj *obj;
  596. Xregister boolean ininv, dummy;
  597. Xregister struct monst *shkp;
  598. X{
  599. X    register struct obj *otmp;
  600. X
  601. X    for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
  602. X
  603. X        if(obj->otyp == GOLD_PIECE) continue;
  604. X        /* the "top" box is added in addtobill() */
  605. X        if(!otmp->no_charge)
  606. X            add_one_tobill(otmp, dummy);
  607. X        if(Is_container(otmp))
  608. X            bill_box_content(otmp, ininv, dummy, shkp);
  609. X    }
  610. X
  611. X}
  612. X
  613. Xvoid
  614. Xaddtobill(obj, ininv, dummy, silent)
  615. Xregister struct obj *obj;
  616. Xregister boolean ininv, dummy, silent;
  617. X{
  618. X    register struct monst *shkp;
  619. X    register char roomno = *u.ushops;
  620. X    long ltmp = 0L, cltmp = 0L, gltmp = 0L;
  621. X    register boolean container = Is_container(obj);
  622. X
  623. X    if(!*u.ushops) return;
  624. X
  625. X    if(!(shkp = shop_keeper(roomno))) return;
  626. X
  627. X    if(!inhishop(shkp)) return;
  628. X
  629. X    if(/* perhaps we threw it away earlier */
  630. X         onbill(obj, shkp, FALSE) ||
  631. X         (obj->oclass == FOOD_CLASS && obj->oeaten)
  632. X          ) return;
  633. X
  634. X    if(ESHK(shkp)->billct == BILLSZ) {
  635. X        You("got that for free!");
  636. X        return;
  637. X    }
  638. X
  639. X    if(obj->oclass == GOLD_CLASS) {
  640. X        costly_gold(obj->ox, obj->oy, obj->quan);
  641. X        return;
  642. X    }
  643. X
  644. X    if(!obj->no_charge) ltmp = get_cost(obj, shkp);
  645. X
  646. X    if (obj->no_charge && !container) {
  647. X        obj->no_charge = 0;
  648. X        return;
  649. X    }
  650. X
  651. X    if(container) {
  652. X        if(obj->cobj == (struct obj *)0) {
  653. X        if(obj->no_charge) {
  654. X            obj->no_charge = 0;
  655. X            return;
  656. X        } else {
  657. X            add_one_tobill(obj, dummy);
  658. X            goto speak;
  659. X        }
  660. X        } else {
  661. X        cltmp += contained_cost(obj, shkp, cltmp, FALSE);
  662. X        gltmp += contained_gold(obj);
  663. X        }
  664. X
  665. X        if(ltmp) add_one_tobill(obj, dummy);
  666. X        if(cltmp) bill_box_content(obj, ininv, dummy, shkp);
  667. X        picked_container(obj); /* reset contained obj->no_charge */
  668. X
  669. X        ltmp += cltmp;
  670. X
  671. X        if(gltmp) {
  672. X        costly_gold(obj->ox, obj->oy, gltmp);
  673. X        if(!ltmp) return;
  674. X        }
  675. X
  676. X        if(obj->no_charge)
  677. X        obj->no_charge = 0;
  678. X
  679. X    } else /* i.e., !container */
  680. X        add_one_tobill(obj, dummy);
  681. Xspeak:
  682. X    if(!shkp->msleep && !shkp->mfrozen && !silent) {
  683. X        char buf[BUFSZ];
  684. X
  685. X        if(!ltmp) {
  686. X        pline("%s has no interest in %s.", Monnam(shkp),
  687. X                         the(xname(obj)));
  688. X        return;
  689. X        }
  690. X        Strcpy(buf, "\"For you, ");
  691. X        if (ANGRY(shkp)) Strcat(buf, "scum ");
  692. X        else {
  693. X        switch(rnd(4) + u.uevent.udemigod) {
  694. X          case 1: Strcat(buf, "good");
  695. X              break;
  696. X          case 2: Strcat(buf, "honored");
  697. X              break;
  698. X          case 3: Strcat(buf, "most gracious");
  699. X              break;
  700. X          case 4: Strcat(buf, "esteemed");
  701. X              break;
  702. X          case 5: Strcat(buf, "most renowned and sacred");
  703. X              break;
  704. X        }
  705. X#ifdef POLYSELF
  706. X        if(!is_human(uasmon)) Strcat(buf, " creature");
  707. X        else
  708. X#endif
  709. X            Strcat(buf, (flags.female) ? " lady" : " sir");
  710. X        }
  711. X        /* after all, the shk is telling you what it is */
  712. X        obj->dknown = 1;
  713. X        exercise(A_WIS, TRUE);
  714. X        if(ininv) {
  715. X        long quan = obj->quan;
  716. X        obj->quan = 1L; /* fool xname() into giving singular */
  717. X        pline("%s; only %ld %s %s.\"", buf, ltmp,
  718. X            (quan > 1L) ? "per" : "for this", xname(obj));
  719. X        obj->quan = quan;
  720. X        } else
  721. X        pline("%s will cost you %ld zorkmid%s%s.",
  722. X            The(xname(obj)), ltmp, plur(ltmp),
  723. X            (obj->quan > 1L) ? " each" : "");
  724. X    } else if(!silent) {
  725. X        if(ltmp) pline("The list price of %s is %ld zorkmid%s%s.",
  726. X                   the(xname(obj)), ltmp, plur(ltmp),
  727. X                   (obj->quan > 1L) ? " each" : "");
  728. X        else pline("%s does not notice.", Monnam(shkp));
  729. X    }
  730. X}
  731. X
  732. Xvoid
  733. Xsplitbill(obj, otmp)
  734. Xregister struct obj *obj, *otmp;
  735. X{
  736. X    /* otmp has been split off from obj */
  737. X    register struct bill_x *bp;
  738. X    register long tmp;
  739. X    register struct monst *shkp = shop_keeper(*u.ushops);
  740. X
  741. X    if(!shkp || !inhishop(shkp)) {
  742. X        impossible("splitbill: no resident shopkeeper??");
  743. X        return;
  744. X    }
  745. X    bp = onbill(obj, shkp, FALSE);
  746. X    if(!bp) {
  747. X        impossible("splitbill: not on bill?");
  748. X        return;
  749. X    }
  750. X    if(bp->bquan < otmp->quan) {
  751. X        impossible("Negative quantity on bill??");
  752. X    }
  753. X    if(bp->bquan == otmp->quan) {
  754. X        impossible("Zero quantity on bill??");
  755. X    }
  756. X    bp->bquan -= otmp->quan;
  757. X
  758. X    if(ESHK(shkp)->billct == BILLSZ) otmp->unpaid = 0;
  759. X    else {
  760. X        tmp = bp->price;
  761. X        bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
  762. X        bp->bo_id = otmp->o_id;
  763. X        bp->bquan = otmp->quan;
  764. X        bp->useup = 0;
  765. X        bp->price = tmp;
  766. X        ESHK(shkp)->billct++;
  767. X    }
  768. X}
  769. X
  770. Xstatic void
  771. Xsub_one_frombill(obj, shkp)
  772. Xregister struct obj *obj;
  773. Xregister struct monst *shkp;
  774. X{
  775. X    register struct bill_x *bp;
  776. X
  777. X    if((bp = onbill(obj, shkp, FALSE)) != 0) {
  778. X        register struct obj *otmp;
  779. X
  780. X        obj->unpaid = 0;
  781. X        if(bp->bquan > obj->quan){
  782. X            otmp = newobj(0);
  783. X            *otmp = *obj;
  784. X            bp->bo_id = otmp->o_id = flags.ident++;
  785. X            otmp->quan = (bp->bquan -= obj->quan);
  786. X            otmp->owt = 0;    /* superfluous */
  787. X            otmp->onamelth = 0;
  788. X            bp->useup = 1;
  789. X            otmp->nobj = billobjs;
  790. X            billobjs = otmp;
  791. X            return;
  792. X        }
  793. X        ESHK(shkp)->billct--;
  794. X#ifdef DUMB
  795. X        {
  796. X        /* DRS/NS 2.2.6 messes up -- Peter Kendell */
  797. X            int indx = ESHK(shkp)->billct;
  798. X            *bp = ESHK(shkp)->bill_p[indx];
  799. X        }
  800. X#else
  801. X        *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
  802. X#endif
  803. X        return;
  804. X    } else if (obj->unpaid) {
  805. X        impossible("sub_one_frombill: unpaid object not on bill");
  806. X        obj->unpaid = 0;
  807. X    }
  808. X}
  809. X
  810. X/* recursive check of unpaid objects within nested containers. */
  811. Xvoid
  812. Xsubfrombill(obj, shkp)
  813. Xregister struct obj *obj;
  814. Xregister struct monst *shkp;
  815. X{
  816. X    register struct obj *otmp;
  817. X
  818. X    sub_one_frombill(obj, shkp);
  819. X
  820. X    if(Is_container(obj))
  821. X        for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
  822. X        if(otmp->otyp == GOLD_PIECE) continue;
  823. X
  824. X        if(Is_container(otmp))
  825. X            subfrombill(otmp, shkp);
  826. X        else
  827. X            sub_one_frombill(otmp, shkp);
  828. X        }
  829. X}
  830. X
  831. Xstatic long
  832. Xstolen_container(obj, shkp, price, ininv)
  833. Xregister struct obj *obj;
  834. Xregister struct monst *shkp;
  835. Xlong price;
  836. Xregister boolean ininv;
  837. X{
  838. X    register struct obj *otmp;
  839. X
  840. X    if(ininv && obj->unpaid)
  841. X        price += get_cost(obj, shkp);
  842. X    else {
  843. X        if(!obj->no_charge)
  844. X        price += get_cost(obj, shkp);
  845. X        obj->no_charge = 0;
  846. X    }
  847. X
  848. X    /* the price of contained objects, if any */
  849. X    for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
  850. X
  851. X        if(otmp->otyp == GOLD_PIECE) continue;
  852. X
  853. X        if(!Is_container(otmp)) {
  854. X        if(ininv) {
  855. X            if(otmp->unpaid)
  856. X            price += get_cost(otmp, shkp);
  857. X        } else {
  858. X            if(!otmp->no_charge) {
  859. X            if(!(otmp->oclass == BALL_CLASS ||
  860. X                (otmp->oclass == FOOD_CLASS && otmp->oeaten) ||
  861. X                (Is_candle(otmp) && otmp->age <
  862. X                  20L * (long)objects[otmp->otyp].oc_cost))
  863. X              ) price += get_cost(otmp, shkp);
  864. X            }
  865. X            otmp->no_charge = 0;
  866. X        }
  867. X        } else
  868. X        price += stolen_container(otmp, shkp, price, ininv);
  869. X    }
  870. X
  871. X    return(price);
  872. X}
  873. X
  874. Xlong
  875. Xstolen_value(obj, x, y, peaceful, silent)
  876. Xregister struct obj *obj;
  877. Xregister xchar x, y;
  878. Xregister boolean peaceful, silent;
  879. X{
  880. X    register long value = 0L, gvalue = 0L;
  881. X    register struct monst *shkp;
  882. X    register boolean goods;
  883. X
  884. X    shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
  885. X
  886. X    if (!shkp || !inhishop(shkp))
  887. X        return (0L);
  888. X
  889. X    goods = saleable(rooms[ESHK(shkp)->shoproom -
  890. X                   ROOMOFFSET].rtype-SHOPBASE, obj);
  891. X    goods = (goods && !obj->no_charge);
  892. X
  893. X    if(obj->otyp == GOLD_PIECE) {
  894. X        gvalue += obj->quan;
  895. X    } else if(Is_container(obj)) {
  896. X        register boolean ininv = !!count_unpaid(obj->cobj);
  897. X
  898. X        value += stolen_container(obj, shkp, value, ininv);
  899. X        if(!ininv) gvalue += contained_gold(obj);
  900. X    } else if(goods) {
  901. X        value += get_cost(obj, shkp);
  902. X    }
  903. X
  904. X    if(gvalue + value == 0L) return(0L);
  905. X
  906. X    value += gvalue;
  907. X
  908. X    if(peaceful) {
  909. X        value = check_credit(value, shkp);
  910. X        ESHK(shkp)->debit += value;
  911. X
  912. X        if(!silent) {
  913. X        if(obj->otyp == GOLD_PIECE)
  914. X            You("owe %s %ld zorkmids!", mon_nam(shkp), value);
  915. X        else You("owe %s %ld zorkmids for %s!",
  916. X            mon_nam(shkp),
  917. X            value,
  918. X            obj->quan > 1L ? "them" : "it");
  919. X        }
  920. X    } else {
  921. X        ESHK(shkp)->robbed += value;
  922. X
  923. X        if(!silent) {
  924. X        if(cansee(shkp->mx, shkp->my)) {
  925. X            if(ESHK(shkp)->customer[0] == 0)
  926. X            (void) strncpy(ESHK(shkp)->customer,plname,PL_NSIZ);
  927. X            Norep("%s booms: \"%s, you are a thief!\"",
  928. X                Monnam(shkp), plname);
  929. X        } else  Norep("You hear a scream, \"Thief!\"");
  930. X        }
  931. X        hot_pursuit(shkp);
  932. X        (void) angry_guards(FALSE);
  933. X    }
  934. X    return(value);
  935. X}
  936. X
  937. X/* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */
  938. Xstatic char sell_response = 'a';
  939. X
  940. Xvoid
  941. Xsellobj_state(deliberate)    /* called from dodrop(do.c) and doddrop() */
  942. Xregister boolean deliberate;
  943. X{
  944. X    /* If we're deliberately dropping something, there's no automatic
  945. X    response to the shopkeeper's "want to sell" query; however, if we
  946. X    accidentally drop anything, the shk will buy it/them without asking.
  947. X    This retains the old pre-query risk that slippery fingers while in
  948. X    shops entailed:  you drop it, you've lost it.
  949. X     */
  950. X    sell_response = deliberate ? '\0' : 'a';
  951. X}
  952. X
  953. Xvoid
  954. Xsellobj(obj, x, y)
  955. Xregister struct obj *obj;
  956. Xregister xchar x, y;
  957. X{
  958. X    register struct monst *shkp;
  959. X    register struct eshk *eshkp;
  960. X    register long ltmp = 0L, cltmp = 0L, gltmp = 0L, offer;
  961. X    boolean saleitem, cgold = FALSE, container = Is_container(obj);
  962. X    boolean isgold = (obj->oclass == GOLD_CLASS);
  963. X
  964. X    if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) ||
  965. X       !inhishop(shkp)) return;
  966. X    if(!costly_spot(x, y))    return;
  967. X    if(!*u.ushops) return;
  968. X
  969. X    saleitem = saleable(rooms[ESHK(shkp)->shoproom -
  970. X                    ROOMOFFSET].rtype-SHOPBASE, obj);
  971. X
  972. X    if(obj->unpaid && !container && !isgold) {
  973. X        sub_one_frombill(obj, shkp);
  974. X        return;
  975. X    }
  976. X    if(container) {
  977. X        if(obj->cobj == (struct obj *)0) {
  978. X        if(obj->unpaid) {
  979. X            sub_one_frombill(obj, shkp);
  980. X            return;
  981. X        }
  982. X        } else {
  983. X        /* find the price of content before subfrombill */
  984. X        cltmp += contained_cost(obj, shkp, cltmp, TRUE);
  985. X        /* find the value of contained gold */
  986. X        gltmp += contained_gold(obj);
  987. X        cgold = (gltmp > 0L);
  988. X        }
  989. X    }
  990. X
  991. X    if(!isgold && !obj->unpaid && saleitem)
  992. X        ltmp = set_cost(obj, shkp);
  993. X
  994. X    offer = ltmp + cltmp;
  995. X
  996. X    if(!isgold && (offer + gltmp) == 0L) {
  997. X        register boolean unpaid = (obj->unpaid ||
  998. X                  (container && count_unpaid(obj->cobj)));
  999. X
  1000. X        if(container) {
  1001. X            if(obj->cobj != (struct obj *)0) {
  1002. X            dropped_container(obj);
  1003. X            if(obj->unpaid || count_unpaid(obj->cobj))
  1004. X                subfrombill(obj, shkp);
  1005. X            } else obj->no_charge = 1;
  1006. X        } else obj->no_charge = 1;
  1007. X
  1008. X        if(!unpaid)
  1009. X            pline("%s seems uninterested.", Monnam(shkp));
  1010. X        return;
  1011. X    }
  1012. X
  1013. X    /* you dropped something of your own - probably want to sell it */
  1014. X    if(shkp->msleep || !shkp->mcanmove) {
  1015. X        if(container && obj->cobj != (struct obj *)0) {
  1016. X            dropped_container(obj);
  1017. X        }
  1018. X        if(!shkp->mcanmove) {
  1019. X            if(ANGRY(shkp) && !rn2(4))
  1020. X            pline("%s utters a curse.", Monnam(shkp));
  1021. X            else pline("%s is indisposed.", Monnam(shkp));
  1022. X        } else if(!rn2(3)) {
  1023. X            pline("%s snores indifferently.", Monnam(shkp));
  1024. X        }
  1025. X        subfrombill(obj, shkp);
  1026. X        return;
  1027. X    }
  1028. X
  1029. X    eshkp = ESHK(shkp);
  1030. X
  1031. X    if(isgold || cgold) {
  1032. X        if(ANGRY(shkp)) {
  1033. X            if(!offer) {
  1034. X             pline("%s is not appeased.", Monnam(shkp));
  1035. X             if(cgold) subfrombill(obj, shkp);
  1036. X             return;
  1037. X            } else goto move_on;
  1038. X        }
  1039. X
  1040. X        if(!cgold) gltmp = obj->quan;
  1041. X
  1042. X        if(eshkp->debit >= gltmp) {
  1043. X            if(eshkp->loan) { /* you carry shop's gold */
  1044. X             if(eshkp->loan >= gltmp)
  1045. X                 eshkp->loan -= gltmp;
  1046. X             else eshkp->loan = 0L;
  1047. X            }
  1048. X            eshkp->debit -= gltmp;
  1049. X            Your("debt is %spaid off.",
  1050. X                eshkp->debit ? "partially " : "");
  1051. X        } else {
  1052. X            long delta = gltmp - eshkp->debit;
  1053. X
  1054. X            eshkp->credit += delta;
  1055. X            if(eshkp->debit) {
  1056. X            eshkp->debit = 0L;
  1057. X            eshkp->loan = 0L;
  1058. X            Your("debt is paid off.");
  1059. X            }
  1060. X            pline("%ld zorkmid%s added to your credit.",
  1061. X                delta, delta > 1L ? "s are" : " is");
  1062. X        }
  1063. X        if(offer) goto move_on;
  1064. X        else {
  1065. X            if(container && obj->cobj != (struct obj *)0) {
  1066. X            dropped_container(obj);
  1067. X            }
  1068. X            subfrombill(obj, shkp);
  1069. X            obj->no_charge = 1;
  1070. X            return;
  1071. X        }
  1072. X    }
  1073. Xmove_on:
  1074. X    if (ANGRY(shkp)) { /* they become shop-objects, no pay */
  1075. X        pline("Thank you, scum!");
  1076. X        subfrombill(obj, shkp);
  1077. X        return;
  1078. X    }
  1079. X
  1080. X    if((!saleitem && !(container && cltmp > 0L))
  1081. X       || eshkp->billct == BILLSZ
  1082. X       || obj->oclass == BALL_CLASS || offer == 0L
  1083. X       || (obj->oclass == FOOD_CLASS && obj->oeaten)
  1084. X       || (Is_candle(obj) &&
  1085. X           obj->age < 20L * (long)objects[obj->otyp].oc_cost)) {
  1086. X        pline("%s seems not interested%s.", Monnam(shkp),
  1087. X                       cgold ? " in the rest" : "");
  1088. X        if(container && obj->cobj != (struct obj *)0) {
  1089. X            dropped_container(obj);
  1090. X        }
  1091. X        obj->no_charge = 1;
  1092. X        return;
  1093. X    }
  1094. X
  1095. X    if(eshkp->robbed) {  /* shkp is not angry? */
  1096. X        if((eshkp->robbed -= offer < 0L))
  1097. X            eshkp->robbed = 0L;
  1098. X        verbalize(
  1099. X  "Thank you for your contribution to restock this recently plundered shop.");
  1100. X        subfrombill(obj, shkp);
  1101. X        return;
  1102. X    }
  1103. X
  1104. X    if(!shkp->mgold) {
  1105. X        long tmpcr = (ltmp + cltmp) * 2L;
  1106. X
  1107. X        pline("%s cannot pay you at present.", Monnam(shkp));
  1108. X        pline("Will you accept %ld zorkmids in credit for %s? ",
  1109. X                     tmpcr, doname(obj));
  1110. X        /* cannot use a yn function here */
  1111. X        if (readchar() == 'y') {
  1112. X            You("have %ld zorkmids in %scredit.", tmpcr,
  1113. X                ESHK(shkp)->credit > 0L ? "additional " : "");
  1114. X            ESHK(shkp)->credit += tmpcr;
  1115. X            subfrombill(obj, shkp);
  1116. X        } else {
  1117. X            if(container && obj->cobj != (struct obj *)0) {
  1118. X                dropped_container(obj);
  1119. X            }
  1120. X            subfrombill(obj, shkp);
  1121. X            obj->no_charge = 1;
  1122. X        }
  1123. X    } else {
  1124. X        int qlen;
  1125. X        char qbuf[BUFSZ];
  1126. X        boolean short_funds = (offer > shkp->mgold);
  1127. X
  1128. X        if (short_funds) offer = shkp->mgold;
  1129. X
  1130. X        if (!sell_response) {
  1131. X            Sprintf(qbuf,
  1132. X                "%s offers%s %ld gold piece%s for%s your %s.",
  1133. X                Monnam(shkp), short_funds ? " only" : "",
  1134. X                offer, plur(offer),
  1135. X                (!ltmp && cltmp) ? " the contents of" : "",
  1136. X                xname(obj));
  1137. X            qlen = strlen(qbuf);
  1138. X            /*  Will the prompt fit on the topline? (or would
  1139. X             *    "--more--" force line wrap anyway?)  If so, combine
  1140. X             *    the message and prompt; otherwise, flush message
  1141. X             *    and prompt separately.
  1142. X             */
  1143. X            if (qlen > COLNO - 24 && qlen <= COLNO - 8)
  1144. X            pline(qbuf),  qbuf[0] = '\0';
  1145. X            else  Strcat(qbuf, "  ");
  1146. X            Strcat(strcat(qbuf, "Sell "),
  1147. X                (obj->quan == 1L ? "it?" : "them?"));
  1148. X        } else  qbuf[0] = '\0';        /* just to pacify lint */
  1149. X
  1150. X        switch (sell_response ? sell_response : ynaq(qbuf)) {
  1151. X         case 'q':  sell_response = 'n';
  1152. X         case 'n':  if(container && obj->cobj != (struct obj *)0) {
  1153. X                dropped_container(obj);
  1154. X                }
  1155. X                subfrombill(obj, shkp);
  1156. X                obj->no_charge = 1;
  1157. X                break;
  1158. X         case 'a':  sell_response = 'y';
  1159. X         case 'y':  subfrombill(obj, shkp);
  1160. X                pay(-offer, shkp);
  1161. X                You("sold %s for %ld gold piece%s.", doname(obj),
  1162. X                offer, plur(offer));
  1163. X                break;
  1164. X         default:   impossible("invalid sell response");
  1165. X        }
  1166. X    }
  1167. X}
  1168. X
  1169. Xint
  1170. Xdoinvbill(mode)
  1171. Xint mode;        /* 0: deliver count 1: paged */
  1172. X{
  1173. X    register struct monst* shkp;
  1174. X    register struct bill_x *bp, *end_bp;
  1175. X    register struct obj *obj;
  1176. X    long totused;
  1177. X    char *buf_p;
  1178. X    winid datawin;
  1179. X
  1180. X    shkp = shop_keeper(*u.ushops);
  1181. X
  1182. X    if(mode == 0) {
  1183. X        register int cnt = 0;
  1184. X
  1185. X        if(shkp && inhishop(shkp))
  1186. X        for (bp = ESHK(shkp)->bill_p,
  1187. X            end_bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
  1188. X            bp < end_bp; bp++)
  1189. X            if(bp->useup ||
  1190. X               ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
  1191. X            cnt++;
  1192. X        return(cnt);
  1193. X    }
  1194. X
  1195. X    if(!shkp || !inhishop(shkp)) {
  1196. X        impossible("doinvbill: no shopkeeper?");
  1197. X        return(0);
  1198. X    }
  1199. X
  1200. X    datawin = create_nhwindow(NHW_MENU);
  1201. X    putstr(datawin, 0, "Unpaid articles already used up:");
  1202. X    putstr(datawin, 0, "");
  1203. X
  1204. X    totused = 0L;
  1205. X    for (bp = ESHK(shkp)->bill_p,
  1206. X        end_bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
  1207. X        bp < end_bp; bp++) {
  1208. X        obj = bp_to_obj(bp);
  1209. X        if(!obj) {
  1210. X        impossible("Bad shopkeeper administration.");
  1211. X        goto quit;
  1212. X        }
  1213. X        if(bp->useup || bp->bquan > obj->quan) {
  1214. X        register long oquan, uquan;
  1215. X        long thisused;
  1216. X
  1217. X        oquan = obj->quan;
  1218. X        uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
  1219. X        thisused = bp->price * uquan;
  1220. X        totused += thisused;
  1221. X        obj->quan = uquan;        /* cheat doname */
  1222. X        buf_p = xprname(obj, ' ', FALSE, thisused);
  1223. X        obj->quan = oquan;        /* restore value */
  1224. X        putstr(datawin, 0, buf_p);
  1225. X        }
  1226. X    }
  1227. X    buf_p = xprname((struct obj *)0, '*', FALSE, totused);
  1228. X    putstr(datawin, 0, "");
  1229. X    putstr(datawin, 0, buf_p);
  1230. X    display_nhwindow(datawin, FALSE);
  1231. X    quit:
  1232. X    destroy_nhwindow(datawin);
  1233. X    return(0);
  1234. X}
  1235. X
  1236. X#define HUNGRY    2
  1237. X
  1238. Xstatic long
  1239. Xgetprice(obj)
  1240. Xregister struct obj *obj;
  1241. X{
  1242. X    register long tmp = (long) objects[obj->otyp].oc_cost;
  1243. X
  1244. X    switch(obj->oclass) {
  1245. X    case FOOD_CLASS:
  1246. X        /* simpler hunger check, (2-4)*cost */
  1247. X        if (u.uhs >= HUNGRY) tmp *= (long) u.uhs;
  1248. X        if (obj->oeaten) tmp = 0L;
  1249. X        break;
  1250. X    case WAND_CLASS:
  1251. X        if (obj->spe == -1) tmp = 0L;
  1252. X        break;
  1253. X    case POTION_CLASS:
  1254. X        if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
  1255. X            tmp = 0L;
  1256. X        break;
  1257. X    case ARMOR_CLASS:
  1258. X    case WEAPON_CLASS:
  1259. X        if (obj->spe > 0) tmp += 10L * (long) obj->spe;
  1260. X        break;
  1261. X    case CHAIN_CLASS:
  1262. X        pline("Strange... carrying a chain?");
  1263. X        break;
  1264. X    case TOOL_CLASS:
  1265. X        if (Is_candle(obj) &&
  1266. X            obj->age < 20L * (long)objects[obj->otyp].oc_cost)
  1267. X            tmp /= 2L;
  1268. X        break;
  1269. X    }
  1270. X    if (obj->oartifact) tmp *= 25L;
  1271. X    return tmp;
  1272. X}
  1273. X
  1274. Xint
  1275. Xshkcatch(obj, x, y)
  1276. Xregister struct obj *obj;
  1277. Xregister xchar x, y;
  1278. X{
  1279. X    register struct monst *shkp;
  1280. X
  1281. X    if (!(shkp = shop_keeper(inside_shop(x, y))) ||
  1282. X        !inhishop(shkp)) return(0);
  1283. X
  1284. X    if (shkp->mcanmove && !shkp->msleep &&
  1285. X        (*u.ushops != ESHK(shkp)->shoproom || !inside_shop(u.ux, u.uy)) &&
  1286. X        dist2(shkp->mx, shkp->my, x, y) < 3 &&
  1287. X        /* if it is the shk's pos, you hit and anger him */
  1288. X        (shkp->mx != x || shkp->my != y)) {
  1289. X        if (mnearto(shkp, x, y, TRUE))
  1290. X            verbalize("Out of my way, scum!");
  1291. X        pline("%s nimbly catches %s.", Monnam(shkp), the(xname(obj)));
  1292. X        mpickobj(shkp, obj);
  1293. X        subfrombill(obj, shkp);
  1294. X        return(1);
  1295. X    }
  1296. X    return(0);
  1297. X}
  1298. X
  1299. Xvoid
  1300. Xadd_damage(x, y, cost)
  1301. Xregister xchar x, y;
  1302. Xlong cost;
  1303. X{
  1304. X    struct damage *tmp_dam;
  1305. X    char *shops;
  1306. X
  1307. X    if (IS_DOOR(levl[x][y].typ))
  1308. X        /* Don't schedule for repair unless it's a real shop entrance */
  1309. X        for (shops = in_rooms(x, y, SHOPBASE); *shops; shops++) {
  1310. X        struct monst *mtmp = shop_keeper(*shops);
  1311. X
  1312. X        if (!mtmp)
  1313. X            continue;
  1314. X        if ((x != ESHK(mtmp)->shd.x) || (y != ESHK(mtmp)->shd.y))
  1315. X            return;
  1316. X        }
  1317. X    tmp_dam = (struct damage *)alloc((unsigned)sizeof(struct damage));
  1318. X    tmp_dam->when = monstermoves;
  1319. X    tmp_dam->place.x = x;
  1320. X    tmp_dam->place.y = y;
  1321. X    tmp_dam->cost = cost;
  1322. X    tmp_dam->typ = levl[x][y].typ;
  1323. X    tmp_dam->next = level.damagelist;
  1324. X    level.damagelist = tmp_dam;
  1325. X    /* If player saw damage, display as a wall forever */
  1326. X    if (cansee(x, y))
  1327. X        levl[x][y].seen = 1;
  1328. X}
  1329. X
  1330. X/*
  1331. X * Do something about damage. Either (!croaked) try to repair it, or
  1332. X * (croaked) just discard damage structs for non-shared locations, since
  1333. X * they'll never get repaired. Assume that shared locations will get
  1334. X * repaired eventually by the other shopkeeper(s). This might be an erroneous
  1335. X * assumption (they might all be dead too), but we have no reasonable way of
  1336. X * telling that.
  1337. X */
  1338. Xstatic
  1339. Xvoid
  1340. Xremove_damage(shkp, croaked)
  1341. Xregister struct monst *shkp;
  1342. Xregister boolean croaked;
  1343. X{
  1344. X    register struct damage *tmp_dam, *tmp2_dam;
  1345. X    register boolean did_repair = FALSE, saw_door = FALSE;
  1346. X    register boolean saw_floor = FALSE, stop_picking = FALSE;
  1347. X    uchar saw_walls = 0;
  1348. X
  1349. X    tmp_dam = level.damagelist;
  1350. X    tmp2_dam = 0;
  1351. X    while (tmp_dam) {
  1352. X        register xchar x = tmp_dam->place.x, y = tmp_dam->place.y;
  1353. X        char shops[5];
  1354. X        uchar disposition;
  1355. X
  1356. X        disposition = 0;
  1357. X        Strcpy(shops, in_rooms(x, y, SHOPBASE));
  1358. X        if (index(shops, ESHK(shkp)->shoproom)) {
  1359. X        if (croaked)
  1360. X            disposition = (shops[1])? 0 : 1;
  1361. X        else if (stop_picking)
  1362. X            disposition = repair_damage(shkp, tmp_dam);
  1363. X        else {
  1364. X            /* Defer the stop_occupation() until after repair msgs */
  1365. X            if (closed_door(x, y))
  1366. X            stop_picking = picking_at(x, y);
  1367. X            disposition = repair_damage(shkp, tmp_dam);
  1368. X            if (!disposition)
  1369. X            stop_picking = FALSE;
  1370. X        }
  1371. X        }
  1372. X
  1373. X        if (!disposition) {
  1374. X        tmp2_dam = tmp_dam;
  1375. X        tmp_dam = tmp_dam->next;
  1376. X        continue;
  1377. X        }
  1378. X
  1379. X        if (disposition > 1) {
  1380. X        did_repair = TRUE;
  1381. X        if (cansee(x, y)) {
  1382. X            if (IS_WALL(levl[x][y].typ))
  1383. X            saw_walls++;
  1384. X            else if (IS_DOOR(levl[x][y].typ))
  1385. X            saw_door = TRUE;
  1386. X            else
  1387. X            saw_floor = TRUE;
  1388. X        }
  1389. X        }
  1390. X
  1391. X        tmp_dam = tmp_dam->next;
  1392. X        if (!tmp2_dam) {
  1393. X        free((genericptr_t)level.damagelist);
  1394. X        level.damagelist = tmp_dam;
  1395. X        } else {
  1396. X        free((genericptr_t)tmp2_dam->next);
  1397. X        tmp2_dam->next = tmp_dam;
  1398. X        }
  1399. X    }
  1400. X    if (!did_repair)
  1401. X        return;
  1402. X    if (saw_walls) {
  1403. X        pline("Suddenly, %s section%s of wall close%s up!",
  1404. X          (saw_walls == 1) ? "a" : (saw_walls <= 3) ?
  1405. X                          "some" : "several",
  1406. X          (saw_walls == 1) ? "" : "s", (saw_walls == 1) ? "s" : "");
  1407. X        if (saw_door)
  1408. X        pline("The shop door reappears!");
  1409. X        if (saw_floor)
  1410. X        pline("The floor is repaired!");
  1411. X    } else {
  1412. X        if (saw_door)
  1413. X        pline("Suddenly, the shop door reappears!");
  1414. X        else if (saw_floor)
  1415. X        pline("Suddenly, the floor damage is gone!");
  1416. X        else if (inside_shop(u.ux, u.uy) == ESHK(shkp)->shoproom)
  1417. X        You("feel more claustrophobic than before.");
  1418. X        else if (flags.soundok && !rn2(10))
  1419. X        Norep("The dungeon acoustics noticeably change.");
  1420. X    }
  1421. X    if (stop_picking)
  1422. X        stop_occupation();
  1423. X}
  1424. X
  1425. X/*
  1426. X * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
  1427. X */
  1428. Xchar
  1429. Xrepair_damage(shkp, tmp_dam)
  1430. Xregister struct monst *shkp;
  1431. Xregister struct damage *tmp_dam;
  1432. X{
  1433. X    register xchar x, y, i;
  1434. X    xchar litter[9];
  1435. X    register struct monst *mtmp;
  1436. X    register struct obj *otmp;
  1437. X    register struct trap *ttmp;
  1438. X
  1439. X    if ((monstermoves - tmp_dam->when) < REPAIR_DELAY)
  1440. X        return(0);
  1441. X    if (ESHK(shkp)->following)
  1442. X        return(0);
  1443. X    x = tmp_dam->place.x;
  1444. X    y = tmp_dam->place.y;
  1445. X    if (!IS_ROOM(tmp_dam->typ)) {
  1446. X        if ((x == u.ux) && (y == u.uy))
  1447. X#ifdef POLYSELF
  1448. X        if (!passes_walls(uasmon))
  1449. X#endif
  1450. X            return(0);
  1451. X        if ((x == shkp->mx) && (y == shkp->my))
  1452. X        return(0);
  1453. X        if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data)))
  1454. X        return(0);
  1455. X    }
  1456. X    if ((ttmp = t_at(x, y)) != 0)
  1457. X        deltrap(ttmp);
  1458. X    if (IS_ROOM(tmp_dam->typ)) {
  1459. X        /* No messages if player already filled trapdoor */
  1460. X        if (!ttmp)
  1461. X        return(1);
  1462. X        newsym(x, y);
  1463. X        return(2);
  1464. X    }
  1465. X    if (!ttmp && (tmp_dam->typ == levl[x][y].typ) &&
  1466. X        (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN)))
  1467. X        /* No messages if player already replaced shop door */
  1468. X        return(1);
  1469. X    levl[x][y].typ = tmp_dam->typ;
  1470. X    (void) memset((genericptr_t)litter, 0, sizeof(litter));
  1471. X    if ((otmp = level.objects[x][y]) != 0) {
  1472. X        /* Scatter objects haphazardly into the shop */
  1473. X#define NEED_UPDATE 1
  1474. X#define OPEN        2
  1475. X#define INSHOP        4
  1476. X#define horiz(i) ((i%3)-1)
  1477. X#define vert(i)  ((i/3)-1)
  1478. X        for (i = 0; i < 9; i++) {
  1479. X        if ((i == 4) || (!ZAP_POS(levl[x+horiz(i)][y+vert(i)].typ)))
  1480. X            continue;
  1481. X        litter[i] = OPEN;
  1482. X        if (inside_shop(x+horiz(i),
  1483. X                y+vert(i)) == ESHK(shkp)->shoproom)
  1484. X            litter[i] |= INSHOP;
  1485. X        }
  1486. X        if (Punished && ((uchain->ox == x && uchain->oy == y) ||
  1487. X                    (uball->ox == x && uball->oy == y))) {
  1488. X        /*
  1489. X         * Either the ball or chain is in the repair location.
  1490. X         *
  1491. X         * Take the easy way out and put ball&chain under hero.
  1492. X         */
  1493. X        verbalize("Get your junk out of my wall!");
  1494. X        unplacebc();    /* pick 'em up */
  1495. X        placebc();    /* put 'em down */
  1496. X        }
  1497. X        while ((otmp = level.objects[x][y]) != 0)
  1498. X        /* Don't mess w/ boulders -- just merge into wall */
  1499. X        if ((otmp->otyp == BOULDER) || (otmp->otyp == ROCK)) {
  1500. X            freeobj(otmp);
  1501. X            obfree(otmp, (struct obj *)0);
  1502. X        } else {
  1503. X            while (!(litter[i = rn2(9)] & INSHOP));
  1504. X            remove_object(otmp);
  1505. X            place_object(otmp, x+horiz(i), y+vert(i));
  1506. X            litter[i] |= NEED_UPDATE;
  1507. X        }
  1508. X    }
  1509. X    block_point(x, y);
  1510. X    if(IS_DOOR(tmp_dam->typ)) {
  1511. X        levl[x][y].doormask = D_CLOSED; /* arbitrary */
  1512. X        newsym(x, y);
  1513. X    } else {
  1514. X        levl[x][y].doormask = D_NODOOR;
  1515. X        if (IS_WALL(tmp_dam->typ) && cansee(x, y)) {
  1516. X        /* Player sees actual repair process, so they KNOW it's a wall */
  1517. X        levl[x][y].seen = 1;
  1518. X        newsym(x, y);
  1519. X        } else if (levl[x][y].seen) {
  1520. X        /* Force a display update */
  1521. X        levl[x][y].diggable |= W_REPAIRED;
  1522. X        }
  1523. X    }
  1524. X    for (i = 0; i < 9; i++)
  1525. X        if (litter[i] & NEED_UPDATE)
  1526. X        newsym(x+horiz(i), y+vert(i));
  1527. X    return(2);
  1528. X#undef NEED_UPDATE
  1529. X#undef OPEN
  1530. X#undef INSHOP
  1531. X#undef vert
  1532. X#undef horiz
  1533. X}
  1534. X
  1535. X/*
  1536. X * shk_move: return 1: moved  0: didn't  -1: let m_move do it  -2: died
  1537. X */
  1538. Xint
  1539. Xshk_move(shkp)
  1540. Xregister struct monst *shkp;
  1541. X{
  1542. X    register xchar gx,gy,omx,omy;
  1543. X    register int udist;
  1544. X    register schar appr;
  1545. X    register struct eshk *eshkp = ESHK(shkp);
  1546. X    int z;
  1547. X    boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv;
  1548. X
  1549. X    omx = shkp->mx;
  1550. X    omy = shkp->my;
  1551. X
  1552. X    if (inhishop(shkp))
  1553. X        remove_damage(shkp, FALSE);
  1554. X
  1555. X    if((udist = distu(omx,omy)) < 3 &&
  1556. X       (shkp->data != &mons[PM_GRID_BUG] || (omx==u.ux || omy==u.uy))) {
  1557. X        if(ANGRY(shkp) ||
  1558. X           (Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
  1559. X            if(Displaced)
  1560. X              Your("displaced image doesn't fool %s!",
  1561. X                mon_nam(shkp));
  1562. X            (void) mattacku(shkp);
  1563. X            return(0);
  1564. X        }
  1565. X        if(eshkp->following) {
  1566. X            if(strncmp(eshkp->customer, plname, PL_NSIZ)) {
  1567. X                verbalize("Hello, %s!  I was looking for %s.",
  1568. X                    plname, eshkp->customer);
  1569. X                    eshkp->following = 0;
  1570. X                return(0);
  1571. X            }
  1572. X            if(moves > followmsg+4) {
  1573. X                verbalize("Hello, %s!  Didn't you forget to pay?",
  1574. X                    plname);
  1575. X                followmsg = moves;
  1576. X                if (!rn2(4)) {
  1577. X        pline ("%s doesn't like customers who don't pay.", Monnam(shkp));
  1578. X                rile_shk(shkp);
  1579. X                }
  1580. X            }
  1581. X            if(udist < 2)
  1582. X                return(0);
  1583. X        }
  1584. X    }
  1585. X
  1586. X    appr = 1;
  1587. X    gx = eshkp->shk.x;
  1588. X    gy = eshkp->shk.y;
  1589. X    satdoor = (gx == omx && gy == omy);
  1590. X    if(eshkp->following || ((z = holetime()) >= 0 && z*z <= udist)){
  1591. X        if(udist > 4)
  1592. X            return(-1);    /* leave it to m_move */
  1593. X        gx = u.ux;
  1594. X        gy = u.uy;
  1595. X    } else if(ANGRY(shkp)) {
  1596. X        /* Move towards the hero if the shopkeeper can see him. */
  1597. X        if(shkp->mcansee && m_canseeu(shkp)) {
  1598. X            gx = u.ux;
  1599. X            gy = u.uy;
  1600. X        }
  1601. X        avoid = FALSE;
  1602. X    } else {
  1603. X#define    GDIST(x,y)    (dist2(x,y,gx,gy))
  1604. X        if(Invis) {
  1605. X            avoid = FALSE;
  1606. X        } else {
  1607. X            uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y);
  1608. X            if(uondoor) {
  1609. X            badinv = (!!carrying(PICK_AXE));
  1610. X            if(satdoor && badinv)
  1611. X                return(0);
  1612. X            avoid = !badinv;
  1613. X            } else {
  1614. X            avoid = (*u.ushops && distu(gx,gy) > 8);
  1615. X            badinv = FALSE;
  1616. X            }
  1617. X
  1618. X            if(((!eshkp->robbed && !eshkp->billct && !eshkp->debit)
  1619. X            || avoid) && GDIST(omx,omy) < 3) {
  1620. X            if (!badinv && !onlineu(omx,omy))
  1621. X                return(0);
  1622. X            if(satdoor)
  1623. X                appr = gx = gy = 0;
  1624. X            }
  1625. X        }
  1626. X    }
  1627. X
  1628. X    return(move_special(shkp,inhishop(shkp),
  1629. X                appr,uondoor,avoid,omx,omy,gx,gy));
  1630. X}
  1631. X
  1632. X/* for use in levl_follower (mondata.c) */
  1633. Xboolean
  1634. Xis_fshk(mtmp)
  1635. Xregister struct monst *mtmp;
  1636. X{
  1637. X    return(mtmp->isshk && ESHK(mtmp)->following);
  1638. X}
  1639. X
  1640. X/* You are digging in the shop. */
  1641. Xvoid
  1642. Xshopdig(fall)
  1643. Xregister int fall;
  1644. X{
  1645. X    register struct monst *shkp = shop_keeper(*u.ushops);
  1646. X
  1647. X    if(!shkp) return;
  1648. X
  1649. X    if(!inhishop(shkp)) {
  1650. X    if (pl_character[0] == 'K') adjalign(-sgn(u.ualign.type));
  1651. X    return;
  1652. X    }
  1653. X
  1654. X    if(!fall) {
  1655. X    if(u.utraptype == TT_PIT)
  1656. X        verbalize("Be careful, %s, or you might fall through the floor.",
  1657. X        flags.female ? "madam" : "sir");
  1658. X    else
  1659. X        verbalize("%s, do not damage the floor here!",
  1660. X            flags.female ? "Madam" : "Sir");
  1661. X    if (pl_character[0] == 'K') adjalign(-sgn(u.ualign.type));
  1662. X    } else if(!um_dist(shkp->mx, shkp->my, 5) &&
  1663. X        !shkp->msleep && shkp->mcanmove &&
  1664. X        (ESHK(shkp)->billct || ESHK(shkp)->debit)) {
  1665. X        register struct obj *obj, *obj2;
  1666. X
  1667. X        if (distu(shkp->mx, shkp->my) > 2) {
  1668. X        mnexto(shkp);
  1669. X        /* for some reason the shopkeeper can't come next to you */
  1670. X        if (distu(shkp->mx, shkp->my) > 2) {
  1671. X            pline("%s curses you in anger and frustration!",
  1672. X                    shkname(shkp));
  1673. X            rile_shk(shkp);
  1674. X            return;
  1675. X        } else pline("%s leaps, and grabs your backpack!",
  1676. X                    shkname(shkp));
  1677. X        } else pline("%s grabs your backpack!", shkname(shkp));
  1678. X
  1679. X        for(obj = invent; obj; obj = obj2) {
  1680. X        obj2 = obj->nobj;
  1681. X        if(obj->owornmask) continue;
  1682. X#ifdef WALKIES
  1683. X        if(obj->otyp == LEASH && obj->leashmon) continue;
  1684. X#endif
  1685. X        freeinv(obj);
  1686. X        obj->nobj = shkp->minvent;
  1687. X        shkp->minvent = obj;
  1688. X        subfrombill(obj, shkp);
  1689. X        }
  1690. X    }
  1691. X}
  1692. X
  1693. X#ifdef KOPS
  1694. XSTATIC_OVL void
  1695. Xmakekops(mm)        /* returns the number of (all types of) Kops  made */
  1696. Xcoord *mm;
  1697. X{
  1698. X    register int cnt = depth(&u.uz) + rnd(5);
  1699. X    register int scnt = (cnt / 3) + 1;    /* at least one sarge */
  1700. X    register int lcnt = (cnt / 6);        /* maybe a lieutenant */
  1701. X    register int kcnt = (cnt / 9);        /* and maybe a kaptain */
  1702. X
  1703. X    if (!(mons[PM_KEYSTONE_KOP].geno & G_EXTINCT)) {
  1704. X        while(cnt--) {
  1705. X        if (enexto(mm, mm->x, mm->y, &mons[PM_KEYSTONE_KOP]))
  1706. X            (void) makemon(&mons[PM_KEYSTONE_KOP], mm->x, mm->y);
  1707. X        }
  1708. X    }
  1709. X    if (!(mons[PM_KOP_SERGEANT].geno & G_EXTINCT)) {
  1710. X        while(scnt--) {
  1711. X        if (enexto(mm, mm->x, mm->y, &mons[PM_KOP_SERGEANT]))
  1712. X            (void) makemon(&mons[PM_KOP_SERGEANT], mm->x, mm->y);
  1713. X        }
  1714. X    }
  1715. X    if (!(mons[PM_KOP_LIEUTENANT].geno & G_EXTINCT)) {
  1716. X        while(lcnt--) {
  1717. X        if (enexto(mm, mm->x, mm->y, &mons[PM_KOP_LIEUTENANT]))
  1718. X            (void) makemon(&mons[PM_KOP_LIEUTENANT], mm->x, mm->y);
  1719. X        }
  1720. X    }
  1721. X    if (!(mons[PM_KOP_KAPTAIN].geno & G_EXTINCT)) {
  1722. X        while(kcnt--) {
  1723. X        if (enexto(mm, mm->x, mm->y, &mons[PM_KOP_KAPTAIN]))
  1724. X            (void) makemon(&mons[PM_KOP_KAPTAIN], mm->x, mm->y);
  1725. X        }
  1726. X    }
  1727. X}
  1728. X#endif    /* KOPS */
  1729. X
  1730. Xvoid
  1731. Xpay_for_damage(dmgstr)
  1732. Xconst char *dmgstr;
  1733. X{
  1734. X    register struct monst *shkp = (struct monst *)0;
  1735. X    char shops_affected[5];
  1736. X    register boolean uinshp = (*u.ushops != '\0');
  1737. X    char qbuf[80];
  1738. X    register xchar x, y;
  1739. X    register boolean dugwall = !strcmp(dmgstr, "dig into");
  1740. X    struct damage *tmp_dam, *appear_here = 0;
  1741. X    /* any number >= (80*80)+(24*24) would do, actually */
  1742. X    long cost_of_damage = 0L;
  1743. X    unsigned int nearest_shk = 7000, nearest_damage = 7000;
  1744. X    int picks = 0;
  1745. X
  1746. X    for (tmp_dam = level.damagelist;
  1747. X         (tmp_dam && (tmp_dam->when == monstermoves));
  1748. X         tmp_dam = tmp_dam->next) {
  1749. X        char *shp;
  1750. X
  1751. X        if (!tmp_dam->cost)
  1752. X        continue;
  1753. X        cost_of_damage += tmp_dam->cost;
  1754. X        Strcpy(shops_affected,
  1755. X           in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
  1756. X        for (shp = shops_affected; *shp; shp++) {
  1757. X        struct monst *tmp_shk;
  1758. X        unsigned int shk_distance;
  1759. X
  1760. X        if (!(tmp_shk = shop_keeper(*shp)))
  1761. X            continue;
  1762. X        if (tmp_shk == shkp) {
  1763. X            unsigned int damage_distance =
  1764. X                   distu(tmp_dam->place.x, tmp_dam->place.y);
  1765. X
  1766. X            if (damage_distance < nearest_damage) {
  1767. X            nearest_damage = damage_distance;
  1768. X            appear_here = tmp_dam;
  1769. X            }
  1770. X            continue;
  1771. X        }
  1772. X        if (!inhishop(tmp_shk))
  1773. X            continue;
  1774. X        shk_distance = distu(tmp_shk->mx, tmp_shk->my);
  1775. X        if (shk_distance > nearest_shk)
  1776. X            continue;
  1777. X        if ((shk_distance == nearest_shk) && picks) {
  1778. X            if (rn2(++picks))
  1779. X            continue;
  1780. X        } else
  1781. X            picks = 1;
  1782. X        shkp = tmp_shk;
  1783. X        nearest_shk = shk_distance;
  1784. X        appear_here = tmp_dam;
  1785. X        nearest_damage = distu(tmp_dam->place.x, tmp_dam->place.y);
  1786. X        }
  1787. X    }
  1788. X
  1789. X    if (!cost_of_damage || !shkp)
  1790. X        return;
  1791. X
  1792. X    x = appear_here->place.x;
  1793. X    y = appear_here->place.y;
  1794. X
  1795. X    /* not the best introduction to the shk... */
  1796. X    (void) strncpy(ESHK(shkp)->customer,plname,PL_NSIZ);
  1797. X
  1798. X    /* if the shk is already on the war path, be sure it's all out */
  1799. X    if(ANGRY(shkp) || ESHK(shkp)->following) {
  1800. X        hot_pursuit(shkp);
  1801. X        return;
  1802. X    }
  1803. X
  1804. X    /* if the shk is not in their shop.. */
  1805. X    if(!*in_rooms(shkp->mx,shkp->my,SHOPBASE)) {
  1806. X        if(!cansee(shkp->mx, shkp->my))
  1807. X            return;
  1808. X        goto getcad;
  1809. X    }
  1810. X
  1811. X    if(uinshp) {
  1812. X        if(um_dist(shkp->mx, shkp->my, 1) &&
  1813. X            !um_dist(shkp->mx, shkp->my, 3)) {
  1814. X            pline("%s leaps towards you!", shkname(shkp));
  1815. X            mnexto(shkp);
  1816. X        }
  1817. X        if(um_dist(shkp->mx, shkp->my, 1)) goto getcad;
  1818. X    } else {
  1819. X        /*
  1820. X         * Make shkp show up at the door.  Effect:  If there is a monster
  1821. X         * in the doorway, have the hero hear the shopkeeper yell a bit,
  1822. X         * pause, then have the shopkeeper appear at the door, having
  1823. X         * yanked the hapless critter out of the way.
  1824. X         */
  1825. X        if (MON_AT(x, y)) {
  1826. X        if(flags.soundok) {
  1827. X            You("hear an angry voice:");
  1828. X            verbalize("Out of my way, scum!");
  1829. X            wait_synch();
  1830. X#if defined(UNIX) || defined(VMS)
  1831. X# if defined(SYSV) || defined(ULTRIX) || defined(VMS)
  1832. X            (void)
  1833. X# endif
  1834. X            sleep(1);
  1835. X#endif
  1836. X        }
  1837. X        }
  1838. X        (void) mnearto(shkp, x, y, TRUE);
  1839. X    }
  1840. X
  1841. X    if((um_dist(x, y, 1) && !uinshp) ||
  1842. X            (u.ugold + ESHK(shkp)->credit) < cost_of_damage
  1843. X                || !rn2(50)) {
  1844. X        if(um_dist(x, y, 1) && !uinshp) {
  1845. X            pline("%s shouts:", shkname(shkp));
  1846. X            verbalize("Who dared %s my %s?", dmgstr,
  1847. X                     dugwall ? "shop" : "door");
  1848. X        } else {
  1849. Xgetcad:
  1850. X            verbalize("How dare you %s my %s?", dmgstr,
  1851. X                     dugwall ? "shop" : "door");
  1852. X        }
  1853. X        hot_pursuit(shkp);
  1854. X        return;
  1855. X    }
  1856. X
  1857. X    if(Invis) Your("invisibility does not fool %s!", shkname(shkp));
  1858. X    Sprintf(qbuf,"\"Cad!  You did %ld zorkmids worth of damage!\"  Pay? ",
  1859. X         cost_of_damage);
  1860. X    if(yn(qbuf) != 'n') {
  1861. X        cost_of_damage = check_credit(cost_of_damage, shkp);
  1862. X        u.ugold -= cost_of_damage;
  1863. X        shkp->mgold += cost_of_damage;
  1864. X        flags.botl = 1;
  1865. X        pline("Mollified, %s accepts your restitution.",
  1866. X            shkname(shkp));
  1867. X        /* move shk back to his home loc */
  1868. X        home_shk(shkp, FALSE);
  1869. X        pacify_shk(shkp);
  1870. X    } else {
  1871. X        verbalize("Oh, yes!  You'll pay!");
  1872. X        hot_pursuit(shkp);
  1873. X        adjalign(-sgn(u.ualign.type));
  1874. X    }
  1875. X}
  1876. X
  1877. X/* called in dokick.c when we kick an object that might be in a store */
  1878. Xboolean
  1879. Xcostly_spot(x, y)
  1880. Xregister xchar x, y;
  1881. X{
  1882. X    register struct monst *shkp;
  1883. X
  1884. X    if (!level.flags.has_shop) return FALSE;
  1885. X    shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
  1886. X    if(!shkp || !inhishop(shkp)) return(FALSE);
  1887. X
  1888. X    return(inside_shop(x, y) &&
  1889. X        !(x == ESHK(shkp)->shk.x &&
  1890. X            y == ESHK(shkp)->shk.y));
  1891. X}
  1892. X
  1893. X/* called by dotalk(sounds.c) when #chatting; returns obj if location
  1894. X   contains shop goods and shopkeeper is willing & able to speak */
  1895. Xstruct obj *
  1896. Xshop_object(x, y)
  1897. Xregister xchar x, y;
  1898. X{
  1899. X    register struct obj *otmp;
  1900. X    register struct monst *shkp;
  1901. X
  1902. X    if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
  1903. X    return(struct obj *)0;
  1904. X
  1905. X    for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  1906. X    if (otmp->otyp != GOLD_PIECE)
  1907. X        break;
  1908. X    /* note: otmp might have ->no_charge set, but that's ok */
  1909. X    return (otmp && costly_spot(x, y) && NOTANGRY(shkp)
  1910. X        && !shkp->msleep && !shkp->mfrozen)
  1911. X        ? otmp : (struct obj *)0;
  1912. X}
  1913. X
  1914. X/* give price quotes for all objects linked to this one (ie, on this spot) */
  1915. Xvoid
  1916. Xprice_quote(first_obj)
  1917. Xregister struct obj *first_obj;
  1918. X{
  1919. X    register struct obj *otmp;
  1920. X    char buf[BUFSZ], price[40];
  1921. X    long cost;
  1922. X    int cnt = 0;
  1923. X    winid tmpwin;
  1924. X
  1925. X    tmpwin = create_nhwindow(NHW_MENU);
  1926. X    putstr(tmpwin, 0, "Fine goods for sale:");
  1927. X    putstr(tmpwin, 0, "");
  1928. X    for (otmp = first_obj; otmp; otmp = otmp->nexthere) {
  1929. X    if (otmp->otyp == GOLD_PIECE) {
  1930. X     /* if (otmp == first_obj)  first_obj = otmp->nexthere; */
  1931. X        continue;    /* don't quote a price on this */
  1932. X    } else if (otmp->no_charge) {
  1933. X        Strcpy(price, "no charge");
  1934. X    } else {
  1935. X        cost = get_cost(otmp, (struct monst *)0);
  1936. X        Sprintf(price, "%ld zorkmid%s%s", cost, plur(cost),
  1937. X            otmp->quan > 1L ? " each" : "");
  1938. X    }
  1939. X    Sprintf(buf, "%s, %s", doname(otmp), price);
  1940. X    putstr(tmpwin, 0, buf),  cnt++;
  1941. X    }
  1942. X    if (cnt > 1) {
  1943. X    display_nhwindow(tmpwin, TRUE);
  1944. X    } else if (cnt == 1) {
  1945. X    cost = get_cost(first_obj, (struct monst *)0);
  1946. X    pline("%s, price %ld zorkmid%s%s%s", doname(first_obj),
  1947. X        cost, plur(cost), first_obj->quan > 1L ? " each" : "",
  1948. X        shk_embellish(first_obj, cost));
  1949. X    }
  1950. X    destroy_nhwindow(tmpwin);
  1951. X}
  1952. X
  1953. Xstatic const char *
  1954. Xshk_embellish(itm, cost)
  1955. Xregister struct obj *itm;
  1956. Xlong cost;
  1957. X{
  1958. X    if (!rn2(3)) {
  1959. X    register int o, choice = rn2(5);
  1960. X    if (choice == 0) choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
  1961. X    switch (choice) {
  1962. X        case 4:
  1963. X        if (cost < 10L) break; else o = itm->oclass;
  1964. X        if (o == FOOD_CLASS) return ", gourmets' delight!";
  1965. X        if (objects[itm->otyp].oc_name_known
  1966. X            ? objects[itm->otyp].oc_magic
  1967. X            : (o == AMULET_CLASS || o == RING_CLASS   ||
  1968. X               o == WAND_CLASS   || o == POTION_CLASS ||
  1969. X               o == SCROLL_CLASS || o == SPBOOK_CLASS))
  1970. X            return ", painstakingly developed!";
  1971. X        return ", superb craftsmanship!";
  1972. X        case 3: return ", finest quality.";
  1973. X        case 2: return ", an excellent choice.";
  1974. X        case 1: return ", a real bargain.";
  1975. X       default: break;
  1976. X    }
  1977. X    } else if (itm->oartifact) {
  1978. X    return ", one of a kind!";
  1979. X    }
  1980. X    return ".";
  1981. X}
  1982. X
  1983. X#ifdef KOPS
  1984. Xstatic void
  1985. Xkops_gone(silent)
  1986. Xregister boolean silent;
  1987. X{
  1988. X    register int cnt = 0;
  1989. X    register struct monst *mtmp, *mtmp2;
  1990. X
  1991. X    /* turn off automatic resurrection of kops */
  1992. X    allow_kops = FALSE;
  1993. X
  1994. X    for(mtmp = fmon; mtmp; mtmp = mtmp2) {
  1995. X        mtmp2 = mtmp->nmon;
  1996. X        if(mtmp->data->mlet == S_KOP) {
  1997. X            mongone(mtmp);
  1998. X            cnt++;
  1999. X        }
  2000. X    }
  2001. X    if(cnt && !silent)
  2002. X        pline("The Kops (disappointed) disappear into thin air.");
  2003. X    allow_kops = TRUE;
  2004. X}
  2005. X#endif    /* KOPS */
  2006. X
  2007. Xstatic long
  2008. Xcost_per_charge(otmp)
  2009. Xregister struct obj *otmp;
  2010. X{
  2011. X    register long tmp = 0L;
  2012. X    register struct monst *shkp = shop_keeper(*u.ushops);
  2013. X
  2014. X    if(!shkp || !inhishop(shkp)) return(0L); /* insurance */
  2015. X    tmp = get_cost(otmp, shkp);
  2016. X
  2017. X    /* The idea is to make the exhaustive use of */
  2018. X    /* an unpaid item more expensive than buying */
  2019. X    /* it outright.                     */
  2020. X    if(otmp->otyp == MAGIC_LAMP) {             /* 1 */
  2021. X        tmp += tmp / 3L;
  2022. X    } else if(otmp->otyp == MAGIC_MARKER) {         /* 70 - 100 */
  2023. X        /* no way to determine in advance   */
  2024. X        /* how many charges will be wasted. */
  2025. X        /* so, arbitrarily, one half of the */
  2026. X        /* price per use.            */
  2027. X        tmp /= 2L;
  2028. X    } else if(otmp->otyp == BAG_OF_TRICKS ||     /* 1 - 20 */
  2029. X          otmp->otyp == HORN_OF_PLENTY) {
  2030. X        tmp /= 5L;
  2031. X    } else if(otmp->otyp == CRYSTAL_BALL ||         /* 1 - 5 */
  2032. X          otmp->otyp == OIL_LAMP ||         /* 1 - 10 */
  2033. X          otmp->otyp == BRASS_LANTERN ||
  2034. X         (otmp->otyp >= MAGIC_FLUTE &&
  2035. X          otmp->otyp <= DRUM_OF_EARTHQUAKE) ||     /* 5 - 9 */
  2036. X          otmp->oclass == WAND_CLASS) {         /* 3 - 11 */
  2037. X            if (otmp->spe > 1) tmp /= 4L;
  2038. X    } else if (otmp->oclass == SPBOOK_CLASS) {
  2039. X            tmp -= tmp / 5L;
  2040. X    }
  2041. X    return(tmp);
  2042. X}
  2043. X
  2044. X/* for using charges of unpaid objects */
  2045. Xvoid
  2046. Xcheck_unpaid(otmp)
  2047. Xregister struct obj *otmp;
  2048. X{
  2049. X    if(!*u.ushops) return;
  2050. X
  2051. X    if(otmp->oclass != SPBOOK_CLASS && otmp->spe <= 0) return;
  2052. X
  2053. X    if(otmp->unpaid) {
  2054. X        register long tmp = cost_per_charge(otmp);
  2055. X        register struct monst *shkp = shop_keeper(*u.ushops);
  2056. X
  2057. X        if(!shkp || !inhishop(shkp)) return;
  2058. X
  2059. X        if(otmp->oclass == SPBOOK_CLASS && tmp > 0L)
  2060. X            pline("\"%sYou owe%s %ld zorkmids.\"",
  2061. X            rn2(2) ? "This is no free library, cad!  " : "",
  2062. X            ESHK(shkp)->debit > 0L ? " additional" : "", tmp);
  2063. X        ESHK(shkp)->debit += tmp;
  2064. X        exercise(A_WIS, TRUE);        /* you just got info */
  2065. X    }
  2066. X}
  2067. X
  2068. Xvoid
  2069. Xcostly_gold(x, y, amount)
  2070. Xregister xchar x, y;
  2071. Xregister long amount;
  2072. X{
  2073. X    register long delta;
  2074. X    register struct monst *shkp;
  2075. X    register struct eshk *eshkp;
  2076. X
  2077. X    if(!costly_spot(x, y)) return;
  2078. X    /* shkp now guaranteed to exist by costly_spot() */
  2079. X    shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
  2080. X
  2081. X    eshkp = ESHK(shkp);
  2082. X    if(eshkp->credit >= amount) {
  2083. X        if(eshkp->credit > amount)
  2084. X        Your("credit is reduced by %ld zorkmid%s.",
  2085. X                    amount, plur(amount));
  2086. X        else Your("credit is erased.");
  2087. X        eshkp->credit -= amount;
  2088. X    } else {
  2089. X        delta = amount - eshkp->credit;
  2090. X        if(eshkp->credit)
  2091. X        Your("credit is erased.");
  2092. X        if(eshkp->debit)
  2093. X        Your("debt increases by %ld zorkmid%s.",
  2094. X                    delta, plur(delta));
  2095. X        else You("owe %s %ld zorkmid%s.",
  2096. X                shkname(shkp), delta, plur(delta));
  2097. X        eshkp->debit += delta;
  2098. X        eshkp->loan += delta;
  2099. X        eshkp->credit = 0L;
  2100. X    }
  2101. X}
  2102. X
  2103. X/* used in domove to block diagonal shop-exit */
  2104. X/* x,y should always be a door */
  2105. Xboolean
  2106. Xblock_door(x,y)
  2107. Xregister xchar x, y;
  2108. X{
  2109. X    register int roomno = *in_rooms(x, y, SHOPBASE);
  2110. X    register struct monst *shkp;
  2111. X
  2112. X    if(roomno < 0 || !IS_SHOP(roomno)) return(FALSE);
  2113. X    if(!IS_DOOR(levl[x][y].typ)) return(FALSE);
  2114. X    if(roomno != *u.ushops) return(FALSE);
  2115. X
  2116. X    if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp))
  2117. X        return(FALSE);
  2118. X
  2119. X    if(shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y
  2120. X        /* Actually, the shk should be made to block _any_
  2121. X         * door, including a door the player digs, if the
  2122. X         * shk is within a 'jumping' distance.
  2123. X         */
  2124. X        && ESHK(shkp)->shd.x == x && ESHK(shkp)->shd.y == y
  2125. X        && shkp->mcanmove && !shkp->msleep
  2126. X        && (ESHK(shkp)->debit || ESHK(shkp)->billct ||
  2127. X        ESHK(shkp)->robbed)) {
  2128. X        pline("%s%s blocks your way!", shkname(shkp),
  2129. X                Invis ? " senses your motion and" : "");
  2130. X        return(TRUE);
  2131. X    }
  2132. X    return(FALSE);
  2133. X}
  2134. X
  2135. X/* used in domove to block diagonal shop-entry */
  2136. X/* u.ux, u.uy should always be a door */
  2137. Xboolean
  2138. Xblock_entry(x,y)
  2139. Xregister xchar x, y;
  2140. X{
  2141. X    register xchar sx, sy;
  2142. X    register int roomno;
  2143. X    register struct monst *shkp;
  2144. X
  2145. X    if(!(IS_DOOR(levl[u.ux][u.uy].typ) &&
  2146. X        levl[u.ux][u.uy].doormask == D_BROKEN)) return(FALSE);
  2147. X
  2148. X    roomno = *in_rooms(x, y, SHOPBASE);
  2149. X    if(roomno < 0 || !IS_SHOP(roomno)) return(FALSE);
  2150. X    if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp))
  2151. X        return(FALSE);
  2152. X
  2153. X    if(ESHK(shkp)->shd.x != u.ux || ESHK(shkp)->shd.y != u.uy)
  2154. X        return(FALSE);
  2155. X
  2156. X    sx = ESHK(shkp)->shk.x;
  2157. X    sy = ESHK(shkp)->shk.y;
  2158. X
  2159. X    if(shkp->mx == sx && shkp->my == sy
  2160. X        && shkp->mcanmove && !shkp->msleep
  2161. X        && (x == sx-1 || x == sx+1 || y == sy-1 || y == sy+1)
  2162. X        && (Invis || carrying(PICK_AXE))
  2163. X      ) {
  2164. X        pline("%s%s blocks your way!", shkname(shkp),
  2165. X                Invis ? " senses your motion and" : "");
  2166. X        return(TRUE);
  2167. X    }
  2168. X    return(FALSE);
  2169. X}
  2170. X
  2171. X#endif /* OVLB */
  2172. X
  2173. X/*shk.c*/
  2174. END_OF_FILE
  2175. if test 41942 -ne `wc -c <'src/shk.c2'`; then
  2176.     echo shar: \"'src/shk.c2'\" unpacked with wrong size!
  2177. fi
  2178. # end of 'src/shk.c2'
  2179. fi
  2180. echo shar: End of archive 33 \(of 108\).
  2181. cp /dev/null ark33isdone
  2182. MISSING=""
  2183. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2184. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2185. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2186. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2187. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2188. 101 102 103 104 105 106 107 108 ; do
  2189.     if test ! -f ark${I}isdone ; then
  2190.     MISSING="${MISSING} ${I}"
  2191.     fi
  2192. done
  2193. if test "${MISSING}" = "" ; then
  2194.     echo You have unpacked all 108 archives.
  2195.     echo "Now execute 'rebuild.sh'"
  2196.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2197. else
  2198.     echo You still need to unpack the following archives:
  2199.     echo "        " ${MISSING}
  2200. fi
  2201. ##  End of shell archive.
  2202. exit 0
  2203.