home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume7 / nethack3 / part07 < prev    next >
Internet Message Format  |  1989-07-31  |  56KB

  1. Path: uunet!zephyr.ens.tek.com!tektronix!tekgen!tekred!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v07i062:  NetHack3 -  display oriented dungeons & dragons (Ver. 3.0), Part07/38
  5. Message-ID: <4315@tekred.CNA.TEK.COM>
  6. Date: 24 Jul 89 05:00:38 GMT
  7. Sender: nobody@tekred.CNA.TEK.COM
  8. Lines: 2123
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
  12. Posting-number: Volume 7, Issue 62
  13. Archive-name: NetHack3/Part07
  14.  
  15.  
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 7 (of 38)."
  24. # Contents:  src/pickup.c src/shk.c
  25. # Wrapped by billr@saab on Sun Jul 23 21:32:50 1989
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'src/pickup.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'src/pickup.c'\"
  29. else
  30. echo shar: Extracting \"'src/pickup.c'\" \(14035 characters\)
  31. sed "s/^X//" >'src/pickup.c' <<'END_OF_FILE'
  32. X/*    SCCS Id: @(#)pickup.c    3.0    88/07/12
  33. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  34. X/* NetHack may be freely redistributed.  See license for details. */
  35. X
  36. X/*
  37. X *    Contains code for picking objects up, and container use.
  38. X */
  39. X
  40. X#include    "hack.h"
  41. X
  42. Xvoid explode_bag();
  43. X
  44. Xvoid
  45. Xpickup(all)
  46. Xint all;
  47. X{
  48. X    register struct gold *gold = g_at(u.ux, u.uy);
  49. X    register struct obj *obj, *obj2;
  50. X    register int wt;
  51. X    char buf[BUFSZ];
  52. X    register char *ip;
  53. X    register char sym;
  54. X    register int oletct = 0, iletct = 0;
  55. X    boolean all_of_a_type = FALSE, selective = FALSE;
  56. X    char olets[20], ilets[20];
  57. X    struct obj dummygold;
  58. X
  59. X    dummygold.ox = u.ux;
  60. X    dummygold.oy = u.uy;
  61. X    dummygold.olet = GOLD_SYM;
  62. X    dummygold.nobj = fobj;
  63. X    dummygold.cobj = 0;
  64. X
  65. X    if(Levitation) return;
  66. X    if (all && !flags.pickup) {
  67. X        int ct = 0;
  68. X
  69. X        for (obj = fobj; obj; obj = obj->nobj)
  70. X            if(obj->ox == u.ux && obj->oy == u.uy)
  71. X                if(!obj->cobj)
  72. X                if (obj != uchain)
  73. X                    ct++;
  74. X
  75. X        /* Stop on a zorkmid */
  76. X        if (gold) ct++;
  77. X
  78. X        /* If there are objects here, take a look.
  79. X         */
  80. X        if (ct) {
  81. X            if (flags.run)
  82. X                nomul(0);
  83. X            nscr();
  84. X            if (ct < 5)
  85. X                (void) dolook();
  86. X            else {
  87. X                read_engr_at(u.ux,u.uy);
  88. X                pline("There are several objects here.");
  89. X            }
  90. X        } else read_engr_at(u.ux,u.uy);
  91. X        return;
  92. X    }
  93. X
  94. X    /* check for more than one object */
  95. X    if(!all) {
  96. X        register int ct = 0;
  97. X
  98. X        if (gold) ct++;
  99. X        for(obj = fobj; obj; obj = obj->nobj)
  100. X            if(obj->ox == u.ux && obj->oy == u.uy)
  101. X            if(!obj->cobj) ct++;
  102. X        if(ct < 2)
  103. X            all++;
  104. X        else
  105. X            pline("There are several objects here.");
  106. X    }
  107. X
  108. X    /* added by GAN 10/24/86 to allow selective picking up */
  109. X    if(!all)  {
  110. X        register struct obj *otmp = fobj;
  111. X
  112. X        ilets[iletct] = 0;
  113. X        if(gold) {
  114. X            ilets[iletct++] = GOLD_SYM;
  115. X            ilets[iletct] = 0;
  116. X        }
  117. X        while(otmp) {
  118. X            if(!index(ilets, otmp->olet) && !otmp->cobj &&
  119. X               otmp->ox == u.ux && otmp->oy == u.uy)  {
  120. X                ilets[iletct++] = otmp->olet;
  121. X                ilets[iletct] = 0;
  122. X            }
  123. X            otmp = otmp->nobj;
  124. X        }
  125. X        if(iletct == 1)
  126. X            Strcpy(buf,ilets);
  127. X        else  {
  128. X            ilets[iletct++] = ' ';
  129. X            ilets[iletct++] = 'a';
  130. X            ilets[iletct++] = 'A';
  131. X            ilets[iletct] = 0;
  132. X
  133. X            pline("What kinds of thing do you want to pick up? [%s] ", ilets);
  134. X            getlin(buf);
  135. X            if(buf[0] == '\033') {
  136. X                clrlin();
  137. X                return;
  138. X            }
  139. X            else if(!buf[0]) selective = TRUE;
  140. X        }
  141. X        ip = buf;
  142. X        olets[0] = 0;
  143. X        while(sym = *ip++){
  144. X            /* new A function (selective all) added by
  145. X             * GAN 01/09/87
  146. X             */
  147. X            if(sym == ' ') continue;
  148. X            if(sym == 'A') selective = TRUE;
  149. X            else if(sym == 'a') all_of_a_type = TRUE;
  150. X            else if(index(ilets, sym)){
  151. X                if(!index(olets, sym)){
  152. X                    olets[oletct++] = sym;
  153. X                    olets[oletct] = 0;
  154. X                }
  155. X            }
  156. X            else pline("There are no %c's here.", sym);
  157. X        }
  158. X    }
  159. X    if(all_of_a_type && !olets[0]) all = TRUE;
  160. X
  161. X    for(obj = (gold ? &dummygold : fobj); obj; obj = obj2) {
  162. X        obj2 = obj->nobj;   /* perhaps obj will be picked up */
  163. X        if(!obj->cobj && obj->ox == u.ux && obj->oy == u.uy) {
  164. X        if(flags.run) nomul(0);
  165. X
  166. X        if(!all)  {
  167. X            char c;
  168. X
  169. X            if(!selective && !index(olets,obj->olet)) continue;
  170. X
  171. X            if (!all_of_a_type) {
  172. X                if (obj == &dummygold)
  173. X                    pline("Pick up %ld gold piece%s? ",
  174. X                        gold->amount, plur(gold->amount));
  175. X                else pline("Pick up %s? ", doname(obj));
  176. X                if((c = ynaq()) == 'q') return;
  177. X                if(c == 'n') continue;
  178. X                if(c == 'a') {
  179. X                    all_of_a_type = TRUE;
  180. X                    if (selective) {
  181. X                        selective = FALSE;
  182. X                        olets[0] = obj->olet;
  183. X                        olets[1] = 0;
  184. X                        /* oletct = 1; */
  185. X                    }
  186. X                }
  187. X            }
  188. X        }
  189. X
  190. X        if(obj == &dummygold) {
  191. X            int iw = inv_weight();
  192. X            long gold_capacity;
  193. X
  194. X#ifndef lint /* long/int conversion */
  195. X            iw -= (int)((u.ugold + 500)/1000);
  196. X#endif
  197. X            gold_capacity = ((-iw) * 1000L) - 500 + 999 - u.ugold;
  198. X            if (gold_capacity <= 0L) {
  199. X     pline("There %s %ld gold piece%s here, but you cannot carry any more.",
  200. X                (gold->amount == 1) ? "is" : "are",
  201. X                gold->amount, plur(gold->amount));
  202. X            continue;
  203. X            }
  204. X            if (gold_capacity >= gold->amount) {
  205. X            pline("%ld gold piece%s.",
  206. X                gold->amount, plur(gold->amount));
  207. X            u.ugold += gold->amount;
  208. X            freegold(gold);
  209. X            if(Invisible) newsym(u.ux,u.uy);
  210. X            } else {
  211. X    pline("You can only carry %s of the %ld gold pieces lying here.",
  212. X                gold_capacity == 1L ? "one" : "some", gold->amount);
  213. X            pline("%ld gold piece%s.",
  214. X                 gold_capacity, plur(gold_capacity));
  215. X            u.ugold += gold_capacity;
  216. X            gold->amount -= gold_capacity;
  217. X            }
  218. X            flags.botl = 1;
  219. X            if(flags.run) nomul(0);
  220. X            continue;
  221. X        }
  222. X
  223. X        if((obj->otyp == CORPSE && obj->corpsenm == PM_COCKATRICE) &&
  224. X           !uarmg
  225. X#ifdef POLYSELF
  226. X            && !resists_ston(uasmon)
  227. X#endif
  228. X                        ) {
  229. X            pline("Touching the dead cockatrice is a fatal mistake.");
  230. X            You("turn to stone.");
  231. X            You("die...");
  232. X            killer = "cockatrice cadaver";
  233. X            done("stoned");
  234. X        }
  235. X
  236. X        if(obj->otyp == SCR_SCARE_MONSTER){
  237. X          if(!obj->spe) obj->spe = 1;
  238. X          else {
  239. X            pline("The scroll turns to dust as you pick it up.");
  240. X            if(!(objects[SCR_SCARE_MONSTER].oc_name_known) &&
  241. X               !(objects[SCR_SCARE_MONSTER].oc_uname))
  242. X                docall(obj);
  243. X            delobj(obj);
  244. X            continue;
  245. X          }
  246. X        }
  247. X
  248. X        /* do not pick up uchain */
  249. X        if(obj == uchain)
  250. X            continue;
  251. X
  252. X        wt = inv_weight() + obj->owt;
  253. X        if (obj->otyp == LOADSTONE)
  254. X            goto lift_some; /* pick it up even if too heavy */
  255. X#ifdef POLYSELF
  256. X        if (obj->otyp == BOULDER && throws_rocks(uasmon)) {
  257. X            wt = inv_weight();
  258. X            goto lift_some;
  259. X        }
  260. X#endif
  261. X        if(wt > 0) {
  262. X            if(obj->quan > 1) {
  263. X                /* see how many we can lift */
  264. X                int savequan = obj->quan;
  265. X                int iw = inv_weight();
  266. X                int qq;
  267. X                for(qq = 1; qq < savequan; qq++){
  268. X                    obj->quan = qq;
  269. X                    if(iw + weight(obj) > 0)
  270. X                        break;
  271. X                }
  272. X                obj->quan = savequan;
  273. X                qq--;
  274. X                /* we can carry qq of them */
  275. X                if(!qq) goto too_heavy;
  276. X            You("can only carry %s of the %s lying here.",
  277. X                    (qq == 1) ? "one" : "some",
  278. X                    doname(obj));
  279. X                {
  280. X                register struct obj *obj3;
  281. X
  282. X                obj3 = splitobj(obj, qq);
  283. X                if(obj3->otyp == SCR_SCARE_MONSTER)
  284. X                    if(obj3->spe) obj->spe = 0;
  285. X                }
  286. X                goto lift_some;
  287. X            }
  288. X        too_heavy:
  289. X            pline("There %s %s here, but %s.",
  290. X                (obj->quan == 1) ? "is" : "are",
  291. X                doname(obj),
  292. X                !invent ? "it is too heavy for you to lift"
  293. X                    : "you cannot carry any more");
  294. X                if(obj->otyp == SCR_SCARE_MONSTER)
  295. X                    if(obj->spe) obj->spe = 0;
  296. X            break;
  297. X        }
  298. X    lift_some:
  299. X        if(inv_cnt() >= 52) {
  300. X            Your("knapsack cannot accommodate any more items.");
  301. X                if(obj->otyp == SCR_SCARE_MONSTER)
  302. X                    if(obj->spe) obj->spe = 0;
  303. X            break;
  304. X        }
  305. X        freeobj(obj);
  306. X        if(Invisible) newsym(u.ux,u.uy);
  307. X        addtobill(obj, TRUE);       /* sets obj->unpaid if necessary */
  308. X        if(wt > -5) You("have a little trouble lifting");
  309. X        { int pickquan = obj->quan;
  310. X          int mergquan;
  311. X        if(!Blind) obj->dknown = 1;
  312. X        obj = addinv(obj);    /* might merge it with other objects */
  313. X          mergquan = obj->quan;
  314. X          obj->quan = pickquan; /* to fool prinv() */
  315. X        prinv(obj);
  316. X          obj->quan = mergquan;
  317. X        }
  318. X        }
  319. X    }
  320. X    set_omask(u.ux, u.uy);
  321. X}
  322. X
  323. Xint
  324. Xdoloot() {    /* loot a container on the floor. */
  325. X
  326. X    register struct obj *cobj;
  327. X    register int c;
  328. X
  329. X    if (Levitation) {
  330. X        pline("You cannot reach the floor.");
  331. X        return(0);
  332. X    }
  333. X    if(levl[u.ux][u.uy].omask)
  334. X    for(cobj = fobj; cobj; cobj = cobj->nobj) {
  335. X
  336. X        if(cobj->ox == u.ux && cobj->oy == u.uy)
  337. X        if(Is_container(cobj)) {
  338. X
  339. X            pline("There is %s here, loot it? ", doname(cobj));
  340. X            c = ynq();
  341. X            if(c == 'q') return 0;
  342. X            if(c == 'n') continue;
  343. X
  344. X            if(cobj->olocked) {
  345. X
  346. X            pline("Hmmm, it seems to be locked.");
  347. X            continue;
  348. X            }
  349. X            if(cobj->otyp == BAG_OF_TRICKS) {
  350. X
  351. X            You("carefully open the bag...");
  352. X            pline("It develops a huge set of teeth and bites you!");
  353. X            losehp(rnd(10), "carnivorous bag");
  354. X            makeknown(BAG_OF_TRICKS);
  355. X            continue;
  356. X            }
  357. X
  358. X            You("carefully open the %s...", xname(cobj));
  359. X            if(cobj->otrapped) chest_trap(cobj, FINGER);
  360. X
  361. X            use_container(cobj, 0);
  362. X        }
  363. X    }
  364. X    return 0;
  365. X}
  366. X
  367. Xstatic
  368. Xstruct obj *current_container;    /* a local variable of use_container, to be
  369. X                used by its local procedures in/ck_container */
  370. X#define Icebox (current_container->otyp == ICE_BOX)
  371. Xint baggone;    /* used in askchain so bag isn't used after explosion */
  372. X
  373. Xvoid
  374. Xinc_cwt(cobj, obj)
  375. Xregister struct obj *cobj, *obj;
  376. X{
  377. X    if (cobj->otyp == BAG_OF_HOLDING)
  378. X        cobj->owt += (obj->owt/2 + 1);
  379. X    else    cobj->owt += obj->owt;
  380. X}
  381. X
  382. Xstatic int
  383. Xin_container(obj)
  384. Xregister struct obj *obj;
  385. X{
  386. X    if(obj == uball || obj == uchain) {
  387. X        You("must be kidding.");
  388. X        return(0);
  389. X    }
  390. X    if(obj == current_container) {
  391. X        pline("That would be an interesting topological exercise.");
  392. X        return(0);
  393. X    }
  394. X    if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) {
  395. X        You("cannot %s something you are wearing.",
  396. X            Icebox ? "refrigerate" : "stash");
  397. X        return(0);
  398. X    }
  399. X    if((obj->otyp == LOADSTONE) && obj->cursed) {
  400. X        obj->bknown = 1;
  401. X        pline("The stone%s won't leave your person.",
  402. X            obj->quan==1 ? "" : "s");
  403. X        return(0);
  404. X    }
  405. X    /* Prohibit Amulets in containers; if you allow it, monsters can't
  406. X     * steal them.  It also becomes a pain to check to see if someone
  407. X     * has the Amulet.
  408. X     */
  409. X    if(obj->otyp == AMULET_OF_YENDOR && !obj->spe) {
  410. X        pline("The Amulet of Yendor cannot be confined in such trappings.");
  411. X        return(0);
  412. X    }
  413. X    /* no nested containers - they do not save/restore properly. */
  414. X    /* magic bag -> magic bag will self destruct later on. */
  415. X    if(Is_container(obj) && Is_container(current_container) &&
  416. X        (!Is_mbag(obj) || !Is_mbag(current_container))) {
  417. X        pline("It won't go in.");
  418. X        return(1);    /* be careful! */
  419. X    }
  420. X    if(obj == uwep) {
  421. X        if(welded(obj)) {
  422. X            weldmsg(obj, FALSE);
  423. X            return(0);
  424. X        }
  425. X        setuwep((struct obj *) 0);
  426. X        if (uwep) return(0); /* unwielded, died, rewielded */
  427. X    }
  428. X#ifdef WALKIES
  429. X    if(obj->otyp == LEASH && obj->leashmon != 0) {
  430. X        pline("It is attached to your pet.");
  431. X        return(0);
  432. X    }
  433. X#endif
  434. X    inc_cwt(current_container, obj);
  435. X    freeinv(obj);
  436. X
  437. X    obj->cobj = current_container;
  438. X    obj->nobj = fcobj;
  439. X    fcobj = obj;
  440. X
  441. X    if(Icebox)    obj->age = moves - obj->age;    /* actual age */
  442. X
  443. X    else if(Is_mbag(obj->cobj) &&
  444. X        (Is_mbag(obj) ||
  445. X         (obj->otyp == WAN_CANCELLATION && (obj->spe > 0)) )) {
  446. X        explode_bag(obj);
  447. X        You("are blasted by a magical explosion!");
  448. X        losehp(d(6,6),"magical explosion");
  449. X        baggone = 1;
  450. X    }
  451. X    return(1);
  452. X}
  453. X
  454. Xstatic int
  455. Xck_container(obj)
  456. Xregister struct obj *obj;
  457. X{
  458. X    return(obj->cobj == current_container);
  459. X}
  460. X
  461. Xstatic int
  462. Xck_bag()
  463. X{
  464. X    return(!baggone);
  465. X}
  466. X
  467. Xstatic int
  468. Xout_container(obj)
  469. Xregister struct obj *obj;
  470. X{
  471. X    register struct obj *otmp;
  472. X
  473. X    if(inv_cnt() >= 52) {
  474. X        pline("You have no room to hold anything else.");
  475. X        return(0);
  476. X    }
  477. X    if(obj == fcobj) fcobj = fcobj->nobj;
  478. X    else {
  479. X        for(otmp = fcobj; otmp->nobj != obj; otmp = otmp->nobj)
  480. X            if(!otmp->nobj) panic("out_container");
  481. X        otmp->nobj = obj->nobj;
  482. X    }
  483. X    dec_cwt(current_container, obj);
  484. X    obj->cobj = (struct obj *) 0;
  485. X
  486. X    if (Icebox)
  487. X        obj->age = moves - obj->age;    /* simulated point of time */
  488. X
  489. X    (void) addinv(obj);
  490. X    return 0;
  491. X}
  492. X
  493. Xvoid
  494. Xget_all_from_box() {
  495. X    register struct obj *otmp, *cobj, *ootmp, *nxobj;
  496. X
  497. X    for(otmp = invent; otmp; otmp = otmp->nobj) {
  498. X        cobj = otmp;
  499. X        if(Is_container(otmp))
  500. X        for(ootmp=fcobj,nxobj=(fcobj ? fcobj->nobj : 0); ootmp;
  501. X                ootmp=nxobj,nxobj=(ootmp ? ootmp->nobj : 0) )
  502. X            if(ootmp->cobj == cobj)
  503. X            (void)out_container(ootmp);
  504. X    }
  505. X    return;
  506. X}
  507. X
  508. X/* for getobj: 0: allow cnt; #: allow all types; %: expect food */
  509. Xstatic const char frozen_food[] = { '0', '#', FOOD_SYM, 0 };
  510. X
  511. Xvoid
  512. Xuse_container(obj, held)
  513. Xregister struct obj *obj;
  514. Xregister int held;
  515. X{
  516. X    register int cnt = 0;
  517. X    register struct obj *otmp;
  518. X    register struct obj *backobj;
  519. X
  520. X    current_container = obj;    /* for use by in/out_container */
  521. X    if(current_container->olocked) {
  522. X        pline("The %s seems to be locked.", xname(current_container));
  523. X        return;
  524. X    }
  525. X    for(otmp = fcobj, backobj = (struct obj *) 0; otmp;
  526. X        backobj = otmp, otmp = otmp->nobj)
  527. X        if(otmp->cobj == obj)
  528. X            if(Is_mbag(obj) && obj->cursed && !rn2(13)) {
  529. X            if (otmp->known)
  530. X                pline("The %s to have vanished!",
  531. X                            aobjnam(otmp,"seem"));
  532. X            else You("%s %s disappear.",
  533. X                Blind ? "notice" : "see",
  534. X                doname(otmp));
  535. X            if(!backobj) {
  536. X                fcobj = otmp->nobj;
  537. X                dec_cwt(current_container, otmp);
  538. X                obfree(otmp, (struct obj *) 0);
  539. X                otmp = fcobj;
  540. X            } else {
  541. X                backobj->nobj = otmp->nobj;
  542. X                dec_cwt(current_container, otmp);
  543. X                obfree(otmp, (struct obj *) 0);
  544. X                otmp = backobj->nobj;
  545. X            }
  546. X            if (!otmp) break;
  547. X            if(otmp->cobj == obj) cnt++;
  548. X            } else cnt++;
  549. X    if(!cnt)
  550. X        pline("%s %s is empty.", (held) ? "Your" : "The", xname(obj));
  551. X    else if (inv_cnt() < 52) {
  552. X        pline("Do you want to take something out of the %s? ",
  553. X          xname(obj));
  554. X        if(yn() != 'n')
  555. X        if(askchain(fcobj, FALSE, NULL, 0, out_container, ck_container, 0, "nodot"))
  556. X            return;
  557. X    }
  558. X    if(!invent) return;
  559. X    pline("Do you wish to put something in? ");
  560. X    if(yn() != 'y') return;
  561. X    if (Icebox && current_container->dknown) {
  562. X        otmp = getobj(frozen_food, "put in");
  563. X        if(!otmp || !in_container(otmp))
  564. X            flags.move = multi = 0;
  565. X    } else {
  566. X        baggone = 0; /* might be set by in_container */
  567. X        if(askchain(invent, TRUE, NULL, 0, in_container, ck_bag, 0, "nodot"))
  568. X          return;
  569. X    }
  570. X    return;
  571. X}
  572. X
  573. Xvoid
  574. Xdelete_contents(obj)
  575. Xregister struct obj *obj;
  576. X{
  577. X    register struct obj *otmp, *notmp;
  578. X
  579. X    while (fcobj && fcobj->cobj == obj) {
  580. X        otmp = fcobj;
  581. X        fcobj = fcobj->nobj;
  582. X        obfree(otmp,(struct obj *)0);
  583. X    }
  584. X    if (fcobj) {
  585. X        otmp = fcobj;
  586. X        while(otmp->nobj)
  587. X            if (otmp->nobj->cobj == obj) {
  588. X                notmp = otmp->nobj;
  589. X                otmp->nobj = notmp->nobj;
  590. X                obfree(notmp,(struct obj *)0);
  591. X            } else
  592. X                otmp = otmp->nobj;
  593. X    }
  594. X}
  595. X
  596. Xvoid
  597. Xexplode_bag(obj)
  598. Xstruct obj *obj;
  599. X{
  600. X    struct obj *otmp, *cobj;
  601. X
  602. X    cobj = obj->cobj;
  603. X    delete_contents(cobj);
  604. X
  605. X    for (otmp = invent; otmp; otmp = otmp->nobj)
  606. X        if (otmp == cobj) break;
  607. X
  608. X    if (otmp) {
  609. X        You("see your %s blow apart!", xname(otmp));
  610. X        useup(otmp);
  611. X        /*return(0);*/
  612. X    } else    panic("explode_bag: bag not in invent.");
  613. X}
  614. X
  615. Xvoid
  616. Xdec_cwt(cobj, obj)
  617. Xregister struct obj *cobj, *obj;
  618. X{
  619. X    if (Is_mbag(cobj))
  620. X        cobj->owt -= (obj->owt/2 + 1);
  621. X    else    cobj->owt -= obj->owt;
  622. X
  623. X    if(cobj->owt < objects[cobj->otyp].oc_weight)
  624. X        cobj->owt = objects[cobj->otyp].oc_weight;
  625. X}
  626. END_OF_FILE
  627. if test 14035 -ne `wc -c <'src/pickup.c'`; then
  628.     echo shar: \"'src/pickup.c'\" unpacked with wrong size!
  629. fi
  630. # end of 'src/pickup.c'
  631. fi
  632. if test -f 'src/shk.c' -a "${1}" != "-c" ; then 
  633.   echo shar: Will not clobber existing file \"'src/shk.c'\"
  634. else
  635. echo shar: Extracting \"'src/shk.c'\" \(37207 characters\)
  636. sed "s/^X//" >'src/shk.c' <<'END_OF_FILE'
  637. X/*    SCCS Id: @(#)shk.c    3.0    89/02/10
  638. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  639. X/* NetHack may be freely redistributed.  See license for details. */
  640. X
  641. X/* block some unused #defines to avoid overloading some cpp's */
  642. X#define MONATTK_H
  643. X#include "hack.h"
  644. X
  645. X#include "eshk.h"
  646. X
  647. X#ifdef KOPS
  648. Xstatic int makekops();
  649. Xstatic void kops_gone();
  650. X#endif /* KOPS */
  651. X
  652. X#define    NOTANGRY(mon)    mon->mpeaceful
  653. X#define    ANGRY(mon)    !NOTANGRY(mon)
  654. X
  655. X/* Descriptor of current shopkeeper. Note that the bill need not be
  656. X   per-shopkeeper, since it is valid only when in a shop. */
  657. Xstatic struct monst *shopkeeper = 0;
  658. Xstatic struct bill_x *bill;
  659. Xstatic int shlevel = 0;    /* level of this shopkeeper */
  660. X/* struct obj *billobjs;    /* objects on bill with bp->useup */
  661. X                /* only accessed here and by save & restore */
  662. Xstatic long int total;        /* filled by addupbill() */
  663. Xstatic long int followmsg;    /* last time of follow message */
  664. Xstatic void setpaid(), findshk P((int));
  665. Xstatic int dopayobj P((struct bill_x *)), getprice P((struct obj *));
  666. Xstatic struct obj *bp_to_obj P((struct bill_x *));
  667. X
  668. X/*
  669. X    invariants: obj->unpaid iff onbill(obj) [unless bp->useup]
  670. X        obj->quan <= bp->bquan
  671. X */
  672. X
  673. Xchar *
  674. Xshkname(mtmp)                /* called in do_name.c */
  675. Xregister struct monst *mtmp;
  676. X{
  677. X    return(ESHK(mtmp)->shknam);
  678. X}
  679. X
  680. Xvoid
  681. Xshkdead(mtmp)                /* called in mon.c */
  682. Xregister struct monst *mtmp;
  683. X{
  684. X    register struct eshk *eshk = ESHK(mtmp);
  685. X
  686. X    if(eshk->shoplevel == dlevel)
  687. X        rooms[eshk->shoproom].rtype = OROOM;
  688. X    if(mtmp == shopkeeper) {
  689. X        setpaid();
  690. X        shopkeeper = 0;
  691. X        bill = (struct bill_x *) -1000;    /* dump core when referenced */
  692. X    }
  693. X}
  694. X
  695. Xvoid
  696. Xreplshk(mtmp,mtmp2)
  697. Xregister struct monst *mtmp, *mtmp2;
  698. X{
  699. X    if(mtmp == shopkeeper) {
  700. X        shopkeeper = mtmp2;
  701. X        bill = &(ESHK(shopkeeper)->bill[0]);
  702. X    }
  703. X}
  704. X
  705. Xstatic void
  706. Xsetpaid(){    /* caller has checked that shopkeeper exists */
  707. X        /* either we paid or left the shop or he just died */
  708. X    register struct obj *obj;
  709. X    register struct monst *mtmp;
  710. X    for(obj = invent; obj; obj = obj->nobj)
  711. X        obj->unpaid = 0;
  712. X    for(obj = fobj; obj; obj = obj->nobj)
  713. X        obj->unpaid = 0;
  714. X    for(obj = fcobj; obj; obj = obj->nobj)
  715. X        obj->unpaid = 0;
  716. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  717. X        for(obj = mtmp->minvent; obj; obj = obj->nobj)
  718. X            obj->unpaid = 0;
  719. X    for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
  720. X        for(obj = mtmp->minvent; obj; obj = obj->nobj)
  721. X            obj->unpaid = 0;
  722. X    while(obj = billobjs){
  723. X        billobjs = obj->nobj;
  724. X        free((genericptr_t) obj);
  725. X    }
  726. X    if(shopkeeper) {
  727. X        ESHK(shopkeeper)->billct = 0;
  728. X        ESHK(shopkeeper)->credit = 0L;
  729. X        ESHK(shopkeeper)->debit = 0L;
  730. X    }
  731. X}
  732. X
  733. Xstatic void
  734. Xaddupbill(){    /* delivers result in total */
  735. X        /* caller has checked that shopkeeper exists */
  736. X    register int ct = ESHK(shopkeeper)->billct;
  737. X    register struct bill_x *bp = bill;
  738. X    total = 0;
  739. X    while(ct--){
  740. X        total += bp->price * bp->bquan;
  741. X        bp++;
  742. X    }
  743. X}
  744. X
  745. Xint
  746. Xinshop() {
  747. X    register int roomno = inroom(u.ux,u.uy);
  748. X
  749. X    /* Did we just leave a shop? */
  750. X    if(u.uinshop &&
  751. X        (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) {
  752. X
  753. X    /* This is part of the bugfix for shopkeepers not having their
  754. X     * bill paid.  As reported by ab@unido -dgk
  755. X     * I made this standard due to the KOPS code below. -mrs
  756. X     */
  757. X        if(shopkeeper) {
  758. X            if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->debit) {
  759. X            if(inroom(shopkeeper->mx, shopkeeper->my)
  760. X                == u.uinshop - 1)    /* ab@unido */
  761. X                You("escaped the shop without paying!");
  762. X            addupbill();
  763. X            total += ESHK(shopkeeper)->debit;
  764. X            You("stole %ld zorkmids worth of merchandise.",
  765. X                total);
  766. X            ESHK(shopkeeper)->robbed += total;
  767. X            ESHK(shopkeeper)->credit = 0L;
  768. X            ESHK(shopkeeper)->debit = 0L;
  769. X            if (pl_character[0] != 'R') /* stealing is unlawful */
  770. X                adjalign(-sgn(u.ualigntyp));
  771. X            setpaid();
  772. X            if((rooms[ESHK(shopkeeper)->shoproom].rtype == SHOPBASE)
  773. X                == (rn2(3) == 0))
  774. X                ESHK(shopkeeper)->following = 1;
  775. X#ifdef KOPS
  776. X            {   /* Keystone Kops srt@ucla */
  777. X            coord mm;
  778. X
  779. X            if (flags.soundok)
  780. X                pline("An alarm sounds throughout the dungeon!");
  781. X            if(flags.verbose) {
  782. X                if((mons[PM_KEYSTONE_KOP].geno & G_GENOD) &&
  783. X                    (mons[PM_KOP_SERGEANT].geno & G_GENOD) &&
  784. X                    (mons[PM_KOP_LIEUTENANT].geno & G_GENOD) &&
  785. X                   (mons[PM_KOP_KAPTAIN].geno & G_GENOD)) {
  786. X                if (flags.soundok)
  787. X                    pline("But no one seems to respond to it.");
  788. X                } else
  789. X                pline("The Keystone Kops are after you!");
  790. X            }
  791. X            /* Create a swarm near the staircase */
  792. X            mm.x = xdnstair;
  793. X            mm.y = ydnstair;
  794. X            (void) makekops(&mm);
  795. X            /* Create a swarm near the shopkeeper */
  796. X            mm.x = shopkeeper->mx;
  797. X            mm.y = shopkeeper->my;
  798. X            (void) makekops(&mm);
  799. X            }
  800. X#endif
  801. X            }
  802. X            shopkeeper = 0;
  803. X            shlevel = 0;
  804. X        }
  805. X        u.uinshop = 0;
  806. X    }
  807. X
  808. X    /* Did we just enter a zoo of some kind? */
  809. X    /* This counts everything except shops and vaults
  810. X       -- vault.c insists that a vault remain a VAULT */
  811. X    if(roomno >= 0) {
  812. X        register int rt = rooms[roomno].rtype;
  813. X        register struct monst *mtmp;
  814. X
  815. X        switch (rt) {
  816. X        case ZOO:
  817. X            pline("Welcome to David's treasure zoo!");
  818. X            break;
  819. X        case SWAMP:
  820. X            pline("It looks rather muddy down here.");
  821. X            break;
  822. X#ifdef THRONES
  823. X        case COURT:
  824. X            You("enter an opulent throne room!");
  825. X            break;
  826. X#endif
  827. X        case MORGUE:
  828. X            if(midnight())
  829. X            pline("Run away!  Run away!");
  830. X            else
  831. X            You("have an uncanny feeling...");
  832. X            break;
  833. X        case BEEHIVE:
  834. X            You("enter a giant beehive!");
  835. X            break;
  836. X#ifdef ARMY
  837. X        case BARRACKS:
  838. X            if(!((mons[PM_SOLDIER].geno & G_GENOD) &&
  839. X                 (mons[PM_SERGEANT].geno & G_GENOD) &&
  840. X                 (mons[PM_LIEUTENANT].geno & G_GENOD) &&
  841. X                 (mons[PM_CAPTAIN].geno & G_GENOD)))
  842. X                You("enter a military barracks!");
  843. X            else You("enter an abandoned barracks.");
  844. X            break;
  845. X#endif
  846. X#ifdef ORACLE
  847. X        case DELPHI:
  848. X            if(!(mons[PM_ORACLE].geno & G_GENOD))
  849. X                pline("\"Hello, %s, welcome to Delphi!\"", plname);
  850. X            break;
  851. X#endif
  852. X        default:
  853. X            rt = 0;
  854. X        }
  855. X
  856. X        if(rt != 0) {
  857. X            rooms[roomno].rtype = OROOM;
  858. X            if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO)
  859. X            for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  860. X                /* was if(rt != ZOO || !rn2(3)) -- why should ZOO
  861. X                   be different from COURT or MORGUE? */
  862. X                if(!Stealth && !rn2(3))
  863. X                mtmp->msleep = 0;
  864. X        }
  865. X    }
  866. X#if defined(ALTARS) && defined(THEOLOGY)
  867. X    if(roomno >= 0 && rooms[roomno].rtype == TEMPLE) {
  868. X        intemple();
  869. X    }
  870. X#endif
  871. X    /* Did we just enter a shop? */
  872. X    if(roomno >= 0 && rooms[roomno].rtype >= SHOPBASE) {
  873. X        register int rt = rooms[roomno].rtype;
  874. X
  875. X        if(shlevel != dlevel || !shopkeeper
  876. X                 || ESHK(shopkeeper)->shoproom != roomno)
  877. X        findshk(roomno);
  878. X        if(!shopkeeper) {
  879. X        rooms[roomno].rtype = OROOM;
  880. X        u.uinshop = 0;
  881. X        } else if(!u.uinshop){
  882. X        if(!ESHK(shopkeeper)->visitct ||
  883. X           strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)) {
  884. X            /* He seems to be new here */
  885. X            ESHK(shopkeeper)->visitct = 0;
  886. X            ESHK(shopkeeper)->following = 0;
  887. X            (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
  888. X            NOTANGRY(shopkeeper) = 1;
  889. X        }
  890. X        if(!ESHK(shopkeeper)->following && inhishop(shopkeeper)) {
  891. X            if(ANGRY(shopkeeper))
  892. X            pline("\"So, %s, you dare return to %s's %s?!\"",
  893. X                plname,
  894. X                shkname(shopkeeper),
  895. X                shtypes[rt - SHOPBASE].name);
  896. X            else
  897. X            if(ESHK(shopkeeper)->robbed)
  898. X            pline("\"Beware, %s!  I am upset about missing stock!\"",
  899. X                plname);
  900. X            else
  901. X            pline("\"Hello, %s!  Welcome%s to %s's %s!\"",
  902. X                plname,
  903. X                ESHK(shopkeeper)->visitct++ ? " again" : "",
  904. X                shkname(shopkeeper),
  905. X                shtypes[rt - SHOPBASE].name);
  906. X            if(carrying(PICK_AXE) != (struct obj *)0) {
  907. X            pline(NOTANGRY(shopkeeper) ?
  908. X               "\"Will you please leave your pick-axe outside?\"" :
  909. X               "\"Leave the pick-axe outside.\"");
  910. X            if(dochug(shopkeeper)) {
  911. X                u.uinshop = 0;    /* he died moving */
  912. X                return(0);
  913. X            }
  914. X            }
  915. X        }
  916. X        u.uinshop = (unsigned int)(roomno + 1);
  917. X        }
  918. X    }
  919. X    return (int)u.uinshop;
  920. X}
  921. X
  922. Xint
  923. Xinhishop(mtmp)
  924. Xregister struct monst *mtmp;
  925. X{
  926. X    return((ESHK(mtmp)->shoproom == inroom(mtmp->mx, mtmp->my) &&
  927. X        ESHK(mtmp)->shoplevel == dlevel));
  928. X}
  929. X
  930. Xstatic void
  931. Xfindshk(roomno)
  932. Xregister int roomno;
  933. X{
  934. X    register struct monst *mtmp;
  935. X
  936. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  937. X        if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
  938. X               && ESHK(mtmp)->shoplevel == dlevel) {
  939. X        shopkeeper = mtmp;
  940. X        bill = &(ESHK(shopkeeper)->bill[0]);
  941. X        shlevel = dlevel;
  942. X        if(ANGRY(shopkeeper) &&
  943. X           strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ))
  944. X            NOTANGRY(shopkeeper) = 1;
  945. X        /* billobjs = 0; -- this is wrong if we save in a shop */
  946. X        /* (and it is harmless to have too many things in billobjs) */
  947. X        return;
  948. X    }
  949. X    shopkeeper = 0;
  950. X    shlevel = 0;
  951. X    bill = (struct bill_x *) -1000;    /* dump core when referenced */
  952. X}
  953. X
  954. Xstatic struct bill_x *
  955. Xonbill(obj)
  956. Xregister struct obj *obj;
  957. X{
  958. X    register struct bill_x *bp;
  959. X    if(!shopkeeper) return (struct bill_x *)0;
  960. X    for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++)
  961. X        if(bp->bo_id == obj->o_id) {
  962. X            if(!obj->unpaid) pline("onbill: paid obj on bill?");
  963. X            return(bp);
  964. X        }
  965. X    if(obj->unpaid) pline("onbill: unpaid obj not on bill?");
  966. X    return (struct bill_x *)0;
  967. X}
  968. X
  969. X/* called with two args on merge */
  970. Xvoid
  971. Xobfree(obj, merge)
  972. Xregister struct obj *obj, *merge;
  973. X{
  974. X    register struct bill_x *bp = onbill(obj);
  975. X    register struct bill_x *bpm;
  976. X    if(bp) {
  977. X        if(!merge){
  978. X            bp->useup = 1;
  979. X            obj->unpaid = 0;    /* only for doinvbill */
  980. X            obj->nobj = billobjs;
  981. X            billobjs = obj;
  982. X            return;
  983. X        }
  984. X        bpm = onbill(merge);
  985. X        if(!bpm){
  986. X            /* this used to be a rename */
  987. X            impossible("obfree: not on bill??");
  988. X            return;
  989. X        } else {
  990. X            /* this was a merger */
  991. X            bpm->bquan += bp->bquan;
  992. X            ESHK(shopkeeper)->billct--;
  993. X            *bp = bill[ESHK(shopkeeper)->billct];
  994. X        }
  995. X    }
  996. X    free((genericptr_t) obj);
  997. X}
  998. X
  999. Xstatic long
  1000. Xcheck_credit(tmp, shkp)
  1001. Xlong tmp;
  1002. Xregister struct monst *shkp;
  1003. X{
  1004. X    long credit = ESHK(shkp)->credit;
  1005. X
  1006. X    if(credit == 0L) return(tmp);
  1007. X    if(credit >= tmp) {
  1008. X        pline("The price is deducted from your credit.");
  1009. X        ESHK(shkp)->credit -=tmp;
  1010. X        tmp = 0L;
  1011. X    } else {
  1012. X        pline("The price is partially covered by your credit.");
  1013. X        ESHK(shkp)->credit = 0L;
  1014. X        tmp -= credit;
  1015. X    }
  1016. X    return(tmp);
  1017. X}
  1018. X
  1019. Xstatic void
  1020. Xpay(tmp,shkp)
  1021. Xlong tmp;
  1022. Xregister struct monst *shkp;
  1023. X{
  1024. X    long robbed = ESHK(shkp)->robbed;
  1025. X    long balance = ((tmp <= 0) ? tmp : check_credit(tmp, shkp));
  1026. X
  1027. X    u.ugold -= balance;
  1028. X    shkp->mgold += balance;
  1029. X    flags.botl = 1;
  1030. X    if(robbed) {
  1031. X        robbed -= tmp;
  1032. X        if(robbed < 0) robbed = 0;
  1033. X        ESHK(shkp)->robbed = robbed;
  1034. X    }
  1035. X}
  1036. X
  1037. X/* return shkp to home position */
  1038. Xvoid
  1039. Xhome_shk(shkp)
  1040. Xregister struct monst *shkp;
  1041. X{
  1042. X    register xchar x = ESHK(shkp)->shk.x, y = ESHK(shkp)->shk.y;
  1043. X    if(levl[x][y].mmask)
  1044. X        mnearto(m_at(x,y), x, y, FALSE);
  1045. X    levl[shkp->mx][shkp->my].mmask = 0;
  1046. X    shkp->mx = x;
  1047. X    shkp->my = y;
  1048. X    levl[shkp->mx][shkp->my].mmask = 1;
  1049. X    unpmon(shkp);
  1050. X}
  1051. X
  1052. Xvoid
  1053. Xmake_happy_shk(shkp)
  1054. Xstruct monst *shkp;
  1055. X{
  1056. X    register boolean wasmad = ANGRY(shkp);
  1057. X
  1058. X    NOTANGRY(shkp) = 1;
  1059. X    ESHK(shkp)->following = 0;
  1060. X    ESHK(shkp)->robbed = 0;
  1061. X    if (pl_character[0] != 'R')
  1062. X        adjalign(sgn(u.ualigntyp));
  1063. X    if(!inhishop(shkp)) {
  1064. X        pline("Satisfied, %s suddenly disappears!", mon_nam(shkp));
  1065. X        if(ESHK(shkp)->shoplevel == dlevel)
  1066. X            home_shk(shkp);
  1067. X        else
  1068. X            fall_down(shkp, ESHK(shkp)->shoplevel);
  1069. X    } else if(wasmad)
  1070. X        pline("%s calms down.", Monnam(shkp));
  1071. X#ifdef KOPS
  1072. X    kops_gone();
  1073. X#endif
  1074. X}
  1075. X
  1076. Xstatic const char no_money[] = "Moreover, you have no money.";
  1077. X
  1078. Xint
  1079. Xdopay()
  1080. X{
  1081. X    long ltmp;
  1082. X    register struct bill_x *bp;
  1083. X    register struct monst *shkp;
  1084. X    int pass, tmp;
  1085. X
  1086. X    multi = 0;
  1087. X    (void) inshop();
  1088. X    for(shkp = fmon; shkp; shkp = shkp->nmon)
  1089. X        if(shkp->isshk && dist(shkp->mx,shkp->my) < 3)
  1090. X            break;
  1091. X    if(!shkp && u.uinshop && inhishop(shopkeeper))
  1092. X        shkp = shopkeeper;
  1093. X
  1094. X    if(!shkp) {
  1095. X        pline("There is nobody here to receive your payment.");
  1096. X        return(0);
  1097. X    }
  1098. X    ltmp = ESHK(shkp)->robbed;
  1099. X    if(shkp != shopkeeper && NOTANGRY(shkp)) {
  1100. X        if(!ltmp)
  1101. X            You("do not owe %s anything.", mon_nam(shkp));
  1102. X        else if(!u.ugold)
  1103. X            You("have no money.");
  1104. X        else {
  1105. X            long ugold = u.ugold;
  1106. X
  1107. X            if(ugold  > ltmp) {
  1108. X            You("give %s the %ld gold pieces %s asked for.",
  1109. X                mon_nam(shkp), ltmp,
  1110. X                ESHK(shkp)->ismale ? "he" : "she");
  1111. X            pay(ltmp, shkp);
  1112. X            } else {
  1113. X            You("give %s all your gold.", mon_nam(shkp));
  1114. X            pay(u.ugold, shkp);
  1115. X            }
  1116. X            if(ugold < ltmp/2)
  1117. X            pline("Unfortunately, %s doesn't look satisfied.",
  1118. X                ESHK(shkp)->ismale ? "he" : "she");
  1119. X            else
  1120. X            make_happy_shk(shkp);
  1121. X        }
  1122. X        return(1);
  1123. X    }
  1124. X
  1125. X    /* ltmp is still ESHK(shkp)->robbed here */
  1126. X    if(!ESHK(shkp)->billct) {
  1127. X        if(!ltmp && NOTANGRY(shkp)) {
  1128. X            You("do not owe %s anything.", mon_nam(shkp));
  1129. X            if(!u.ugold) pline(no_money);
  1130. X        } else if(ltmp) {
  1131. X            pline("%s is after blood, not money!", mon_nam(shkp));
  1132. X            if(u.ugold < ltmp/2) {
  1133. X            if(!u.ugold) pline(no_money);
  1134. X            else pline("Besides, you don't have enough to interest %s.",
  1135. X                ESHK(shkp)->ismale ? "him" : "her");
  1136. X            return(1);
  1137. X            }
  1138. X            pline("But since %s shop has been robbed recently,",
  1139. X            ESHK(shkp)->ismale ? "his" : "her");
  1140. X            pline("you %scompensate %s for %s losses.",
  1141. X            (u.ugold < ltmp) ? "partially " : "",
  1142. X            mon_nam(shkp),
  1143. X            ESHK(shkp)->ismale ? "his" : "her");
  1144. X            pay(u.ugold < ltmp ? u.ugold : ltmp, shkp);
  1145. X            make_happy_shk(shkp);
  1146. X        } else {
  1147. X            /* shopkeeper is angry, but has not been robbed --
  1148. X             * door broken, attacked, etc. */
  1149. X            pline("%s is after your hide, not your money!",
  1150. X                    mon_nam(shkp));
  1151. X            if(u.ugold < 1000) {
  1152. X            if(!u.ugold) pline(no_money);
  1153. X            else
  1154. X        pline("Besides, you don't have enough to interest %s.",
  1155. X                ESHK(shkp)->ismale ? "him" : "her");
  1156. X            return(1);
  1157. X            }
  1158. X            You("try to appease %s by giving %s 1000 gold pieces.",
  1159. X                a_monnam(shkp, "angry"),
  1160. X                ESHK(shkp)->ismale ? "him" : "her");
  1161. X            pay(1000L,shkp);
  1162. X            if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)
  1163. X                    || rn2(3))
  1164. X            make_happy_shk(shkp);
  1165. X            else
  1166. X            pline("But %s is as angry as ever.", Monnam(shkp));
  1167. X        }
  1168. X        return(1);
  1169. X    }
  1170. X    if(shkp != shopkeeper) {
  1171. X        impossible("dopay: not to shopkeeper?");
  1172. X        if(shopkeeper) setpaid();
  1173. X        return(0);
  1174. X    }
  1175. X    /* pay debt, if any, first */
  1176. X    if(ESHK(shopkeeper)->debit) {
  1177. X            You("owe %s %ld zorkmids for the use of merchandise.",
  1178. X            shkname(shopkeeper), ESHK(shopkeeper)->debit);
  1179. X            if(u.ugold + ESHK(shopkeeper)->credit < 
  1180. X                    ESHK(shopkeeper)->debit) {
  1181. X            pline("But you don't have enough gold%s.",
  1182. X            ESHK(shopkeeper)->credit ? " or credit" : "");
  1183. X            return(1);
  1184. X            } else {
  1185. X            long dtmp = ESHK(shopkeeper)->debit;
  1186. X
  1187. X            if(ESHK(shopkeeper)->credit >= dtmp) {
  1188. X            ESHK(shopkeeper)->credit -= dtmp;
  1189. X            ESHK(shopkeeper)->debit = 0L;
  1190. X                    Your("debt is covered by your credit.");
  1191. X            } else if(!ESHK(shopkeeper)->credit) {
  1192. X            u.ugold -= dtmp;
  1193. X            shopkeeper->mgold += dtmp;
  1194. X            ESHK(shopkeeper)->debit = 0L;
  1195. X            You("pay that debt.");
  1196. X            flags.botl = 1;
  1197. X            } else {
  1198. X            dtmp -= ESHK(shopkeeper)->credit;
  1199. X            ESHK(shopkeeper)->credit = 0L;
  1200. X            u.ugold -= dtmp;
  1201. X            shopkeeper->mgold += dtmp;
  1202. X            ESHK(shopkeeper)->debit = 0L;
  1203. X            pline("That debt is partially offset by your credit.");
  1204. X            You("pay the remainder.");
  1205. X            flags.botl = 1;
  1206. X            }
  1207. X        }
  1208. X    }
  1209. X    for(pass = 0; pass <= 1; pass++) {
  1210. X        tmp = 0;
  1211. X        while(tmp < ESHK(shopkeeper)->billct) {
  1212. X            bp = &bill[tmp];
  1213. X            if(!pass && !bp->useup) {
  1214. X            tmp++;
  1215. X            continue;
  1216. X            }
  1217. X            if(!dopayobj(bp)) return(1);
  1218. X#ifdef MSDOS
  1219. X            *bp = bill[--ESHK(shopkeeper)->billct];
  1220. X#else
  1221. X            bill[tmp] = bill[--ESHK(shopkeeper)->billct];
  1222. X#endif /* MSDOS /**/
  1223. X        }
  1224. X    }
  1225. X    pline("\"Thank you for shopping in %s's %s!\"",
  1226. X        shkname(shopkeeper),
  1227. X        shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - SHOPBASE].name);
  1228. X    NOTANGRY(shopkeeper) = 1;
  1229. X    return(1);
  1230. X}
  1231. X
  1232. X/* return 1 if paid successfully */
  1233. X/*        0 if not enough money */
  1234. X/*       -1 if object could not be found (but was paid) */
  1235. Xstatic int
  1236. Xdopayobj(bp)
  1237. Xregister struct bill_x *bp;
  1238. X{
  1239. X    register struct obj *obj;
  1240. X    long ltmp;
  1241. X
  1242. X    /* find the object on one of the lists */
  1243. X    obj = bp_to_obj(bp);
  1244. X
  1245. X    if(!obj) {
  1246. X        impossible("Shopkeeper administration out of order.");
  1247. X        setpaid();    /* be nice to the player */
  1248. X        return(0);
  1249. X    }
  1250. X
  1251. X    if(!obj->unpaid && !bp->useup){
  1252. X        impossible("Paid object on bill??");
  1253. X        return(1);
  1254. X    }
  1255. X    obj->unpaid = 0;
  1256. X    ltmp = bp->price * bp->bquan;
  1257. X    if(ANGRY(shopkeeper)) ltmp += ltmp/3;
  1258. X    if(u.ugold + ESHK(shopkeeper)->credit < ltmp){
  1259. X        You("don't have gold%s enough to pay for %s.",
  1260. X            (ESHK(shopkeeper)->credit > 0L) ? " or credit" : "",
  1261. X            doname(obj));
  1262. X        obj->unpaid = 1;
  1263. X        return(0);
  1264. X    }
  1265. X    pay(ltmp, shopkeeper);
  1266. X    You("bought %s for %ld gold piece%s.",
  1267. X        doname(obj), ltmp, plur(ltmp));
  1268. X    if(bp->useup) {
  1269. X        register struct obj *otmp = billobjs;
  1270. X        if(obj == billobjs)
  1271. X            billobjs = obj->nobj;
  1272. X        else {
  1273. X            while(otmp && otmp->nobj != obj) otmp = otmp->nobj;
  1274. X            if(otmp) otmp->nobj = obj->nobj;
  1275. X            else pline("Error in shopkeeper administration.");
  1276. X        }
  1277. X        free((genericptr_t) obj);
  1278. X    }
  1279. X    return(1);
  1280. X}
  1281. X
  1282. X/* routine called after dying (or quitting) with nonempty bill or upset shk */
  1283. Xboolean
  1284. Xpaybill(){
  1285. X    register struct monst *mtmp;
  1286. X    register int loss = 0;
  1287. X    register struct obj *otmp;
  1288. X    register xchar ox, oy;
  1289. X    register boolean take = FALSE;
  1290. X    register boolean taken = FALSE;
  1291. X
  1292. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1293. X        if(mtmp->isshk) {
  1294. X        /* for bones: we don't want a shopless shk around */
  1295. X        if(ESHK(mtmp)->shoplevel != dlevel) mongone(mtmp);
  1296. X        else shopkeeper = mtmp;
  1297. X        }
  1298. X
  1299. X    if(!shopkeeper) return(FALSE);
  1300. X
  1301. X    /* get one case out of the way: you die in the shop, the */
  1302. X    /* shopkeeper is peaceful, nothing stolen, nothing owed. */
  1303. X    if(in_shop(u.ux,u.uy) && !IS_DOOR(levl[u.ux][u.uy].typ) &&
  1304. X        !ESHK(shopkeeper)->billct && !ESHK(shopkeeper)->robbed &&
  1305. X        inhishop(shopkeeper) && NOTANGRY(shopkeeper) &&
  1306. X        !ESHK(shopkeeper)->following) {
  1307. X        pline("%s gratefully inherits all your possessions.",
  1308. X                Monnam(shopkeeper));
  1309. X        goto clear;
  1310. X    }
  1311. X
  1312. X    if(ESHK(shopkeeper)->billct || ESHK(shopkeeper)->robbed) {
  1313. X        addupbill();
  1314. X        loss = ((total >= ESHK(shopkeeper)->robbed) ? total :
  1315. X                ESHK(shopkeeper)->robbed);
  1316. X        take = TRUE;
  1317. X    }
  1318. X
  1319. X    if(ESHK(shopkeeper)->following || ANGRY(shopkeeper) || take) {
  1320. X        if((loss > u.ugold) || !loss) {
  1321. X            pline("%s comes and takes all your possessions.",
  1322. X                    Monnam(shopkeeper));
  1323. X            taken = TRUE;
  1324. X            shopkeeper->mgold += u.ugold;
  1325. X            u.ugold = 0;
  1326. X            /* in case bones: make it be for real... */
  1327. X            if(!in_shop(u.ux, u.uy) || IS_DOOR(levl[u.ux][u.uy].typ)) {
  1328. X                /* shk.x,shk.y is the position immediately in
  1329. X                 * front of the door -- move in one more space
  1330. X                 */
  1331. X                ox = ESHK(shopkeeper)->shk.x;
  1332. X                oy = ESHK(shopkeeper)->shk.y;
  1333. X                ox += sgn(ox - ESHK(shopkeeper)->shd.x);
  1334. X                oy += sgn(oy - ESHK(shopkeeper)->shd.y);
  1335. X            } else {
  1336. X                ox = u.ux;
  1337. X                oy = u.uy;
  1338. X            }
  1339. X
  1340. X            if (invent) {
  1341. X                levl[ox][oy].omask = 1;
  1342. X                for(otmp = invent; otmp; otmp = otmp->nobj) {
  1343. X                otmp->ox = ox;
  1344. X                otmp->oy = oy;
  1345. X                otmp->age = 0;
  1346. X                }
  1347. X
  1348. X                /* add to main object list at end so invent is
  1349. X                   still good */
  1350. X                if (fobj) {
  1351. X                otmp = fobj;
  1352. X                while(otmp->nobj)
  1353. X                    otmp = otmp->nobj;
  1354. X                otmp->nobj = invent;
  1355. X                } else
  1356. X                fobj = invent;
  1357. X            }
  1358. X        } else {
  1359. X            u.ugold -= loss;
  1360. X            shopkeeper->mgold += loss;
  1361. X            pline("%s comes and takes %ld zorkmids %sowed %s.",
  1362. X                   Monnam(shopkeeper),
  1363. X                   loss,
  1364. X                   strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ) ? "" : "you ",
  1365. X                   ESHK(shopkeeper)->ismale ? "him" : "her");
  1366. X        }
  1367. X
  1368. X        /* in case we create bones */
  1369. X        if(!inhishop(shopkeeper))
  1370. X            home_shk(shopkeeper);
  1371. X    }
  1372. Xclear:
  1373. X    setpaid();
  1374. X    return(taken);
  1375. X}
  1376. X
  1377. X/* find obj on one of the lists */
  1378. Xstatic struct obj *
  1379. Xbp_to_obj(bp)
  1380. Xregister struct bill_x *bp;
  1381. X{
  1382. X    register struct obj *obj;
  1383. X    register struct monst *mtmp;
  1384. X    register unsigned int id = bp->bo_id;
  1385. X
  1386. X    if(bp->useup)
  1387. X        obj = o_on(id, billobjs);
  1388. X    else if(!(obj = o_on(id, invent)) &&
  1389. X        !(obj = o_on(id, fobj)) &&
  1390. X        !(obj = o_on(id, fcobj))) {
  1391. X            for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1392. X            if(obj = o_on(id, mtmp->minvent))
  1393. X                break;
  1394. X            for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon)
  1395. X            if(obj = o_on(id, mtmp->minvent))
  1396. X                break;
  1397. X        }
  1398. X    return(obj);
  1399. X}
  1400. X
  1401. Xstatic long
  1402. Xget_cost(obj)
  1403. Xregister struct obj *obj;
  1404. X{
  1405. X    register long tmp;
  1406. X
  1407. X    tmp = getprice(obj);
  1408. X    if (!tmp) tmp = 5;
  1409. X    if (ANGRY(shopkeeper) || 
  1410. X        (pl_character[0] == 'T' && u.ulevel < (MAXULEV/2))
  1411. X#ifdef SHIRT
  1412. X        || (uarmu && !uarm) /* wearing just a Hawaiian shirt */
  1413. X#endif
  1414. X       )
  1415. X        tmp += tmp/3;
  1416. X    if (ACURR(A_CHA) > 18)        tmp /= 2;
  1417. X    else if (ACURR(A_CHA) > 17)    tmp = (tmp * 2)/3;
  1418. X    else if (ACURR(A_CHA) > 15)    tmp = (tmp * 3)/4;
  1419. X    else if (ACURR(A_CHA) < 11)    tmp = (tmp * 4)/3;
  1420. X    else if (ACURR(A_CHA) < 8)    tmp = (tmp * 3)/2;
  1421. X    else if (ACURR(A_CHA) < 6)    tmp *= 2;
  1422. X    return(tmp);
  1423. X}
  1424. X
  1425. X
  1426. X/* called in hack.c when we pickup an object */
  1427. Xvoid
  1428. Xaddtobill(obj, ininv)
  1429. Xregister struct obj *obj;
  1430. Xregister boolean ininv;
  1431. X{
  1432. X    register struct bill_x *bp;
  1433. X    char    buf[40];
  1434. X    if(!shopkeeper || !inhishop(shopkeeper)) return;
  1435. X
  1436. X    if(!costly_spot(obj->ox,obj->oy) ||    /* either pickup or kick */
  1437. X        onbill(obj) /* perhaps we threw it away earlier */
  1438. X          ) return;
  1439. X    if(ESHK(shopkeeper)->billct == BILLSZ) {
  1440. X        You("got that for free!");
  1441. X        return;
  1442. X    }
  1443. X    /* To recognize objects the shopkeeper is not interested in. -dgk
  1444. X     */
  1445. X    if (obj->no_charge) {
  1446. X        obj->no_charge = 0;
  1447. X        return;
  1448. X    }
  1449. X    bp = &bill[ESHK(shopkeeper)->billct];
  1450. X    bp->bo_id = obj->o_id;
  1451. X    bp->bquan = obj->quan;
  1452. X    bp->useup = 0;
  1453. X    bp->price = get_cost(obj);
  1454. X    Strcpy(buf, "\"For you, ");
  1455. X    if (ANGRY(shopkeeper)) Strcat(buf, "scum ");
  1456. X    else {
  1457. X        switch(rnd(4)
  1458. X#ifdef HARD
  1459. X           + u.udemigod
  1460. X#endif
  1461. X                ) {
  1462. X        case 1:    Strcat(buf, "good");
  1463. X            break;
  1464. X        case 2:    Strcat(buf, "honored");
  1465. X            break;
  1466. X        case 3:    Strcat(buf, "most gracious");
  1467. X            break;
  1468. X        case 4:    Strcat(buf, "esteemed");
  1469. X            break;
  1470. X        case 5: if (u.ualigntyp == U_CHAOTIC) Strcat(buf, "un");
  1471. X            Strcat(buf, "holy");
  1472. X            break;
  1473. X        }
  1474. X#ifdef POLYSELF
  1475. X        if(!is_human(uasmon)) Strcat(buf, " creature");
  1476. X        else
  1477. X#endif
  1478. X        Strcat(buf, (flags.female) ? " lady" : " sir");
  1479. X    }
  1480. X    obj->dknown = 1; /* after all, the shk is telling you what it is */
  1481. X    if(ininv) {
  1482. X        obj->quan = 1; /* fool xname() into giving singular */
  1483. X        pline("%s; only %d %s %s.\"", buf, bp->price,
  1484. X            (bp->bquan > 1) ? "per" : "for this", xname(obj));
  1485. X        obj->quan = bp->bquan;
  1486. X    } else pline("The %s will cost you %d zorkmids%s.",
  1487. X            xname(obj), bp->price,
  1488. X            (bp->bquan > 1) ? " each" : "");
  1489. X    ESHK(shopkeeper)->billct++;
  1490. X    obj->unpaid = 1;
  1491. X}
  1492. X
  1493. Xvoid
  1494. Xsplitbill(obj, otmp)
  1495. Xregister struct obj *obj, *otmp;
  1496. X{
  1497. X    /* otmp has been split off from obj */
  1498. X    register struct bill_x *bp;
  1499. X    register int tmp;
  1500. X    bp = onbill(obj);
  1501. X    if(!bp) {
  1502. X        impossible("splitbill: not on bill?");
  1503. X        return;
  1504. X    }
  1505. X    if(bp->bquan < otmp->quan) {
  1506. X        impossible("Negative quantity on bill??");
  1507. X    }
  1508. X    if(bp->bquan == otmp->quan) {
  1509. X        impossible("Zero quantity on bill??");
  1510. X    }
  1511. X    bp->bquan -= otmp->quan;
  1512. X
  1513. X    if(ESHK(shopkeeper)->billct == BILLSZ) otmp->unpaid = 0;
  1514. X    else {
  1515. X        tmp = bp->price;
  1516. X        bp = &bill[ESHK(shopkeeper)->billct];
  1517. X        bp->bo_id = otmp->o_id;
  1518. X        bp->bquan = otmp->quan;
  1519. X        bp->useup = 0;
  1520. X        bp->price = tmp;
  1521. X        ESHK(shopkeeper)->billct++;
  1522. X    }
  1523. X}
  1524. X
  1525. Xvoid
  1526. Xsubfrombill(obj)
  1527. Xregister struct obj *obj;
  1528. X{
  1529. X    long ltmp;
  1530. X    /* register int tmp;    /* use of tmp commented out below */
  1531. X    register struct obj *otmp;
  1532. X    register struct bill_x *bp;
  1533. X    if(!costly_spot(u.ux,u.uy))
  1534. X        return;
  1535. X    if((bp = onbill(obj)) != 0) {
  1536. X        obj->unpaid = 0;
  1537. X        if(bp->bquan > obj->quan){
  1538. X            otmp = newobj(0);
  1539. X            *otmp = *obj;
  1540. X            bp->bo_id = otmp->o_id = flags.ident++;
  1541. X            otmp->quan = (bp->bquan -= obj->quan);
  1542. X            otmp->owt = 0;    /* superfluous */
  1543. X            otmp->onamelth = 0;
  1544. X            bp->useup = 1;
  1545. X            otmp->nobj = billobjs;
  1546. X            billobjs = otmp;
  1547. X            return;
  1548. X        }
  1549. X        ESHK(shopkeeper)->billct--;
  1550. X        *bp = bill[ESHK(shopkeeper)->billct];
  1551. X        return;
  1552. X    }
  1553. X    if(obj->unpaid) {
  1554. X        if(inhishop(shopkeeper))
  1555. X            pline("%s didn't notice.", Monnam(shopkeeper));
  1556. X        obj->unpaid = 0;
  1557. X        return;        /* %% */
  1558. X    }
  1559. X    /* he dropped something of his own - probably wants to sell it */
  1560. X    if(shopkeeper->msleep || shopkeeper->mfroz || !inhishop(shopkeeper))
  1561. X        return;
  1562. X    ltmp = getprice(obj) * obj->quan;
  1563. X    if(ESHK(shopkeeper)->billct == BILLSZ
  1564. X       || !saleable(rooms[ESHK(shopkeeper)->shoproom].rtype-SHOPBASE, obj)
  1565. X       || otmp->olet == BALL_SYM || ltmp == 0L) {
  1566. X        pline("%s seems not interested.", Monnam(shopkeeper));
  1567. X        obj->no_charge = 1;
  1568. X        return;
  1569. X    }
  1570. X    if (ANGRY(shopkeeper) || (pl_character[0] == 'T' && u.ulevel < (MAXULEV/2))
  1571. X#ifdef SHIRT
  1572. X        || (uarmu && !uarm) /* wearing just a Hawaiian shirt */
  1573. X#endif
  1574. X       ) {
  1575. X        ltmp /= 3;
  1576. X        NOTANGRY(shopkeeper) = 1;
  1577. X    } else    ltmp /= 2;
  1578. X    if(ESHK(shopkeeper)->robbed) {
  1579. X        if((ESHK(shopkeeper)->robbed -= ltmp) < 0)
  1580. X            ESHK(shopkeeper)->robbed = 0;
  1581. Xpline("\"Thank you for your contribution to restock this recently plundered shop.\"");
  1582. X        return;
  1583. X    }
  1584. X    if(ltmp > shopkeeper->mgold)
  1585. X        ltmp = shopkeeper->mgold;
  1586. X    pay(-ltmp, shopkeeper);
  1587. X    if(!ltmp) {
  1588. X        pline("%s gladly accepts %s but cannot pay you at present.",
  1589. X            Monnam(shopkeeper), doname(obj));
  1590. X            obj->no_charge = 1;
  1591. X    } else
  1592. X    You("sold %s for %ld gold piece%s.", doname(obj), ltmp,
  1593. X        plur(ltmp));
  1594. X}
  1595. X
  1596. Xint
  1597. Xdoinvbill(mode)
  1598. Xint mode;        /* 0: deliver count 1: paged */
  1599. X{
  1600. X    register struct bill_x *bp;
  1601. X    register struct obj *obj;
  1602. X    long totused, thisused;
  1603. X    char buf[BUFSZ];
  1604. X
  1605. X    if(mode == 0) {
  1606. X        register int cnt = 0;
  1607. X
  1608. X        if(shopkeeper)
  1609. X        for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++)
  1610. X            if(bp->useup ||
  1611. X              ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
  1612. X            cnt++;
  1613. X        return(cnt);
  1614. X    }
  1615. X
  1616. X    if(!shopkeeper) {
  1617. X        impossible("doinvbill: no shopkeeper?");
  1618. X        return(0);
  1619. X    }
  1620. X
  1621. X    set_pager(0);
  1622. X    if(page_line("Unpaid articles already used up:") || page_line(""))
  1623. X        goto quit;
  1624. X
  1625. X    totused = 0;
  1626. X    for(bp = bill; bp - bill < ESHK(shopkeeper)->billct; bp++) {
  1627. X        obj = bp_to_obj(bp);
  1628. X        if(!obj) {
  1629. X        impossible("Bad shopkeeper administration.");
  1630. X        goto quit;
  1631. X        }
  1632. X        if(bp->useup || bp->bquan > obj->quan) {
  1633. X        register int cnt, oquan, uquan;
  1634. X
  1635. X        oquan = obj->quan;
  1636. X        uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
  1637. X        thisused = bp->price * uquan;
  1638. X        totused += thisused;
  1639. X        obj->quan = uquan;        /* cheat doname */
  1640. X        Sprintf(buf, "x -  %s", doname(obj));
  1641. X        obj->quan = oquan;        /* restore value */
  1642. X        for(cnt = 0; buf[cnt]; cnt++);
  1643. X        while(cnt < 50)
  1644. X            buf[cnt++] = ' ';
  1645. X        Sprintf(&buf[cnt], " %5ld zorkmids", thisused);
  1646. X        if(page_line(buf))
  1647. X            goto quit;
  1648. X        }
  1649. X    }
  1650. X    Sprintf(buf, "Total:%50ld zorkmids", totused);
  1651. X    if(page_line("") || page_line(buf))
  1652. X        goto quit;
  1653. X    set_pager(1);
  1654. X    return(0);
  1655. Xquit:
  1656. X    set_pager(2);
  1657. X    return(0);
  1658. X}
  1659. X
  1660. X#define HUNGRY    2
  1661. Xstatic int
  1662. Xgetprice(obj)
  1663. Xregister struct obj *obj;
  1664. X{
  1665. X    register int tmp = objects[obj->otyp].oc_cost;
  1666. X
  1667. X    switch(obj->olet) {
  1668. X    case AMULET_SYM:
  1669. X        if(obj->otyp == AMULET_OF_YENDOR) {
  1670. X            /* don't let the player get rich selling fakes */
  1671. X            tmp = (obj->spe < 0 ? 0 : 3500);
  1672. X        }
  1673. X        break;
  1674. X    case FOOD_SYM:
  1675. X        /* simpler hunger check, (2-4)*cost */
  1676. X        if (u.uhs >= HUNGRY) tmp *= u.uhs;
  1677. X        break;
  1678. X    case WAND_SYM:
  1679. X        if (obj->spe == -1) tmp = 0;
  1680. X        break;
  1681. X    case POTION_SYM:
  1682. X        if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
  1683. X            tmp = 0;
  1684. X        break;
  1685. X    case ARMOR_SYM:
  1686. X        if (u.uac > 0) tmp += u.uac * 2;
  1687. X    case WEAPON_SYM:
  1688. X        if (obj->spe > 0) tmp += 10 * obj->spe;
  1689. X        break;
  1690. X    case CHAIN_SYM:
  1691. X        pline("Strange... carrying a chain?");
  1692. X        break;
  1693. X    }
  1694. X    return(tmp);
  1695. X}
  1696. X
  1697. Xint
  1698. Xshkcatch(obj)
  1699. Xregister struct obj *obj;
  1700. X{
  1701. X    register struct monst *shkp = shopkeeper;
  1702. X
  1703. X    if(u.uinshop && shkp && !shkp->mfroz && !shkp->msleep &&
  1704. X        u.dx && u.dy &&
  1705. X        inroom(u.ux+u.dx, u.uy+u.dy) + 1 == u.uinshop &&
  1706. X        shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y &&
  1707. X        u.ux == ESHK(shkp)->shd.x && u.uy == ESHK(shkp)->shd.y) {
  1708. X        pline("%s nimbly catches the %s.", Monnam(shkp), xname(obj));
  1709. X        obj->nobj = shkp->minvent;
  1710. X        shkp->minvent = obj;
  1711. X        return(1);
  1712. X    }
  1713. X    return(0);
  1714. X}
  1715. X
  1716. X/*
  1717. X * shk_move: return 1: he moved  0: he didn't  -1: let m_move do it  -2: died
  1718. X */
  1719. Xint
  1720. Xshk_move(shkp)
  1721. Xregister struct monst *shkp;
  1722. X{
  1723. X    register xchar gx,gy,omx,omy;
  1724. X    register int udist;
  1725. X    register schar appr;
  1726. X    int z;
  1727. X    schar shkroom;
  1728. X    boolean uondoor, satdoor, avoid, badinv;
  1729. X
  1730. X    omx = shkp->mx;
  1731. X    omy = shkp->my;
  1732. X
  1733. X    if((udist = dist(omx,omy)) < 3) {
  1734. X        if(ANGRY(shkp)) {
  1735. X            if(Displaced)
  1736. X              Your("displaced image doesn't fool %s!",
  1737. X                Monnam(shkp));
  1738. X            (void) mattacku(shkp);
  1739. X            return(0);
  1740. X        }
  1741. X        if(ESHK(shkp)->following) {
  1742. X            if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ)) {
  1743. X                pline("\"Hello, %s!  I was looking for %s.\"",
  1744. X                    plname, ESHK(shkp)->customer);
  1745. X                    ESHK(shkp)->following = 0;
  1746. X                return(0);
  1747. X            }
  1748. X            if(moves > followmsg+4) {
  1749. X                pline("\"Hello, %s!  Didn't you forget to pay?\"",
  1750. X                    plname);
  1751. X                followmsg = moves;
  1752. X#ifdef HARD
  1753. X                if (!rn2(4)) {
  1754. X        pline ("%s doesn't like customers who don't pay.", Monnam(shkp));
  1755. X                NOTANGRY(shkp) = 0;
  1756. X                }
  1757. X#endif
  1758. X            }
  1759. X            if(udist < 2)
  1760. X                return(0);
  1761. X        }
  1762. X    }
  1763. X
  1764. X    shkroom = inroom(omx,omy);
  1765. X    appr = 1;
  1766. X    gx = ESHK(shkp)->shk.x;
  1767. X    gy = ESHK(shkp)->shk.y;
  1768. X    satdoor = (gx == omx && gy == omy);
  1769. X    if(ESHK(shkp)->following || ((z = holetime()) >= 0 && z*z <= udist)){
  1770. X        gx = u.ux;
  1771. X        gy = u.uy;
  1772. X        if(shkroom < 0 || shkroom != inroom(u.ux,u.uy))
  1773. X            if(udist > 4)
  1774. X            return(-1);    /* leave it to m_move */
  1775. X    } else if(ANGRY(shkp)) {
  1776. X        long saveBlind = Blinded;
  1777. X        struct obj *saveUblindf = ublindf;
  1778. X        Blinded = 0;
  1779. X        ublindf = (struct obj *)0;
  1780. X        if(shkp->mcansee && !Invis && cansee(omx,omy)) {
  1781. X            gx = u.ux;
  1782. X            gy = u.uy;
  1783. X        }
  1784. X        Blinded = saveBlind;
  1785. X        ublindf = saveUblindf;
  1786. X        avoid = FALSE;
  1787. X    } else {
  1788. X#define    GDIST(x,y)    (dist2(x,y,gx,gy))
  1789. X        if(Invis)
  1790. X            avoid = FALSE;
  1791. X        else {
  1792. X            uondoor = (u.ux == ESHK(shkp)->shd.x &&
  1793. X                u.uy == ESHK(shkp)->shd.y);
  1794. X            if(uondoor) {
  1795. X            if(ESHK(shkp)->billct && inhishop(shkp))
  1796. X                pline(NOTANGRY(shkp) ?
  1797. X                "\"Hello, %s!  Will you please pay before leaving?\"" :
  1798. X                "\"Hey, %s!  Don't leave without paying!\"",
  1799. X                plname);
  1800. X            badinv = (!!carrying(PICK_AXE));
  1801. X            if(satdoor && badinv)
  1802. X                return(0);
  1803. X            avoid = !badinv;
  1804. X            } else {
  1805. X            avoid = (u.uinshop && dist(gx,gy) > 8);
  1806. X            badinv = FALSE;
  1807. X            }
  1808. X
  1809. X            if(((!ESHK(shkp)->robbed && !ESHK(shkp)->billct) || avoid)
  1810. X            && GDIST(omx,omy) < 3) {
  1811. X            if(!badinv && !online(omx,omy))
  1812. X                return(0);
  1813. X            if(satdoor)
  1814. X                appr = gx = gy = 0;
  1815. X            }
  1816. X        }
  1817. X    }
  1818. X    
  1819. X    return(move_special(shkp,shkroom,appr,uondoor,avoid,omx,omy,gx,gy));
  1820. X}
  1821. X
  1822. Xint
  1823. Xonline(x,y)        /*    New version to speed things up.
  1824. X             *    Compiler dependant, may not always work.
  1825. X             */
  1826. Xregister xchar x, y;
  1827. X{
  1828. X    return((x-=u.ux) == 0 || (y-=u.uy) == 0 || x == y || (x+=y) == 0);
  1829. X}
  1830. X
  1831. X/*            Original version, just in case...
  1832. X *online(x,y) {
  1833. X *    return(x==u.ux || y==u.uy || (x-u.ux)*(x-u.ux) == (y-u.uy)*(y-u.uy));
  1834. X *}
  1835. X */
  1836. X
  1837. X/* for use in levl_follower (mondata.c) */
  1838. Xboolean
  1839. Xis_fshk(mtmp)
  1840. Xregister struct monst *mtmp;
  1841. X{
  1842. X    return(mtmp->isshk && ESHK(mtmp)->following);
  1843. X}
  1844. X
  1845. X/* He is digging in the shop. */
  1846. Xvoid
  1847. Xshopdig(fall)
  1848. Xregister int fall;
  1849. X{
  1850. X    if(!shopkeeper) return;
  1851. X    if(!inhishop(shopkeeper)) {
  1852. X    if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp));
  1853. X    return;
  1854. X    }
  1855. X
  1856. X    if(!fall) {
  1857. X    if(u.utraptype == TT_PIT)
  1858. X        pline("\"Be careful, %s, or you might fall through the floor.\"",
  1859. X        flags.female ? "madam" : "sir");
  1860. X    else
  1861. X        pline("\"%s, do not damage the floor here!\"",
  1862. X            flags.female ? "Madam" : "Sir");
  1863. X    if (pl_character[0] == 'K') adjalign(-sgn(u.ualigntyp));
  1864. X    } else if(um_dist(shopkeeper->mx, shopkeeper->my, 2)) {
  1865. X    register struct obj *obj, *obj2;
  1866. X
  1867. X    if(dist(shopkeeper->mx, shopkeeper->my) > 2) {
  1868. X        mnexto(shopkeeper);
  1869. X        /* for some reason he can't come next to you */
  1870. X        if(dist(shopkeeper->mx, shopkeeper->my) > 2) {
  1871. X            pline("%s curses you in anger and frustration!",
  1872. X                    shkname(shopkeeper));
  1873. X            NOTANGRY(shopkeeper) = 0;
  1874. X            return;
  1875. X        } else pline("%s leaps, and grabs your backpack!",
  1876. X                    shkname(shopkeeper));
  1877. X    } else pline("%s grabs your backpack!", shkname(shopkeeper));
  1878. X
  1879. X    for(obj = invent; obj; obj = obj2) {
  1880. X        obj2 = obj->nobj;
  1881. X        if(obj->owornmask) continue;
  1882. X        freeinv(obj);
  1883. X        obj->nobj = shopkeeper->minvent;
  1884. X        shopkeeper->minvent = obj;
  1885. X        if(obj->unpaid)
  1886. X            subfrombill(obj);
  1887. X    }
  1888. X    }
  1889. X}
  1890. X
  1891. X#ifdef KOPS
  1892. Xstatic int
  1893. Xmakekops(mm)        /* returns the number of (all types of) Kops  made */
  1894. Xcoord *mm;
  1895. X{
  1896. X    register int cnt = dlevel + rnd(5);
  1897. X    register int scnt = (cnt / 3) + 1;    /* at least one sarge */
  1898. X    register int lcnt = (cnt / 6);        /* maybe a lieutenant */
  1899. X    register int kcnt = (cnt / 9);        /* and maybe a kaptain */
  1900. X
  1901. X    while(cnt--) {
  1902. X        enexto(mm, mm->x, mm->y);
  1903. X        (void) makemon(&mons[PM_KEYSTONE_KOP], mm->x, mm->y);
  1904. X    }
  1905. X    while(scnt--) {
  1906. X        enexto(mm, mm->x, mm->y);
  1907. X        (void) makemon(&mons[PM_KOP_SERGEANT], mm->x, mm->y);
  1908. X    }
  1909. X    while(lcnt--) {
  1910. X        enexto(mm, mm->x, mm->y);
  1911. X        (void) makemon(&mons[PM_KOP_LIEUTENANT], mm->x, mm->y);
  1912. X    }
  1913. X    while(kcnt--) {
  1914. X        enexto(mm, mm->x, mm->y);
  1915. X        (void) makemon(&mons[PM_KOP_KAPTAIN], mm->x, mm->y);
  1916. X    }
  1917. X    return(cnt + scnt + lcnt + kcnt);
  1918. X}
  1919. X#endif
  1920. X
  1921. Xboolean
  1922. Xin_shop(x,y)
  1923. Xregister int x, y;
  1924. X{
  1925. X    register int roomno = inroom(x, y);
  1926. X
  1927. X    if (roomno < 0) return(FALSE);
  1928. X    return (IS_SHOP(rooms[roomno]));
  1929. X}
  1930. X
  1931. Xvoid
  1932. Xpay_for_door(x,y,dmgstr)
  1933. Xregister int x, y;
  1934. Xregister char *dmgstr;
  1935. X{
  1936. X    register struct monst *mtmp;
  1937. X    register int ox, oy;
  1938. X    register int roomno = inroom(x, y);
  1939. X    register int damage = (ACURR(A_STR) > 18) ? 400 : 20 * ACURR(A_STR);
  1940. X
  1941. X    /* make sure this function is not used in the wrong place */
  1942. X    if(!(IS_DOOR(levl[x][y].typ) && in_shop(x, y))) return;
  1943. X
  1944. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1945. X        if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno
  1946. X               && ESHK(mtmp)->shoplevel == dlevel) {
  1947. X        shopkeeper = mtmp;
  1948. X    }
  1949. X
  1950. X    if(!shopkeeper) return;
  1951. X
  1952. X    /* not the best introduction to the shk... */
  1953. X    (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ);
  1954. X
  1955. X    /* if he is already on the war path, be sure it's all out */
  1956. X    if(ANGRY(shopkeeper) || ESHK(shopkeeper)->following) {
  1957. X        NOTANGRY(shopkeeper) = 0;
  1958. X        ESHK(shopkeeper)->following = 1;
  1959. X        return;
  1960. X    }
  1961. X
  1962. X    ox = shopkeeper->mx;
  1963. X    oy = shopkeeper->my;
  1964. X
  1965. X    /* if he's not in his shop.. */
  1966. X    if(!in_shop(ox, oy)) return;
  1967. X
  1968. X    /* if a !shopkeeper shows up at the door, move him */
  1969. X    if(levl[x][y].mmask && (mtmp = m_at(x, y)) != shopkeeper) {
  1970. X        if(flags.soundok) {
  1971. X            You("hear an angry voice: \"Out of my way, scum!\"");
  1972. X            (void) fflush(stdout);
  1973. X#if defined(SYSV) || defined(ULTRIX)
  1974. X            (void)
  1975. X#endif
  1976. X#ifdef UNIX
  1977. X            sleep(1);
  1978. X#endif
  1979. X        }
  1980. X        mnearto(mtmp, x, y, FALSE);
  1981. X    }
  1982. X
  1983. X    /* make shk show up at the door */
  1984. X    levl[shopkeeper->mx][shopkeeper->my].mmask = 0;
  1985. X    levl[x][y].mmask = 1;
  1986. X    shopkeeper->mx = x;
  1987. X    shopkeeper->my = y;
  1988. X    pmon(shopkeeper);
  1989. X
  1990. X    if(um_dist(x, y, 1)) goto chase;
  1991. X
  1992. X    if(u.ugold < damage || !rn2(50)) {
  1993. Xchase:
  1994. X        if(um_dist(x, y, 1))
  1995. X            pline("%s shouts: \"Who dared %s my door?\"",
  1996. X                shkname(shopkeeper), dmgstr);
  1997. X        else pline("\"How dare you %s my door?\"", dmgstr);
  1998. X        NOTANGRY(shopkeeper) = 0;
  1999. X        ESHK(shopkeeper)->following = 1;
  2000. X        return;
  2001. X    }
  2002. X
  2003. X    pline("\"Cad!  You did %d zorkmids worth of damage!\"  Pay? ", damage);
  2004. X    if(yn() != 'n') {
  2005. X        u.ugold -= damage;
  2006. X        shopkeeper->mgold += damage;
  2007. X        flags.botl = 1;
  2008. X        pline("Mollified, %s accepts your restitution.",
  2009. X            shkname(shopkeeper));
  2010. X
  2011. X        /* clear ox oy of another monster, if one got there somehow */
  2012. X        if(levl[ox][oy].mmask) mnearto(m_at(ox,oy),ox,oy,FALSE);
  2013. X
  2014. X        /* move shk back to his orig loc */
  2015. X        levl[shopkeeper->mx][shopkeeper->my].mmask = 0;
  2016. X        levl[ox][oy].mmask = 1;
  2017. X        shopkeeper->mx = ox;
  2018. X        shopkeeper->my = oy;
  2019. X        unpmon(shopkeeper);
  2020. X        NOTANGRY(shopkeeper) = 1;
  2021. X    }
  2022. X    else {
  2023. X        pline("\"Oh, yes!  You'll pay!\"");
  2024. X        ESHK(shopkeeper)->following = 1;
  2025. X        NOTANGRY(shopkeeper) = 0;
  2026. X        adjalign(-sgn(u.ualigntyp));
  2027. X    }
  2028. X}
  2029. X
  2030. X/* called in dokick.c when we kick an object in a store */
  2031. Xboolean
  2032. Xcostly_spot(x, y)
  2033. Xregister int x, y;
  2034. X{
  2035. X    register struct monst *shkp = shopkeeper;
  2036. X    
  2037. X    if(!shkp) return(FALSE);
  2038. X
  2039. X    return(in_shop(x, y) && levl[x][y].typ != DOOR &&
  2040. X        !(x == ESHK(shkp)->shk.x && y == ESHK(shkp)->shk.y));
  2041. X}
  2042. X
  2043. X#ifdef KOPS
  2044. Xstatic void
  2045. Xkops_gone()
  2046. X{
  2047. X    register int cnt = 0;
  2048. X    register struct monst *mtmp, *mtmp2;
  2049. X
  2050. X    /* turn off automatic resurrection of kops */
  2051. X    allow_kops = FALSE;
  2052. X
  2053. X    for(mtmp = fmon; mtmp; mtmp = mtmp2) {
  2054. X        mtmp2 = mtmp->nmon;
  2055. X        if(mtmp->data->mlet == S_KOP) {
  2056. X            mongone(mtmp);
  2057. X            cnt++;
  2058. X        }
  2059. X    }
  2060. X    if(cnt) pline("The Kops (disappointed) disappear into thin air.");
  2061. X    allow_kops = TRUE;
  2062. X}
  2063. X#endif
  2064. X
  2065. Xstatic long
  2066. Xcost_per_charge(otmp)
  2067. Xregister struct obj *otmp;
  2068. X{
  2069. X    register long tmp = get_cost(otmp);
  2070. X
  2071. X    /* The idea is to make the exhaustive use of */
  2072. X    /* an unpaid item more expansive than buying */
  2073. X    /* outright.                     */
  2074. X    if(otmp->otyp == MAGIC_LAMP) {             /* 1 */
  2075. X        tmp += (tmp/3L);
  2076. X    } else if(otmp->otyp == MAGIC_MARKER) {       /* 70 - 100 */
  2077. X        /* no way to determine in advance   */
  2078. X        /* how many charges will be wasted. */
  2079. X        /* so, arbitrarily, one half of the */
  2080. X        /* price per use.            */
  2081. X        tmp = (tmp/2L);
  2082. X    } else if(otmp->otyp == BAG_OF_TRICKS) {      /* 1 - 20 */
  2083. X        tmp = (tmp/5L);
  2084. X    } else if(otmp->otyp == CRYSTAL_BALL ||       /* 1 - 5 */
  2085. X          otmp->otyp == LAMP ||                     /* 1-10 */
  2086. X#ifdef MUSIC
  2087. X         (otmp->otyp >= MAGIC_FLUTE &&
  2088. X          otmp->otyp <= DRUM_OF_EARTHQUAKE) ||      /* 5 - 9 */
  2089. X#endif
  2090. X            otmp->olet == WAND_SYM) {         /* 3 - 11 */
  2091. X        if(otmp->spe == 1) tmp += (tmp/3L);
  2092. X        else tmp = (tmp/4L);
  2093. X    }
  2094. X    else return(0L);
  2095. X    return(tmp);
  2096. X}
  2097. X
  2098. X/* for using charges of unpaid objects */
  2099. Xvoid
  2100. Xcheck_unpaid(otmp)
  2101. Xregister struct obj *otmp;
  2102. X{
  2103. X    if(!in_shop(u.ux, u.uy)) return;
  2104. X    
  2105. X    if(otmp->spe <= 0) return;
  2106. X
  2107. X    if(otmp->unpaid) {
  2108. X        ESHK(shopkeeper)->debit += cost_per_charge(otmp);
  2109. X    }
  2110. X}
  2111. END_OF_FILE
  2112. if test 37207 -ne `wc -c <'src/shk.c'`; then
  2113.     echo shar: \"'src/shk.c'\" unpacked with wrong size!
  2114. fi
  2115. # end of 'src/shk.c'
  2116. fi
  2117. echo shar: End of archive 7 \(of 38\).
  2118. cp /dev/null ark7isdone
  2119. MISSING=""
  2120. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; do
  2121.     if test ! -f ark${I}isdone ; then
  2122.     MISSING="${MISSING} ${I}"
  2123.     fi
  2124. done
  2125. if test "${MISSING}" = "" ; then
  2126.     echo You have unpacked all 38 archives.
  2127.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2128. else
  2129.     echo You still need to unpack the following archives:
  2130.     echo "        " ${MISSING}
  2131. fi
  2132. ##  End of shell archive.
  2133. exit 0
  2134.