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

  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: v16i034:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part34/108
  5. Message-ID: <4322@master.CNA.TEK.COM>
  6. Date: 29 Jan 93 20:47:05 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1942
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1591
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 34
  14. Archive-name: nethack31/Part34
  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 34 (of 108)."
  27. # Contents:  src/hack.c sys/os2/Install.os2
  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/hack.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/hack.c'\"
  32. else
  33. echo shar: Extracting \"'src/hack.c'\" \(39188 characters\)
  34. sed "s/^X//" >'src/hack.c' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)hack.c    3.1    92/12/04    */
  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
  41. XSTATIC_DCL int NDECL(moverock);
  42. X#ifdef POLYSELF
  43. XSTATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P));
  44. X#endif
  45. X#ifdef SINKS
  46. XSTATIC_DCL void NDECL(dosinkfall);
  47. X#endif
  48. XSTATIC_DCL boolean FDECL(bad_rock,(XCHAR_P,XCHAR_P));
  49. XSTATIC_DCL boolean FDECL(monstinroom, (struct permonst *,int));
  50. X
  51. Xstatic void FDECL(move_update, (BOOLEAN_P));
  52. X
  53. X#define IS_SHOP(x)    (rooms[x].rtype >= SHOPBASE)
  54. X
  55. X#ifdef OVL2
  56. X
  57. Xboolean
  58. Xrevive_nasty(x, y, msg)
  59. Xint x,y;
  60. Xconst char *msg;
  61. X{
  62. X    register struct obj *otmp, *otmp2;
  63. X    struct monst *mtmp;
  64. X    coord cc;
  65. X    boolean revived = FALSE;
  66. X
  67. X    /* prevent freeobj() of revivable corpses */
  68. X    for(otmp = level.objects[x][y]; otmp; otmp = otmp2) {
  69. X    otmp2 = otmp->nexthere;
  70. X    if (otmp->otyp == CORPSE &&
  71. X        (is_rider(&mons[otmp->corpsenm]) ||
  72. X         otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
  73. X        /* move any living monster already at that location */
  74. X        if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data))
  75. X        rloc_to(mtmp, cc.x, cc.y);
  76. X        if(msg) Norep("%s", msg);
  77. X        revive_corpse(otmp, 0, FALSE);
  78. X        revived = MON_AT(x,y);
  79. X    }
  80. X    }
  81. X
  82. X    /* this location might not be safe, if not, move revived monster */
  83. X    if (revived) {
  84. X    mtmp = m_at(x,y);
  85. X    if (mtmp && !goodpos(x, y, mtmp, mtmp->data) &&
  86. X        enexto(&cc, x, y, mtmp->data)) {
  87. X        rloc_to(mtmp, cc.x, cc.y);
  88. X    }
  89. X    /* else impossible? */
  90. X    }
  91. X
  92. X    return (revived);
  93. X}
  94. X
  95. XSTATIC_OVL int
  96. Xmoverock()
  97. X{
  98. X    register xchar rx, ry;
  99. X    register struct obj *otmp, *otmp2;
  100. X    register struct trap *ttmp;
  101. X    register struct monst *mtmp;
  102. X
  103. X    while ((otmp = sobj_at(BOULDER, u.ux+u.dx, u.uy+u.dy)) != 0) {
  104. X    rx = u.ux+2*u.dx;
  105. X    ry = u.uy+2*u.dy;
  106. X    nomul(0);
  107. X    if (Levitation || Is_airlevel(&u.uz)) {
  108. X        if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
  109. X        You("don't have enough leverage to push %s.", the(xname(otmp)));
  110. X        /* Give them a chance to climb over it? */
  111. X        return -1;
  112. X    }
  113. X#ifdef POLYSELF
  114. X    if (verysmall(uasmon)) {
  115. X        if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
  116. X        pline("You're too small to push that %s.", xname(otmp));
  117. X        goto cannot_push;
  118. X    }
  119. X#endif
  120. X    if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
  121. X        (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || (
  122. X#ifdef REINCARNATION
  123. X        !Is_rogue_level(&u.uz) &&
  124. X#endif
  125. X        (levl[rx][ry].doormask & ~D_BROKEN) == D_NODOOR)) &&
  126. X        !sobj_at(BOULDER, rx, ry)) {
  127. X        ttmp = t_at(rx, ry);
  128. X        mtmp = m_at(rx, ry);
  129. X
  130. X        if (revive_nasty(rx, ry, "You sense movement on the other side."))
  131. X        return (-1);
  132. X
  133. X        if (mtmp && (!mtmp->mtrapped ||
  134. X             !(ttmp && ((ttmp->ttyp == PIT) ||
  135. X                    (ttmp->ttyp == SPIKED_PIT))))) {
  136. X        if (canseemon(mtmp))
  137. X            pline("There's %s on the other side.", mon_nam(mtmp));
  138. X        else {
  139. X            if (Blind) feel_location(u.ux+u.dx,u.uy+u.dy);
  140. X            You("hear a monster behind %s.", the(xname(otmp)));
  141. X        }
  142. X        if (flags.verbose)
  143. X            pline("Perhaps that's why you cannot move it.");
  144. X        goto cannot_push;
  145. X        }
  146. X
  147. X        if (ttmp)
  148. X        switch(ttmp->ttyp) {
  149. X        case SPIKED_PIT:
  150. X        case PIT:
  151. X            freeobj(otmp);
  152. X            if (!flooreffects(otmp, rx, ry, "fall")) {
  153. X            place_object(otmp, rx, ry);
  154. X            otmp->nobj = fobj;
  155. X            fobj = otmp;
  156. X            }
  157. X            continue;
  158. X        case TRAPDOOR:
  159. X            pline("%s falls into and plugs a hole in the ground!",
  160. X              The(xname(otmp)));
  161. X            deltrap(ttmp);
  162. X            delobj(otmp);
  163. X            delallobj(rx, ry);
  164. X            if (cansee(rx,ry)) newsym(rx,ry);
  165. X            continue;
  166. X        case LEVEL_TELEP:
  167. X        case TELEP_TRAP:
  168. X            You("push %s and suddenly it disappears!",
  169. X            the(xname(otmp)));
  170. X            rloco(otmp);
  171. X            continue;
  172. X        }
  173. X        if (closed_door(rx, ry))
  174. X        goto nopushmsg;
  175. X        if (boulder_hits_pool(otmp, rx, ry, TRUE))
  176. X        continue;
  177. X        /*
  178. X         * Re-link at top of fobj chain so that pile order is preserved
  179. X         * when level is restored.
  180. X         */
  181. X        if (otmp != fobj) {
  182. X        otmp2 = fobj;
  183. X        while (otmp2->nobj && otmp2->nobj != otmp)
  184. X            otmp2 = otmp2->nobj;
  185. X        if (!otmp2->nobj) {
  186. X            impossible("moverock: error in fobj chain");
  187. X        } else {
  188. X            otmp2->nobj = otmp->nobj;    
  189. X            otmp->nobj = fobj;
  190. X            fobj = otmp;
  191. X        }
  192. X        }
  193. X
  194. X        {
  195. X#ifdef LINT /* static long lastmovetime; */
  196. X        long lastmovetime;
  197. X        lastmovetime = 0;
  198. X#else
  199. X        static long NEARDATA lastmovetime;
  200. X#endif
  201. X        /* note: this var contains garbage initially and
  202. X           after a restore */
  203. X        if (moves > lastmovetime+2 || moves < lastmovetime)
  204. X            pline("With great effort you move %s.", the(xname(otmp)));
  205. X        exercise(A_STR, TRUE);
  206. X        lastmovetime = moves;
  207. X        }
  208. X
  209. X        /* Move the boulder *after* the message. */
  210. X        move_object(otmp, rx, ry);
  211. X        if (Blind) {
  212. X        feel_location(rx,ry);
  213. X        feel_location(u.ux+u.dx, u.uy+u.dy);
  214. X        } else {
  215. X        newsym(rx,ry);
  216. X        newsym(u.ux+u.dx, u.uy+u.dy);
  217. X        }
  218. X    } else {
  219. X    nopushmsg:
  220. X        You("try to move %s, but in vain.", the(xname(otmp)));
  221. X        if (Blind) feel_location(u.ux+u.dx, u.uy+u.dy);
  222. X    cannot_push:
  223. X#ifdef POLYSELF
  224. X        if (throws_rocks(uasmon)) {
  225. X        if (!flags.pickup)
  226. X            pline("However, you easily can push it aside.");
  227. X        else
  228. X            pline("However, you easily can pick it up.");
  229. X        break;
  230. X        }
  231. X#endif
  232. X        if (((!invent || inv_weight() <= -850) &&
  233. X         (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy+u.dy].typ)
  234. X                     && IS_ROCK(levl[u.ux+u.dx][u.uy].typ))))
  235. X#ifdef POLYSELF
  236. X        || verysmall(uasmon)
  237. X#endif
  238. X        ) {
  239. X        pline("However, you can squeeze yourself into a small opening.");
  240. X        break;
  241. X        } else
  242. X        return (-1);
  243. X    }
  244. X    }
  245. X    return (0);
  246. X}
  247. X
  248. X#ifdef POLYSELF
  249. X/*
  250. X *  still_chewing()
  251. X *  
  252. X *  Chew on a wall, door, or boulder.  Returns TRUE if still eating, FALSE
  253. X *  when done.
  254. X */
  255. XSTATIC_OVL int
  256. Xstill_chewing(x,y)
  257. X    xchar x, y;
  258. X{
  259. X    struct rm *lev      = &(levl[x][y]);
  260. X    struct obj *boulder = sobj_at(BOULDER,x,y);
  261. X
  262. X    if (dig_pos.x != x || dig_pos.y != y ||
  263. X                !on_level(&dig_level, &u.uz) || dig_down) {
  264. X    if (!boulder && (lev->diggable & W_NONDIGGABLE))
  265. X        You("hurt your teeth on the hard stone.");
  266. X    else {
  267. X        dig_down = FALSE;
  268. X        dig_pos.x = x;
  269. X        dig_pos.y = y;
  270. X        assign_level(&dig_level, &u.uz);
  271. X        dig_effort = IS_ROCK(lev->typ) ? 30 : 60; /* rock takes more time */
  272. X        if (boulder)
  273. X        You("start chewing on a boulder.");
  274. X        else
  275. X        You("start chewing a hole in the %s.",
  276. X                    IS_ROCK(lev->typ) ? "rock" : "door");
  277. X    }
  278. X    return 1;
  279. X    } else if ((dig_effort += 30) < 100)  {
  280. X    if (flags.verbose)
  281. X        You("continue chewing on the %s.", boulder ? "boulder" :
  282. X                    (IS_ROCK(lev->typ) ? "rock" : "door"));
  283. X    return 1;
  284. X    }
  285. X
  286. X    if (boulder) {
  287. X    You("eat the boulder.");    /* yum */
  288. X    delobj(boulder);        /* boulder goes bye-bye */
  289. X
  290. X    /*
  291. X     *  The location could still block because of
  292. X     *      1. More than one boulder
  293. X     *      2. Boulder stuck in a wall/stone/door.
  294. X     *
  295. X     *  [perhaps use does_block() below (from vision.c)]
  296. X     */
  297. X    if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) {
  298. X        block_point(x,y);    /* delobj will unblock the point */
  299. X        dig_pos.x = 0;    /* reset dig messages */
  300. X        return 1;
  301. X    }
  302. X    
  303. X    } else if (IS_WALL(lev->typ)) {
  304. X    You("chew a hole in the wall.");
  305. X    if (level.flags.is_maze_lev) {
  306. X        lev->typ = ROOM;
  307. X    } else if (level.flags.is_cavernous_lev) {
  308. X        lev->typ = CORR;
  309. X    } else {
  310. X        lev->typ = DOOR;
  311. X        lev->doormask = D_NODOOR;
  312. X    }
  313. X    } else if (lev->typ == SDOOR) {
  314. X    if (lev->doormask & D_TRAPPED) {
  315. X        b_trapped("secret door");
  316. X        lev->doormask = D_NODOOR;
  317. X    } else {
  318. X        You("chew through the secret door.");
  319. X        lev->doormask = D_BROKEN;
  320. X    }
  321. X    lev->typ = DOOR;
  322. X
  323. X    } else if (IS_DOOR(lev->typ)) {
  324. X    if (lev->doormask & D_TRAPPED) {
  325. X        b_trapped("door");
  326. X        lev->doormask = D_NODOOR;
  327. X    } else {
  328. X        You("chew through the door.");
  329. X        lev->doormask = D_BROKEN;
  330. X    }
  331. X
  332. X    } else { /* STONE or SCORR */
  333. X    You("chew a passage through the rock.");
  334. X    lev->typ = CORR;
  335. X    }
  336. X
  337. X    unblock_point(x, y);    /* vision */
  338. X    newsym(x, y);
  339. X    dig_level.dnum = 0;
  340. X    dig_level.dlevel = -1;
  341. X    return 0;
  342. X}
  343. X#endif /* POLYSELF */
  344. X
  345. X#endif /* OVL2 */
  346. X#ifdef OVLB
  347. X
  348. Xvoid
  349. Xmovobj(obj, ox, oy)
  350. Xregister struct obj *obj;
  351. Xregister xchar ox, oy;
  352. X{
  353. X    remove_object(obj);
  354. X    newsym(obj->ox, obj->oy);
  355. X    place_object(obj, ox, oy);
  356. X    newsym(ox, oy);
  357. X}
  358. X
  359. X#ifdef SINKS
  360. XSTATIC_OVL void
  361. Xdosinkfall()
  362. X{
  363. X    register struct obj *obj;
  364. X
  365. X# ifdef POLYSELF
  366. X    if (is_floater(uasmon)) {
  367. X        You("wobble unsteadily for a moment.");
  368. X    } else {
  369. X# endif
  370. X        You("crash to the floor!");
  371. X        losehp((rn1(10, 20 - (int)ACURR(A_CON))),
  372. X            "fell onto a sink", NO_KILLER_PREFIX);
  373. X        exercise(A_DEX, FALSE);
  374. X        for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
  375. X            if(obj->oclass == WEAPON_CLASS) {
  376. X            You("fell on %s.",doname(obj));
  377. X            losehp(rn2(3),"fell onto a sink", NO_KILLER_PREFIX);
  378. X            exercise(A_CON, FALSE);
  379. X            }
  380. X# ifdef POLYSELF
  381. X    }
  382. X# endif
  383. X
  384. X    HLevitation = (HLevitation & ~TIMEOUT) + 1;
  385. X    if(uleft && uleft->otyp == RIN_LEVITATION) {
  386. X        obj = uleft;
  387. X        Ring_off(obj);
  388. X        off_msg(obj);
  389. X    }
  390. X    if(uright && uright->otyp == RIN_LEVITATION) {
  391. X        obj = uright;
  392. X        Ring_off(obj);
  393. X        off_msg(obj);
  394. X    }
  395. X    if(uarmf && uarmf->otyp == LEVITATION_BOOTS) {
  396. X        obj = uarmf;
  397. X        (void)Boots_off();
  398. X        off_msg(obj);
  399. X    }
  400. X    HLevitation--;
  401. X}
  402. X#endif
  403. X
  404. X#endif /* OVLB */
  405. X
  406. X#ifdef OVLB
  407. X
  408. Xboolean
  409. Xmay_dig(x,y)
  410. Xregister xchar x,y;
  411. X/* intended to be called only on ROCKs */
  412. X{
  413. Xreturn (!(IS_STWALL(levl[x][y].typ) && (levl[x][y].diggable & W_NONDIGGABLE)));
  414. X}
  415. X
  416. X#endif /* OVLB */
  417. X#ifdef OVL1
  418. X
  419. XSTATIC_OVL boolean
  420. Xbad_rock(x,y)
  421. Xregister xchar x,y;
  422. X{
  423. X    return(IS_ROCK(levl[x][y].typ)
  424. X#ifdef POLYSELF
  425. X            && !passes_walls(uasmon)
  426. X            && (!tunnels(uasmon) || needspick(uasmon) || !may_dig(x,y))
  427. X#endif
  428. X    );
  429. X}
  430. X
  431. Xboolean
  432. Xinvocation_pos(x, y)
  433. Xxchar x, y;
  434. X{
  435. X        return(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y);
  436. X}
  437. X
  438. X#endif /* OVL1 */
  439. X#ifdef OVL3
  440. X
  441. Xvoid
  442. Xdomove()
  443. X{
  444. X    register struct monst *mtmp;
  445. X    register struct rm *tmpr,*ust;
  446. X    register xchar x,y;
  447. X    struct trap *trap;
  448. X    int wtcap;
  449. X    boolean on_ice;
  450. X    xchar chainx, chainy, ballx, bally;    /* ball&chain new positions */
  451. X    int bc_control;                /* control for ball&chain */
  452. X
  453. X    u_wipe_engr(rnd(5));
  454. X
  455. X    if(((wtcap = near_capacity()) >= OVERLOADED
  456. X        || (wtcap > SLT_ENCUMBER && (u.uhp < 10 && u.uhp != u.uhpmax)))
  457. X       && !Is_airlevel(&u.uz)) {
  458. X        if(wtcap < OVERLOADED) {
  459. X        You("don't have enough stamina to move.");
  460. X            exercise(A_CON, FALSE);
  461. X        } else
  462. X        You("collapse under your load.");
  463. X        nomul(0);
  464. X        return;
  465. X    }
  466. X    if(u.uswallow) {
  467. X        u.dx = u.dy = 0;
  468. X        u.ux = x = u.ustuck->mx;
  469. X        u.uy = y = u.ustuck->my;
  470. X        mtmp = u.ustuck;
  471. X    } else {
  472. X        if(Is_airlevel(&u.uz) && rn2(4) && !Levitation
  473. X#ifdef POLYSELF
  474. X           && !is_flyer(uasmon)
  475. X#endif
  476. X           ) {
  477. X            switch(rn2(3)) {
  478. X            case 0:
  479. X            You("tumble in place.");
  480. X            exercise(A_DEX, FALSE);
  481. X            break;
  482. X            case 1:
  483. X            You("can't control your movements very well."); break;
  484. X            case 2:
  485. X            pline("It's hard to walk in thin air.");
  486. X            exercise(A_DEX, TRUE);
  487. X            break;
  488. X            }
  489. X            return;
  490. X        }
  491. X
  492. X        /* check slippery ice */
  493. X        on_ice = !Levitation && is_ice(u.ux, u.uy);
  494. X        if (on_ice) {
  495. X            static int skates = 0;
  496. X            if (!skates) skates = find_skates();
  497. X            if ((uarmf && uarmf->otyp == skates)
  498. X#ifdef POLYSELF
  499. X            || resists_cold(uasmon) || is_flyer(uasmon)
  500. X            || is_floater(uasmon) || is_clinger(uasmon)
  501. X            || is_whirly(uasmon)
  502. X#endif
  503. X               ) on_ice = FALSE;
  504. X            else if (!rn2(Cold_resistance ? 3 : 2)) {
  505. X            Fumbling |= FROMOUTSIDE;
  506. X            if (!(Fumbling & TIMEOUT)) Fumbling += rnd(20);
  507. X            }
  508. X        }
  509. X        if (!on_ice && (Fumbling & FROMOUTSIDE)) {
  510. X            Fumbling &= ~FROMOUTSIDE;
  511. X            if (!(Fumbling & ~TIMEOUT)) Fumbling = 0;
  512. X        }
  513. X
  514. X        x = u.ux + u.dx;
  515. X        y = u.uy + u.dy;
  516. X        if(Stunned || (Confusion && !rn2(5))) {
  517. X            register int tries = 0;
  518. X
  519. X            do {
  520. X                if(tries++ > 50) {
  521. X                    nomul(0);
  522. X                    return;
  523. X                }
  524. X                confdir();
  525. X                x = u.ux + u.dx;
  526. X                y = u.uy + u.dy;
  527. X            } while(!isok(x, y) || bad_rock(x, y));
  528. X        }
  529. X        if(!isok(x, y)) {
  530. X            nomul(0);
  531. X            return;
  532. X        }
  533. X        if((trap = t_at(x, y)) && trap->tseen) {
  534. X            if(flags.run >= 2) {
  535. X                nomul(0);
  536. X                flags.move = 0;
  537. X                return;
  538. X            } else
  539. X                nomul(0);
  540. X        }
  541. X            
  542. X        if(u.ustuck && (x != u.ustuck->mx ||
  543. X                y != u.ustuck->my)) {
  544. X            if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
  545. X            /* perhaps it fled (or was teleported or ... ) */
  546. X                u.ustuck = 0;
  547. X            } else {
  548. X#ifdef POLYSELF
  549. X                /* If polymorphed into a sticking monster,
  550. X                 * u.ustuck means it's stuck to you, not you
  551. X                 * to it.
  552. X                 */
  553. X                if (sticks(uasmon)) {
  554. X                    You("release %s.", mon_nam(u.ustuck));
  555. X                    u.ustuck = 0;
  556. X                } else {
  557. X#endif
  558. X                    You("cannot escape from %s!",
  559. X                        mon_nam(u.ustuck));
  560. X                    nomul(0);
  561. X                    return;
  562. X#ifdef POLYSELF
  563. X                }
  564. X#endif
  565. X            }
  566. X        }
  567. X        mtmp = m_at(x,y);
  568. X        if (mtmp) {
  569. X            /* Don't attack if you're running, and can see it */
  570. X            if (flags.run &&
  571. X                ((!Blind && mon_visible(mtmp) &&
  572. X                  ((mtmp->m_ap_type != M_AP_FURNITURE &&
  573. X                mtmp->m_ap_type != M_AP_OBJECT) ||
  574. X                   Protection_from_shape_changers)) ||
  575. X                 sensemon(mtmp))) {
  576. X                nomul(0);
  577. X                flags.move = 0;
  578. X                return;
  579. X            }
  580. X        }
  581. X    }
  582. X
  583. X    u.ux0 = u.ux;
  584. X    u.uy0 = u.uy;
  585. X    bhitpos.x = x;
  586. X    bhitpos.y = y;
  587. X    tmpr = &levl[x][y];
  588. X
  589. X    /* attack monster */
  590. X    if(mtmp) {
  591. X        nomul(0);
  592. X        /* only attack if we know it's there */
  593. X        /* or if it hides_under, in which case we call attack() to print
  594. X         * the Wait! message.
  595. X         * This is different from ceiling hiders, who aren't handled in
  596. X         * attack().
  597. X         */
  598. X        if(!mtmp->mundetected || sensemon(mtmp) ||
  599. X            (hides_under(mtmp->data) && !is_safepet(mtmp))){
  600. X        gethungry();
  601. X        if(wtcap >= HVY_ENCUMBER && moves%3) {
  602. X            if(u.uhp > 1)
  603. X            u.uhp--;
  604. X            else {
  605. X            pline("You pass out from exertion!");
  606. X            exercise(A_CON, FALSE);
  607. X            nomul(-10);
  608. X            u.usleep = 1;
  609. X            }
  610. X        }
  611. X        if(multi < 0) return;    /* we just fainted */
  612. X
  613. X        /* try to attack; note that it might evade */
  614. X        /* also, we don't attack tame when _safepet_ */
  615. X        if(attack(mtmp)) return;
  616. X        }
  617. X    }
  618. X
  619. X    /* not attacking an animal, so we try to move */
  620. X#ifdef POLYSELF
  621. X    if(!uasmon->mmove) {
  622. X        You("are rooted %s.",
  623. X            Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
  624. X            "in place" : "to the ground");
  625. X        nomul(0);
  626. X        return;
  627. X    }
  628. X#endif
  629. X    if(u.utrap) {
  630. X        if(u.utraptype == TT_PIT) {
  631. X            if (!rn2(2) && sobj_at(BOULDER, u.ux, u.uy)) {
  632. X            Your("%s gets stuck in a crevice.", body_part(LEG));
  633. X            display_nhwindow(WIN_MESSAGE, FALSE);
  634. X            clear_nhwindow(WIN_MESSAGE);
  635. X            You("free your %s.", body_part(LEG));
  636. X            } else if (!(--u.utrap)) {
  637. X            You("crawl to the edge of the pit.");
  638. X            fill_pit(u.ux, u.uy);
  639. X            vision_full_recalc = 1;    /* vision limits change */
  640. X            } else if (flags.verbose) 
  641. X            Norep( (Hallucination && !rn2(5)) ?
  642. X                "You've fallen, and you can't get up." :
  643. X                "You are still in a pit." );
  644. X        } else if (u.utraptype == TT_LAVA) {
  645. X            if(flags.verbose)
  646. X                Norep("You are stuck in the lava.");
  647. X            if(!is_lava(x,y)) {
  648. X            u.utrap--;
  649. X            if((u.utrap & 0xff) == 0) {
  650. X                You("pull yourself to the edge of the lava.");
  651. X                u.utrap = 0;
  652. X            }
  653. X            }
  654. X            u.umoved = TRUE;
  655. X        } else if (u.utraptype == TT_WEB) {
  656. X            if(--u.utrap) {
  657. X            if(flags.verbose)
  658. X                Norep("You are stuck to the web.");
  659. X            } else You("disentangle yourself.");
  660. X        } else if (u.utraptype == TT_INFLOOR) {
  661. X            if(--u.utrap) {
  662. X            if(flags.verbose)
  663. X                Norep("You are stuck in the floor.");
  664. X            } else You("finally wiggle free.");
  665. X        } else {
  666. X            if(flags.verbose)
  667. X            Norep("You are caught in a bear trap.");
  668. X            if((u.dx && u.dy) || !rn2(5)) u.utrap--;
  669. X        }
  670. X        return;
  671. X    }
  672. X
  673. X
  674. X    /*
  675. X     *  Check for physical obstacles.  First, the place we are going.
  676. X     */
  677. X    if (IS_ROCK(tmpr->typ)) {
  678. X        if (Blind) feel_location(x,y);
  679. X#ifdef POLYSELF
  680. X        if (passes_walls(uasmon)) {
  681. X        ;    /* do nothing */
  682. X        } else if (tunnels(uasmon) && !needspick(uasmon)) {
  683. X        /* Eat the rock. */
  684. X        if (still_chewing(x,y)) return;
  685. X        } else {
  686. X#endif
  687. X        if (Is_stronghold(&u.uz) && is_db_wall(x,y))
  688. X            pline("The drawbridge is up!");
  689. X        flags.move = 0;
  690. X        nomul(0);
  691. X        return;
  692. X#ifdef POLYSELF
  693. X        }
  694. X#endif
  695. X    } else if (IS_DOOR(tmpr->typ)) {
  696. X        if (closed_door(x,y)) {
  697. X        if (Blind) feel_location(x,y);
  698. X#ifdef POLYSELF
  699. X        if (passes_walls(uasmon))
  700. X            ;    /* do nothing */
  701. X        else if (amorphous(uasmon))
  702. X            You("ooze under the door.");
  703. X        else if (tunnels(uasmon) && !needspick(uasmon)) {
  704. X            /* Eat the door. */
  705. X            if (still_chewing(x,y)) return;
  706. X        } else {
  707. X#endif
  708. X            flags.move = 0;
  709. X            if (x == u.ux || y == u.uy) {
  710. X            if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
  711. X                pline("Ouch!  You bump into a door.");
  712. X                exercise(A_DEX, FALSE);
  713. X            } else pline("That door is closed.");
  714. X            }
  715. X            nomul(0);
  716. X            return;
  717. X#ifdef POLYSELF
  718. X        }
  719. X#endif
  720. X        } else if (u.dx && u.dy
  721. X#ifdef POLYSELF
  722. X            && !passes_walls(uasmon)
  723. X#endif
  724. X            && ((tmpr->doormask & ~D_BROKEN)
  725. X#ifdef REINCARNATION
  726. X                    || Is_rogue_level(&u.uz)
  727. X#endif
  728. X                    || block_door(x,y))) {
  729. X        /* Diagonal moves into a door are not allowed. */
  730. X        if (Blind) feel_location(x,y);    /* ?? */
  731. X        flags.move = 0;
  732. X        nomul(0);
  733. X        return;
  734. X        }
  735. X    }
  736. X    if (u.dx && u.dy && bad_rock(u.ux,y) && bad_rock(x,u.uy)) {
  737. X        /* Move at a diagonal. */
  738. X#ifdef POLYSELF
  739. X        if (bigmonst(uasmon)) {
  740. X        Your("body is too large to fit through.");
  741. X        nomul(0);
  742. X        return;
  743. X        }
  744. X#endif
  745. X        if (invent && inv_weight() > -400) {
  746. X        You("are carrying too much to get through.");
  747. X        nomul(0);
  748. X        return;
  749. X        }
  750. X    }
  751. X
  752. X    ust = &levl[u.ux][u.uy];
  753. X
  754. X    /* Now see if other things block our way . . */
  755. X    if (u.dx && u.dy
  756. X#ifdef POLYSELF
  757. X             && !passes_walls(uasmon)
  758. X#endif
  759. X             && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN)
  760. X#ifdef REINCARNATION
  761. X                 || Is_rogue_level(&u.uz)
  762. X#endif
  763. X                 || block_entry(x, y))
  764. X                 )) {
  765. X        /* Can't move at a diagonal out of a doorway with door. */
  766. X        flags.move = 0;
  767. X        nomul(0);
  768. X        return;
  769. X    }
  770. X
  771. X    if (sobj_at(BOULDER,x,y)
  772. X#ifdef POLYSELF
  773. X                && !passes_walls(uasmon)
  774. X#endif
  775. X                            ) {
  776. X        if (!(Blind || Hallucination) && (flags.run >= 2)) {
  777. X        nomul(0);
  778. X        flags.move = 0;
  779. X        return;
  780. X        }
  781. X#ifdef POLYSELF
  782. X        /* tunneling monsters will chew before pushing */
  783. X        if (tunnels(uasmon) && !needspick(uasmon)) {
  784. X        if (still_chewing(x,y)) return;
  785. X        } else
  786. X#endif
  787. X        if (moverock() < 0) return;
  788. X    }
  789. X
  790. X    /* OK, it is a legal place to move. */
  791. X
  792. X    /* Move ball and chain.  */
  793. X    if (Punished)
  794. X        if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy))
  795. X        return;
  796. X
  797. X    /* now move the hero */
  798. X    mtmp = m_at(x, y);
  799. X    if (u.uinwater) water_friction();
  800. X    u.ux += u.dx;
  801. X    u.uy += u.dy;
  802. X    /* if safepet at destination then move the pet to the hero's
  803. X     * previous location using the same conditions as in attack().
  804. X     * there are special extenuating circumstances:
  805. X     * (1) if the pet dies then your god angers,
  806. X     * (2) if the pet gets trapped then your god may disapprove,
  807. X     * (3) if the pet was already trapped and you attempt to free it
  808. X     * not only do you encounter the trap but you may frighten your
  809. X     * pet causing it to go wild!  moral: don't abuse this privilege.
  810. X     */
  811. X    /* Ceiling-hiding pets are skipped by this section of code, to
  812. X     * be caught by the normal falling-monster code.
  813. X     */
  814. X    if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
  815. X        int swap_result;
  816. X
  817. X        /* if trapped, there's a chance the pet goes wild */
  818. X        if (mtmp->mtrapped && !rn2(4)) {
  819. X            pline ("%s suddenly goes wild!",
  820. X               mtmp->mnamelth ? NAME(mtmp) : Monnam(mtmp));
  821. X            mtmp->mtame = mtmp->mpeaceful = mtmp->msleep = 0;
  822. X        }
  823. X
  824. X        mtmp->mtrapped = 0;
  825. X        mtmp->mundetected = 0;
  826. X        remove_monster(x, y);
  827. X        place_monster(mtmp, u.ux0, u.uy0);
  828. X
  829. X        /* check first to see if monster drowned.
  830. X         * then check for traps.
  831. X         */
  832. X        if (minwater(mtmp)) {
  833. X            swap_result = 2;
  834. X        } else swap_result = mintrap(mtmp);
  835. X
  836. X        switch (swap_result) {
  837. X        case 0:
  838. X            You("%s %s.", mtmp->mtame ? "displaced" : "frightened",
  839. X                mtmp->mnamelth ? NAME(mtmp) : mon_nam(mtmp));
  840. X            break;
  841. X        case 1:    /* trapped */
  842. X        case 3: /* changed levels */
  843. X            /* there's already been a trap message, reinforce it */
  844. X            pline("Trapping your pet was a selfish move.");
  845. X            if (!rn2(4)) {
  846. X            pline("You'll pay!");
  847. X            adjalign(-5);
  848. X            }
  849. X            break;
  850. X        case 2:
  851. X            /* it may have drowned or died.  that's no way to
  852. X             * treat a pet!  your god gets angry and complains.
  853. X             */
  854. X            if (rn2(4)) {
  855. X            pline ("%s complains in a booming voice:", u_gname());
  856. X            verbalize("Losing your pet like this was a mistake!");
  857. X            u.ugangr++ ;
  858. X            adjalign(-15);
  859. X            }
  860. X            break;
  861. X        default:
  862. X            pline("that's strange, unknown mintrap result!");
  863. X            break;
  864. X        }
  865. X    }
  866. X
  867. X    reset_occupations();
  868. X    if(flags.run) {
  869. X        if(IS_DOOR(tmpr->typ) ||
  870. X#ifdef POLYSELF
  871. X        (IS_ROCK(tmpr->typ)) ||
  872. X#endif
  873. X        (xupstair == u.ux && yupstair == u.uy) ||
  874. X        (xdnstair == u.ux && ydnstair == u.uy)
  875. X        || (sstairs.sx == u.ux && sstairs.sy == u.uy)
  876. X        || (xupladder == u.ux && yupladder == u.uy)
  877. X        || (xdnladder == u.ux && ydnladder == u.uy)
  878. X        || IS_FOUNTAIN(tmpr->typ)
  879. X        || IS_THRONE(tmpr->typ)
  880. X#ifdef SINKS
  881. X        || IS_SINK(tmpr->typ)
  882. X#endif
  883. X        || IS_ALTAR(tmpr->typ)
  884. X        )
  885. X            nomul(0);
  886. X    }
  887. X#ifdef POLYSELF
  888. X    if (hides_under(uasmon))
  889. X        u.uundetected = OBJ_AT(u.ux, u.uy);
  890. X    else if (u.dx || u.dy) { /* piercer */
  891. X        if (u.usym == S_MIMIC_DEF)
  892. X        u.usym = S_MIMIC;
  893. X        u.uundetected = 0;
  894. X    }
  895. X#endif
  896. X
  897. X#ifdef WALKIES
  898. X    check_leash(u.ux0,u.uy0);
  899. X#endif
  900. X    if(u.ux0 != u.ux || u.uy0 != u.uy) {
  901. X        u.umoved = TRUE;
  902. X        /* Clean old position -- vision_recalc() will print our new one. */
  903. X        newsym(u.ux0,u.uy0);
  904. X        /* Since the hero has moved, adjust what can be seen/unseen. */
  905. X        vision_recalc(1);    /* Do the work now in the recover time. */
  906. X
  907. X        /* a special clue-msg when on the Invocation position */
  908. X        if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
  909. X            register struct obj *otmp;
  910. X
  911. X            You("feel a strange vibration under your %s.",
  912. X            makeplural(body_part(FOOT)));
  913. X
  914. X        for(otmp = invent; otmp; otmp = otmp->nobj) {
  915. X                if(otmp->otyp == CANDELABRUM_OF_INVOCATION &&
  916. X               otmp->spe == 7 && otmp->lamplit) {
  917. X                      pline("%s glows with a strange light!",
  918. X                The(xname(otmp)));
  919. X              break;
  920. X               }
  921. X            }
  922. X        
  923. X        }
  924. X    }
  925. X
  926. X    if (Punished)                /* put back ball and chain */
  927. X        move_bc(0,bc_control,ballx,bally,chainx,chainy);
  928. X
  929. X    spoteffects();
  930. X}
  931. X
  932. X#endif /* OVL3 */
  933. X#ifdef OVL2
  934. X
  935. Xvoid
  936. Xspoteffects()
  937. X{
  938. X    register struct trap *trap;
  939. X    register struct monst *mtmp;
  940. X
  941. X    if(u.uinwater) {
  942. X        int was_underwater;
  943. X
  944. X        if (!is_pool(u.ux,u.uy)) {
  945. X            if (Is_waterlevel(&u.uz))
  946. X                You("pop into an air bubble.");
  947. X            else
  948. X                You("are on solid ground again.");
  949. X        }
  950. X        else if (Is_waterlevel(&u.uz))
  951. X            goto stillinwater;
  952. X        else if (Levitation || is_floater(uasmon))
  953. X            You("pop out of the water like a cork!");
  954. X        else if (is_flyer(uasmon))
  955. X            You("fly out of the water.");
  956. X        else if (Wwalking)
  957. X            You("slowly rise above the surface.");
  958. X        else
  959. X            goto stillinwater;
  960. X        was_underwater = Underwater && !Is_waterlevel(&u.uz);
  961. X        u.uinwater = 0;        /* leave the water */
  962. X        if (was_underwater) {    /* restore vision */
  963. X            docrt();
  964. X            vision_full_recalc = 1;
  965. X        }
  966. X    }
  967. Xstillinwater:;
  968. X    if(!Levitation && !u.ustuck
  969. X#ifdef POLYSELF
  970. X       && !is_flyer(uasmon)
  971. X#endif
  972. X       ) {
  973. X        /* limit recursive calls through teleds() */
  974. X        if(is_lava(u.ux,u.uy) && lava_effects())
  975. X            return;
  976. X        if(is_pool(u.ux,u.uy) && !Wwalking && drown())
  977. X            return;
  978. X    }
  979. X    check_special_room(FALSE);
  980. X#ifdef SINKS
  981. X    if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
  982. X        dosinkfall();
  983. X#endif
  984. X    if(!flags.nopick && OBJ_AT(u.ux, u.uy) &&
  985. X       (!is_pool(u.ux,u.uy) || Underwater))
  986. X        pickup(1);
  987. X    else read_engr_at(u.ux,u.uy);
  988. X    if(trap = t_at(u.ux,u.uy))
  989. X        dotrap(trap);    /* fall into pit, arrow trap, etc. */
  990. X    if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
  991. X        mtmp->mundetected = 0;
  992. X        switch(mtmp->data->mlet) {
  993. X            case S_PIERCER:
  994. X            pline("%s suddenly drops from the ceiling!",
  995. X                  Amonnam(mtmp));
  996. X            if(mtmp->mtame) /* jumps to greet you, not attack */
  997. X                ;
  998. X            else if(uarmh)
  999. X                pline("Its blow glances off your helmet.");
  1000. X            else if (u.uac + 3 <= rnd(20))
  1001. X                You("are almost hit by %s!",
  1002. X                x_monnam(mtmp, 2, "falling", 1));
  1003. X            else {
  1004. X                int dmg;
  1005. X                You("are hit by %s!",
  1006. X                x_monnam(mtmp, 2, "falling", 1));
  1007. X                dmg = d(4,6);
  1008. X                if(Half_physical_damage) dmg = (dmg+1) / 2;
  1009. X                mdamageu(mtmp, dmg);
  1010. X            }
  1011. X            break;
  1012. X            default:    /* monster surprises you. */
  1013. X            if(mtmp->mtame)
  1014. X                pline("%s jumps near you from the ceiling.",
  1015. X                    Amonnam(mtmp));
  1016. X            else if(mtmp->mpeaceful) {
  1017. X                You("surprise %s!",
  1018. X                    Blind && !sensemon(mtmp) ?
  1019. X                    "something" : a_monnam(mtmp));
  1020. X                mtmp->mpeaceful = 0;
  1021. X            } else
  1022. X                pline("%s attacks you by surprise!",
  1023. X                    Amonnam(mtmp));
  1024. X            break;
  1025. X        }
  1026. X        mnexto(mtmp); /* have to move the monster */
  1027. X    }
  1028. X}
  1029. X
  1030. XSTATIC_OVL boolean
  1031. Xmonstinroom(mdat,roomno)
  1032. Xstruct permonst *mdat;
  1033. Xint roomno;
  1034. X{
  1035. X    register struct monst *mtmp;
  1036. X
  1037. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1038. X        if(mtmp->data == mdat && 
  1039. X           index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
  1040. X            return(TRUE);
  1041. X    return(FALSE);
  1042. X}
  1043. X
  1044. Xchar *
  1045. Xin_rooms(x, y, typewanted)
  1046. Xregister xchar x, y;
  1047. Xregister int typewanted;
  1048. X{
  1049. X    static char buf[5];
  1050. X    char rno, *ptr = &buf[4];
  1051. X    int typefound, min_x, min_y, max_x, max_y_offset, step;
  1052. X    register struct rm *lev;
  1053. X
  1054. X#define goodtype(rno) (!typewanted || \
  1055. X         ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \
  1056. X         ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \
  1057. X
  1058. X    switch (rno = levl[x][y].roomno) { 
  1059. X        case NO_ROOM:
  1060. X            return(ptr);
  1061. X        case SHARED:
  1062. X            step = 2;
  1063. X            break;
  1064. X        case SHARED_PLUS:
  1065. X            step = 1;
  1066. X            break;
  1067. X        default:            /* i.e. a regular room # */
  1068. X            if (goodtype(rno)) 
  1069. X                *(--ptr) = rno;
  1070. X            return(ptr);
  1071. X    }
  1072. X
  1073. X    min_x = x - 1;
  1074. X    max_x = x + 1;
  1075. X    if (x < 0)
  1076. X        min_x += step;
  1077. X    else 
  1078. X    if (x >= COLNO)
  1079. X        max_x -= step;
  1080. X
  1081. X    min_y = y - 1;
  1082. X    max_y_offset = 2;
  1083. X    if (min_y < 0) {
  1084. X        min_y += step;
  1085. X        max_y_offset -= step;
  1086. X    } else
  1087. X    if ((min_y + max_y_offset) >= ROWNO)
  1088. X        max_y_offset -= step;
  1089. X
  1090. X    for (x = min_x; x <= max_x; x += step) {
  1091. X        lev = &levl[x][min_y];
  1092. X        y = 0;
  1093. X        if (((rno = lev[y].roomno) >= ROOMOFFSET) && 
  1094. X            !index(ptr, rno) && goodtype(rno)) 
  1095. X            *(--ptr) = rno;
  1096. X        y += step;
  1097. X        if (y > max_y_offset)
  1098. X            continue;
  1099. X        if (((rno = lev[y].roomno) >= ROOMOFFSET) && 
  1100. X                 !index(ptr, rno) && goodtype(rno))
  1101. X            *(--ptr) = rno;
  1102. X        y += step;
  1103. X        if (y > max_y_offset)
  1104. X            continue;
  1105. X        if (((rno = lev[y].roomno) >= ROOMOFFSET) && 
  1106. X            !index(ptr, rno) && goodtype(rno))
  1107. X            *(--ptr) = rno;
  1108. X    }
  1109. X    return(ptr);
  1110. X}
  1111. X
  1112. Xstatic void 
  1113. Xmove_update(newlev)
  1114. Xregister boolean newlev;
  1115. X{
  1116. X    char *ptr1, *ptr2, *ptr3, *ptr4;
  1117. X
  1118. X    Strcpy(u.urooms0, u.urooms);
  1119. X    Strcpy(u.ushops0, u.ushops);
  1120. X    if (newlev) {
  1121. X        u.urooms[0] = '\0';
  1122. X        u.uentered[0] = '\0';
  1123. X        u.ushops[0] = '\0';
  1124. X        u.ushops_entered[0] = '\0';
  1125. X        Strcpy(u.ushops_left, u.ushops0);
  1126. X        return;
  1127. X    } 
  1128. X    Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
  1129. X
  1130. X    for (ptr1 = &u.urooms[0], 
  1131. X         ptr2 = &u.uentered[0], 
  1132. X         ptr3 = &u.ushops[0],
  1133. X         ptr4 = &u.ushops_entered[0]; 
  1134. X         *ptr1; ptr1++) {
  1135. X        if (!index(u.urooms0, *ptr1))
  1136. X            *(ptr2++) = *ptr1;    
  1137. X        if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
  1138. X            *(ptr3++) = *ptr1;
  1139. X            if (!index(u.ushops0, *ptr1))
  1140. X                *(ptr4++) = *ptr1;
  1141. X        }
  1142. X    }
  1143. X    *ptr2 = '\0';
  1144. X    *ptr3 = '\0';
  1145. X    *ptr4 = '\0';
  1146. X
  1147. X    /* filter u.ushops0 -> u.ushops_left */
  1148. X    for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
  1149. X        if (!index(u.ushops, *ptr1))
  1150. X            *(ptr2++) = *ptr1;
  1151. X    *ptr2 = '\0';
  1152. X}
  1153. X
  1154. Xvoid
  1155. Xcheck_special_room(newlev) 
  1156. Xregister boolean newlev;
  1157. X{
  1158. X    register struct monst *mtmp;
  1159. X    char *ptr;
  1160. X
  1161. X    move_update(newlev);
  1162. X
  1163. X    if (*u.ushops0)
  1164. X        u_left_shop(u.ushops_left, newlev);
  1165. X
  1166. X    if (!*u.uentered && !*u.ushops_entered) 
  1167. X        return;        /* no entrance messages necessary */
  1168. X
  1169. X    /* Did we just enter a shop? */
  1170. X    if (*u.ushops_entered)
  1171. X            u_entered_shop(u.ushops_entered);
  1172. X
  1173. X    for (ptr = &u.uentered[0]; *ptr; ptr++) {
  1174. X        register int roomno = *ptr - ROOMOFFSET, rt = rooms[roomno].rtype;
  1175. X
  1176. X        /* Did we just enter some other special room? */
  1177. X        /* vault.c insists that a vault remain a VAULT,
  1178. X         * and temples should remain TEMPLEs,
  1179. X         * but everything else gives a message only the first time */
  1180. X        if(!newlev) 
  1181. X           switch (rt) {
  1182. X            case ZOO:
  1183. X               pline("Welcome to David's treasure zoo!");
  1184. X                break;
  1185. X            case SWAMP:
  1186. X                pline("It %s rather %s down here.",
  1187. X                      Blind ? "feels" : "looks",
  1188. X                      Blind ? "humid" : "muddy");
  1189. X                break;
  1190. X            case COURT:
  1191. X            You("enter an opulent throne room!");
  1192. X                break;
  1193. X            case MORGUE:
  1194. X                if(midnight())
  1195. X                pline("Run away!  Run away!");
  1196. X                else
  1197. X                You("have an uncanny feeling...");
  1198. X                break;
  1199. X            case BEEHIVE:
  1200. X                You("enter a giant beehive!");
  1201. X                break;
  1202. X#ifdef ARMY
  1203. X            case BARRACKS:
  1204. X                if(monstinroom(&mons[PM_SOLDIER], roomno) ||
  1205. X                monstinroom(&mons[PM_SERGEANT], roomno) ||
  1206. X                monstinroom(&mons[PM_LIEUTENANT], roomno) ||
  1207. X                monstinroom(&mons[PM_CAPTAIN], roomno))
  1208. X                    You("enter a military barracks!");
  1209. X                else 
  1210. X                You("enter an abandoned barracks.");
  1211. X                break;
  1212. X#endif
  1213. X            case DELPHI:
  1214. X                if(monstinroom(&mons[PM_ORACLE], roomno))
  1215. X                verbalize("Hello, %s, welcome to Delphi!", plname);
  1216. X                break;
  1217. X            case TEMPLE:
  1218. X            intemple(roomno + ROOMOFFSET);
  1219. X                /* fall through */
  1220. X            default:
  1221. X                rt = 0;
  1222. X            } 
  1223. X        else 
  1224. X        rt = 0;
  1225. X
  1226. X        if(rt != 0) {
  1227. X        rooms[roomno].rtype = OROOM;
  1228. X        if (!search_special(rt)) {
  1229. X            /* No more room of that type */
  1230. X            switch(rt) {
  1231. X                case COURT:
  1232. X                level.flags.has_court = 0;
  1233. X                break;
  1234. X                case SWAMP:
  1235. X                level.flags.has_swamp = 0;
  1236. X                break;
  1237. X                case MORGUE:
  1238. X                level.flags.has_morgue = 0;
  1239. X                break;
  1240. X                case ZOO:
  1241. X                level.flags.has_zoo = 0;
  1242. X                break;
  1243. X#ifdef ARMY
  1244. X                case BARRACKS:
  1245. X                level.flags.has_barracks = 0;
  1246. X                break;
  1247. X#endif
  1248. X                case TEMPLE:
  1249. X                level.flags.has_temple = 0;
  1250. X                break;
  1251. X                case BEEHIVE:
  1252. X                level.flags.has_beehive = 0;
  1253. X                break;
  1254. X            }
  1255. X        }
  1256. X        if(rt==COURT || rt==SWAMP || rt==MORGUE || rt==ZOO)
  1257. X            for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1258. X                if(!Stealth && !rn2(3))
  1259. X                    mtmp->msleep = 0;
  1260. X        }
  1261. X    }
  1262. X
  1263. X    return;
  1264. X}
  1265. X
  1266. X#endif /* OVL2 */
  1267. X#ifdef OVLB
  1268. X
  1269. Xint
  1270. Xdopickup()
  1271. X{
  1272. X    int count;
  1273. X    /* awful kludge to work around parse()'s pre-decrement */
  1274. X    count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
  1275. X    multi = 0;    /* always reset */
  1276. X    /* uswallow case added by GAN 01/29/87 */
  1277. X    if(u.uswallow) {
  1278. X        if (is_animal(u.ustuck->data)) {
  1279. X            You("pick up %s tongue.", 
  1280. X                        s_suffix(mon_nam(u.ustuck)));
  1281. X            pline("But it's kind of slimy, so you drop it.");
  1282. X        } else
  1283. X            You("don't %s anything in here to pick up.",
  1284. X              Blind ? "feel" : "see");
  1285. X        return(1);
  1286. X    }
  1287. X    if(!OBJ_AT(u.ux, u.uy)) {
  1288. X        pline("There is nothing here to pick up.");
  1289. X        return(0);
  1290. X    }
  1291. X    if(Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) {
  1292. X        You("cannot reach the floor.");
  1293. X        return(1);
  1294. X    }
  1295. X    if(is_pool(u.ux, u.uy)) {
  1296. X        if(Wwalking
  1297. X#ifdef POLYSELF
  1298. X           || is_flyer(uasmon) || is_clinger(uasmon)
  1299. X#endif
  1300. X           ) {
  1301. X            You("cannot dive into the water to pick things up.");
  1302. X            return(1);
  1303. X        }
  1304. X        else if(!Underwater) {
  1305. X            You("can't even see the bottom, let alone pick up something.");
  1306. X            return(1);
  1307. X        }
  1308. X    }
  1309. X    pickup(-count);
  1310. X    return(1);
  1311. X}
  1312. X
  1313. X#endif /* OVLB */
  1314. X#ifdef OVL2
  1315. X
  1316. X/* stop running if we see something interesting */
  1317. X/* turn around a corner if that is the only way we can proceed */
  1318. X/* do not turn left or right twice */
  1319. Xvoid
  1320. Xlookaround()
  1321. X{
  1322. X    register int x, y, i, x0 = 0, y0 = 0, m0 = 1, i0 = 9;
  1323. X    register int corrct = 0, noturn = 0;
  1324. X    register struct monst *mtmp;
  1325. X    register struct trap *trap;
  1326. X
  1327. X#ifdef POLYSELF
  1328. X    /* Grid bugs stop if trying to move diagonal, even if blind.  Maybe */
  1329. X    /* they polymorphed while in the middle of a long move. */
  1330. X    if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
  1331. X        nomul(0);
  1332. X        return;
  1333. X    }
  1334. X#endif
  1335. X    if(Blind || flags.run == 0) return;
  1336. X    for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) {
  1337. X        if(!isok(x,y)) continue;
  1338. X#ifdef POLYSELF
  1339. X    if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue;
  1340. X#endif
  1341. X    if(x == u.ux && y == u.uy) continue;
  1342. X
  1343. X    if((mtmp = m_at(x,y)) &&
  1344. X            mtmp->m_ap_type != M_AP_FURNITURE &&
  1345. X            mtmp->m_ap_type != M_AP_OBJECT &&
  1346. X            (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
  1347. X        if((flags.run != 1 && !mtmp->mtame)
  1348. X                    || (x == u.ux+u.dx && y == u.uy+u.dy))
  1349. X        goto stop;
  1350. X    }
  1351. X
  1352. X    if (levl[x][y].typ == STONE) continue;
  1353. X    if (x == u.ux-u.dx && y == u.uy-u.dy) continue;
  1354. X
  1355. X    if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||
  1356. X        IS_AIR(levl[x][y].typ))
  1357. X        continue;
  1358. X    else if (closed_door(x,y)) {
  1359. X        if(x != u.ux && y != u.uy) continue;
  1360. X        if(flags.run != 1) goto stop;
  1361. X        goto bcorr;
  1362. X    } else if (levl[x][y].typ == CORR) {
  1363. Xbcorr:
  1364. X        if(levl[u.ux][u.uy].typ != ROOM) {
  1365. X        if(flags.run == 1 || flags.run == 3) {
  1366. X            i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
  1367. X            if(i > 2) continue;
  1368. X            if(corrct == 1 && dist2(x,y,x0,y0) != 1)
  1369. X            noturn = 1;
  1370. X            if(i < i0) {
  1371. X            i0 = i;
  1372. X            x0 = x;
  1373. X            y0 = y;
  1374. X            m0 = mtmp ? 1 : 0;
  1375. X            }
  1376. X        }
  1377. X        corrct++;
  1378. X        }
  1379. X        continue;
  1380. X    } else if ((trap = t_at(x,y)) && trap->tseen) {
  1381. X        if(flags.run == 1) goto bcorr;    /* if you must */
  1382. X        if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
  1383. X        continue;
  1384. X    } else if (is_pool(x,y) || is_lava(x,y)) {
  1385. X        /* water and lava only stop you if directly in front, and stop
  1386. X         * you even if you are running
  1387. X         */
  1388. X        if(!Levitation &&
  1389. X#ifdef POLYSELF
  1390. X            !is_flyer(uasmon) && !is_clinger(uasmon) &&
  1391. X#endif
  1392. X            /* No Wwalking check; otherwise they'd be able
  1393. X             * to test boots by trying to SHIFT-direction
  1394. X             * into a pool and seeing if the game allowed it
  1395. X             */
  1396. X            x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
  1397. X        continue;
  1398. X    } else {        /* e.g. objects or trap or stairs */
  1399. X        if(flags.run == 1) goto bcorr;
  1400. X        if(mtmp) continue;        /* d */
  1401. X        if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||
  1402. X           ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
  1403. X           continue;
  1404. X    }
  1405. Xstop:
  1406. X    nomul(0);
  1407. X    return;
  1408. X    } /* end for loops */
  1409. X
  1410. X    if(corrct > 1 && flags.run == 2) goto stop;
  1411. X    if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
  1412. X                (corrct == 1 || (corrct == 2 && i0 == 1))) {
  1413. X    /* make sure that we do not turn too far */
  1414. X    if(i0 == 2) {
  1415. X        if(u.dx == y0-u.uy && u.dy == u.ux-x0)
  1416. X        i = 2;        /* straight turn right */
  1417. X        else
  1418. X        i = -2;        /* straight turn left */
  1419. X    } else if(u.dx && u.dy) {
  1420. X        if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
  1421. X        i = -1;        /* half turn left */
  1422. X        else
  1423. X        i = 1;        /* half turn right */
  1424. X    } else {
  1425. X        if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy))
  1426. X        i = 1;        /* half turn right */
  1427. X        else
  1428. X        i = -1;        /* half turn left */
  1429. X    }
  1430. X
  1431. X    i += u.last_str_turn;
  1432. X    if(i <= 2 && i >= -2) {
  1433. X        u.last_str_turn = i;
  1434. X        u.dx = x0-u.ux;
  1435. X        u.dy = y0-u.uy;
  1436. X    }
  1437. X    }
  1438. X}
  1439. X
  1440. X/* something like lookaround, but we are not running */
  1441. X/* react only to monsters that might hit us */
  1442. Xint
  1443. Xmonster_nearby()
  1444. X{
  1445. X    register int x,y;
  1446. X    register struct monst *mtmp;
  1447. X
  1448. X    if(!Blind)
  1449. X    for(x = u.ux-1; x <= u.ux+1; x++)
  1450. X        for(y = u.uy-1; y <= u.uy+1; y++) {
  1451. X        if(!isok(x,y)) continue;
  1452. X        if(x == u.ux && y == u.uy) continue;
  1453. X        if((mtmp = m_at(x,y)) &&
  1454. X           mtmp->m_ap_type != M_AP_FURNITURE &&
  1455. X           mtmp->m_ap_type != M_AP_OBJECT &&
  1456. X           !mtmp->mpeaceful &&
  1457. X           (!is_hider(mtmp->data) || !mtmp->mundetected) &&
  1458. X           !noattacks(mtmp->data) &&
  1459. X           mtmp->mcanmove && !mtmp->msleep &&  /* aplvax!jcn */
  1460. X           (!mtmp->minvis || See_invisible) &&
  1461. X           !onscary(u.ux, u.uy, mtmp))
  1462. X            return(1);
  1463. X    }
  1464. X    return(0);
  1465. X}
  1466. X
  1467. Xvoid
  1468. Xnomul(nval)
  1469. X    register int nval;
  1470. X{
  1471. X    if(multi < nval) return;    /* This is a bug fix by ab@unido */
  1472. X    u.uinvulnerable = FALSE;    /* Kludge to avoid ctrl-C bug -dlc */
  1473. X    u.usleep = 0;
  1474. X    multi = nval;
  1475. X    flags.mv = flags.run = 0;
  1476. X}
  1477. X
  1478. X#endif /* OVL2 */
  1479. X#ifdef OVL1
  1480. X
  1481. Xvoid
  1482. Xlosehp(n, knam, k_format)
  1483. Xregister int n;
  1484. Xregister const char *knam;
  1485. Xboolean k_format;
  1486. X{
  1487. X#ifdef POLYSELF
  1488. X    if (u.mtimedone) {
  1489. X        u.mh -= n;
  1490. X        if (u.mhmax < u.mh) u.mhmax = u.mh;
  1491. X        flags.botl = 1;
  1492. X        if (u.mh < 1) rehumanize();
  1493. X        return;
  1494. X    }
  1495. X#endif
  1496. X    u.uhp -= n;
  1497. X    if(u.uhp > u.uhpmax)
  1498. X        u.uhpmax = u.uhp;    /* perhaps n was negative */
  1499. X    flags.botl = 1;
  1500. X    if(u.uhp < 1) {
  1501. X        killer_format = k_format;
  1502. X        killer = knam;        /* the thing that killed you */
  1503. X        You("die...");
  1504. X        done(DIED);
  1505. X    } else if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50 && n > 0){
  1506. X        wailmsg = moves;
  1507. X        if(index("WEV", pl_character[0])) {
  1508. X            if (u.uhp == 1)
  1509. X                pline("%s is about to die.", pl_character);
  1510. X            else if (4 <= (!!(HTeleportation & INTRINSIC)) +
  1511. X                    (!!(HSee_invisible & INTRINSIC)) +
  1512. X                    (!!(HPoison_resistance & INTRINSIC)) +
  1513. X                    (!!(HCold_resistance & INTRINSIC)) +
  1514. X                    (!!(HShock_resistance & INTRINSIC)) +
  1515. X                    (!!(HFire_resistance & INTRINSIC)) +
  1516. X                    (!!(HSleep_resistance & INTRINSIC)) +
  1517. X                    (!!(HDisint_resistance & INTRINSIC)) +
  1518. X                    (!!(HTeleport_control & INTRINSIC)) +
  1519. X                    (!!(Stealth & INTRINSIC)) +
  1520. X                    (!!(Fast & INTRINSIC)) +
  1521. X                    (!!(HInvis & INTRINSIC)))
  1522. X                pline("%s, all your powers will be lost...",
  1523. X                    pl_character);
  1524. X            else
  1525. X                pline("%s, your life force is running out.",
  1526. X                    pl_character);
  1527. X        } else {
  1528. X            if(u.uhp == 1)
  1529. X                You("hear the wailing of the Banshee...");
  1530. X            else
  1531. X                You("hear the howling of the CwnAnnwn...");
  1532. X        }
  1533. X    }
  1534. X}
  1535. X
  1536. Xint
  1537. Xweight_cap()
  1538. X{
  1539. X    register long carrcap;
  1540. X
  1541. X    carrcap = (((ACURRSTR + ACURR(A_CON))/2)+1)*50;
  1542. X#ifdef POLYSELF
  1543. X    if (u.mtimedone) {
  1544. X        /* consistent with can_carry() in mon.c */
  1545. X        if (u.usym == S_NYMPH)
  1546. X                carrcap = MAX_CARR_CAP;
  1547. X        else if (!uasmon->cwt)
  1548. X            carrcap = (carrcap * (long)uasmon->msize) / MZ_HUMAN;
  1549. X        else if (!strongmonst(uasmon)
  1550. X            || (strongmonst(uasmon) && (uasmon->cwt > WT_HUMAN)))
  1551. X            carrcap = (carrcap * (long)uasmon->cwt / WT_HUMAN);
  1552. X    }
  1553. X#endif
  1554. X    if(Levitation || Is_airlevel(&u.uz))    /* pugh@cornell */
  1555. X        carrcap = MAX_CARR_CAP;
  1556. X    else {
  1557. X        if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
  1558. X        if(Wounded_legs & LEFT_SIDE) carrcap -= 100;
  1559. X        if(Wounded_legs & RIGHT_SIDE) carrcap -= 100;
  1560. X    }
  1561. X    return((int) carrcap);
  1562. X}
  1563. X
  1564. X/* returns how far beyond the normal capacity the player is currently. */
  1565. X/* inv_weight() is negative if the player is below normal capacity. */
  1566. Xint
  1567. Xinv_weight()
  1568. X{
  1569. X    register struct obj *otmp = invent;
  1570. X#ifdef LINT    /* long to int conversion */
  1571. X    register int wt = 0;
  1572. X#else
  1573. X    register int wt = (int)((u.ugold + 50L)/100L);
  1574. X#endif /* LINT */
  1575. X    while(otmp){
  1576. X#ifdef POLYSELF
  1577. X        if (otmp->otyp != BOULDER || !throws_rocks(uasmon))
  1578. X#endif
  1579. X            wt += otmp->owt;
  1580. X        otmp = otmp->nobj;
  1581. X    }
  1582. X    return(wt - weight_cap());
  1583. X}
  1584. X
  1585. X/*
  1586. X * Returns 0 if below normal capacity, or the number of "capacity units"
  1587. X * over the normal capacity the player is loaded.  Max is 5.
  1588. X */
  1589. Xint
  1590. Xnear_capacity()
  1591. X{
  1592. X    int cap, wt = inv_weight();
  1593. X
  1594. X    if (wt < 0) return UNENCUMBERED;
  1595. X    cap = (wt / (weight_cap()/2)) + 1;
  1596. X    return min(cap, OVERLOADED);
  1597. X}
  1598. X
  1599. Xint
  1600. Xmax_capacity()
  1601. X{
  1602. X    return(inv_weight() - (2 * weight_cap()));
  1603. X}
  1604. X
  1605. Xboolean
  1606. Xcheck_capacity(str)
  1607. Xconst char *str;
  1608. X{
  1609. X    if(near_capacity() >= EXT_ENCUMBER) {
  1610. X    if(str)
  1611. X        pline(str);
  1612. X    else
  1613. X        You("can't do that while carrying so much stuff.");
  1614. X    return 1;
  1615. X    }
  1616. X    return 0;
  1617. X}
  1618. X
  1619. X#endif /* OVL1 */
  1620. X#ifdef OVLB
  1621. X
  1622. Xint
  1623. Xinv_cnt()
  1624. X{
  1625. X    register struct obj *otmp = invent;
  1626. X    register int ct = 0;
  1627. X
  1628. X    while(otmp){
  1629. X        ct++;
  1630. X        otmp = otmp->nobj;
  1631. X    }
  1632. X    return(ct);
  1633. X}
  1634. X
  1635. Xint
  1636. Xidentify(otmp)        /* also called by newmail() */
  1637. X    register struct obj *otmp;
  1638. X{
  1639. X    makeknown(otmp->otyp);
  1640. X    otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
  1641. X    prinv(NULL, otmp, 0L);
  1642. X    return(1);
  1643. X}
  1644. X
  1645. X#endif /* OVLB */
  1646. X
  1647. X/*hack.c*/
  1648. END_OF_FILE
  1649. if test 39188 -ne `wc -c <'src/hack.c'`; then
  1650.     echo shar: \"'src/hack.c'\" unpacked with wrong size!
  1651. fi
  1652. # end of 'src/hack.c'
  1653. fi
  1654. if test -f 'sys/os2/Install.os2' -a "${1}" != "-c" ; then 
  1655.   echo shar: Will not clobber existing file \"'sys/os2/Install.os2'\"
  1656. else
  1657. echo shar: Extracting \"'sys/os2/Install.os2'\" \(14816 characters\)
  1658. sed "s/^X//" >'sys/os2/Install.os2' <<'END_OF_FILE'
  1659. X             Instructions for compiling and installing NetHack 3.1
  1660. X                               on an OS/2 system
  1661. X             =====================================================
  1662. X                                Timo Hakulinen
  1663. X                          Last revision: 24 Jan 1993
  1664. X
  1665. X0.  Read this entire file before starting, and come back to the Notes below if
  1666. X    you have any problems.
  1667. X
  1668. X1.  Make sure all the NetHack files are in the appropriate directory
  1669. X    structure.  You should have a top directory (e.g. nh31, or whatever you
  1670. X    like) with subdirectories dat, doc, include, src, util, sys\share,
  1671. X    sys\os2, and win\tty.  You may have other subdirectories under sys and
  1672. X    win, but they will not affect compilation for an OS/2 system.  If you do
  1673. X    not follow this structure, the makefile will not function properly.  The
  1674. X    .c files for the main program belong in src, those for utility programs in
  1675. X    util, and OS/2-specific ones in sys\os2.  All the .h files belong in
  1676. X    include, the documentation in doc, and assorted data files in dat.  There
  1677. X    are also some necessary files in sys\share (pc*.c, random.c, dgn_*.*,
  1678. X    lev_*.*).  A more detailed explanation of the directory structure is found
  1679. X    in file Files, which should be in the top directory.
  1680. X
  1681. X    If you downloaded or ftp'd the sources from a UNIX system, the lines may
  1682. X    end in UNIX-style newlines, instead of the carriage return and line feed
  1683. X    pairs used by DOS and OS/2.  You'll have to convert them (with a utility
  1684. X    like Rahul Dhesi's "flip").  Also, every file should end with a carriage
  1685. X    return / line feed pair, because Microsoft C has had a habit of ignoring
  1686. X    the last line of each file otherwise.  Besides, even editing UNIX-style
  1687. X    files with DOS editors is often a royal pain.
  1688. X
  1689. X2.  The makefile for OS/2, Makefile.os2, is found in directory sys\os2.  Copy
  1690. X    it to directory src and rename it Makefile.  From now on, Makefile.os2
  1691. X    will be referred to as "Makefile" in this document.
  1692. X
  1693. X    The Makefile supports the following make utilities:
  1694. X
  1695. X    NDMAKE      a public domain make utility for DOS by Don Kneller
  1696. X    NMAKE       make shipped with Microsoft languages and IBM C Set/2
  1697. X    DMAKE       a public domain make for DOS and OS/2 by Dennis Vadura
  1698. X
  1699. X    Both NDMAKE and DMAKE are available at major archive sites.  The
  1700. X    following compilers are supported:
  1701. X
  1702. X    compiler:                           runs in:            compiles for:
  1703. X
  1704. X    Microsoft C 5.1                     DOS / OS/2 1.0-2.x  OS/2 1.x
  1705. X    Microsoft 6.0A (see note 5)         - " -               - " -
  1706. X    IBM C Set/2 1.00, Toolkit/2 2.00    OS/2 2.x            OS/2 2.x
  1707. X    GCC emx 0.8f (see note 6)           OS/2 2.x            OS/2 2.x
  1708. X
  1709. X    Note that code compiled for OS/2 versions 1.0-1.3 runs unmodified in OS/2
  1710. X    versions 2.0 and up.  It should in principle be possible to cross compile
  1711. X    NetHack 3.1 for OS/2 in DOS using NDMAKE and MSC, but this is not
  1712. X    recommended (see note 3).
  1713. X
  1714. X    If you're using some other compiler than one listed above, you will have
  1715. X    to adapt Makefile to your needs.  In particular, change the CC, CFLAGS,
  1716. X    LINK, and LFLAGS macros to your C compiler's and linker's liking.  See
  1717. X    Makefile for more information.
  1718. X
  1719. X    If you are going to be constructing the Fred Fish termlib library you will
  1720. X    need Makefile.lib in sys\share (see note 4).
  1721. X
  1722. X3.  Go to the include subdirectory.  First edit config.h according to the
  1723. X    comments to match your system and desired set of features.  In particular,
  1724. X    make sure that OS2 is defined, and that UNIX, HACKDIR, and COMPRESS are
  1725. X    *not* defined.  If your compiler is ANSI compliant (like practically all
  1726. X    OS/2 compilers are), it's probable that nothing else needs to be
  1727. X    configured in config.h.  However, if you have VISION_TABLES defined and
  1728. X    get a compilation error while processing vis_tab.c, you may have to
  1729. X    uncomment BRACES too.
  1730. X
  1731. X    Next look at os2conf.h.  This file shouldn't need much changing.  If you
  1732. X    want to use the hardcoded OS/2 system definitions in def_os2.h instead of
  1733. X    the compiler's standard headers, comment out OS2_USESYSHEADERS.  This may
  1734. X    become necessary if you are using a compiler which doesn't come with
  1735. X    proper system headers by default.  In this case you may have to edit the
  1736. X    definitions there, because every compiler has its own way of declaring
  1737. X    the necessary system functions and data structures.  In general you
  1738. X    should prefer the compiler's offerings, if possible.
  1739. X
  1740. X    If you are using a 32 bit compiler other than GCC emx 0.8f or C Set/2 in
  1741. X    OS/2 2.x, force OS2_32BITAPI to be defined.  Otherwise it is defined only
  1742. X    for the above mentioned compilers.
  1743. X
  1744. X    If you are not going to include random.c, because you are using the
  1745. X    random number generator provided by your compiler, you will need to
  1746. X    comment out RANDOM.
  1747. X
  1748. X    If you want to muck with different termcap settings, uncomment TERMLIB to
  1749. X    enable use of termcap routines (see note 4).  This is not necessary to
  1750. X    create a fully functional game, however.
  1751. X
  1752. X4.  If you are using another compiler than MSC, GCC, or IBM C Set/2, you may
  1753. X    want to look through system.h in the include directory.  This file matches
  1754. X    the return and parameter types for system calls and library routines with
  1755. X    various flavors of compilers and operating systems.  Leaving this file
  1756. X    alone is unlikely to cause problems, but if you get compile errors with
  1757. X    any functions in the standard library, it's worth checking the
  1758. X    declarations there.
  1759. X
  1760. X5.  If you want to change the high score list behavior, examine the top of
  1761. X    topten.c, in the src directory.  You may want to change the definitions of
  1762. X    PERSMAX, POINTSMIN, and ENTRYMAX.
  1763. X
  1764. X6.  Go to the src directory and edit the top of Makefile.  Be sure the
  1765. X    directory you want the game installed in actually exists.
  1766. X
  1767. X    You'll need nroff and/or TeX to do the files in doc.  If you don't have
  1768. X    either of these, you can skip it.
  1769. X
  1770. X    If you elected not to use the high-quality BSD random number routines by
  1771. X    commenting out RANDOM in os2conf.h, comment out (or set equal to nothing)
  1772. X    the RANDOM macro in Makefile.
  1773. X
  1774. X    If you elected to use Fred Fish's termcap library (bundled in as
  1775. X    termcap.uu in directory sys\share), you will have to generate termlib.lib
  1776. X    from those sources by typing "make -f makefile.lib termlib.lib".  You must
  1777. X    set the TERMLIB option in Makefile to link in the resulting termlib.lib.
  1778. X
  1779. X    If you are recompiling after patching your sources, or if you got your
  1780. X    files from somewhere other than the official distribution, "touch
  1781. X    makedefs.c" to ensure that certain files (onames.h and pm.h) are remade,
  1782. X    lest potentially troublesome timestamps fool make.
  1783. X
  1784. X    If you have lex and yacc programs, or the equivalent flex and bison
  1785. X    programs, you can set up Makefile to generate the appropriate .h and .c
  1786. X    files from their .l and .y counterparts whenever you recompile.  This is
  1787. X    done by changing the do_yacc and do_lex targets in Makefile to depend on
  1788. X    targets yacc_act and lex_act instead of yacc_cpy and lex_cpy.  Otherwise
  1789. X    Makefile will copy pre-generated yacc and lex output files dgn_*.* and
  1790. X    lev_*.* from directory sys\share to util and include.
  1791. X
  1792. X    Now, enter "make all", and take a siesta; your computer will be occupied
  1793. X    for a fair amount of time.  If all goes well, you will get an executable.
  1794. X
  1795. X7.  All the support data files should have been copied to the game directory
  1796. X    by the make process.  Here is the complete list in alphabetical order of
  1797. X    all the files that should have gotten there during a full build:
  1798. X
  1799. X    A-filla.lev    A-fillb.lev    A-goal.lev     A-locate.lev   A-start.lev
  1800. X    B-filla.lev    B-fillb.lev    B-goal.lev     B-locate.lev   B-start.lev
  1801. X    C-filla.lev    C-fillb.lev    C-goal.lev     C-locate.lev   C-start.lev
  1802. X    E-filla.lev    E-fillb.lev    E-goal.lev     E-locate.lev   E-start.lev
  1803. X    H-filla.lev    H-fillb.lev    H-goal.lev     H-locate.lev   H-start.lev
  1804. X    K-filla.lev    K-fillb.lev    K-goal.lev     K-locate.lev   K-start.lev
  1805. X    P-filla.lev    P-fillb.lev    P-goal.lev     P-locate.lev   P-start.lev
  1806. X    R-filla.lev    R-fillb.lev    R-goal.lev     R-locate.lev   R-start.lev
  1807. X    S-filla.lev    S-fillb.lev    S-goal.lev     S-locate.lev   S-start.lev
  1808. X    T-filla.lev    T-fillb.lev    T-goal.lev     T-locate.lev   T-start.lev
  1809. X    V-filla.lev    V-fillb.lev    V-goal.lev     V-locate.lev   V-start.lev
  1810. X    W-filla.lev    W-fillb.lev    W-goal.lev     W-locate.lev   W-start.lev
  1811. X    air.lev        asmodeus.lev   astral.lev     baalz.lev      bigroom.lev
  1812. X    castle.lev     cmdhelp        data           dungeon        earth.lev
  1813. X    fakewiz1.lev   fakewiz2.lev   fire.lev       help           hh
  1814. X    history        juiblex.lev    knox.lev       license        medusa-1.lev
  1815. X    medusa-2.lev   mine_end.lev   minefill.lev   minetown.lev   nethack.cmd
  1816. X    nethack.cnf    nethack.exe    nethack.ico    opthelp        options
  1817. X    oracle.lev     oracles        orcus.lev      quest.dat      recover.exe
  1818. X    rumors         sanctum.lev    tower1.lev     tower2.lev     tower3.lev
  1819. X    valley.lev     water.lev      wizard1.lev    wizard2.lev    wizard3.lev
  1820. X    wizhelp
  1821. X
  1822. X    Yes.  It's 106 files for a full featured NetHack 3.1.  If any of the files
  1823. X    are missing, try to rerun make.  If that doesn't help, you'll have to try
  1824. X    to decipher Makefile to find out how to manually create the missing
  1825. X    files.  These kinds of troubles shouldn't happen except for two reasons:
  1826. X    You've run out of disk space while compiling or your make utility doesn't
  1827. X    understand Makefile properly for some reason.  In either case, you should
  1828. X    get some warnings from the make, though.
  1829. X
  1830. X    If you have old record, logfile, or news files in the game directory, they
  1831. X    are not overwritten.  Of course, old records from NetHack 3.0 are not
  1832. X    worth keeping with 3.1, since these games are really quite different.
  1833. X
  1834. X    Edit file nethack.cnf in the game directory to reflect your particular
  1835. X    setup and personal preferences, following the comments there.  More info
  1836. X    about settable options can be found in the file opthelp and the Guidebook.
  1837. X
  1838. X    If you compiled in the TERMLIB feature, also move the sys\share\termcap
  1839. X    file to your game directory.
  1840. X
  1841. X8.  If you'll be running NetHack from a different subdirectory, you will want
  1842. X    to "set HACKDIR=c:\games\nh31" (or whatever directory you want to use).
  1843. X    Add it to your config.sys, if you'll be playing often.
  1844. X
  1845. X    You can also create a special NetHack entry in your Presentation Manager /
  1846. X    Workplace Shell desktop.  This will use the included NetHack icon.
  1847. X    The following is a sample program description for OS/2 1.3 desktop, but
  1848. X    it's similar for OS/2 2.0:
  1849. X
  1850. X    Program title:          NetHack 3.1
  1851. X    Path and file name:     c:\games\nh31\nethack.cmd
  1852. X    Parameters:
  1853. X    Working directory:      c:\games\nh31
  1854. X    Program type:           OS/2 Full screen
  1855. X
  1856. X    Naturally you must fill in your own game directory and parameters if you
  1857. X    want to set any.  The program type can be either OS/2 Full screen or OS/2
  1858. X    Windowed.  Note that you should set the executable path to use the .cmd
  1859. X    file generated by Makefile.  This file generates an extra pause after the
  1860. X    program exit, because otherwise you wouldn't get to see the high score
  1861. X    list upon quitting due to PM/WPS automatically closing the program window.
  1862. X    When starting NetHack normally from OS/2 command prompt, the command
  1863. X    processor starts nethack.exe instead, so no extra pause is generated.
  1864. X
  1865. X9.  If you want to clear up the temporary files and objects created by the
  1866. X    compilation process, you may issue "make spotless".  This will return your
  1867. X    source tree to near-distribution condition.  Naturally, it will not touch
  1868. X    your newly built game files in any way.
  1869. X
  1870. X10. Play NetHack.  If it works, you're done!
  1871. X
  1872. X
  1873. XNotes
  1874. X-----
  1875. X
  1876. X1)  Save files and bones files from previous versions will not work with
  1877. X    NetHack 3.1.  Don't bother trying to keep them.
  1878. X
  1879. X2)  To install an update of NetHack after changing something, enter "make"
  1880. X    from the src directory.  If you add, delete, or reorder monsters or
  1881. X    objects, or you change the format of saved level files, delete any save
  1882. X    and bones files.  (Trying to use such files sometimes produces amusing
  1883. X    confusions on the game's part, but usually crashes.)
  1884. X
  1885. X3)  When cross-compiling for OS/2 in DOS, NDMAKE is the best choice because it
  1886. X    requires the least RAM for itself.  Note however, that cross-compilation
  1887. X    in DOS is discouraged, because it is considered obsolete (OS/2 is really
  1888. X    a much better place to compile).  If you still want to try, here are some
  1889. X    suggestions:
  1890. X
  1891. X    During linking, the Microsoft linker will need temporary storage space.
  1892. X    Make sure you have about a meg of free disk where-ever you have defined
  1893. X    your temporary storage.  It is also a good idea to compile with as much
  1894. X    free RAM as possible.  It may otherwise get crowded with the bigger, more
  1895. X    complex source files (compiler bombs with "out of heap space" or similar).
  1896. X    If this happens, strip your configuration, zap TSR's, get a better memory
  1897. X    manager etc.
  1898. X
  1899. X4)  The file sys\share\termcap.uu is the fixed version of the Fred Fish
  1900. X    termcap library.  You will need to run a uudecode utility on it to
  1901. X    generate the file termcap.zip.  termcap.zip contains several files of
  1902. X    termcap routines.  Using them with NetHack involves very little knowledge
  1903. X    of the UNIX concept of a termcap database; mostly you need to know enough
  1904. X    to set a TERM environment variable.  You can unzip termcap.zip in the
  1905. X    sys\share directory, but if you are going to use it, it is probably best
  1906. X    to unzip a copy in the src directory.  That way you will not miss copying
  1907. X    any files over.  Wherever you unzip it, get rid of the included makefile
  1908. X    since a better version has been provided as Makefile.lib.  After creating
  1909. X    the termcap library file termlib.lib, copy it to src before compiling the
  1910. X    game main source.
  1911. X
  1912. X5)  When compiling with MSC 6.0, the maintenance version 6.0A should be used
  1913. X    instead of the original 6.0, which was all too buggy to successfully build
  1914. X    NetHack 3.1.
  1915. X
  1916. X6)  Note that emx 0.8f is the first version of GCC for OS/2 that can properly
  1917. X    compile NetHack.  Earlier versions do not work, because they don't support
  1918. X    the 16 bit API calls of OS/2.
  1919. X
  1920. X    GCC emx 0.8f does not currently work properly when fseek() function is
  1921. X    used with text files.  This is well documented in the compiler's
  1922. X    documentation.  Unfortunately NetHack uses fseek() in several places in
  1923. X    connection with text data.  This means that some help texts may not come
  1924. X    out right, but no serious problems should emerge.
  1925. END_OF_FILE
  1926. if test 14816 -ne `wc -c <'sys/os2/Install.os2'`; then
  1927.     echo shar: \"'sys/os2/Install.os2'\" unpacked with wrong size!
  1928. fi
  1929. # end of 'sys/os2/Install.os2'
  1930. fi
  1931. echo shar: End of archive 34 \(of 108\).
  1932. cp /dev/null ark34isdone
  1933. MISSING=""
  1934. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  1935. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  1936. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  1937. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  1938. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  1939. 101 102 103 104 105 106 107 108 ; do
  1940.     if test ! -f ark${I}isdone ; then
  1941.     MISSING="${MISSING} ${I}"
  1942.     fi
  1943. done
  1944. if test "${MISSING}" = "" ; then
  1945.     echo You have unpacked all 108 archives.
  1946.     echo "Now execute 'rebuild.sh'"
  1947.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  1948. else
  1949.     echo You still need to unpack the following archives:
  1950.     echo "        " ${MISSING}
  1951. fi
  1952. ##  End of shell archive.
  1953. exit 0
  1954.