home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume16 / nethck31 / part44 < prev    next >
Encoding:
Internet Message Format  |  1993-01-31  |  58.2 KB

  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: v16i052:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part44/108
  5. Message-ID: <4346@master.CNA.TEK.COM>
  6. Date: 30 Jan 93 01:13:37 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2104
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1601
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 52
  14. Archive-name: nethack31/Part44
  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 44 (of 108)."
  27. # Contents:  src/vision.c1 src/wizard.c
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:03 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/vision.c1' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/vision.c1'\"
  32. else
  33. echo shar: Extracting \"'src/vision.c1'\" \(38940 characters\)
  34. sed "s/^X//" >'src/vision.c1' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)vision.c    3.1    92/11/14    */
  36. X/* Copyright (c) Dean Luick, with acknowledgements to Dave Cohrs, 1990.    */
  37. X/* NetHack may be freely redistributed.  See license for details.    */
  38. X#include "hack.h"
  39. X
  40. X/* Circles ==================================================================*/
  41. X
  42. X/*
  43. X * These numbers are limit offsets for one quadrant of a circle of a given
  44. X * radius (the first number of each line) from the source.  The number in
  45. X * the comment is the element number (so pointers can be set up).  Each
  46. X * "circle" has as many elements as its radius+1.  The radius is the number
  47. X * of points away from the source that the limit exists.  The radius of the
  48. X * offset on the same row as the source *is* included so we don't have to
  49. X * make an extra check.  For example, a circle of radius 4 has offsets:
  50. X *
  51. X *                XXX    +2
  52. X *                ...X    +3
  53. X *                ....X    +4
  54. X *                ....X    +4
  55. X *                @...X   +4
  56. X *  
  57. X */
  58. Xstatic char circle_data[] = {
  59. X/*  0*/     1, 1,
  60. X/*  2*/     2, 2, 1,
  61. X/*  5*/     3, 3, 2, 1,
  62. X/*  9*/     4, 4, 4, 3, 2,
  63. X/* 14*/     5, 5, 5, 4, 3, 2,
  64. X/* 20*/     6, 6, 6, 5, 5, 4, 2,
  65. X/* 27*/     7, 7, 7, 6, 6, 5, 4, 2,
  66. X/* 35*/     8, 8, 8, 7, 7, 6, 6, 4, 2,
  67. X/* 44*/     9, 9, 9, 9, 8, 8, 7, 6, 5, 3,
  68. X/* 54*/    10,10,10,10, 9, 9, 8, 7, 6, 5, 3,
  69. X/* 65*/    11,11,11,11,10,10, 9, 9, 8, 7, 5, 3,
  70. X/* 77*/    12,12,12,12,11,11,10,10, 9, 8, 7, 5, 3,
  71. X/* 90*/    13,13,13,13,12,12,12,11,10,10, 9, 7, 6, 3,
  72. X/*104*/    14,14,14,14,13,13,13,12,12,11,10, 9, 8, 6, 3,
  73. X/*119*/    15,15,15,15,14,14,14,13,13,12,11,10, 9, 8, 6, 3,
  74. X/*135*/ 16 /* should be MAX_RADIUS+1; used to terminate range loops -dlc */
  75. X};
  76. X
  77. X/*
  78. X * These are the starting indexes into the circle_data[] array for a
  79. X * circle of a given radius.
  80. X */
  81. Xstatic char circle_start[] = {
  82. X/*  */      0,    /* circles of radius zero are not used */
  83. X/* 1*/    0,
  84. X/* 2*/      2,
  85. X/* 3*/      5,
  86. X/* 4*/      9,
  87. X/* 5*/     14,
  88. X/* 6*/     20,
  89. X/* 7*/     27,
  90. X/* 8*/     35,
  91. X/* 9*/     44,
  92. X/*10*/     54,
  93. X/*11*/     65,
  94. X/*12*/     77,
  95. X/*13*/     90,
  96. X/*14*/    104,
  97. X/*15*/    119,
  98. X};
  99. X
  100. X
  101. X/*===========================================================================*/
  102. X/* Vision (arbitrary line of sight) =========================================*/
  103. X
  104. X/*------ global variables ------*/
  105. X
  106. X#if 0    /* (moved to decl.c) */
  107. X/* True if we need to run a full vision recalculation. */
  108. Xboolean    vision_full_recalc = 0;
  109. X
  110. X/* Pointers to the current vision array. */
  111. Xchar    **viz_array;
  112. X#endif
  113. Xchar    *viz_rmin, *viz_rmax;        /* current vision cs bounds */
  114. X
  115. X
  116. X/*------ local variables ------*/
  117. X
  118. X
  119. Xstatic char could_see[2][ROWNO][COLNO];        /* vision work space */
  120. Xstatic char *cs_rows0[ROWNO], *cs_rows1[ROWNO];
  121. Xstatic char  cs_rmin0[ROWNO],  cs_rmax0[ROWNO];
  122. Xstatic char  cs_rmin1[ROWNO],  cs_rmax1[ROWNO];
  123. X
  124. Xstatic char  viz_clear[ROWNO][COLNO];        /* vision clear/blocked map */
  125. Xstatic char *viz_clear_rows[ROWNO];
  126. X
  127. Xstatic char  left_ptrs[ROWNO][COLNO];        /* LOS algorithm helpers */
  128. Xstatic char right_ptrs[ROWNO][COLNO];
  129. X
  130. X/* Forward declarations. */
  131. Xstatic void FDECL(fill_point, (int,int));
  132. Xstatic void FDECL(dig_point, (int,int));
  133. Xstatic void NDECL(view_init);
  134. Xstatic void FDECL(view_from,(int,int,char **,char *,char *,int,
  135. X                 void (*)(int,int,genericptr_t),genericptr_t));
  136. Xstatic void FDECL(get_unused_cs, (char ***,char **,char **));
  137. X#ifdef REINCARNATION
  138. Xstatic void FDECL(rogue_vision, (char **,char *,char *));
  139. X#endif
  140. X
  141. X/* Macro definitions that I can't find anywhere. */
  142. X#define sign(z) ((z) < 0 ? -1 : ((z) ? 1 : 0 ))
  143. X#define abs(z)  ((z) < 0 ? -(z) : (z))
  144. X
  145. X/*
  146. X * vision_init()
  147. X *
  148. X * The one-time vision initialization routine.
  149. X *
  150. X * This must be called before mklev() is called in newgame() [allmain.c],
  151. X * or before a game restore.   Else we die a horrible death.
  152. X */
  153. Xvoid
  154. Xvision_init()
  155. X{
  156. X    int i;
  157. X
  158. X    /* Set up the pointers. */
  159. X    for (i = 0; i < ROWNO; i++) {
  160. X    cs_rows0[i] = could_see[0][i];
  161. X    cs_rows1[i] = could_see[1][i];
  162. X    viz_clear_rows[i] = viz_clear[i];
  163. X    }
  164. X
  165. X    /* Start out with cs0 as our current array */
  166. X    viz_array = cs_rows0;
  167. X    viz_rmin  = cs_rmin0;
  168. X    viz_rmax  = cs_rmax0;
  169. X
  170. X    vision_full_recalc = 0;
  171. X    (void) memset((genericptr_t) could_see, 0, sizeof(could_see));
  172. X
  173. X    /* Initialize the vision algorithm (currently C or D). */
  174. X    view_init();
  175. X
  176. X#ifdef VISION_TABLES
  177. X    /* Note:  this initializer doesn't do anything except guarantee that
  178. X          we're linked properly.
  179. X    */
  180. X    vis_tab_init();
  181. X#endif
  182. X}
  183. X
  184. X/*
  185. X * does_block()
  186. X *
  187. X * Returns true if the level feature, object, or monster at (x,y) blocks
  188. X * sight.
  189. X */
  190. Xint
  191. Xdoes_block(x,y,lev)
  192. X    int x, y;
  193. X    register struct rm    *lev;
  194. X{
  195. X    struct obj   *obj;
  196. X    struct monst *mon;
  197. X
  198. X    /* Features that block . . */
  199. X    if (IS_ROCK(lev->typ) || (IS_DOOR(lev->typ) &&
  200. X                (lev->doormask & (D_CLOSED|D_LOCKED|D_TRAPPED) )))
  201. X    return 1;
  202. X
  203. X    if (lev->typ == CLOUD || lev->typ == WATER ||
  204. X            (lev->typ == MOAT && Underwater))
  205. X    return 1;
  206. X
  207. X    /* Boulders block light. */
  208. X    for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
  209. X    if (obj->otyp == BOULDER) return 1;
  210. X
  211. X    /* Mimics mimicing a door or boulder block light. */
  212. X    if ((mon = m_at(x,y)) && (!mon->minvis || See_invisible) &&
  213. X      ((mon->m_ap_type == M_AP_FURNITURE &&
  214. X      (mon->mappearance == S_hcdoor || mon->mappearance == S_vcdoor)) ||
  215. X      (mon->m_ap_type == M_AP_OBJECT && mon->mappearance == BOULDER)))
  216. X    return 1;
  217. X
  218. X    return 0;
  219. X}
  220. X
  221. X/*
  222. X * vision_reset()
  223. X *
  224. X * This must be called *after* the levl[][] structure is set with the new
  225. X * level and the level monsters and objects are in place.
  226. X */
  227. Xvoid
  228. Xvision_reset()
  229. X{
  230. X    int y;
  231. X    register int x, i, dig_left, block;
  232. X    register struct rm    *lev;
  233. X
  234. X    /* Start out with cs0 as our current array */
  235. X    viz_array = cs_rows0;
  236. X    viz_rmin  = cs_rmin0;
  237. X    viz_rmax  = cs_rmax0;
  238. X
  239. X    (void) memset((genericptr_t) could_see, 0, sizeof(could_see));
  240. X
  241. X    /* Reset the pointers and clear so that we have a "full" dungeon. */
  242. X    (void) memset((genericptr_t) viz_clear,        0, sizeof(viz_clear));
  243. X
  244. X    /* Dig the level */
  245. X    for (y = 0; y < ROWNO; y++) {
  246. X    dig_left = 0;
  247. X    block = TRUE;    /* location (0,y) is always stone; it's !isok() */
  248. X    lev = &levl[1][y];
  249. X    for (x = 1; x < COLNO; x++, lev += ROWNO)
  250. X        if (block != (IS_ROCK(lev->typ) || does_block(x,y,lev))) {
  251. X        if(block) {
  252. X            for(i=dig_left; i<x; i++) {
  253. X            left_ptrs [y][i] = dig_left;
  254. X            right_ptrs[y][i] = x-1;
  255. X            }
  256. X        } else {
  257. X            i = dig_left;
  258. X            if(dig_left) dig_left--; /* point at first blocked point */
  259. X            for(; i<x; i++) {
  260. X            left_ptrs [y][i] = dig_left;
  261. X            right_ptrs[y][i] = x;
  262. X            viz_clear[y][i] = 1;
  263. X            }
  264. X        }
  265. X        dig_left = x;
  266. X        block = !block;
  267. X        }
  268. X    /* handle right boundary; almost identical for blocked/unblocked */
  269. X    i = dig_left;
  270. X    if(!block && dig_left) dig_left--; /* point at first blocked point */
  271. X    for(; i<COLNO; i++) {
  272. X        left_ptrs [y][i] = dig_left;
  273. X        right_ptrs[y][i] = (COLNO-1);
  274. X        viz_clear[y][i] = !block;
  275. X    }
  276. X    }
  277. X
  278. X    vision_full_recalc = 1;    /* we want to run vision_recalc() */
  279. X}
  280. X
  281. X
  282. X/*
  283. X * get_unused_cs()
  284. X *
  285. X * Called from vision_recalc() and at least one light routine.  Get pointers
  286. X * to the unused vision work area.
  287. X */
  288. Xstatic void
  289. Xget_unused_cs(rows, rmin, rmax)
  290. X    char ***rows;
  291. X    char **rmin, **rmax;
  292. X{
  293. X    register int  row;
  294. X    register char *nrmin, *nrmax;
  295. X
  296. X    if (viz_array == cs_rows0) {
  297. X    *rows = cs_rows1;
  298. X    *rmin = cs_rmin1;
  299. X    *rmax = cs_rmax1;
  300. X    } else {
  301. X    *rows = cs_rows0;
  302. X    *rmin = cs_rmin0;
  303. X    *rmax = cs_rmax0;
  304. X    }
  305. X
  306. X    /* return an initialized, unused work area */
  307. X    nrmin = *rmin;
  308. X    nrmax = *rmax;
  309. X
  310. X    (void) memset((genericptr_t)**rows, 0, ROWNO*COLNO);  /* we see nothing */
  311. X    for (row = 0; row < ROWNO; row++) {        /* set row min & max */
  312. X    *nrmin++ = COLNO-1;
  313. X    *nrmax++ = 0;
  314. X    }
  315. X}
  316. X
  317. X
  318. X#ifdef REINCARNATION
  319. X/*
  320. X * rogue_vision()
  321. X *
  322. X * Set the "could see" and in sight bits so vision acts just like the old
  323. X * rogue game:
  324. X *
  325. X *    + If in a room, the hero can see to the room boundaries.
  326. X *    + The hero can always see adjacent squares.
  327. X *
  328. X * We set the in_sight bit here as well to escape a bug that shows up
  329. X * due to the one-sided lit wall hack.
  330. X */
  331. Xstatic void
  332. Xrogue_vision(next, rmin, rmax)
  333. X    char **next;    /* could_see array pointers */
  334. X    char *rmin, *rmax;
  335. X{
  336. X    int rnum = levl[u.ux][u.uy].roomno - ROOMOFFSET; /* no SHARED... */
  337. X    int start, stop, in_door;
  338. X    register int zx, zy;
  339. X
  340. X    /* If in a lit room, we are able to see to its boundaries. */
  341. X    /* If dark, set COULD_SEE so various spells work -dlc */
  342. X    if (rnum >= 0) {
  343. X    for (zy = rooms[rnum].ly-1; zy <= rooms[rnum].hy+1; zy++) {
  344. X        rmin[zy] = start = rooms[rnum].lx-1;
  345. X        rmax[zy] = stop  = rooms[rnum].hx+1;
  346. X
  347. X        for (zx = start; zx <= stop; zx++) {
  348. X        if (rooms[rnum].rlit) {
  349. X            next[zy][zx] = COULD_SEE | IN_SIGHT;
  350. X            levl[zx][zy].seen = 1;    /* see the walls */
  351. X        } else
  352. X            next[zy][zx] = COULD_SEE;
  353. X        }
  354. X    }
  355. X    }
  356. X
  357. X    in_door = levl[u.ux][u.uy].typ == DOOR;
  358. X
  359. X    /* Can always see adjacent. */
  360. X    for (zy = u.uy-1; zy <= u.uy+1; zy++) {
  361. X    rmin[zy] = min(rmin[zy],u.ux-1);
  362. X    rmax[zy] = max(rmax[zy],u.ux+1);
  363. X
  364. X    for (zx = u.ux-1; zx <= u.ux+1; zx++) {
  365. X        next[zy][zx] = COULD_SEE | IN_SIGHT;
  366. X        /*
  367. X         * Yuck, update adjacent non-diagonal positions when in a doorway.
  368. X         * We need to do this to catch the case when we first step into
  369. X         * a room.  The room's walls were not seen from the outside, but
  370. X         * now are seen (the seen bit is set just above).  However, the
  371. X         * positions are not updated because they were already in sight.
  372. X         * So, we have to do it here.
  373. X         */
  374. X        if (in_door && (zx == u.ux || zy == u.uy)) newsym(zx,zy);
  375. X    }
  376. X    }
  377. X}
  378. X#endif /* REINCARNATION */
  379. X
  380. X
  381. X/*
  382. X * vision_recalc()
  383. X *
  384. X * Do all of the heavy vision work.  Recalculate all locations that could
  385. X * possibly be seen by the hero --- if the location were lit, etc.  Note
  386. X * which locations are actually seen because of lighting.  Then add to
  387. X * this all locations that be seen by hero due to night vision and x-ray
  388. X * vision.  Finally, compare with what the hero was able to see previously.
  389. X * Update the difference.
  390. X *
  391. X * This function is usually called only when the variable 'vision_full_recalc'
  392. X * is set.  The following is a list of places where this function is called,
  393. X * with three valid values for the control flag parameter:
  394. X *
  395. X * Control flag = 0.  A complete vision recalculation.  Generate the vision
  396. X * tables from scratch.  This is necessary to correctly set what the hero
  397. X * can see.  (1) and (2) call this routine for synchronization purposes, (3)
  398. X * calls this routine so it can operate correctly.
  399. X *
  400. X *    + After the monster move, before input from the player. [moveloop()]
  401. X *    + At end of moveloop. [moveloop() ??? not sure why this is here]
  402. X *    + Right before something is printed. [pline()]
  403. X *    + Right before we do a vision based operation. [do_clear_area()]
  404. X *    + screen redraw, so we can renew all positions in sight. [docrt()]
  405. X *
  406. X * Control flag = 1.  An adjacent vision recalculation.  The hero has moved
  407. X * one square.  Knowing this, it might be possible to optimize the vision
  408. X * recalculation using the current knowledge.  This is presently unimplemented
  409. X * and is treated as a control = 0 call.
  410. X *
  411. X *    + Right after the hero moves. [domove()]
  412. X *
  413. X * Control flag = 2.  Turn off the vision system.  Nothing new will be
  414. X * displayed, since nothing is seen.  This is usually done when you need
  415. X * a newsym() run on all locations in sight, or on some locations but you
  416. X * don't know which ones.
  417. X *
  418. X *    + Before a screen redraw, so all positions are renewed. [docrt()]
  419. X *    + Right before the hero arrives on a new level. [goto_level()]
  420. X *    + Right after a scroll of light is read. [litroom()]
  421. X *    + After an option has changed that affects vision [parseoptions()]
  422. X *    + Right after the hero is swallowed. [gulpmu()]
  423. X *    + Just before bubbles are moved. [movebubbles()]
  424. X */
  425. Xvoid
  426. Xvision_recalc(control)
  427. X    int control;
  428. X{
  429. X    char **temp_array;    /* points to the old vision array */
  430. X    char **next_array;    /* points to the new vision array */
  431. X    char *next_row;    /* row pointer for the new array */
  432. X    char *old_row;    /* row pointer for the old array */
  433. X    char *next_rmin;    /* min pointer for the new array */
  434. X    char *next_rmax;    /* max pointer for the new array */
  435. X    char *ranges;    /* circle ranges -- used for xray & night vision */
  436. X    int row;        /* row counter (outer loop)  */
  437. X    int start, stop;    /* inner loop starting/stopping index */
  438. X    int dx, dy;        /* one step from a lit door or lit wall (see below) */
  439. X    register int col;    /* inner loop counter */
  440. X    register struct rm *lev;    /* pointer to current pos */
  441. X    struct rm *flev;    /* pointer to position in "front" of current pos */
  442. X
  443. X    vision_full_recalc = 0;            /* reset flag */
  444. X
  445. X#ifdef GCC_WARN
  446. X    row = 0;
  447. X#endif
  448. X
  449. X    /*
  450. X     * Either the light sources have been taken care of, or we must
  451. X     * recalculate them here.
  452. X     */
  453. X
  454. X    /* Get the unused could see, row min, and row max arrays. */
  455. X    get_unused_cs(&next_array, &next_rmin, &next_rmax);
  456. X
  457. X    /* You see nothing, nothing can see you --- if swallowed or refreshing. */
  458. X    if (u.uswallow || control == 2) {
  459. X    /* do nothing -- get_unused_cs() nulls out the new work area */
  460. X
  461. X    } else if (Blind) {
  462. X    /*
  463. X     * Calculate the could_see array even when blind so that monsters
  464. X     * can see you, even if you can't see them.  Note that the current
  465. X     * setup allows:
  466. X     *
  467. X     *    + Monsters to see with the "new" vision, even on the rogue
  468. X     *      level.
  469. X     *
  470. X     *    + Monsters to see you even when you're in a pit.
  471. X     */
  472. X    view_from(u.uy, u.ux, next_array, next_rmin, next_rmax,
  473. X                    0,(void(*)())0,(genericptr_t)0);
  474. X
  475. X    /*
  476. X     * Our own version of the update loop below.  We know we can't see
  477. X     * anything, so we only need update positions we used to be able
  478. X     * to see.
  479. X     */
  480. X    temp_array = viz_array;    /* set viz_array so newsym() will work */
  481. X    viz_array = next_array;
  482. X
  483. X    for (row = 0; row < ROWNO; row++) {
  484. X        old_row = temp_array[row];
  485. X
  486. X        /* Find the min and max positions on the row. */
  487. X        start = min(viz_rmin[row], next_rmin[row]);
  488. X        stop  = max(viz_rmax[row], next_rmax[row]);
  489. X
  490. X        for (col = start; col <= stop; col++)
  491. X        if (old_row[col] & IN_SIGHT) newsym(col,row);
  492. X    }
  493. X
  494. X    /* skip the normal update loop */
  495. X    goto skip;
  496. X    }
  497. X#ifdef REINCARNATION
  498. X    else if (Is_rogue_level(&u.uz)) {
  499. X    rogue_vision(next_array,next_rmin,next_rmax);
  500. X    }
  501. X#endif
  502. X    else {
  503. X    int has_night_vision = 1;    /* hero has night vision */
  504. X
  505. X    if (Underwater && !Is_waterlevel(&u.uz)) {
  506. X        /*
  507. X         * The hero is under water.  Only see surrounding locations if
  508. X         * they are also underwater.  This overrides night vision but
  509. X         * does not override x-ray vision.
  510. X         */
  511. X        has_night_vision = 0;
  512. X
  513. X        for (row = u.uy-1; row <= u.uy+1; row++)
  514. X        for (col = u.ux-1; col <= u.ux+1; col++) {
  515. X            if (!isok(col,row) || !is_pool(col,row)) continue;
  516. X
  517. X            next_rmin[row] = min(next_rmin[row], col);
  518. X            next_rmax[row] = max(next_rmax[row], col);
  519. X            next_array[row][col] = IN_SIGHT;
  520. X        }
  521. X        }
  522. X
  523. X    /* if in a pit, just update for immediate locations */
  524. X    else if (u.utrap && u.utraptype == TT_PIT) {
  525. X        for (row = u.uy-1; row <= u.uy+1; row++) {
  526. X        if (row < 0) continue;    if (row >= ROWNO) break;
  527. X
  528. X        next_rmin[row] = max(      0, u.ux - 1);
  529. X        next_rmax[row] = min(COLNO-1, u.ux + 1);
  530. X        next_row = next_array[row];
  531. X
  532. X        for(col=next_rmin[row]; col <= next_rmax[row]; col++)
  533. X            next_row[col] = IN_SIGHT;
  534. X        }
  535. X    } else
  536. X        view_from(u.uy, u.ux, next_array, next_rmin, next_rmax,
  537. X                    0,(void(*)())0,(genericptr_t)0);
  538. X
  539. X    /*
  540. X     * Set the IN_SIGHT bit for xray and night vision.
  541. X     */
  542. X    if (u.xray_range >= 0) {
  543. X        if (u.xray_range) {
  544. X        ranges = circle_ptr(u.xray_range);
  545. X
  546. X        for (row = u.uy-u.xray_range; row <= u.uy+u.xray_range; row++) {
  547. X            if (row < 0) continue;    if (row >= ROWNO) break;
  548. X            dy = abs(u.uy-row);        next_row = next_array[row];
  549. X
  550. X            start = max(      0, u.ux - ranges[dy]);
  551. X            stop  = min(COLNO-1, u.ux + ranges[dy]);
  552. X
  553. X            for (col = start; col <= stop; col++) {
  554. X            next_row[col] |= IN_SIGHT;
  555. X            levl[col][row].seen = 1;    /* we see walls */
  556. X            }
  557. X
  558. X            next_rmin[row] = min(start, next_rmin[row]);
  559. X            next_rmax[row] = max(stop, next_rmax[row]);
  560. X        }
  561. X
  562. X        } else {    /* range is 0 */
  563. X        next_array[u.uy][u.ux] |= IN_SIGHT;
  564. X        levl[u.ux][u.uy].seen = 1;
  565. X        next_rmin[u.uy] = min(u.ux, next_rmin[u.uy]);
  566. X        next_rmax[u.uy] = max(u.ux, next_rmax[u.uy]);
  567. X        }
  568. X    }
  569. X
  570. X    if (has_night_vision && u.xray_range < u.nv_range) {
  571. X        if (!u.nv_range) {    /* range is 0 */
  572. X        next_array[u.uy][u.ux] |= IN_SIGHT;
  573. X        levl[u.ux][u.uy].seen = 1;
  574. X        next_rmin[u.uy] = min(u.ux, next_rmin[u.uy]);
  575. X        next_rmax[u.uy] = max(u.ux, next_rmax[u.uy]);
  576. X        } else if (u.nv_range > 0) {
  577. X        ranges = circle_ptr(u.nv_range);
  578. X
  579. X        for (row = u.uy-u.nv_range; row <= u.uy+u.nv_range; row++) {
  580. X            if (row < 0) continue;    if (row >= ROWNO) break;
  581. X            dy = abs(u.uy-row);        next_row = next_array[row];
  582. X
  583. X            start = max(      0, u.ux - ranges[dy]);
  584. X            stop  = min(COLNO-1, u.ux + ranges[dy]);
  585. X
  586. X            for (col = start; col <= stop; col++)
  587. X            if (next_row[col]) next_row[col] |= IN_SIGHT;
  588. X
  589. X            next_rmin[row] = min(start, next_rmin[row]);
  590. X            next_rmax[row] = max(stop, next_rmax[row]);
  591. X        }
  592. X        }
  593. X    }
  594. X    }
  595. X
  596. X
  597. X    /*
  598. X     * Make the viz_array the new array so that cansee() will work correctly.
  599. X     */
  600. X    temp_array = viz_array;
  601. X    viz_array = next_array;
  602. X
  603. X    /*
  604. X     * The main update loop.  Here we do two things:
  605. X     *
  606. X     *        + Set the IN_SIGHT bit for places that we could see and are lit.
  607. X     *        + Reset changed places.
  608. X     *
  609. X     * There are two things that make deciding what the hero can see
  610. X     * difficult:
  611. X     *
  612. X     *  1.  Walls.  Walls are only seen as walls from the inside of a room.
  613. X     *        On the outside they look like stone.  The "seen" bit in the rm
  614. X     *        structure is used in the display system to decide what to
  615. X     *        display, but it is here where we decide to set the seen bit.
  616. X     *        In this case the wall must already be in sight (either by night
  617. X     *        vision or could be seen and lit) *and* we must see the wall
  618. X     *        from across a room-typ square.
  619. X     *
  620. X     *  2.  Directional lighting.  Items that block light create problems.
  621. X     *      The worst offenders are doors.  Suppose a door to a lit room
  622. X     *      is closed.  It is lit on one side, but not on the other.  How
  623. X     *      do you know?  You have to check the closest adjacent position.
  624. X     *        Even so, that is not entirely correct.  But it seems close
  625. X     *        enough for now.
  626. X     */
  627. X    for (row = 0; row < ROWNO; row++) {
  628. X    dy = u.uy - row;                dy = sign(dy);
  629. X    next_row = next_array[row];     old_row = temp_array[row];
  630. X
  631. X    /* Find the min and max positions on the row. */
  632. X    start = min(viz_rmin[row], next_rmin[row]);
  633. X    stop  = max(viz_rmax[row], next_rmax[row]);
  634. X    lev = &levl[start][row];
  635. X
  636. X    for (col = start; col <= stop; col++, lev += ROWNO) {
  637. X        if (next_row[col] & IN_SIGHT) {
  638. X        /*
  639. X         * We see this position because of night- or xray-vision.
  640. X         *
  641. X         * Check for "unseen" walls.
  642. X         */
  643. X        if ( (!lev->seen || (lev->diggable & W_REPAIRED)) && 
  644. X             (IS_WALL(lev->typ) || lev->typ == SDOOR) ) {
  645. X            /* Check the closest adjacent position. */
  646. X            dx = u.ux - col;    dx = sign(dx);
  647. X            flev = &(levl[col+dx][row+dy]);
  648. X
  649. X            /* If it was a non-corridor "open" area, we see the wall */
  650. X            if ((ZAP_POS(flev->typ) && (flev->typ != CORR)) ||
  651. X            (lev->diggable & W_REPAIRED)) {
  652. X            lev->seen = 1;    /* we've seen it */
  653. X            lev->diggable &= ~W_REPAIRED;
  654. X
  655. X            /* Make sure newly "seen" walls show up */
  656. X            newsym(col,row);
  657. X            }
  658. X
  659. X            /* Update position if it was not in sight before. */
  660. X            else if (!(old_row[col]&IN_SIGHT)) newsym(col,row);
  661. X        }
  662. X
  663. X        /* Update position if it was not in sight before. */
  664. X        else if ( !(old_row[col] & IN_SIGHT) ) {
  665. X            lev->seen = 1;
  666. X            newsym(col,row);
  667. X        }
  668. X        }
  669. X
  670. X        else if ( next_row[col] && lev->lit ) {
  671. X        /*
  672. X         * We see this position because it is lit.
  673. X         *
  674. X         * It is assumed here that lit walls are lit from the
  675. X         * inside of the room,  Hence, walls are not "seen"
  676. X         * unless we can see them from across a lit room square.
  677. X         */
  678. X        if (IS_WALL(lev->typ) || lev->typ == SDOOR) {
  679. X
  680. X            /* Check the closest adjacent position. */
  681. X            dx = u.ux - col;    dx = sign(dx);
  682. X            flev = &(levl[col+dx][row+dy]);
  683. X            /*
  684. X             * If it is a non-corridor "open" area, and it is lit,
  685. X             * then we see the wall as a wall.
  686. X             *
  687. X             * What happens when the hero is standing on this
  688. X             * location (dx == dy == 0)?
  689. X             */
  690. X            if (ZAP_POS(flev->typ) && (flev->typ != CORR) &&
  691. X                                flev->lit) {
  692. X            next_row[col] |= IN_SIGHT;    /* we see it */
  693. X            if (!lev->seen || (lev->diggable & W_REPAIRED)) {
  694. X                lev->seen = 1;        /* see it as a wall */
  695. X                lev->diggable &= ~W_REPAIRED;
  696. X                /*
  697. X                 * Force an update on the position, even if it
  698. X                 * was previously in sight.  Reason:  the hero
  699. X                 * could have been in a corridor or outside of
  700. X                 * an undiscovered wall and then teleported into
  701. X                 * the room.  The wall was in sight before, but
  702. X                 * seen as stone.  Now we need to see it as a
  703. X                 * wall.
  704. X                 */
  705. X                newsym(col,row);
  706. X            }
  707. X            } else
  708. X            goto not_in_sight;    /* we don't see it */
  709. X
  710. X        } else if (IS_DOOR(lev->typ) && !viz_clear[row][col]) {
  711. X            /*
  712. X             * Make sure doors, boulders or mimics don't show up
  713. X             * at the end of dark hallways.  We do this by checking
  714. X             * the adjacent position.  If it is lit, then we can see
  715. X             * the door, otherwise we can't.
  716. X             */
  717. X            dx = u.ux - col;    dx = sign(dx);
  718. X            flev = &(levl[col+dx][row+dy]);
  719. X            if (flev->lit) {
  720. X            next_row[col] |= IN_SIGHT;    /* we see it */
  721. X
  722. X            /* Update position if it was not in sight before. */
  723. X            if (!(old_row[col] & IN_SIGHT)) newsym(col,row);
  724. X            } else
  725. X            goto not_in_sight;    /* we don't see it */
  726. X
  727. X        } else {
  728. X            next_row[col] |= IN_SIGHT;    /* we see it */
  729. X
  730. X            /* Update position if it was not in sight before. */
  731. X            if ( !(old_row[col] & IN_SIGHT) ) {
  732. X            lev->seen = 1;
  733. X            newsym(col,row);
  734. X            }
  735. X        }
  736. X        } else if (next_row[col] && lev->waslit ) {
  737. X        /*
  738. X         * If we make it here, the hero _could see_ the location
  739. X         * (next_row[col] is true), but doesn't see it (lit is false).
  740. X         * However, the hero _remembers_ it as lit (waslit is true).
  741. X         * The hero can now see that it is not lit, so change waslit
  742. X         * and update the location.
  743. X         */
  744. X        lev->waslit = 0; /* remember lit condition */
  745. X        newsym(col,row);
  746. X        }
  747. X        /*
  748. X         * At this point we know that the row position is *not* in
  749. X         * sight.  If the old one *was* in sight, then clean up the
  750. X         * position.
  751. X         */
  752. X        else {
  753. Xnot_in_sight:
  754. X        if (old_row[col] & IN_SIGHT) newsym(col,row);
  755. X        }
  756. X
  757. X    } /* end for col . . */
  758. X    }    /* end for row . .  */
  759. X
  760. Xskip:
  761. X    newsym(u.ux,u.uy);        /* Make sure the hero shows up! */
  762. X
  763. X    /* Set the new min and max pointers. */
  764. X    viz_rmin  = next_rmin;
  765. X    viz_rmax = next_rmax;
  766. X}
  767. X
  768. X
  769. X/*
  770. X * block_point()
  771. X *
  772. X * Make the location opaque to light.
  773. X */
  774. Xvoid
  775. Xblock_point(x,y)
  776. X    int x, y;
  777. X{
  778. X    fill_point(y,x);
  779. X
  780. X    /* recalc light sources here? */
  781. X
  782. X    /*
  783. X     * We have to do a full vision recalculation if we "could see" the
  784. X     * location.  Why? Suppose some monster opened a way so that the
  785. X     * hero could see a lit room.  However, the position of the opening
  786. X     * was out of night-vision range of the hero.  Suddenly the hero should
  787. X     * see the lit room.
  788. X     */
  789. X    if (viz_array[y][x]) vision_full_recalc = 1;
  790. X}
  791. X
  792. X/*
  793. X * unblock_point()
  794. X *
  795. X * Make the location transparent to light.
  796. X */
  797. Xvoid
  798. Xunblock_point(x,y)
  799. X    int x, y;
  800. X{
  801. X    dig_point(y,x);
  802. X
  803. X    /* recalc light sources here? */
  804. X
  805. X    if (viz_array[y][x]) vision_full_recalc = 1;
  806. X}
  807. X
  808. X
  809. X/*===========================================================================*\
  810. X |                                         |
  811. X |    Everything below this line uses (y,x) instead of (x,y) --- the         |
  812. X |    algorithms are faster if they are less recursive and can scan         |
  813. X |    on a row longer.                             |
  814. X |                                         |
  815. X\*===========================================================================*/
  816. X
  817. X
  818. X/* ========================================================================= *\
  819. X            Left and Right Pointer Updates
  820. X\* ========================================================================= */
  821. X
  822. X/*
  823. X *            LEFT and RIGHT pointer rules
  824. X *
  825. X *
  826. X * **NOTE**  The rules changed on 4/4/90.  This comment reflects the
  827. X * new rules.  The change was so that the stone-wall optimization
  828. X * would work.
  829. X *
  830. X * OK, now the tough stuff.  We must maintain our left and right
  831. X * row pointers.  The rules are as follows:
  832. X *  
  833. X * Left Pointers:
  834. X * ______________
  835. X *
  836. X * + If you are a clear spot, your left will point to the first
  837. X *   stone to your left.  If there is none, then point the first
  838. X *   legal position in the row (0).
  839. X *
  840. X * + If you are a blocked spot, then your left will point to the
  841. X *   left-most blocked spot to your left that is connected to you.
  842. X *   This means that a left-edge (a blocked spot that has an open
  843. X *   spot on its left) will point to itself.
  844. X *
  845. X *
  846. X * Right Pointers:
  847. X * ---------------
  848. X * + If you are a clear spot, your right will point to the first
  849. X *   stone to your right.  If there is none, then point the last
  850. X *   legal position in the row (COLNO-1).
  851. X *
  852. X * + If you are a blocked spot, then your right will point to the
  853. X *   right-most blocked spot to your right that is connected to you.
  854. X *   This means that a right-edge (a blocked spot that has an open
  855. X *    spot on its right) will point to itself.
  856. X */
  857. Xstatic void
  858. Xdig_point(row,col)
  859. X    int row,col;
  860. X{
  861. X    int i;
  862. X
  863. X    if (viz_clear[row][col]) return;        /* already done */
  864. X
  865. X    viz_clear[row][col] = 1;
  866. X
  867. X    /*
  868. X     * Boundary cases first.
  869. X     */
  870. X    if (col == 0) {                /* left edge */
  871. X    if (viz_clear[row][1]) {
  872. X        right_ptrs[row][0] = right_ptrs[row][1];
  873. X    } else {
  874. X        right_ptrs[row][0] = 1;
  875. X        for (i = 1; i <= right_ptrs[row][1]; i++)
  876. X        left_ptrs[row][i] = 1;
  877. X    }
  878. X    } else if (col == (COLNO-1)) {        /* right edge */
  879. X
  880. X    if (viz_clear[row][COLNO-2]) {
  881. X        left_ptrs[row][COLNO-1] = left_ptrs[row][COLNO-2];
  882. X    } else {
  883. X        left_ptrs[row][COLNO-1] = COLNO-2;
  884. X        for (i = left_ptrs[row][COLNO-2]; i < COLNO-1; i++)
  885. X        right_ptrs[row][i] = COLNO-2;
  886. X    }
  887. X    }
  888. X     
  889. X    /*
  890. X     * At this point, we know we aren't on the boundaries.
  891. X     */
  892. X    else if (viz_clear[row][col-1] && viz_clear[row][col+1]) {
  893. X    /* Both sides clear */
  894. X    for (i = left_ptrs[row][col-1]; i <= col; i++) {
  895. X        if (!viz_clear[row][i]) continue;    /* catch non-end case */
  896. X        right_ptrs[row][i] = right_ptrs[row][col+1];
  897. X    }
  898. X    for (i = col; i <= right_ptrs[row][col+1]; i++) {
  899. X        if (!viz_clear[row][i]) continue;    /* catch non-end case */
  900. X        left_ptrs[row][i] = left_ptrs[row][col-1];
  901. X    }
  902. X
  903. X    } else if (viz_clear[row][col-1]) {
  904. X    /* Left side clear, right side blocked. */
  905. X    for (i = col+1; i <= right_ptrs[row][col+1]; i++)
  906. X        left_ptrs[row][i] = col+1;
  907. X
  908. X    for (i = left_ptrs[row][col-1]; i <= col; i++) {
  909. X        if (!viz_clear[row][i]) continue;    /* catch non-end case */
  910. X        right_ptrs[row][i] = col+1;
  911. X    }
  912. X    left_ptrs[row][col] = left_ptrs[row][col-1];
  913. X
  914. X    } else if (viz_clear[row][col+1]) {
  915. X    /* Right side clear, left side blocked. */
  916. X    for (i = left_ptrs[row][col-1]; i < col; i++)
  917. X        right_ptrs[row][i] = col-1;
  918. X
  919. X    for (i = col; i <= right_ptrs[row][col+1]; i++) {
  920. X        if (!viz_clear[row][i]) continue;    /* catch non-end case */
  921. X        left_ptrs[row][i] = col-1;
  922. X    }
  923. X    right_ptrs[row][col] = right_ptrs[row][col+1];
  924. X
  925. X    } else {
  926. X    /* Both sides blocked */
  927. X    for (i = left_ptrs[row][col-1]; i < col; i++)
  928. X        right_ptrs[row][i] = col-1;
  929. X
  930. X    for (i = col+1; i <= right_ptrs[row][col+1]; i++)
  931. X        left_ptrs[row][i] = col+1;
  932. X
  933. X    left_ptrs[row][col]  = col-1;
  934. X    right_ptrs[row][col] = col+1;
  935. X    }
  936. X}
  937. X
  938. Xstatic void
  939. Xfill_point(row,col)
  940. X    int row, col;
  941. X{
  942. X    int i;
  943. X
  944. X    if (!viz_clear[row][col]) return;
  945. X
  946. X    viz_clear[row][col] = 0;
  947. X
  948. X    if (col == 0) {
  949. X    if (viz_clear[row][1]) {            /* adjacent is clear */
  950. X        right_ptrs[row][0] = 0;
  951. X    } else {
  952. X        right_ptrs[row][0] = right_ptrs[row][1];
  953. X        for (i = 1; i <= right_ptrs[row][1]; i++)
  954. X        left_ptrs[row][i] = 0;
  955. X    }
  956. X    } else if (col == COLNO-1) {
  957. X    if (viz_clear[row][COLNO-2]) {        /* adjacent is clear */
  958. X        left_ptrs[row][COLNO-1] = COLNO-1;
  959. X    } else {
  960. X        left_ptrs[row][COLNO-1] = left_ptrs[row][COLNO-2];
  961. X        for (i = left_ptrs[row][COLNO-2]; i < COLNO-1; i++)
  962. X        right_ptrs[row][i] = COLNO-1;
  963. X    }
  964. X    }
  965. X
  966. X    /*
  967. X     * Else we know that we are not on an edge.
  968. X     */
  969. X    else if (viz_clear[row][col-1] && viz_clear[row][col+1]) {
  970. X    /* Both sides clear */
  971. X    for (i = left_ptrs[row][col-1]+1; i <= col; i++)
  972. X        right_ptrs[row][i] = col;
  973. X
  974. X    if (!left_ptrs[row][col-1])        /* catch the end case */
  975. X        right_ptrs[row][0] = col;
  976. X
  977. X    for (i = col; i < right_ptrs[row][col+1]; i++)
  978. X        left_ptrs[row][i] = col;
  979. X
  980. X    if (right_ptrs[row][col+1] == COLNO-1)    /* catch the end case */
  981. X        left_ptrs[row][COLNO-1] = col;
  982. X
  983. X    } else if (viz_clear[row][col-1]) {
  984. X    /* Left side clear, right side blocked. */
  985. X    for (i = col; i <= right_ptrs[row][col+1]; i++)
  986. X        left_ptrs[row][i] = col;
  987. X
  988. X    for (i = left_ptrs[row][col-1]+1; i < col; i++)
  989. X        right_ptrs[row][i] = col;
  990. X
  991. X    if (!left_ptrs[row][col-1])        /* catch the end case */
  992. X        right_ptrs[row][i] = col;
  993. X
  994. X    right_ptrs[row][col] = right_ptrs[row][col+1];
  995. X
  996. X    } else if (viz_clear[row][col+1]) {
  997. X    /* Right side clear, left side blocked. */
  998. X    for (i = left_ptrs[row][col-1]; i <= col; i++)
  999. X        right_ptrs[row][i] = col;
  1000. X
  1001. X    for (i = col+1; i < right_ptrs[row][col+1]; i++)
  1002. X        left_ptrs[row][i] = col;
  1003. X
  1004. X    if (right_ptrs[row][col+1] == COLNO-1)    /* catch the end case */
  1005. X        left_ptrs[row][i] = col;
  1006. X
  1007. X    left_ptrs[row][col] = left_ptrs[row][col-1];
  1008. X
  1009. X    } else {
  1010. X    /* Both sides blocked */
  1011. X    for (i = left_ptrs[row][col-1]; i <= col; i++)
  1012. X        right_ptrs[row][i] = right_ptrs[row][col+1];
  1013. X
  1014. X    for (i = col; i <= right_ptrs[row][col+1]; i++)
  1015. X        left_ptrs[row][i] = left_ptrs[row][col-1];
  1016. X    }
  1017. X}
  1018. X
  1019. X
  1020. X/*===========================================================================*/
  1021. X/*===========================================================================*/
  1022. X/* Use either algorithm C or D.  See the config.h for more details. =========*/
  1023. X
  1024. X/*
  1025. X * Variables local to both Algorithms C and D.
  1026. X */
  1027. Xstatic int  start_row;
  1028. Xstatic int  start_col;
  1029. Xstatic int  step;
  1030. Xstatic char **cs_rows;
  1031. Xstatic char *cs_left;
  1032. Xstatic char *cs_right;
  1033. X
  1034. Xstatic void FDECL((*vis_func), (int,int,genericptr_t));
  1035. Xstatic genericptr_t varg;
  1036. X
  1037. X/*
  1038. X * Both Algorithms C and D use the following macros.
  1039. X *
  1040. X *      good_row(z)      - Return TRUE if the argument is a legal row.
  1041. X *      set_cs(rowp,col)  - Set the local could see array.
  1042. X *      set_min(z)      - Save the min value of the argument and the current
  1043. X *                    row minimum.
  1044. X *      set_max(z)      - Save the max value of the argument and the current
  1045. X *                    row maximum.
  1046. X *  
  1047. X * The last three macros depend on having local pointers row_min, row_max,
  1048. X * and rowp being set correctly.
  1049. X */
  1050. X#define set_cs(rowp,col) (rowp[col] = COULD_SEE)
  1051. X#define good_row(z) ((z) >= 0 && (z) < ROWNO)
  1052. X#define set_min(z) if (*row_min > (z)) *row_min = (z)
  1053. X#define set_max(z) if (*row_max < (z)) *row_max = (z)
  1054. X#define is_clear(row,col) viz_clear_rows[row][col]
  1055. X
  1056. X/*
  1057. X * clear_path()        expanded into 4 macros/functions:
  1058. X *
  1059. X *    q1_path()
  1060. X *    q2_path()
  1061. X *    q3_path()
  1062. X *    q4_path()
  1063. X *
  1064. X * "Draw" a line from the start to the given location.  Stop if we hit
  1065. X * something that blocks light.  The start and finish points themselves are
  1066. X * not checked, just the points between them.  These routines do _not_
  1067. X * expect to be called with the same starting and stopping point.
  1068. X *
  1069. X * These routines use the generalized integer Bresenham's algorithm (fast
  1070. X * line drawing) for all quadrants.  The algorithm was taken from _Procedural
  1071. X * Elements for Computer Graphics_, by David F. Rogers.  McGraw-Hill, 1985.
  1072. X */
  1073. X#ifdef MACRO_CPATH    /* quadrant calls are macros */
  1074. X
  1075. X/*
  1076. X * When called, the result is in "result".
  1077. X * The first two arguments (srow,scol) are one end of the path.  The next
  1078. X * two arguments (row,col) are the destination.  The last argument is
  1079. X * used as a C language label.  This means that it must be different
  1080. X * in each pair of calls.
  1081. X */
  1082. X
  1083. X/*
  1084. X *  Quadrant I (step < 0).
  1085. X */
  1086. X#define q1_path(srow,scol,y2,x2,label)                   \
  1087. X{                            \
  1088. X    int dx, dy;                        \
  1089. X    register int k, err, x, y, dxs, dys;        \
  1090. X                            \
  1091. X    x  = (scol);    y  = (srow);            \
  1092. X    dx = (x2) - x;    dy = y - (y2);            \
  1093. X                            \
  1094. X    result = 0;         /* default to a blocked path */\
  1095. X                            \
  1096. X    dxs = dx << 1;       /* save the shifted values */\
  1097. X    dys = dy << 1;                    \
  1098. X    if (dy > dx) {                    \
  1099. X    err = dxs - dy;                    \
  1100. X                            \
  1101. X    for (k = dy-1; k; k--) {            \
  1102. X        if (err >= 0) {                \
  1103. X        x++;                    \
  1104. X        err -= dys;                \
  1105. X        }                        \
  1106. X        y--;                    \
  1107. X        err += dxs;                    \
  1108. X        if (!is_clear(y,x)) goto label;/* blocked */\
  1109. X    }                        \
  1110. X    } else {                        \
  1111. X    err = dys - dx;                    \
  1112. X                            \
  1113. X    for (k = dx-1; k; k--) {            \
  1114. X        if (err >= 0) {                \
  1115. X        y--;                    \
  1116. X        err -= dxs;                \
  1117. X        }                        \
  1118. X        x++;                    \
  1119. X        err += dys;                    \
  1120. X        if (!is_clear(y,x)) goto label;/* blocked */\
  1121. X    }                        \
  1122. X    }                            \
  1123. X                            \
  1124. X    result = 1;                        \
  1125. X}
  1126. X
  1127. X/*
  1128. X * Quadrant IV (step > 0).
  1129. X */
  1130. X#define q4_path(srow,scol,y2,x2,label)            \
  1131. X{                            \
  1132. X    int dx, dy;                        \
  1133. X    register int k, err, x, y, dxs, dys;        \
  1134. X                            \
  1135. X    x  = (scol);    y  = (srow);            \
  1136. X    dx = (x2) - x;    dy = (y2) - y;            \
  1137. X                            \
  1138. X    result = 0;         /* default to a blocked path */\
  1139. X                            \
  1140. X    dxs = dx << 1;       /* save the shifted values */\
  1141. X    dys = dy << 1;                    \
  1142. X    if (dy > dx) {                    \
  1143. X    err = dxs - dy;                    \
  1144. X                            \
  1145. X    for (k = dy-1; k; k--) {            \
  1146. X        if (err >= 0) {                \
  1147. X        x++;                    \
  1148. X        err -= dys;                \
  1149. X        }                        \
  1150. X        y++;                    \
  1151. X        err += dxs;                    \
  1152. X        if (!is_clear(y,x)) goto label;/* blocked */\
  1153. X    }                        \
  1154. X                            \
  1155. X    } else {                        \
  1156. X    err = dys - dx;                    \
  1157. X                            \
  1158. X    for (k = dx-1; k; k--) {            \
  1159. X        if (err >= 0) {                \
  1160. X        y++;                    \
  1161. X        err -= dxs;                \
  1162. X        }                        \
  1163. X        x++;                    \
  1164. X        err += dys;                    \
  1165. X        if (!is_clear(y,x)) goto label;/* blocked */\
  1166. X    }                        \
  1167. X    }                            \
  1168. X                            \
  1169. X    result = 1;                        \
  1170. X}
  1171. X
  1172. X/*
  1173. X * Quadrant II (step < 0).
  1174. X */
  1175. X#define q2_path(srow,scol,y2,x2,label)                   \
  1176. X{                            \
  1177. X    int dx, dy;                        \
  1178. X    register int k, err, x, y, dxs, dys;        \
  1179. X                            \
  1180. X    x  = (scol);    y  = (srow);            \
  1181. X    dx = x - (x2);    dy = y - (y2);            \
  1182. X                            \
  1183. X    result = 0;         /* default to a blocked path */\
  1184. X                            \
  1185. X    dxs = dx << 1;       /* save the shifted values */\
  1186. X    dys = dy << 1;                    \
  1187. X    if (dy > dx) {                    \
  1188. X    err = dxs - dy;                    \
  1189. X                            \
  1190. X    for (k = dy-1; k; k--) {            \
  1191. X        if (err >= 0) {                \
  1192. X        x--;                    \
  1193. X        err -= dys;                \
  1194. X        }                        \
  1195. X        y--;                    \
  1196. X        err += dxs;                    \
  1197. X        if (!is_clear(y,x)) goto label;/* blocked */\
  1198. X    }                        \
  1199. X    } else {                        \
  1200. X    err = dys - dx;                    \
  1201. X                            \
  1202. X    for (k = dx-1; k; k--) {            \
  1203. X        if (err >= 0) {                \
  1204. X        y--;                    \
  1205. X        err -= dxs;                \
  1206. X        }                        \
  1207. X        x--;                    \
  1208. X        err += dys;                    \
  1209. X        if (!is_clear(y,x)) goto label;/* blocked */\
  1210. X    }                        \
  1211. X    }                            \
  1212. X                            \
  1213. X    result = 1;                        \
  1214. X}
  1215. X
  1216. X/*
  1217. X * Quadrant III (step > 0).
  1218. X */
  1219. X#define q3_path(srow,scol,y2,x2,label)            \
  1220. X{                            \
  1221. X    int dx, dy;                        \
  1222. X    register int k, err, x, y, dxs, dys;        \
  1223. X                            \
  1224. X    x  = (scol);    y  = (srow);            \
  1225. X    dx = x - (x2);    dy = (y2) - y;            \
  1226. X                            \
  1227. X    result = 0;         /* default to a blocked path */\
  1228. X                            \
  1229. X    dxs = dx << 1;       /* save the shifted values */\
  1230. X    dys = dy << 1;                    \
  1231. X    if (dy > dx) {                    \
  1232. X    err = dxs - dy;                    \
  1233. X                            \
  1234. X    for (k = dy-1; k; k--) {            \
  1235. X        if (err >= 0) {                \
  1236. X        x--;                    \
  1237. X        err -= dys;                \
  1238. X        }                        \
  1239. X        y++;                    \
  1240. X        err += dxs;                    \
  1241. X        if (!is_clear(y,x)) goto label;/* blocked */\
  1242. X    }                        \
  1243. X                            \
  1244. X    } else {                        \
  1245. X    err = dys - dx;                    \
  1246. X                            \
  1247. X    for (k = dx-1; k; k--) {            \
  1248. X        if (err >= 0) {                \
  1249. X        y++;                    \
  1250. X        err -= dxs;                \
  1251. X        }                        \
  1252. X        x--;                    \
  1253. X        err += dys;                    \
  1254. X        if (!is_clear(y,x)) goto label;/* blocked */\
  1255. X    }                        \
  1256. X    }                            \
  1257. X                            \
  1258. X    result = 1;                        \
  1259. X}
  1260. X
  1261. X#else   /* quadrants are really functions */
  1262. X
  1263. Xstatic int FDECL(_q1_path, (int,int,int,int));
  1264. Xstatic int FDECL(_q2_path, (int,int,int,int));
  1265. Xstatic int FDECL(_q3_path, (int,int,int,int));
  1266. Xstatic int FDECL(_q4_path, (int,int,int,int));
  1267. X
  1268. X#define q1_path(sy,sx,y,x,dummy) result = _q1_path(sy,sx,y,x)
  1269. X#define q2_path(sy,sx,y,x,dummy) result = _q2_path(sy,sx,y,x)
  1270. X#define q3_path(sy,sx,y,x,dummy) result = _q3_path(sy,sx,y,x)
  1271. X#define q4_path(sy,sx,y,x,dummy) result = _q4_path(sy,sx,y,x)
  1272. X
  1273. X/*
  1274. X * Quadrant I (step < 0).
  1275. X */
  1276. Xstatic int
  1277. X_q1_path(srow,scol,y2,x2)
  1278. X    int scol, srow, y2, x2;
  1279. X{
  1280. X    int dx, dy;
  1281. X    register int k, err, x, y, dxs, dys;
  1282. X
  1283. X    x  = scol;        y  = srow;
  1284. X    dx = x2 - x;    dy = y - y2;
  1285. X
  1286. X    dxs = dx << 1;       /* save the shifted values */
  1287. X    dys = dy << 1;
  1288. X    if (dy > dx) {
  1289. X    err = dxs - dy;
  1290. X
  1291. X    for (k = dy-1; k; k--) {
  1292. X        if (err >= 0) {
  1293. X        x++;
  1294. X        err -= dys;
  1295. X        }
  1296. X        y--;
  1297. X        err += dxs;
  1298. X        if (!is_clear(y,x)) return 0; /* blocked */
  1299. X    }
  1300. X    } else {
  1301. X    err = dys - dx;
  1302. X
  1303. X    for (k = dx-1; k; k--) {
  1304. X        if (err >= 0) {
  1305. X        y--;
  1306. X        err -= dxs;
  1307. X        }
  1308. X        x++;
  1309. X        err += dys;
  1310. X        if (!is_clear(y,x)) return 0;/* blocked */
  1311. X    }
  1312. X    }
  1313. X
  1314. X    return 1;
  1315. X}
  1316. X
  1317. X/*
  1318. X * Quadrant IV (step > 0).
  1319. X */
  1320. Xstatic int
  1321. X_q4_path(srow,scol,y2,x2)
  1322. X    int scol, srow, y2, x2;
  1323. X{
  1324. X    int dx, dy;
  1325. X    register int k, err, x, y, dxs, dys;
  1326. X
  1327. X    x  = scol;        y  = srow;
  1328. X    dx = x2 - x;    dy = y2 - y;
  1329. X
  1330. X    dxs = dx << 1;       /* save the shifted values */
  1331. X    dys = dy << 1;
  1332. X    if (dy > dx) {
  1333. X    err = dxs - dy;
  1334. X
  1335. X    for (k = dy-1; k; k--) {
  1336. X        if (err >= 0) {
  1337. X        x++;
  1338. X        err -= dys;
  1339. X        }
  1340. X        y++;
  1341. X        err += dxs;
  1342. X        if (!is_clear(y,x)) return 0; /* blocked */
  1343. X    }
  1344. X    } else {
  1345. X    err = dys - dx;
  1346. X
  1347. X    for (k = dx-1; k; k--) {
  1348. X        if (err >= 0) {
  1349. X        y++;
  1350. X        err -= dxs;
  1351. X        }
  1352. X        x++;
  1353. X        err += dys;
  1354. X        if (!is_clear(y,x)) return 0;/* blocked */
  1355. X    }
  1356. X    }
  1357. X
  1358. X    return 1;
  1359. X}
  1360. X
  1361. X/*
  1362. X * Quadrant II (step < 0).
  1363. X */
  1364. Xstatic int
  1365. X_q2_path(srow,scol,y2,x2)
  1366. X    int scol, srow, y2, x2;
  1367. X{
  1368. X    int dx, dy;
  1369. X    register int k, err, x, y, dxs, dys;
  1370. X
  1371. X    x  = scol;        y  = srow;
  1372. X    dx = x - x2;    dy = y - y2;
  1373. X
  1374. X    dxs = dx << 1;       /* save the shifted values */
  1375. X    dys = dy << 1;
  1376. X    if (dy > dx) {
  1377. X    err = dxs - dy;
  1378. X
  1379. X    for (k = dy-1; k; k--) {
  1380. X        if (err >= 0) {
  1381. X        x--;
  1382. X        err -= dys;
  1383. X        }
  1384. X        y--;
  1385. X        err += dxs;
  1386. X        if (!is_clear(y,x)) return 0; /* blocked */
  1387. X    }
  1388. X    } else {
  1389. X    err = dys - dx;
  1390. X
  1391. X    for (k = dx-1; k; k--) {
  1392. X        if (err >= 0) {
  1393. X        y--;
  1394. X        err -= dxs;
  1395. X        }
  1396. X        x--;
  1397. X        err += dys;
  1398. X        if (!is_clear(y,x)) return 0;/* blocked */
  1399. X    }
  1400. X    }
  1401. X
  1402. X    return 1;
  1403. X}
  1404. X
  1405. X/*
  1406. X * Quadrant III (step > 0).
  1407. X */
  1408. Xstatic int
  1409. X_q3_path(srow,scol,y2,x2)
  1410. X    int scol, srow, y2, x2;
  1411. X{
  1412. X    int dx, dy;
  1413. X    register int k, err, x, y, dxs, dys;
  1414. X
  1415. X    x  = scol;        y  = srow;
  1416. X    dx = x - x2;    dy = y2 - y;
  1417. X
  1418. X    dxs = dx << 1;       /* save the shifted values */
  1419. X    dys = dy << 1;
  1420. X    if (dy > dx) {
  1421. X    err = dxs - dy;
  1422. X
  1423. X    for (k = dy-1; k; k--) {
  1424. X        if (err >= 0) {
  1425. X        x--;
  1426. X        err -= dys;
  1427. X        }
  1428. X        y++;
  1429. X        err += dxs;
  1430. X        if (!is_clear(y,x)) return 0; /* blocked */
  1431. X    }
  1432. X    } else {
  1433. X    err = dys - dx;
  1434. X
  1435. X    for (k = dx-1; k; k--) {
  1436. X        if (err >= 0) {
  1437. X        y++;
  1438. X        err -= dxs;
  1439. X        }
  1440. X        x--;
  1441. X        err += dys;
  1442. X        if (!is_clear(y,x)) return 0;/* blocked */
  1443. X    }
  1444. X    }
  1445. X
  1446. X    return 1;
  1447. X}
  1448. X
  1449. X#endif    /* quadrants are functions */
  1450. X
  1451. END_OF_FILE
  1452. if test 38940 -ne `wc -c <'src/vision.c1'`; then
  1453.     echo shar: \"'src/vision.c1'\" unpacked with wrong size!
  1454. fi
  1455. # end of 'src/vision.c1'
  1456. fi
  1457. if test -f 'src/wizard.c' -a "${1}" != "-c" ; then 
  1458.   echo shar: Will not clobber existing file \"'src/wizard.c'\"
  1459. else
  1460. echo shar: Extracting \"'src/wizard.c'\" \(15887 characters\)
  1461. sed "s/^X//" >'src/wizard.c' <<'END_OF_FILE'
  1462. X/*    SCCS Id: @(#)wizard.c    3.1    92/11/13          */
  1463. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  1464. X/* NetHack may be freely redistributed.  See license for details. */
  1465. X
  1466. X/* wizard code - inspired by rogue code from Merlyn Leroy (digi-g!brian) */
  1467. X/*           - heavily modified to give the wiz balls.  (genat!mike)   */
  1468. X/*           - dewimped and given some maledictions. -3. */
  1469. X/*           - generalized for 3.1 (mike@bullns.on01.bull.ca) */
  1470. X
  1471. X#include "hack.h"
  1472. X#ifdef MULDGN
  1473. X#include "qtext.h"
  1474. X#endif
  1475. X
  1476. X#ifdef OVLB
  1477. X
  1478. Xstatic short FDECL(which_arti, (UCHAR_P));
  1479. Xstatic boolean FDECL(mon_has_arti, (struct monst *,SHORT_P));
  1480. Xstatic struct monst *FDECL(other_mon_has_arti, (struct monst *,SHORT_P));
  1481. Xstatic struct obj *FDECL(on_ground, (SHORT_P));
  1482. Xstatic boolean FDECL(you_have, (UCHAR_P));
  1483. Xstatic long FDECL(target_on, (UCHAR_P,struct monst *));
  1484. Xstatic long FDECL(strategy, (struct monst *));
  1485. X
  1486. X/*    TODO:    Expand this list.    */
  1487. Xstatic const int NEARDATA nasties[] = {
  1488. X    PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR, PM_RED_DRAGON,
  1489. X    PM_GREEN_DRAGON, PM_OWLBEAR, PM_PURPLE_WORM, PM_ROCK_TROLL, PM_XAN,
  1490. X    PM_GREMLIN, PM_UMBER_HULK, PM_VAMPIRE_LORD, PM_XORN, PM_ZRUTY,
  1491. X    PM_ELF_LORD, PM_ELVENKING, PM_YELLOW_DRAGON, PM_LEOCROTTA,
  1492. X    PM_CARNIVOROUS_APE, PM_FIRE_GIANT, PM_COUATL,
  1493. X#ifdef ARMY
  1494. X    PM_CAPTAIN,
  1495. X#endif
  1496. X    };
  1497. X
  1498. Xstatic const unsigned NEARDATA wizapp[] = {
  1499. X    PM_HUMAN, PM_WATER_DEMON, PM_VAMPIRE,
  1500. X    PM_RED_DRAGON, PM_TROLL, PM_UMBER_HULK,
  1501. X    PM_XORN, PM_XAN, PM_COCKATRICE,
  1502. X    PM_FLOATING_EYE,
  1503. X    PM_GUARDIAN_NAGA,
  1504. X    PM_TRAPPER
  1505. X};
  1506. X
  1507. X#endif /* OVLB */
  1508. X#ifdef OVL0
  1509. X
  1510. X/* If you've found the Amulet, make the Wizard appear after some time */
  1511. X/* Also, give hints about portal locations, if amulet is worn/wielded -dlc */
  1512. Xvoid
  1513. Xamulet()
  1514. X{
  1515. X    register struct monst *mtmp;
  1516. X    struct obj *amu;
  1517. X
  1518. X    if ((((amu = uamul) && uamul->otyp == AMULET_OF_YENDOR) ||
  1519. X         ((amu = uwep) && uwep->otyp == AMULET_OF_YENDOR)) && !rn2(15)) {
  1520. X        register struct trap *ttmp;
  1521. X        for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
  1522. X        if(ttmp->ttyp == MAGIC_PORTAL) {
  1523. X            int du = distu(ttmp->tx, ttmp->ty);
  1524. X            if (du <= 9)
  1525. X            pline("%s feels hot!", The(xname(amu)));
  1526. X            else if (du <= 64)
  1527. X            pline("%s feels very warm.", The(xname(amu)));
  1528. X            else if (du <= 144)
  1529. X            pline("%s feels warm.", The(xname(amu)));
  1530. X            /* else, the amulet feels normal */
  1531. X            break;
  1532. X        }
  1533. X        }
  1534. X    }
  1535. X
  1536. X    if (!flags.no_of_wizards || !u.uhave.amulet)
  1537. X        return;
  1538. X    /* find Wizard, and wake him if necessary */
  1539. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1540. X        if(mtmp->iswiz && mtmp->msleep && !rn2(40)) {
  1541. X        mtmp->msleep = 0;
  1542. X        if (distu(mtmp->mx,mtmp->my) > 2)
  1543. X            You(
  1544. X    "get the creepy feeling that somebody noticed your taking the Amulet."
  1545. X            );
  1546. X        return;
  1547. X        }
  1548. X}
  1549. X
  1550. X#endif /* OVL0 */
  1551. X#ifdef OVLB
  1552. X
  1553. Xint
  1554. Xmon_has_amulet(mtmp)
  1555. Xregister struct monst *mtmp;
  1556. X{
  1557. X    register struct obj *otmp;
  1558. X
  1559. X    for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  1560. X        if(otmp->otyp == AMULET_OF_YENDOR) return(1);
  1561. X    return(0);
  1562. X}
  1563. X
  1564. Xint
  1565. Xmon_has_special(mtmp)
  1566. Xregister struct monst *mtmp;
  1567. X{
  1568. X    register struct obj *otmp;
  1569. X
  1570. X    for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  1571. X        if(otmp->otyp == AMULET_OF_YENDOR ||
  1572. X#ifdef MULDGN
  1573. X            is_quest_artifact(otmp) ||
  1574. X#endif
  1575. X            otmp->otyp == BELL_OF_OPENING ||
  1576. X            otmp->otyp == CANDELABRUM_OF_INVOCATION ||
  1577. X            otmp->otyp == SPE_BOOK_OF_THE_DEAD) return(1);
  1578. X    return(0);
  1579. X}
  1580. X
  1581. X/*
  1582. X *    New for 3.1  Strategy / Tactics for the wiz, as well as other
  1583. X *    monsters that are "after" something (defined via mflag3).
  1584. X *
  1585. X *    The strategy section decides *what* the monster is going
  1586. X *    to attempt, the tactics section implements the decision.
  1587. X */
  1588. X#define STRAT(w, x, y, typ) (w | ((long)(x)<<16) | ((long)(y)<<8) | (long)typ)
  1589. X#define ST_NONE    0L
  1590. X#define    ST_HEAL    -1L
  1591. X#define ST_GROUND 0x04000000
  1592. X#define ST_MONSTR 0x02000000
  1593. X#define ST_PLAYER 0x01000000
  1594. X
  1595. X#define    M_Wants(mask)    (mtmp->data->mflags3 & (mask))
  1596. X
  1597. Xstatic short
  1598. Xwhich_arti(mask)
  1599. X    register uchar mask;
  1600. X{
  1601. X    switch(mask) {
  1602. X        case M3_WANTSAMUL:    return(AMULET_OF_YENDOR);
  1603. X        case M3_WANTSBELL:    return(BELL_OF_OPENING);
  1604. X        case M3_WANTSCAND:    return(CANDELABRUM_OF_INVOCATION);
  1605. X        case M3_WANTSBOOK:    return(SPE_BOOK_OF_THE_DEAD);
  1606. X        default:        break;    /* 0 signifies quest artifact */
  1607. X    }
  1608. X    return(0);
  1609. X}
  1610. X
  1611. X/*
  1612. X *    If "otyp" is zero, it triggers a check for the quest_artifact,
  1613. X *    since bell, book, candle, and amulet are all objects, not really
  1614. X *    artifacts right now.    [MRS]
  1615. X */
  1616. Xstatic boolean
  1617. Xmon_has_arti(mtmp, otyp)
  1618. X    register struct monst *mtmp;
  1619. X    register short    otyp;
  1620. X{
  1621. X    register struct obj *otmp;
  1622. X
  1623. X    for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) {
  1624. X        if(otyp) {
  1625. X        if(otmp->otyp == otyp)
  1626. X            return(1);
  1627. X        }
  1628. X#ifdef MULDGN
  1629. X         else if(is_quest_artifact(otmp)) return(1);
  1630. X#endif
  1631. X    }
  1632. X    return(0);
  1633. X
  1634. X}
  1635. X
  1636. Xstatic struct monst *
  1637. Xother_mon_has_arti(mtmp, otyp)
  1638. X    register struct monst *mtmp;
  1639. X    register short    otyp;
  1640. X{
  1641. X    register struct monst *mtmp2;
  1642. X
  1643. X    for(mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon)
  1644. X        if(mtmp2 != mtmp)
  1645. X        if(mon_has_arti(mtmp2, otyp)) return(mtmp2);
  1646. X
  1647. X    return((struct monst *)0);
  1648. X}
  1649. X
  1650. Xstatic struct obj *
  1651. Xon_ground(otyp)
  1652. X    register short    otyp;
  1653. X{
  1654. X    register struct obj *otmp;
  1655. X
  1656. X    for(otmp = fobj; otmp; otmp = otmp->nobj)
  1657. X        if(otyp) {
  1658. X        if(otmp->otyp == otyp)
  1659. X            return(otmp);
  1660. X        }
  1661. X#ifdef MULDGN
  1662. X         else if(is_quest_artifact(otmp)) return(otmp);
  1663. X#endif
  1664. X    return((struct obj *)0);
  1665. X}
  1666. X
  1667. Xstatic boolean
  1668. Xyou_have(mask)
  1669. X    register uchar    mask;
  1670. X{
  1671. X    switch(mask) {
  1672. X        case M3_WANTSAMUL:    return(u.uhave.amulet);
  1673. X        case M3_WANTSBELL:    return(u.uhave.bell);
  1674. X        case M3_WANTSCAND:    return(u.uhave.menorah);
  1675. X        case M3_WANTSBOOK:    return(u.uhave.book);
  1676. X#ifdef MULDGN
  1677. X        case M3_WANTSARTI:    return(u.uhave.questart);
  1678. X#endif
  1679. X        default:        break;
  1680. X    }
  1681. X    return(0);
  1682. X}
  1683. X
  1684. Xstatic long
  1685. Xtarget_on(mask, mtmp)
  1686. X    register uchar  mask;
  1687. X    register struct monst *mtmp;
  1688. X{
  1689. X    register short    otyp;
  1690. X    register struct obj *otmp;
  1691. X    register struct monst *mtmp2;
  1692. X
  1693. X    if(!M_Wants(mask))    return(ST_NONE);
  1694. X
  1695. X    otyp = which_arti(mask);
  1696. X    if(!mon_has_arti(mtmp, otyp)) {
  1697. X        if(you_have(mask))
  1698. X        return(STRAT(ST_PLAYER, u.ux, u.uy, mask));
  1699. X        else if((otmp = on_ground(otyp)))
  1700. X        return(STRAT(ST_GROUND, otmp->ox, otmp->oy, mask));
  1701. X        else if((mtmp2 = other_mon_has_arti(mtmp, otyp)))
  1702. X        return(STRAT(ST_MONSTR, mtmp2->mx, mtmp2->my, mask));
  1703. X    }
  1704. X    return(ST_NONE);
  1705. X}
  1706. X
  1707. Xstatic long
  1708. Xstrategy(mtmp)
  1709. X    register struct monst *mtmp;
  1710. X{
  1711. X    long strat, dstrat;
  1712. X
  1713. X    if(!is_covetous(mtmp->data)) return(ST_NONE);
  1714. X
  1715. X    switch((mtmp->mhp*3)/mtmp->mhpmax) {    /* 0-3 */
  1716. X
  1717. X       default:
  1718. X        case 0:    /* panic time - mtmp is almost snuffed */
  1719. X            return(ST_HEAL);
  1720. X
  1721. X        case 1:    /* the wiz is less cautious */
  1722. X            if(mtmp->data != &mons[PM_WIZARD_OF_YENDOR])
  1723. X                return(ST_HEAL);
  1724. X            /* else fall through */
  1725. X
  1726. X        case 2:    dstrat = ST_HEAL;
  1727. X            break;
  1728. X
  1729. X        case 3:    dstrat = ST_NONE;
  1730. X            break;
  1731. X    }
  1732. X
  1733. X    if(flags.made_amulet)
  1734. X        if((strat = target_on(M3_WANTSAMUL, mtmp)) != ST_NONE)
  1735. X        return(strat);
  1736. X
  1737. X    if(u.uevent.invoked) {        /* priorities change once gate opened */
  1738. X
  1739. X#ifdef MULDGN
  1740. X        if((strat = target_on(M3_WANTSARTI, mtmp)) != ST_NONE)
  1741. X        return(strat);
  1742. X#endif
  1743. X        if((strat = target_on(M3_WANTSBOOK, mtmp)) != ST_NONE)
  1744. X        return(strat);
  1745. X        if((strat = target_on(M3_WANTSBELL, mtmp)) != ST_NONE)
  1746. X        return(strat);
  1747. X        if((strat = target_on(M3_WANTSCAND, mtmp)) != ST_NONE)
  1748. X        return(strat);
  1749. X    } else {
  1750. X
  1751. X        if((strat = target_on(M3_WANTSBOOK, mtmp)) != ST_NONE)
  1752. X        return(strat);
  1753. X        if((strat = target_on(M3_WANTSBELL, mtmp)) != ST_NONE)
  1754. X        return(strat);
  1755. X        if((strat = target_on(M3_WANTSCAND, mtmp)) != ST_NONE)
  1756. X        return(strat);
  1757. X#ifdef MULDGN
  1758. X        if((strat = target_on(M3_WANTSARTI, mtmp)) != ST_NONE)
  1759. X        return(strat);
  1760. X#endif
  1761. X    }
  1762. X    return(dstrat);
  1763. X}
  1764. X
  1765. Xint
  1766. Xtactics(mtmp)
  1767. X    register struct monst *mtmp;
  1768. X{
  1769. X    mtmp->mstrategy = strategy(mtmp);
  1770. X
  1771. X    switch (mtmp->mstrategy) {
  1772. X        case ST_HEAL:    /* hide and recover */
  1773. X        /* if wounded, hole up on or near the stairs (to block them) */
  1774. X        /* unless, of course, there are no stairs (e.g. endlevel */
  1775. X        if((xupstair || yupstair))
  1776. X            if (mtmp->mx != xupstair || mtmp->my != yupstair)
  1777. X            (void) mnearto(mtmp, xupstair, yupstair, TRUE);
  1778. X
  1779. X        /* if you're not around, cast healing spells */
  1780. X        if (distu(mtmp->mx,mtmp->my) > (BOLT_LIM * BOLT_LIM))
  1781. X            if(mtmp->mhp <= mtmp->mhpmax - 8) {
  1782. X            mtmp->mhp += rnd(8);
  1783. X            return(1);
  1784. X            }
  1785. X        /* fall through :-) */
  1786. X
  1787. X        case ST_NONE:    /* harrass */
  1788. X            if(!rn2(5)) mnexto(mtmp);
  1789. X        return(0);
  1790. X
  1791. X        default:        /* kill, maim, pillage! */
  1792. X        {
  1793. X        long  where = (mtmp->mstrategy & 0xff000000);
  1794. X        xchar tx = (xchar)((mtmp->mstrategy >> 16) & 0xff),
  1795. X              ty = (xchar)((mtmp->mstrategy >> 8) & 0xff);
  1796. X        uchar targ = (xchar)(mtmp->mstrategy & 0xff);
  1797. X        struct obj *otmp;
  1798. X
  1799. X        if(!targ) { /* simply wants you to close */
  1800. X            return(0);
  1801. X        }
  1802. X        if((u.ux == tx && u.uy == ty) || where == ST_PLAYER) {
  1803. X            /* player is standing on it (or has it) */
  1804. X            mnexto(mtmp);
  1805. X            return(0);
  1806. X        }
  1807. X        if(where == ST_GROUND) {
  1808. X          if(!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) {
  1809. X
  1810. X            /* teleport to it and pick it up */
  1811. X            rloc_to(mtmp, tx, ty);     /* clean old pos */
  1812. X
  1813. X            if((otmp = on_ground(which_arti(targ)))) {
  1814. X
  1815. X            if (cansee(mtmp->mx, mtmp->my))
  1816. X                pline("%s picks up %s.",
  1817. X                  Monnam(mtmp), the(xname(otmp)));
  1818. X            freeobj(otmp);
  1819. X            mpickobj(mtmp, otmp);
  1820. X            return(1);
  1821. X            } else return(0);
  1822. X          }
  1823. X            } else { /* a monster has it - 'port beside it. */
  1824. X            (void) mnearto(mtmp, tx, ty, TRUE);
  1825. X            return(0);
  1826. X        }
  1827. X        }
  1828. X    }
  1829. X    /* NOTREACHED */
  1830. X    return(0);
  1831. X}
  1832. X
  1833. Xvoid
  1834. Xaggravate()
  1835. X{
  1836. X    register struct monst *mtmp;
  1837. X
  1838. X    for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  1839. X        mtmp->msleep = 0;
  1840. X        if(!mtmp->mcanmove && !rn2(5)) {
  1841. X            mtmp->mfrozen = 0;
  1842. X            mtmp->mcanmove = 1;
  1843. X        }
  1844. X    }
  1845. X}
  1846. X
  1847. Xvoid
  1848. Xclonewiz()
  1849. X{
  1850. X    register struct monst *mtmp2;
  1851. X
  1852. X    if(mtmp2 = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy)) {
  1853. X        mtmp2->msleep = mtmp2->mtame = mtmp2->mpeaceful = 0;
  1854. X        if (!u.uhave.amulet && rn2(2)) {  /* give clone a fake */
  1855. X            mtmp2->minvent = mksobj(FAKE_AMULET_OF_YENDOR, TRUE, FALSE);
  1856. X        }
  1857. X        mtmp2->m_ap_type = M_AP_MONSTER;
  1858. X        mtmp2->mappearance = wizapp[rn2(SIZE(wizapp))];
  1859. X        newsym(mtmp2->mx,mtmp2->my);
  1860. X    }
  1861. X}
  1862. X
  1863. X/* create some nasty monsters, aligned or neutral with the caster */
  1864. X/* a null caster defaults to a chaotic caster (e.g. the wizard) */
  1865. Xvoid
  1866. Xnasty(mcast)
  1867. X    struct monst *mcast;
  1868. X{
  1869. X    register struct monst    *mtmp;
  1870. X    register int    i, j, tmp;
  1871. X    int castalign = (mcast ? mcast->data->maligntyp : -1);
  1872. X
  1873. X    if(!rn2(10) && Inhell) msummon(&mons[PM_WIZARD_OF_YENDOR]);
  1874. X    else {
  1875. X    tmp = (u.ulevel > 3) ? u.ulevel/3 : 1; /* just in case -- rph */
  1876. X
  1877. X    for(i = rnd(tmp); i > 0; --i)
  1878. X        for(j=0; j<20; j++) {
  1879. X        if((mtmp = makemon(&mons[nasties[rn2(SIZE(nasties))]],
  1880. X                   u.ux, u.uy))) {
  1881. X            mtmp->msleep = mtmp->mpeaceful = mtmp->mtame = 0;
  1882. X            set_malign(mtmp);
  1883. X        } else /* GENOD? */
  1884. X            mtmp = makemon((struct permonst *)0, u.ux, u.uy);
  1885. X        if(mtmp->data->maligntyp == 0 ||
  1886. X           sgn(mtmp->data->maligntyp) == sgn(castalign))
  1887. X            break;
  1888. X        }
  1889. X    }
  1890. X    return;
  1891. X}
  1892. X
  1893. X/*    Let's resurrect the wizard, for some unexpected fun.    */
  1894. Xvoid
  1895. Xresurrect()
  1896. X{
  1897. X    register struct monst    *mtmp;
  1898. X
  1899. X    if(mtmp = makemon(&mons[PM_WIZARD_OF_YENDOR], u.ux, u.uy)) {
  1900. X        mtmp->msleep = mtmp->mtame = mtmp->mpeaceful = 0;
  1901. X        set_malign(mtmp);
  1902. X        pline("A voice booms out...");
  1903. X        verbalize("So thou thought thou couldst kill me, fool.");
  1904. X    }
  1905. X
  1906. X}
  1907. X
  1908. X/*    Here, we make trouble for the poor shmuck who actually    */
  1909. X/*    managed to do in the Wizard.                */
  1910. Xvoid
  1911. Xintervene() {
  1912. X
  1913. X    switch(rn2(6)) {
  1914. X
  1915. X        case 0:
  1916. X        case 1:    You("feel vaguely nervous.");
  1917. X            break;
  1918. X        case 2:    if (!Blind)
  1919. X                You("notice a %s glow surrounding you.",
  1920. X                  Hallucination ? hcolor() : Black);
  1921. X            rndcurse();
  1922. X            break;
  1923. X        case 3:    aggravate();
  1924. X            break;
  1925. X        case 4:    nasty((struct monst *)0);
  1926. X            break;
  1927. X        case 5:    if (!flags.no_of_wizards) resurrect();
  1928. X            break;
  1929. X    }
  1930. X}
  1931. X
  1932. Xvoid
  1933. Xwizdead(mtmp)
  1934. Xregister struct monst    *mtmp;
  1935. X{
  1936. X    flags.no_of_wizards--;
  1937. X    if (!u.uevent.udemigod) {
  1938. X        u.uevent.udemigod = TRUE;
  1939. X        u.udg_cnt = rn1(250, 50);
  1940. X
  1941. X        /* Make the wizard meaner the next time he appears */
  1942. X        mtmp->data->mlevel++;
  1943. X        mtmp->data->ac--;
  1944. X    } else  
  1945. X        mtmp->data->mlevel++;
  1946. X}
  1947. X
  1948. Xconst char *random_insult[] = {
  1949. X    "antic",
  1950. X    "blackguard",
  1951. X    "caitiff",
  1952. X    "chucklehead",
  1953. X    "coistrel",
  1954. X    "craven",
  1955. X    "cretin",
  1956. X    "cur",
  1957. X    "dastard",
  1958. X    "demon fodder",
  1959. X    "dimwit",
  1960. X    "dolt",
  1961. X    "fool",
  1962. X    "footpad",
  1963. X    "imbecile",
  1964. X    "knave",
  1965. X    "maledict",
  1966. X    "miscreant",
  1967. X    "niddering",
  1968. X    "poltroon",
  1969. X    "rattlepate",
  1970. X    "reprobate",
  1971. X    "scapegrace",
  1972. X    "varlet",
  1973. X    "villein",    /* (sic.) */
  1974. X    "wittol",
  1975. X    "worm",
  1976. X    "wretch",
  1977. X};
  1978. X
  1979. Xconst char *random_malediction[] = {
  1980. X    "Hell shall soon claim thy remains,",
  1981. X    "I chortle at thee, thou pathetic",
  1982. X    "Prepare to die, thou",
  1983. X    "Resistance is useless,",
  1984. X    "Surrender or die, thou",
  1985. X    "There shall be no mercy, thou",
  1986. X    "Thou shalt repent of thy cunning,",
  1987. X    "Thou art as a flea to me,",
  1988. X    "Thou art doomed,",
  1989. X    "Thy fate is sealed,",
  1990. X    "Verily, thou shalt be one dead"
  1991. X};
  1992. X
  1993. X#ifdef SOUNDS
  1994. X# ifndef MULDGN
  1995. X/* Any %s will be filled in by the appropriate diety's name */
  1996. Xconst char *angelic_malediction[] = {
  1997. X    "Repent, and thou shalt be saved!",
  1998. X    "Thou shalt pay for thine insolence!",
  1999. X    "Very soon, my child, thou shalt meet thy maker.",
  2000. X    "%s has sent me to make you pay for your sins!",
  2001. X    "The wrath of %s is now upon you!",
  2002. X    "Thy life belongs to %s now!",
  2003. X    "Dost thou wish to receive thy final blessing?",
  2004. X    "Thou art but a godless void.",
  2005. X    "Thou art not worthy to seek the Amulet.",
  2006. X    "No one expects the Spanish Inquisition!",
  2007. X};
  2008. X
  2009. Xconst char *demonic_malediction[] = {
  2010. X    "I first mistook thee for a statue, when I regarded thy head of stone.",
  2011. X    "Come here often?",
  2012. X    "Dost pain excite thee?  Wouldst thou prefer the whip?",
  2013. X    "Thinkest thou it shall tickle as I rip out thy lungs?",
  2014. X    "Eat slime and die!",
  2015. X    "Go ahead, fetch thy mama!  I shall wait.",
  2016. X    "Go play leapfrog with a herd of unicorns!",
  2017. X    "Hast thou been drinking, or art thou always so clumsy?",
  2018. X    "This time I shall let thee off with a spanking, but let it not happen again.",
  2019. X    "I've met smarter (and prettier) acid blobs.",
  2020. X    "Look!  Thy bootlace is undone!",
  2021. X    "Mercy!  Dost thou wish me to die of laughter?",
  2022. X    "Run away!  Live to flee another day!",    
  2023. X    "Thou hadst best fight better than thou canst dress!",
  2024. X    "Twixt thy cousin and thee, Medusa is the prettier.",
  2025. X    "Methinks thou wert unnaturally interested in yon corpse back there, eh, varlet?",
  2026. X    "Up thy nose with a rubber hose!",
  2027. X    "Verily, thy corpse could not smell worse!",
  2028. X    "Wait!  I shall polymorph into a grid bug to give thee a fighting chance!",
  2029. X    "Why search for the Amulet?  Thou wouldst but lose it, cretin.",
  2030. X};
  2031. X# endif /* MULDGN */
  2032. X#endif
  2033. X
  2034. X/* Insult or intimidate the player */
  2035. Xvoid
  2036. Xcuss(mtmp)
  2037. Xregister struct monst    *mtmp;
  2038. X{
  2039. X#ifdef SOUNDS
  2040. X    if (mtmp->iswiz) {
  2041. X#endif
  2042. X        if (!rn2(5))  /* typical bad guy action */
  2043. X        pline("%s laughs fiendishly.", Monnam(mtmp));
  2044. X        else 
  2045. X        if (u.uhave.amulet && !rn2(SIZE(random_insult)))
  2046. X            verbalize("Relinquish the amulet, %s!",
  2047. X              random_insult[rn2(SIZE(random_insult))]);
  2048. X        else if (u.uhp < 5 && !rn2(2))    /* Panic */
  2049. X            verbalize(rn2(2) ?
  2050. X              "Even now thy life force ebbs, %s!" :
  2051. X              "Savor thy breath, %s, it be thine last!",
  2052. X              random_insult[rn2(SIZE(random_insult))]);
  2053. X        else if (mtmp->mhp < 5 && !rn2(2))    /* Parthian shot */
  2054. X            verbalize(rn2(2) ?
  2055. X                  "I shall return." :
  2056. X                  "I'll be back.");
  2057. X        else
  2058. X            verbalize("%s %s!",
  2059. X              random_malediction[rn2(SIZE(random_malediction))],
  2060. X              random_insult[rn2(SIZE(random_insult))]);
  2061. X#ifdef SOUNDS
  2062. X    } else if(is_lminion(mtmp->data)) {
  2063. X#ifndef MULDGN
  2064. X        verbalize(angelic_malediction[rn2(SIZE(angelic_malediction) - 1
  2065. X                          + (Hallucination ? 1 : 0))],
  2066. X              align_gname(A_LAWFUL));
  2067. X#else
  2068. X        com_pager(rn2(QTN_ANGELIC - 1 + (Hallucination ? 1 : 0)) +
  2069. X                  QT_ANGELIC);
  2070. X#endif
  2071. X    } else {
  2072. X        if (!rn2(5))
  2073. X        pline("%s casts aspersions on your ancestry.", Monnam(mtmp));
  2074. X        else
  2075. X#ifndef MULDGN
  2076. X        verbalize(demonic_malediction[rn2(SIZE(demonic_malediction))]);
  2077. X#else
  2078. X            com_pager(rn2(QTN_DEMONIC) + QT_DEMONIC);
  2079. X#endif
  2080. X    }
  2081. X#endif
  2082. X}
  2083. X
  2084. X#endif /* OVLB */
  2085. X
  2086. X/*wizard.c*/
  2087. END_OF_FILE
  2088. if test 15887 -ne `wc -c <'src/wizard.c'`; then
  2089.     echo shar: \"'src/wizard.c'\" unpacked with wrong size!
  2090. fi
  2091. # end of 'src/wizard.c'
  2092. fi
  2093. echo shar: End of archive 44 \(of 108\).
  2094. cp /dev/null ark44isdone
  2095. MISSING=""
  2096. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2097. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2098. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2099. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2100. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2101. 101 102 103 104 105 106 107 108 ; do
  2102.     if test ! -f ark${I}isdone ; then
  2103.     MISSING="${MISSING} ${I}"
  2104.     fi
  2105. done
  2106. if test "${MISSING}" = "" ; then
  2107.     echo You have unpacked all 108 archives.
  2108.     echo "Now execute 'rebuild.sh'"
  2109.     rm -f ark10[0-8]isdone ark[1-9]isdone ark[1-9][0-9]isdone
  2110. else
  2111.     echo You still need to unpack the following archives:
  2112.     echo "        " ${MISSING}
  2113. fi
  2114. ##  End of shell archive.
  2115. exit 0
  2116.