PageRenderTime 69ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/src/cave.c

https://github.com/NickMcConnell/Beleriand
C | 3427 lines | 1475 code | 583 blank | 1369 comment | 498 complexity | 25ebc5fcf5ba19efa156d85594db611e MD5 | raw file
  1. /** \file cave.c
  2. \brief Map visuals
  3. * distance, LOS (and targetting), destruction of a square, legal object
  4. * and monster codes, hallucination, code for dungeon display, memorization
  5. * of objects and features, small-scale dungeon maps, and management,
  6. * magic mapping, wizard light the dungeon, forget the dungeon, the pro-
  7. * jection code, disturb player, check for quest level.
  8. *
  9. * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
  10. *
  11. * This work is free software; you can redistribute it and/or modify it
  12. * under the terms of either:
  13. *
  14. * a) the GNU General Public License as published by the Free Software
  15. * Foundation, version 2, or
  16. *
  17. * b) the "Angband licence":
  18. * This software may be copied and distributed for educational, research,
  19. * and not for profit purposes provided that this copyright and statement
  20. * are included in all such copies. Other copyrights may also apply.
  21. */
  22. #include "angband.h"
  23. #include "cave.h"
  24. #include "game-event.h"
  25. #include "game-cmd.h"
  26. #include "option.h"
  27. #include "spells.h"
  28. #include "squelch.h"
  29. #include "trap.h"
  30. /**
  31. * Approximate Distance between two points.
  32. *
  33. * When either the X or Y component dwarfs the other component,
  34. * this function is almost perfect, and otherwise, it tends to
  35. * over-estimate about one grid per fifteen grids of distance.
  36. *
  37. * Algorithm: hypot(dy,dx) = max(dy,dx) + min(dy,dx) / 2
  38. */
  39. int distance(int y1, int x1, int y2, int x2)
  40. {
  41. int ay, ax;
  42. /* Find the absolute y/x distance components */
  43. ay = (y1 > y2) ? (y1 - y2) : (y2 - y1);
  44. ax = (x1 > x2) ? (x1 - x2) : (x2 - x1);
  45. /* Hack -- approximate the distance */
  46. return ((ay > ax) ? (ay + (ax >> 1)) : (ax + (ay >> 1)));
  47. }
  48. /**
  49. * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall,
  50. * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.
  51. *
  52. * This function returns TRUE if a "line of sight" can be traced from the
  53. * center of the grid (x1,y1) to the center of the grid (x2,y2), with all
  54. * of the grids along this path (except for the endpoints) being non-wall
  55. * grids, that are also not trees or rubble. Actually, the "chess knight
  56. * move" situation is handled by some special case code which allows the
  57. * grid diagonally next to the player to be obstructed, because this
  58. * yields better gameplay semantics. This algorithm is totally reflexive,
  59. * except for "knight move" situations.
  60. *
  61. * Because this function uses (short) ints for all calculations, overflow
  62. * may occur if dx and dy exceed 90.
  63. *
  64. * Once all the degenerate cases are eliminated, we determine the "slope"
  65. * ("m"), and we use special "fixed point" mathematics in which we use a
  66. * special "fractional component" for one of the two location components
  67. * ("qy" or "qx"), which, along with the slope itself, are "scaled" by a
  68. * scale factor equal to "abs(dy*dx*2)" to keep the math simple. Then we
  69. * simply travel from start to finish along the longer axis, starting at
  70. * the border between the first and second tiles (where the y offset is
  71. * thus half the slope), using slope and the fractional component to see
  72. * when motion along the shorter axis is necessary. Since we assume that
  73. * vision is not blocked by "brushing" the corner of any grid, we must do
  74. * some special checks to avoid testing grids which are "brushed" but not
  75. * actually "entered".
  76. *
  77. * Angband three different "line of sight" type concepts, including this
  78. * function (which is used almost nowhere), the "project()" method (which
  79. * is used for determining the paths of projectables and spells and such),
  80. * and the "update_view()" concept (which is used to determine which grids
  81. * are "viewable" by the player, which is used for many things, such as
  82. * determining which grids are illuminated by the player's torch, and which
  83. * grids and monsters can be "seen" by the player, etc).
  84. */
  85. bool los(int y1, int x1, int y2, int x2)
  86. {
  87. /* Delta */
  88. int dx, dy;
  89. /* Absolute */
  90. int ax, ay;
  91. /* Signs */
  92. int sx, sy;
  93. /* Fractions */
  94. int qx, qy;
  95. /* Scanners */
  96. int tx, ty;
  97. /* Scale factors */
  98. int f1, f2;
  99. /* Slope, or 1/Slope, of LOS */
  100. int m;
  101. /* Extract the offset */
  102. dy = y2 - y1;
  103. dx = x2 - x1;
  104. /* Extract the absolute offset */
  105. ay = ABS(dy);
  106. ax = ABS(dx);
  107. /* Handle adjacent (or identical) grids */
  108. if ((ax < 2) && (ay < 2))
  109. return (TRUE);
  110. /* Directly South/North */
  111. if (!dx) {
  112. /* South -- check for walls */
  113. if (dy > 0) {
  114. for (ty = y1 + 1; ty < y2; ty++) {
  115. if (!cave_project(ty, x1))
  116. return (FALSE);
  117. }
  118. }
  119. /* North -- check for walls */
  120. else {
  121. for (ty = y1 - 1; ty > y2; ty--) {
  122. if (!cave_project(ty, x1))
  123. return (FALSE);
  124. }
  125. }
  126. /* Assume los */
  127. return (TRUE);
  128. }
  129. /* Directly East/West */
  130. if (!dy) {
  131. /* East -- check for walls */
  132. if (dx > 0) {
  133. for (tx = x1 + 1; tx < x2; tx++) {
  134. if (!cave_project(y1, tx))
  135. return (FALSE);
  136. }
  137. }
  138. /* West -- check for walls */
  139. else {
  140. for (tx = x1 - 1; tx > x2; tx--) {
  141. if (!cave_project(y1, tx))
  142. return (FALSE);
  143. }
  144. }
  145. /* Assume los */
  146. return (TRUE);
  147. }
  148. /* Extract some signs */
  149. sx = (dx < 0) ? -1 : 1;
  150. sy = (dy < 0) ? -1 : 1;
  151. /* Vertical "knights" */
  152. if (ax == 1) {
  153. if (ay == 2) {
  154. if (cave_project(y1 + sy, x1))
  155. return (TRUE);
  156. }
  157. }
  158. /* Horizontal "knights" */
  159. else if (ay == 1) {
  160. if (ax == 2) {
  161. if (cave_project(y1, x1 + sx))
  162. return (TRUE);
  163. }
  164. }
  165. /* Calculate scale factor div 2 */
  166. f2 = (ax * ay);
  167. /* Calculate scale factor */
  168. f1 = f2 << 1;
  169. /* Travel horizontally */
  170. if (ax >= ay) {
  171. /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
  172. qy = ay * ay;
  173. m = qy << 1;
  174. tx = x1 + sx;
  175. /* Consider the special case where slope == 1. */
  176. if (qy == f2) {
  177. ty = y1 + sy;
  178. qy -= f1;
  179. } else {
  180. ty = y1;
  181. }
  182. /* Note (below) the case (qy == f2), where */
  183. /* the LOS exactly meets the corner of a tile. */
  184. while (x2 - tx) {
  185. if (!cave_project(ty, tx))
  186. return (FALSE);
  187. qy += m;
  188. if (qy < f2) {
  189. tx += sx;
  190. } else if (qy > f2) {
  191. ty += sy;
  192. if (!cave_project(ty, tx))
  193. return (FALSE);
  194. qy -= f1;
  195. tx += sx;
  196. } else {
  197. ty += sy;
  198. qy -= f1;
  199. tx += sx;
  200. }
  201. }
  202. }
  203. /* Travel vertically */
  204. else {
  205. /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
  206. qx = ax * ax;
  207. m = qx << 1;
  208. ty = y1 + sy;
  209. if (qx == f2) {
  210. tx = x1 + sx;
  211. qx -= f1;
  212. } else {
  213. tx = x1;
  214. }
  215. /* Note (below) the case (qx == f2), where */
  216. /* the LOS exactly meets the corner of a tile. */
  217. while (y2 - ty) {
  218. if (!cave_project(ty, tx))
  219. return (FALSE);
  220. qx += m;
  221. if (qx < f2) {
  222. ty += sy;
  223. } else if (qx > f2) {
  224. tx += sx;
  225. if (!cave_project(ty, tx))
  226. return (FALSE);
  227. qx -= f1;
  228. ty += sy;
  229. } else {
  230. tx += sx;
  231. qx -= f1;
  232. ty += sy;
  233. }
  234. }
  235. }
  236. /* Assume los */
  237. return (TRUE);
  238. }
  239. /**
  240. * Returns true if the player's grid is dark
  241. * Players with the UNLIGHT ability don't need light and always
  242. * return false.
  243. */
  244. bool no_light(void)
  245. {
  246. int py = p_ptr->py;
  247. int px = p_ptr->px;
  248. if (player_has(PF_UNLIGHT) || p_ptr->state.darkness)
  249. return (FALSE);
  250. return (!player_can_see_bold(py, px));
  251. }
  252. /**
  253. * Determine if a given location may be "destroyed"
  254. *
  255. * Used by destruction spells, and for placing stairs, etc.
  256. */
  257. bool cave_valid_bold(int y, int x)
  258. {
  259. object_type *o_ptr;
  260. feature_type *f_ptr = &f_info[cave_feat[y][x]];
  261. /* Forbid perma-grids */
  262. if (tf_has(f_ptr->flags, TF_PERMANENT))
  263. return (FALSE);
  264. /* Check objects */
  265. for (o_ptr = get_first_object(y, x); o_ptr;
  266. o_ptr = get_next_object(o_ptr)) {
  267. /* Forbid artifact grids */
  268. if (artifact_p(o_ptr))
  269. return (FALSE);
  270. }
  271. /* Accept */
  272. return (TRUE);
  273. }
  274. /**
  275. * Table of breath colors. Must match listings in a single set of
  276. * monster spell flags.
  277. *
  278. * The value "255" is special. Monsters with that kind of breath
  279. * may be any color.
  280. */
  281. static byte breath_to_attr[32][2] = {
  282. {0, 0},
  283. {0, 0},
  284. {0, 0},
  285. {0, 0},
  286. {0, 0},
  287. {0, 0},
  288. {0, 0},
  289. {0, 0},
  290. {0, 0},
  291. {TERM_SLATE, TERM_L_DARK}, /* RSF_BRTH_ACID */
  292. {TERM_BLUE, TERM_L_BLUE}, /* RSF_BRTH_ELEC */
  293. {TERM_RED, TERM_L_RED}, /* RSF_BRTH_FIRE */
  294. {TERM_WHITE, TERM_L_WHITE}, /* RSF_BRTH_COLD */
  295. {TERM_GREEN, TERM_L_GREEN}, /* RSF_BRTH_POIS */
  296. {TERM_ORANGE, TERM_RED}, /* RSF_BRTH_PLAS */
  297. {TERM_YELLOW, TERM_ORANGE}, /* RSF_BRTH_LIGHT */
  298. {TERM_L_DARK, TERM_SLATE}, /* RSF_BRTH_DARK */
  299. {TERM_L_UMBER, TERM_UMBER}, /* RSF_BRTH_CONFU */
  300. {TERM_YELLOW, TERM_L_UMBER}, /* RSF_BRTH_SOUND */
  301. {TERM_UMBER, TERM_L_UMBER}, /* RSF_BRTH_SHARD */
  302. {TERM_L_WHITE, TERM_SLATE}, /* RSF_BRTH_INER */
  303. {TERM_L_WHITE, TERM_SLATE}, /* RSF_BRTH_GRAV */
  304. {TERM_UMBER, TERM_L_UMBER}, /* RSF_BRTH_FORCE */
  305. {TERM_L_RED, TERM_VIOLET}, /* RSF_BRTH_NEXUS */
  306. {TERM_L_GREEN, TERM_GREEN}, /* RSF_BRTH_NETHR */
  307. {255, 255}, /* (any color) *//* RSF_BRTH_CHAOS */
  308. {TERM_VIOLET, TERM_VIOLET}, /* RSF_BRTH_DISEN */
  309. {TERM_L_BLUE, TERM_L_BLUE}, /* RSF_BRTH_TIME */
  310. {TERM_BLUE, TERM_SLATE}, /* RSF_BRTH_STORM */
  311. {TERM_RED, TERM_GREEN}, /* RSF_BRTH_DFIRE */
  312. {TERM_WHITE, TERM_L_WHITE}, /* RSF_BRTH_ICE */
  313. {255, 255} /* (any color) *//* RSF_BRTH_ALL */
  314. };
  315. /**
  316. * Multi-hued monsters shimmer acording to their breaths.
  317. *
  318. * If a monster has only one kind of breath, it uses both colors
  319. * associated with that breath. Otherwise, it just uses the first
  320. * color for any of its breaths.
  321. *
  322. * If a monster does not breath anything, it can be any color.
  323. */
  324. static byte multi_hued_attr(monster_race * r_ptr)
  325. {
  326. byte allowed_attrs[15];
  327. int i, j;
  328. int stored_colors = 0;
  329. int breaths = 0;
  330. int first_color = 0;
  331. int second_color = 0;
  332. /* Monsters with no ranged attacks can be any color */
  333. if (!r_ptr->freq_ranged)
  334. return (randint1(BASIC_COLORS - 1));
  335. /* Check breaths */
  336. for (i = 0; i < 32; i++) {
  337. bool stored = FALSE;
  338. /* Don't have that breath */
  339. if (!rsf_has(r_ptr->spell_flags, i))
  340. continue;
  341. /* Get the first color of this breath */
  342. first_color = breath_to_attr[i][0];
  343. /* Breath has no color associated with it */
  344. if (first_color == 0)
  345. continue;
  346. /* Monster can be of any color */
  347. if (first_color == 255)
  348. return (randint1(BASIC_COLORS - 1));
  349. /* Increment the number of breaths */
  350. breaths++;
  351. /* Monsters with lots of breaths may be any color. */
  352. if (breaths == 6)
  353. return (randint1(BASIC_COLORS - 1));
  354. /* Always store the first color */
  355. for (j = 0; j < stored_colors; j++) {
  356. /* Already stored */
  357. if (allowed_attrs[j] == first_color)
  358. stored = TRUE;
  359. }
  360. if (!stored) {
  361. allowed_attrs[stored_colors] = first_color;
  362. stored_colors++;
  363. }
  364. /*
  365. * Remember (but do not immediately store) the second color
  366. * of the first breath.
  367. */
  368. if (breaths == 1) {
  369. second_color = breath_to_attr[i][1];
  370. }
  371. }
  372. /* Monsters with no breaths may be of any color. */
  373. if (breaths == 0)
  374. return (randint1(BASIC_COLORS - 1));
  375. /* If monster has one breath, store the second color too. */
  376. if (breaths == 1) {
  377. allowed_attrs[stored_colors] = second_color;
  378. stored_colors++;
  379. }
  380. /* Pick a color at random */
  381. return (allowed_attrs[randint0(stored_colors)]);
  382. }
  383. /**
  384. * Hack -- Hallucinatory monster
  385. */
  386. static void hallucinatory_monster(int *a, wchar_t * c)
  387. {
  388. while (1) {
  389. /* Select a random monster */
  390. monster_race *r_ptr = &r_info[randint0(z_info->r_max)];
  391. /* Skip non-entries */
  392. if (!r_ptr->name)
  393. continue;
  394. /* Retrieve attr/char */
  395. *a = r_ptr->x_attr;
  396. *c = r_ptr->x_char;
  397. return;
  398. }
  399. }
  400. /**
  401. * Hack -- Hallucinatory object
  402. */
  403. static void hallucinatory_object(int *a, wchar_t * c)
  404. {
  405. while (1) {
  406. /* Select a random object */
  407. object_kind *k_ptr = &k_info[randint0(z_info->k_max - 1) + 1];
  408. /* Skip non-entries */
  409. if (!k_ptr->name)
  410. continue;
  411. /* Retrieve attr/char (HACK - without flavors) */
  412. *a = k_ptr->x_attr;
  413. *c = k_ptr->x_char;
  414. /* HACK - Skip empty entries */
  415. if ((*a == 0) || (*c == 0))
  416. continue;
  417. return;
  418. }
  419. }
  420. /*
  421. * Translate text colours.
  422. *
  423. * This translates a color based on the attribute. We use this to set terrain to
  424. * be lighter or darker, make metallic monsters shimmer, highlight text under the
  425. * mouse, and reduce the colours on mono colour or 16 colour terms to the correct
  426. * colour space.
  427. *
  428. * TODO: Honour the attribute for the term (full color, mono, 16 color) but ensure
  429. * that e.g. the lighter version of yellow becomes white in a 16 color term, but
  430. * light yellow in a full colour term.
  431. */
  432. byte get_color(byte a, int attr, int n)
  433. {
  434. /* Accept any graphical attr (high bit set) */
  435. if (a & (0x80))
  436. return (a);
  437. /* TODO: Honour the attribute for the term (full color, mono, 16 color) */
  438. if (!attr)
  439. return (a);
  440. /* Translate the color N times */
  441. while (n > 0) {
  442. a = color_table[a].color_translate[attr];
  443. n--;
  444. }
  445. /* Return the modified color */
  446. return (a);
  447. }
  448. /*
  449. * Checks if a square is at the (inner) edge of a trap detect area
  450. */
  451. bool dtrap_edge(int y, int x)
  452. {
  453. /* Check if the square is a dtrap in the first place */
  454. if (!cave_has(cave_info[y][x], CAVE_DTRAP))
  455. return FALSE;
  456. /* Check for non-dtrap adjacent grids */
  457. if (in_bounds_fully(y + 1, x) &&
  458. (!cave_has(cave_info[y + 1][x], CAVE_DTRAP)))
  459. return TRUE;
  460. if (in_bounds_fully(y, x + 1) &&
  461. (!cave_has(cave_info[y][x + 1], CAVE_DTRAP)))
  462. return TRUE;
  463. if (in_bounds_fully(y - 1, x) &&
  464. (!cave_has(cave_info[y - 1][x], CAVE_DTRAP)))
  465. return TRUE;
  466. if (in_bounds_fully(y, x - 1) &&
  467. (!cave_has(cave_info[y][x - 1], CAVE_DTRAP)))
  468. return TRUE;
  469. return FALSE;
  470. }
  471. /**
  472. * Apply text lighting effects
  473. */
  474. static void grid_get_attr(grid_data * g, int *a)
  475. {
  476. feature_type *f_ptr = &f_info[g->f_idx];
  477. /* Trap detect edge, but don't colour traps themselves, or treasure */
  478. if (g->trapborder && tf_has(f_ptr->flags, TF_FLOOR) &&
  479. !((int) g->trap < trap_max)) {
  480. *a += MAX_COLORS * BG_TRAP;
  481. } else if (tf_has(f_ptr->flags, TF_TORCH)) {
  482. if (g->lighting == FEAT_LIGHTING_BRIGHT) {
  483. *a = get_color(*a, ATTR_LIGHT, 1);
  484. } else if (g->lighting == FEAT_LIGHTING_DARK) {
  485. *a = get_color(*a, ATTR_DARK, 1);
  486. }
  487. if (OPT(hybrid_walls) && tf_has(f_ptr->flags, TF_WALL)) {
  488. *a = *a + (MAX_COLORS * BG_DARK);
  489. } else if (OPT(solid_walls) && tf_has(f_ptr->flags, TF_WALL)) {
  490. *a = *a + (MAX_COLORS * BG_SAME);
  491. }
  492. } else {
  493. if (g->lighting == FEAT_LIGHTING_DARK) {
  494. *a = get_color(*a, ATTR_DARK, 1);
  495. }
  496. if (OPT(hybrid_walls) && tf_has(f_ptr->flags, TF_WALL)) {
  497. *a = *a + (MAX_COLORS * BG_DARK);
  498. } else if (OPT(solid_walls) && tf_has(f_ptr->flags, TF_WALL)) {
  499. *a = *a + (MAX_COLORS * BG_SAME);
  500. }
  501. }
  502. }
  503. /**
  504. * This function takes a pointer to a grid info struct describing the
  505. * contents of a grid location (as obtained through the function map_info)
  506. * and fills in the character and attr pairs for display.
  507. *
  508. * ap and cp are filled with the attr/char pair for the monster, object or
  509. * floor tile that is at the "top" of the grid (monsters covering objects,
  510. * which cover floor, assuming all are present).
  511. *
  512. * tap and tcp are filled with the attr/char pair for the floor, regardless
  513. * of what is on it. This can be used by graphical displays with
  514. * transparency to place an object onto a floor tile, is desired.
  515. *
  516. * Any lighting effects are also applied to these pairs, clear monsters allow
  517. * the underlying colour or feature to show through (ATTR_CLEAR and
  518. * CHAR_CLEAR), multi-hued colour-changing (ATTR_MULTI) is applied, and so on.
  519. * Technically, the flag "CHAR_MULTI" is supposed to indicate that a monster
  520. * looks strange when examined, but this flag is currently ignored.
  521. *
  522. * NOTES:
  523. * This is called pretty frequently, whenever a grid on the map display
  524. * needs updating, so don't overcomplicate it.
  525. *
  526. * The "zero" entry in the feature/object/monster arrays are
  527. * used to provide "special" attr/char codes, with "monster zero" being
  528. * used for the player attr/char, "object zero" being used for the "pile"
  529. * attr/char, and "feature zero" being used for the "darkness" attr/char.
  530. *
  531. * TODO:
  532. * The transformations for tile colors, or brightness for the 16x16
  533. * tiles should be handled differently. One possibility would be to
  534. * extend feature_type with attr/char definitions for the different states.
  535. * This will probably be done outside of the current text->graphics mappings
  536. * though.
  537. */
  538. void grid_data_as_text(grid_data * g, int *ap, wchar_t * cp, byte * tap,
  539. wchar_t * tcp)
  540. {
  541. feature_type *f_ptr = &f_info[g->f_idx];
  542. int a = f_ptr->x_attr[g->lighting];
  543. wchar_t c = f_ptr->x_char[g->lighting];
  544. /* Don't display hidden objects */
  545. bool ignore_objects = tf_has(f_ptr->flags, TF_HIDE_OBJ);
  546. /* Neutral monsters get shaded background */
  547. bool neutral = FALSE;
  548. /* Check for trap detection boundaries */
  549. if (use_graphics == GRAPHICS_NONE)
  550. grid_get_attr(g, &a);
  551. /* Save the terrain info for the transparency effects */
  552. (*tap) = a;
  553. (*tcp) = c;
  554. /* There is a trap in this grid, and we are not hallucinating */
  555. if (((int) g->trap < trap_max) && (!g->hallucinate)) {
  556. /* Change graphics to indicate a trap (if visible) */
  557. if (get_trap_graphics(g->trap, &a, &c, TRUE)) {
  558. /* Ignore objects stacked on top of this trap */
  559. ignore_objects = TRUE;
  560. }
  561. }
  562. /* If there's an object, deal with that. */
  563. if ((g->first_k_idx) && !ignore_objects) {
  564. if (g->hallucinate) {
  565. /* Just pick a random object to display. */
  566. hallucinatory_object(&a, &c);
  567. } else {
  568. object_kind *k_ptr = &k_info[g->first_k_idx];
  569. /* Normal attr and char */
  570. a = object_kind_attr(g->first_k_idx);
  571. c = object_kind_char(g->first_k_idx);
  572. if (OPT(show_piles) && g->multiple_objects) {
  573. /* Get the "pile" feature instead */
  574. k_ptr = &k_info[0];
  575. a = k_ptr->x_attr;
  576. c = k_ptr->x_char;
  577. }
  578. }
  579. }
  580. /* If there's a monster */
  581. if (g->m_idx > 0) {
  582. if (g->hallucinate) {
  583. /* Just pick a random monster to display. */
  584. hallucinatory_monster(&a, &c);
  585. } else {
  586. monster_type *m_ptr = &m_list[g->m_idx];
  587. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  588. byte da;
  589. wchar_t dc;
  590. /* Desired attr & char */
  591. da = r_ptr->x_attr;
  592. dc = r_ptr->x_char;
  593. /* Neutral monster get shaded background */
  594. if (m_ptr->hostile >= 0)
  595. neutral = TRUE;
  596. /* Special attr/char codes */
  597. if (da & 0x80) {
  598. /* Use attr */
  599. a = da;
  600. /* Use char */
  601. c = dc;
  602. }
  603. /* Multi-hued monster */
  604. else if (rf_has(r_ptr->flags, RF_ATTR_MULTI) ||
  605. rf_has(r_ptr->flags, RF_ATTR_FLICKER)) {
  606. /* Multi-hued attr */
  607. a = multi_hued_attr(r_ptr);
  608. /* Normal char */
  609. c = dc;
  610. }
  611. /* Normal monster (not "clear" in any way) */
  612. else if (!flags_test(r_ptr->flags, RF_SIZE,
  613. RF_ATTR_CLEAR, RF_CHAR_CLEAR, FLAG_END)) {
  614. /* Use attr */
  615. a = da;
  616. /* Desired attr & char */
  617. da = r_ptr->x_attr;
  618. dc = r_ptr->x_char;
  619. /* Use char */
  620. c = dc;
  621. }
  622. /* Hack -- Bizarre grid under monster */
  623. else if ((a & 0x80) || (c & 0x80)) {
  624. /* Use attr */
  625. a = da;
  626. /* Use char */
  627. c = dc;
  628. }
  629. /* Normal char, Clear attr, monster */
  630. else if (!rf_has(r_ptr->flags, RF_CHAR_CLEAR)) {
  631. /* Normal char */
  632. c = dc;
  633. }
  634. /* Normal attr, Clear char, monster */
  635. else if (!rf_has(r_ptr->flags, RF_ATTR_CLEAR)) {
  636. /* Normal attr */
  637. a = da;
  638. }
  639. /* Store the drawing attr so we can use it elsewhere */
  640. m_ptr->attr = a;
  641. }
  642. }
  643. /* Handle "player" */
  644. else if (g->is_player) {
  645. monster_race *r_ptr = &r_info[0];
  646. /* Get the "player" attr */
  647. a = r_ptr->x_attr;
  648. if ((OPT(hp_changes_colour)) && (arg_graphics == GRAPHICS_NONE)) {
  649. switch (p_ptr->chp * 10 / p_ptr->mhp) {
  650. case 10:
  651. case 9:
  652. {
  653. a = TERM_WHITE;
  654. break;
  655. }
  656. case 8:
  657. case 7:
  658. {
  659. a = TERM_YELLOW;
  660. break;
  661. }
  662. case 6:
  663. case 5:
  664. {
  665. a = TERM_ORANGE;
  666. break;
  667. }
  668. case 4:
  669. case 3:
  670. {
  671. a = TERM_L_RED;
  672. break;
  673. }
  674. case 2:
  675. case 1:
  676. case 0:
  677. {
  678. a = TERM_RED;
  679. break;
  680. }
  681. default:
  682. {
  683. a = TERM_WHITE;
  684. break;
  685. }
  686. }
  687. }
  688. /* Get the "player" char */
  689. c = r_ptr->x_char;
  690. }
  691. /* Shaded for neutrals */
  692. if (neutral)
  693. a += MAX_COLORS * BG_DARK;
  694. /* Result */
  695. (*ap) = a;
  696. (*cp) = c;
  697. }
  698. /*
  699. * This function takes a grid location (x, y) and extracts information the
  700. * player is allowed to know about it, filling in the grid_data structure
  701. * passed in 'g'.
  702. *
  703. * The information filled in is as follows:
  704. * - g->f_idx is filled in with the terrain's feature type, or FEAT_NONE
  705. * if the player doesn't know anything about the grid. The function
  706. * makes use of the "mimic" field in terrain in order to allow one
  707. * feature to look like another (hiding secret doors, invisible traps,
  708. * etc). This will return the terrain type the player "Knows" about,
  709. * not necessarily the real terrain.
  710. * - g->m_idx is set to the monster index, or 0 if there is none (or the
  711. * player doesn't know it).
  712. * - g->first_k_idx is set to the index of the first object in a grid
  713. * that the player knows (and cares, as per OPT(hide_squelchable)) about,
  714. * or zero for no object in the grid.
  715. * - g->muliple_objects is TRUE if there is more than one object in the
  716. * grid that the player knows and cares about (to facilitate any special
  717. * floor stack symbol that might be used).
  718. * - g->in_view is TRUE if the player can currently see the grid - this can
  719. * be used to indicate field-of-view, such as through the OPT(view_bright_light)
  720. * option.
  721. * - g->lighting is set to indicate the lighting level for the grid:
  722. * LIGHT_DARK for unlit grids, LIGHT_TORCH for those lit by the player's
  723. * light source, and LIGHT_GLOW for inherently light grids (lit rooms, etc).
  724. * Note that lighting is always LIGHT_GLOW for known "interesting" grids
  725. * like walls.
  726. * - g->is_player is TRUE if the player is on the given grid.
  727. * - g->hallucinate is TRUE if the player is hallucinating something "strange"
  728. * for this grid - this should pick a random monster to show if the m_idx
  729. * is non-zero, and a random object if first_k_idx is non-zero.
  730. *
  731. * NOTES:
  732. * This is called pretty frequently, whenever a grid on the map display
  733. * needs updating, so don't overcomplicate it.
  734. *
  735. * Terrain is remembered separately from objects and monsters, so can be
  736. * shown even when the player can't "see" it. This leads to things like
  737. * doors out of the player's view still change from closed to open and so on.
  738. *
  739. * TODO:
  740. * Hallucination is currently disabled (it was a display-level hack before,
  741. * and we need it to be a knowledge-level hack). The idea is that objects
  742. * may turn into different objects, monsters into different monsters, and
  743. * terrain may be objects, monsters, or stay the same.
  744. */
  745. void map_info(unsigned y, unsigned x, grid_data * g)
  746. {
  747. object_type *o_ptr;
  748. feature_type *f_ptr;
  749. assert(x < ARENA_WID);
  750. assert(y < ARENA_HGT);
  751. /* Default "clear" values, others will be set later where appropriate. */
  752. g->first_k_idx = 0;
  753. g->trap = trap_max;
  754. g->multiple_objects = FALSE;
  755. g->lighting = FEAT_LIGHTING_DARK;
  756. /* Set things we can work out right now */
  757. g->f_idx = cave_feat[y][x];
  758. g->in_view = cave_has(cave_info[y][x], CAVE_SEEN) ? TRUE : FALSE;
  759. g->is_player = (cave_m_idx[y][x] < 0) ? TRUE : FALSE;
  760. g->m_idx = (g->is_player) ? 0 : cave_m_idx[y][x];
  761. g->hallucinate = p_ptr->timed[TMD_IMAGE] ? TRUE : FALSE;
  762. g->trapborder = (dtrap_edge(y, x)) ? TRUE : FALSE;
  763. f_ptr = &f_info[g->f_idx];
  764. /* Apply "mimic" field */
  765. g->f_idx = f_ptr->mimic;
  766. /* If the grid is memorised or can currently be seen */
  767. if (g->in_view) {
  768. g->lighting = FEAT_LIGHTING_LIT;
  769. if (!cave_has(cave_info[y][x], CAVE_GLOW)
  770. && OPT(view_yellow_light))
  771. g->lighting = FEAT_LIGHTING_BRIGHT;
  772. }
  773. /* Unknown */
  774. else if (!cave_has(cave_info[y][x], CAVE_MARK)) {
  775. g->f_idx = FEAT_NONE;
  776. }
  777. /* There is a trap in this grid */
  778. if (cave_has(cave_info[y][x], CAVE_TRAP) &&
  779. cave_has(cave_info[y][x], CAVE_MARK)) {
  780. int i;
  781. /* Scan the current trap list */
  782. for (i = 0; i < trap_max; i++) {
  783. /* Point to this trap */
  784. trap_type *t_ptr = &trap_list[i];
  785. /* Find a trap in this position */
  786. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  787. /* Get the trap */
  788. g->trap = i;
  789. break;
  790. }
  791. }
  792. }
  793. /* Objects */
  794. for (o_ptr = get_first_object(y, x); o_ptr;
  795. o_ptr = get_next_object(o_ptr)) {
  796. /* Memorized objects */
  797. if (o_ptr->marked && !squelch_hide_item(o_ptr)) {
  798. /* First item found */
  799. if (g->first_k_idx == 0) {
  800. g->first_k_idx = o_ptr->k_idx;
  801. } else {
  802. g->multiple_objects = TRUE;
  803. /* And we know all we need to know. */
  804. break;
  805. }
  806. }
  807. }
  808. /* Monsters */
  809. if (g->m_idx > 0) {
  810. /* If the monster isn't "visible", make sure we don't list it. */
  811. monster_type *m_ptr = &m_list[g->m_idx];
  812. if (!m_ptr->ml)
  813. g->m_idx = 0;
  814. }
  815. /* Rare random hallucination on non-outer walls */
  816. if (g->hallucinate && g->m_idx == 0 && g->first_k_idx == 0) {
  817. if (one_in_(256) && (g->f_idx != FEAT_PERM_SOLID)) {
  818. /* Normally, make an imaginary monster */
  819. if (randint0(100) < 75) {
  820. g->m_idx = 1;
  821. }
  822. /* Otherwise, an imaginary object */
  823. else {
  824. g->first_k_idx = 1;
  825. }
  826. } else {
  827. g->hallucinate = FALSE;
  828. }
  829. }
  830. assert(g->f_idx <= z_info->f_max);
  831. if (!g->hallucinate)
  832. assert(g->m_idx < (u32b) m_max);
  833. assert(g->first_k_idx < z_info->k_max);
  834. /* All other g fields are 'flags', mostly booleans. */
  835. }
  836. /*
  837. * Move the cursor to a given map location.
  838. */
  839. static void move_cursor_relative_map(int y, int x)
  840. {
  841. int ky, kx;
  842. term *old;
  843. int j;
  844. /* Scan windows */
  845. for (j = 0; j < ANGBAND_TERM_MAX; j++) {
  846. term *t = angband_term[j];
  847. /* No window */
  848. if (!t)
  849. continue;
  850. /* No relevant flags */
  851. if (!(op_ptr->window_flag[j] & (PW_MAP)))
  852. continue;
  853. /* Location relative to panel */
  854. ky = y - t->offset_y;
  855. if (tile_height > 1) {
  856. ky = tile_height * ky;
  857. }
  858. /* Verify location */
  859. if ((ky < 0) || (ky >= t->hgt))
  860. continue;
  861. /* Location relative to panel */
  862. kx = x - t->offset_x;
  863. if (tile_width > 1) {
  864. kx = tile_width * kx;
  865. }
  866. /* Verify location */
  867. if ((kx < 0) || (kx >= t->wid))
  868. continue;
  869. /* Go there */
  870. old = Term;
  871. Term_activate(t);
  872. (void) Term_gotoxy(kx, ky);
  873. Term_activate(old);
  874. }
  875. }
  876. /*
  877. * Move the cursor to a given map location.
  878. *
  879. * The main screen will always be at least 24x80 in size.
  880. */
  881. void move_cursor_relative(int y, int x)
  882. {
  883. int ky, kx;
  884. int vy, vx;
  885. /* Move the cursor on map sub-windows */
  886. move_cursor_relative_map(y, x);
  887. /* Location relative to panel */
  888. ky = y - Term->offset_y;
  889. /* Verify location */
  890. if ((ky < 0) || (ky >= SCREEN_HGT))
  891. return;
  892. /* Location relative to panel */
  893. kx = x - Term->offset_x;
  894. /* Verify location */
  895. if ((kx < 0) || (kx >= SCREEN_WID))
  896. return;
  897. /* Location in window */
  898. vy = ky + ROW_MAP;
  899. /* Location in window */
  900. vx = kx + COL_MAP;
  901. if (tile_width > 1) {
  902. vx += (tile_width - 1) * kx;
  903. }
  904. if (tile_height > 1) {
  905. vy += (tile_height - 1) * ky;
  906. }
  907. /* Go there */
  908. (void) Term_gotoxy(vx, vy);
  909. }
  910. /*
  911. * Display an attr/char pair at the given map location
  912. *
  913. * Note the inline use of "panel_contains()" for efficiency.
  914. *
  915. * Note the use of "Term_queue_char()" for efficiency.
  916. */
  917. static void print_rel_map(wchar_t c, byte a, int y, int x)
  918. {
  919. int ky, kx;
  920. int j;
  921. /* Scan windows */
  922. for (j = 0; j < ANGBAND_TERM_MAX; j++) {
  923. term *t = angband_term[j];
  924. /* No window */
  925. if (!t)
  926. continue;
  927. /* No relevant flags */
  928. if (!(op_ptr->window_flag[j] & (PW_MAP)))
  929. continue;
  930. /* Location relative to panel */
  931. ky = y - t->offset_y;
  932. if (tile_height > 1) {
  933. ky = tile_height * ky;
  934. if (ky + 1 >= t->hgt)
  935. continue;
  936. }
  937. /* Verify location */
  938. if ((ky < 0) || (ky >= t->hgt))
  939. continue;
  940. /* Location relative to panel */
  941. kx = x - t->offset_x;
  942. if (tile_width > 1) {
  943. kx = tile_width * kx;
  944. if (kx + 1 >= t->wid)
  945. continue;
  946. }
  947. /* Verify location */
  948. if ((kx < 0) || (kx >= t->wid))
  949. continue;
  950. /* Hack -- Queue it */
  951. Term_queue_char(t, kx, ky, a, c, 0, 0);
  952. if ((tile_width > 1) || (tile_height > 1)) {
  953. /* Mega-Hack : Queue dummy chars */
  954. Term_big_queue_char(Term, kx, ky, a, c, 0, 0);
  955. }
  956. }
  957. }
  958. /*
  959. * Display an attr/char pair at the given map location
  960. *
  961. * Note the inline use of "panel_contains()" for efficiency.
  962. *
  963. * Note the use of "Term_queue_char()" for efficiency.
  964. *
  965. * The main screen will always be at least 24x80 in size.
  966. */
  967. void print_rel(wchar_t c, byte a, int y, int x)
  968. {
  969. int ky, kx;
  970. int vy, vx;
  971. /* Print on map sub-windows */
  972. print_rel_map(c, a, y, x);
  973. /* Location relative to panel */
  974. ky = y - Term->offset_y;
  975. /* Verify location */
  976. if ((ky < 0) || (ky >= SCREEN_HGT))
  977. return;
  978. /* Location relative to panel */
  979. kx = x - Term->offset_x;
  980. /* Verify location */
  981. if ((kx < 0) || (kx >= SCREEN_WID))
  982. return;
  983. /* Get right position */
  984. vx = COL_MAP + (tile_width * kx);
  985. vy = ROW_MAP + (tile_height * ky);
  986. /* Hack -- Queue it */
  987. Term_queue_char(Term, vx, vy, a, c, 0, 0);
  988. if ((tile_width > 1) || (tile_height > 1)) {
  989. /* Mega-Hack : Queue dummy chars */
  990. Term_big_queue_char(Term, vx, vy, a, c, 0, 0);
  991. }
  992. }
  993. /*
  994. * Memorize interesting viewable object/features in the given grid
  995. *
  996. * This function should only be called on "legal" grids.
  997. *
  998. * This function will memorize the object and/or feature in the given grid,
  999. * if they are (1) see-able and (2) interesting. Note that all objects are
  1000. * interesting, all terrain features except floors (and invisible traps) are
  1001. * interesting, and floors (and invisible traps) are interesting sometimes
  1002. * (depending on various options involving the illumination of floor grids).
  1003. *
  1004. * The automatic memorization of all objects and non-floor terrain features
  1005. * as soon as they are displayed allows incredible amounts of optimization
  1006. * in various places, especially "map_info()" and this function itself.
  1007. *
  1008. * Note that the memorization of objects is completely separate from the
  1009. * memorization of terrain features, preventing annoying floor memorization
  1010. * when a detected object is picked up from a dark floor, and object
  1011. * memorization when an object is dropped into a floor grid which is
  1012. * memorized but out-of-sight.
  1013. *
  1014. * This function should be called every time the "memorization" of a grid
  1015. * (or the object in a grid) is called into question, such as when an object
  1016. * is created in a grid, when a terrain feature "changes" from "floor" to
  1017. * "non-floor", and when any grid becomes "see-able" for any reason.
  1018. *
  1019. * This function is called primarily from the "update_view()" function, for
  1020. * each grid which becomes newly "see-able".
  1021. */
  1022. void note_spot(int y, int x)
  1023. {
  1024. object_type *o_ptr;
  1025. /* Require "seen" flag */
  1026. if (!cave_has(cave_info[y][x], CAVE_SEEN))
  1027. return;
  1028. /* Hack -- memorize objects */
  1029. for (o_ptr = get_first_object(y, x); o_ptr;
  1030. o_ptr = get_next_object(o_ptr)) {
  1031. /* Memorize objects */
  1032. o_ptr->marked = TRUE;
  1033. }
  1034. /* Hack -- memorize grids */
  1035. if (cave_has(cave_info[y][x], CAVE_MARK))
  1036. return;
  1037. /* Memorize */
  1038. cave_on(cave_info[y][x], CAVE_MARK);
  1039. }
  1040. /**
  1041. * Redraw (on the screen) a given MAP location
  1042. *
  1043. * This function should only be called on "legal" grids
  1044. */
  1045. void light_spot(int y, int x)
  1046. {
  1047. event_signal_point(EVENT_MAP, x, y);
  1048. }
  1049. static void prt_map_aux(void)
  1050. {
  1051. int a;
  1052. wchar_t c;
  1053. byte ta;
  1054. wchar_t tc;
  1055. grid_data g;
  1056. int y, x;
  1057. int vy, vx;
  1058. int ty, tx;
  1059. int j;
  1060. /* Scan windows */
  1061. for (j = 0; j < ANGBAND_TERM_MAX; j++) {
  1062. term *t = angband_term[j];
  1063. /* No window */
  1064. if (!t)
  1065. continue;
  1066. /* No relevant flags */
  1067. if (!(op_ptr->window_flag[j] & (PW_MAP)))
  1068. continue;
  1069. /* Assume screen */
  1070. ty = t->offset_y + (t->hgt / tile_height);
  1071. tx = t->offset_x + (t->wid / tile_width);
  1072. /* Dump the map */
  1073. for (y = t->offset_y, vy = 0; y < ty; vy++, y++) {
  1074. if (vy + tile_height - 1 >= t->hgt)
  1075. continue;
  1076. for (x = t->offset_x, vx = 0; x < tx; vx++, x++) {
  1077. /* Check bounds */
  1078. if (!in_bounds(y, x))
  1079. continue;
  1080. if (vx + tile_width - 1 >= t->wid)
  1081. continue;
  1082. /* Determine what is there */
  1083. map_info(y, x, &g);
  1084. grid_data_as_text(&g, &a, &c, &ta, &tc);
  1085. Term_queue_char(t, vx, vy, a, c, ta, tc);
  1086. if ((tile_width > 1) || (tile_height > 1)) {
  1087. /* Mega-Hack : Queue dummy chars */
  1088. Term_big_queue_char(t, vx, vy, 255, -1, 0, 0);
  1089. }
  1090. }
  1091. }
  1092. }
  1093. }
  1094. /*
  1095. * Redraw (on the screen) the current map panel
  1096. *
  1097. * Note the inline use of "light_spot()" for efficiency.
  1098. *
  1099. * The main screen will always be at least 24x80 in size.
  1100. */
  1101. void prt_map(void)
  1102. {
  1103. int a;
  1104. wchar_t c;
  1105. byte ta;
  1106. wchar_t tc;
  1107. grid_data g;
  1108. int y, x;
  1109. int vy, vx;
  1110. int ty, tx;
  1111. /* Redraw map sub-windows */
  1112. prt_map_aux();
  1113. /* Assume screen */
  1114. ty = Term->offset_y + SCREEN_HGT;
  1115. tx = Term->offset_x + SCREEN_WID;
  1116. /* Dump the map */
  1117. for (y = Term->offset_y, vy = ROW_MAP; y < ty; vy++, y++) {
  1118. for (x = Term->offset_x, vx = COL_MAP; x < tx; vx++, x++) {
  1119. /* Check bounds */
  1120. if (!in_bounds(y, x))
  1121. continue;
  1122. /* Determine what is there */
  1123. map_info(y, x, &g);
  1124. grid_data_as_text(&g, &a, &c, &ta, &tc);
  1125. /* Hack -- Queue it */
  1126. Term_queue_char(Term, vx, vy, a, c, ta, tc);
  1127. if ((tile_width > 1) || (tile_height > 1)) {
  1128. Term_big_queue_char(Term, vx, vy, a, c, TERM_WHITE, L' ');
  1129. if (tile_width > 1) {
  1130. vx += tile_width - 1;
  1131. }
  1132. }
  1133. }
  1134. if (tile_height > 1)
  1135. vy += tile_height - 1;
  1136. }
  1137. }
  1138. /**
  1139. * Display highest priority object in the RATIO by RATIO area
  1140. */
  1141. #define RATIO 3
  1142. /**
  1143. * Display the entire map
  1144. */
  1145. #define MAP_HGT (ARENA_HGT / RATIO)
  1146. #define MAP_WID (ARENA_WID / RATIO)
  1147. /**
  1148. * Display a "small-scale" map of the dungeon in the active Term
  1149. *
  1150. * Note that the "map_info()" function must return fully colorized
  1151. * data or this function will not work correctly.
  1152. *
  1153. * Note that this function must "disable" the special lighting
  1154. * effects so that the "priority" function will work.
  1155. *
  1156. * Note the use of a specialized "priority" function to allow this
  1157. * function to work with any graphic attr/char mappings, and the
  1158. * attempts to optimize this function where possible.
  1159. *
  1160. * cx and cy are offsets from the position of the player. This
  1161. * allows the map to be shifted around - but only works in the
  1162. * wilderness. cx and cy return the position of the player on the
  1163. * possibly shifted map.
  1164. */
  1165. void display_map(int *cy, int *cx)
  1166. {
  1167. int py = p_ptr->py;
  1168. int px = p_ptr->px;
  1169. int map_hgt, map_wid;
  1170. int dungeon_hgt, dungeon_wid, top_row, left_col;
  1171. int row, col;
  1172. int x, y;
  1173. grid_data g;
  1174. int a;
  1175. byte ta;
  1176. wchar_t c, tc;
  1177. byte tp;
  1178. /* Large array on the stack */
  1179. byte mp[ARENA_HGT][ARENA_WID];
  1180. monster_race *r_ptr = &r_info[0];
  1181. /* Desired map height */
  1182. map_hgt = Term->hgt - 2;
  1183. map_wid = Term->wid - 2;
  1184. /* Adjust for town */
  1185. dungeon_hgt = (p_ptr->danger ? ARENA_HGT : 2 * ARENA_HGT / 3);
  1186. dungeon_wid = (p_ptr->danger ? ARENA_WID : 2 * ARENA_WID / 3);
  1187. top_row = (p_ptr->danger ? 0 : ARENA_HGT / 3);
  1188. left_col = (p_ptr->danger ? 0 : ARENA_WID / 3);
  1189. /* Prevent accidents */
  1190. if (map_hgt > dungeon_hgt)
  1191. map_hgt = dungeon_hgt;
  1192. if (map_wid > dungeon_wid)
  1193. map_wid = dungeon_wid;
  1194. /* Prevent accidents */
  1195. if ((map_wid < 1) || (map_hgt < 1))
  1196. return;
  1197. /* Nothing here */
  1198. a = TERM_WHITE;
  1199. c = L' ';
  1200. ta = TERM_WHITE;
  1201. tc = L' ';
  1202. /* Clear the priorities */
  1203. for (y = 0; y < map_hgt; ++y) {
  1204. for (x = 0; x < map_wid; ++x) {
  1205. /* No priority */
  1206. mp[y][x] = 0;
  1207. }
  1208. }
  1209. /* Draw a box around the edge of the term */
  1210. window_make(0, 0, map_wid + 1, map_hgt + 1);
  1211. /* Analyze the actual map */
  1212. for (y = top_row; y < dungeon_hgt; y++) {
  1213. for (x = left_col; x < dungeon_wid; x++) {
  1214. row = ((y - top_row) * map_hgt / dungeon_hgt);
  1215. col = ((x - left_col) * map_wid / dungeon_wid);
  1216. if (tile_width > 1) {
  1217. col = col - (col % tile_width);
  1218. }
  1219. if (tile_height > 1) {
  1220. row = row - (row % tile_height);
  1221. }
  1222. /* Get the attr/char at that map location */
  1223. map_info(y, x, &g);
  1224. grid_data_as_text(&g, &a, &c, &ta, &tc);
  1225. /* Get the priority of that feature */
  1226. tp = f_info[g.f_idx].priority;
  1227. /* Stuff on top of terrain gets higher priority */
  1228. if ((a != ta) || (c != tc))
  1229. tp = 20;
  1230. /* Save "best" */
  1231. if (mp[row][col] < tp) {
  1232. /* Hack - make every grid on the map lit */
  1233. g.lighting = FEAT_LIGHTING_LIT; /*FEAT_LIGHTING_BRIGHT; */
  1234. grid_data_as_text(&g, &a, &c, &ta, &tc);
  1235. /* Add the character */
  1236. Term_putch(col + 1, row + 1, a, c);
  1237. if ((tile_width > 1) || (tile_height > 1)) {
  1238. Term_big_putch(col + 1, row + 1, a, c);
  1239. }
  1240. /* Save priority */
  1241. mp[row][col] = tp;
  1242. }
  1243. }
  1244. }
  1245. /* Player location */
  1246. row = ((py - top_row) * map_hgt / dungeon_hgt);
  1247. col = ((px - left_col) * map_wid / dungeon_wid);
  1248. if (tile_width > 1) {
  1249. col = col - (col % tile_width);
  1250. }
  1251. if (tile_height > 1) {
  1252. row = row - (row % tile_height);
  1253. }
  1254. /*** Make sure the player is visible ***/
  1255. /* Get the "player" attr */
  1256. ta = r_ptr->x_attr;
  1257. /* Get the "player" char */
  1258. tc = r_ptr->x_char;
  1259. /* Draw the player */
  1260. Term_putch(col + 1, row + 1, ta, tc);
  1261. if ((tile_width > 1) || (tile_height > 1)) {
  1262. Term_big_putch(col + 1, row + 1, ta, tc);
  1263. }
  1264. /* Return player location */
  1265. if (cy != NULL)
  1266. (*cy) = row + 1;
  1267. if (cx != NULL)
  1268. (*cx) = col + 1;
  1269. }
  1270. /**
  1271. * Display a map of the type of wilderness surrounding the current stage
  1272. */
  1273. void regional_map(int num, int size)
  1274. {
  1275. /* Completely redo for BELE */
  1276. }
  1277. /**
  1278. * Display a "small-scale" map of the dungeon.
  1279. *
  1280. * Note that the "player" is always displayed on the map.
  1281. */
  1282. void do_cmd_view_map(void)
  1283. {
  1284. int cy, cx;
  1285. int wid, hgt, num_down, num_across, num;
  1286. /* Get size */
  1287. Term_get_size(&wid, &hgt);
  1288. /* Get dimensions for the regional map */
  1289. num_down = (hgt - 6) / 8;
  1290. num_across = (wid - 24) / 20;
  1291. num = (num_down < num_across ? num_down : num_across);
  1292. /* Save screen */
  1293. screen_save();
  1294. /* Note */
  1295. prt("Please wait...", 0, 0);
  1296. /* Flush */
  1297. Term_fresh();
  1298. /* Clear the screen */
  1299. Term_clear();
  1300. /* Display the map */
  1301. display_map(&cy, &cx);
  1302. /* Wait for it */
  1303. put_str("Hit any key to continue", hgt - 1, (wid - COL_MAP) / 2);
  1304. /* Hilight the player */
  1305. Term_gotoxy(cx, cy);
  1306. /* Get any key */
  1307. (void) inkey_ex();
  1308. /* Regional map if not in the dungeon */
  1309. if (chunk_list[p_ptr->stage].z_pos <= 0) {
  1310. /* Flush */
  1311. Term_fresh();
  1312. /* Clear the screen */
  1313. Term_clear();
  1314. /* Display the regional map */
  1315. regional_map(num, (2 * num + 1) * (2 * num + 1));
  1316. /* Wait for it */
  1317. put_str("Hit any key to continue", hgt - 1, (wid - COL_MAP) / 2);
  1318. /* Get any key */
  1319. (void) inkey_ex();
  1320. }
  1321. /* Load screen */
  1322. screen_load();
  1323. }
  1324. /**
  1325. * Some comments on the dungeon related data structures and functions...
  1326. *
  1327. * Angband is primarily a dungeon exploration game, and it should come as
  1328. * no surprise that the internal representation of the dungeon has evolved
  1329. * over time in much the same way as the game itself, to provide semantic
  1330. * changes to the game itself, to make the code simpler to understand, and
  1331. * to make the executable itself faster or more efficient in various ways.
  1332. *
  1333. * There are a variety of dungeon related data structures, and associated
  1334. * functions, which store information about the dungeon, and provide methods
  1335. * by which this information can be accessed or modified.
  1336. *
  1337. * Some of this information applies to the dungeon as a whole, such as the
  1338. * list of unique monsters which are still alive. Some of this information
  1339. * only applies to the current dungeon level, such as the current depth, or
  1340. * the list of monsters currently inhabiting the level. And some of the
  1341. * information only applies to a single grid of the current dungeon level,
  1342. * such as whether the grid is illuminated, or whether the grid contains a
  1343. * monster, or whether the grid can be seen by the player. If Angband was
  1344. * to be turned into a multi-player game, some of the information currently
  1345. * associated with the dungeon should really be associated with the player,
  1346. * such as whether a given grid is viewable by a given player.
  1347. *
  1348. * One of the major bottlenecks in ancient versions of Angband was in the
  1349. * calculation of "line of sight" from the player to various grids, such
  1350. * as those containing monsters, using the relatively expensive "los()"
  1351. * function. This was such a nasty bottleneck that a lot of silly things
  1352. * were done to reduce the dependancy on "line of sight", for example, you
  1353. * could not "see" any grids in a lit room until you actually entered the
  1354. * room, at which point every grid in the room became "illuminated" and
  1355. * all of the grids in the room were "memorized" forever. Other major
  1356. * bottlenecks involved the determination of whether a grid was lit by the
  1357. * player's torch, and whether a grid blocked the player's line of sight.
  1358. * These bottlenecks led to the development of special new functions to
  1359. * optimize issues involved with "line of sight" and "torch lit grids".
  1360. * These optimizations led to entirely new additions to the game, such as
  1361. * the ability to display the player's entire field of view using different
  1362. * colors than were used for the "memorized" portions of the dungeon, and
  1363. * the ability to memorize dark floor grids, but to indicate by the way in
  1364. * which they are displayed that they are not actually illuminated. And
  1365. * of course many of them simply made the game itself faster or more fun.
  1366. * Also, over time, the definition of "line of sight" has been relaxed to
  1367. * allow the player to see a wider "field of view", which is slightly more
  1368. * realistic, and only slightly more expensive to maintain.
  1369. *
  1370. * Currently, a lot of the information about the dungeon is stored in ways
  1371. * that make it very efficient to access or modify the information, while
  1372. * still attempting to be relatively conservative about memory usage, even
  1373. * if this means that some information is stored in multiple places, or in
  1374. * ways which require the use of special code idioms. For example, each
  1375. * monster record in the monster array contains the location of the monster,
  1376. * and each cave grid has an index into the monster array, or a zero if no
  1377. * monster is in the grid. This allows the monster code to efficiently see
  1378. * where the monster is located, while allowing the dungeon code to quickly
  1379. * determine not only if a monster is present in a given grid, but also to
  1380. * find out which monster. The extra space used to store the information
  1381. * twice is inconsequential compared to the speed increase.
  1382. *
  1383. * Some of the information about the dungeon is used by functions which can
  1384. * constitute the "critical efficiency path" of the game itself, and so the
  1385. * way in which they are stored and accessed has been optimized in order to
  1386. * optimize the game itself. For example, the "update_view()" function was
  1387. * originally created to speed up the game itself (when the player was not
  1388. * running), but then it took on extra responsibility as the provider of the
  1389. * new "special effects lighting code", and became one of the most important
  1390. * bottlenecks when the player was running. So many rounds of optimization
  1391. * were performed on both the function itself, and the data structures which
  1392. * it uses, resulting eventually in a function which not only made the game
  1393. * faster than before, but which was responsible for even more calculations
  1394. * (including the determination of which grids are "viewable" by the player,
  1395. * which grids are illuminated by the player's torch, and which grids can be
  1396. * "seen" in some way by the player), as well as for providing the guts of
  1397. * the special effects lighting code, and for the efficient redisplay of any
  1398. * grids whose visual representation may have changed.
  1399. *
  1400. * Several pieces of information about each cave grid are stored in various
  1401. * two dimensional arrays, with one unit of information for each grid in the
  1402. * dungeon. Some of these arrays have been intentionally expanded by a small
  1403. * factor to make the two dimensional array accesses faster by allowing the
  1404. * use of shifting instead of multiplication.
  1405. *
  1406. * Several pieces of information about each cave grid are stored in the
  1407. * "cave_info" array, which is a special two dimensional array of bytes,
  1408. * one for each cave grid, each containing eight separate "flags" which
  1409. * describe some property of the cave grid. These flags can be checked and
  1410. * modified extremely quickly, especially when special idioms are used to
  1411. * force the compiler to keep a local register pointing to the base of the
  1412. * array. Special location offset macros can be used to minimize the number
  1413. * of computations which must be performed at runtime. Note that using a
  1414. * byte for each flag set may be slightly more efficient than using a larger
  1415. * unit, so if another flag (or two) is needed later, and it must be fast,
  1416. * then the two existing flags which do not have to be fast should be moved
  1417. * out into some other data structure and the new flags should take their
  1418. * place. This may require a few minor changes in the savefile code.
  1419. *
  1420. * The "CAVE_ROOM" flag is saved in the savefile and is used to determine
  1421. * which grids are part of "rooms", and thus which grids are affected by
  1422. * "illumination" spells. This flag does not have to be very fast.
  1423. *
  1424. * The "CAVE_ICKY" flag is saved in the savefile and is used to determine
  1425. * which grids are part of "vaults", and thus which grids cannot serve as
  1426. * the destinations of player teleportation. This flag does not have to
  1427. * be very fast.
  1428. *
  1429. * The "CAVE_MARK" flag is saved in the savefile and is used to determine
  1430. * which grids have been "memorized" by the player. This flag is used by
  1431. * the "map_info()" function to determine if a grid should be displayed.
  1432. * This flag is used in a few other places to determine if the player can
  1433. * "know" about a given grid. This flag must be very fast.
  1434. *
  1435. * The "CAVE_GLOW" flag is saved in the savefile and is used to determine
  1436. * which grids are "permanently illuminated". This flag is used by the
  1437. * "update_view()" function to help determine which viewable flags may
  1438. * be "seen" by the player. This flag is used by the "map_info" function
  1439. * to determine if a grid is only lit by the player's torch. This flag
  1440. * has special semantics for wall grids (see "update_view()"). This flag
  1441. * must be very fast.
  1442. *
  1443. * The "CAVE_WALL" flag is used to determine which grids block the player's
  1444. * line of sight. This flag is used by the "update_view()" function to
  1445. * determine which grids block line of sight, and to help determine which
  1446. * grids can be "seen" by the player. This flag must be very fast.
  1447. *
  1448. * The "CAVE_VIEW" flag is used to determine which grids are currently in
  1449. * line of sight of the player. This flag is set by (and used by) the
  1450. * "update_view()" function. This flag is used by any code which needs to
  1451. * know if the player can "view" a given grid. This flag is used by the
  1452. * "map_info()" function for some optional special lighting effects. The
  1453. * "player_has_los_bold()" macro wraps an abstraction around this flag, but
  1454. * certain code idioms are much more efficient. This flag is used to check
  1455. * if a modification to a terrain feature might affect the player's field of
  1456. * view. This flag is used to see if certain monsters are "visible" to the
  1457. * player. This flag is used to allow any monster in the player's field of
  1458. * view to "sense" the presence of the player. This flag must be very fast.
  1459. *
  1460. * The "CAVE_SEEN" flag is used to determine which grids are currently in
  1461. * line of sight of the player and also illuminated in some way. This flag
  1462. * is set by the "update_view()" function, using computations based on the
  1463. * "CAVE_VIEW" and "CAVE_WALL" and "CAVE_GLOW" flags of various grids. This
  1464. * flag is used by any code which needs to know if the player can "see" a
  1465. * given grid. This flag is used by the "map_info()" function both to see
  1466. * if a given "boring" grid can be seen by the player, and for some optional
  1467. * special lighting effects. The "player_can_see_bold()" macro wraps an
  1468. * abstraction around this flag, but certain code idioms are much more
  1469. * efficient. This flag is used to see if certain monsters are "visible" to
  1470. * the player. This flag is never set for a grid unless "CAVE_VIEW" is also
  1471. * set for the grid. Whenever the "CAVE_WALL" or "CAVE_GLOW" flag changes
  1472. * for a grid which has the "CAVE_VIEW" flag set, the "CAVE_SEEN" flag must
  1473. * be recalculated. The simplest way to do this is to call "forget_view()"
  1474. * and "update_view()" whenever the "CAVE_WALL" or "CAVE_GLOW" flags change
  1475. * for a grid which has "CAVE_VIEW" set. This flag must be very fast.
  1476. *
  1477. * The "CAVE_TEMP" flag is used for a variety of temporary purposes. This
  1478. * flag is used to determine if the "CAVE_SEEN" flag for a grid has changed
  1479. * during the "update_view()" function. This flag is used to "spread" light
  1480. * or darkness through a room. This flag is used by the "monster flow code".
  1481. * This flag must always be cleared by any code which sets it, often, this
  1482. * can be optimized by the use of the special "temp_g", "temp_y", "temp_x"
  1483. * arrays (and the special "temp_n" global). This flag must be very fast.
  1484. *
  1485. * Note that the "CAVE_MARK" flag is used for many reasons, some of which
  1486. * are strictly for optimization purposes. The "CAVE_MARK" flag means that
  1487. * even if the player cannot "see" the grid, he "knows" about the terrain in
  1488. * that grid. This is used to "memorize" grids when they are first "seen" by
  1489. * the player, and to allow certain grids to be "detected" by certain magic.
  1490. * Note that most grids are always memorized when they are first "seen", but
  1491. * "boring" grids (floor grids) are only memorized if the "view_torch_grids"
  1492. * option is set, or if the "view_perma_grids" option is set, and the grid
  1493. * in question has the "CAVE_GLOW" flag set.
  1494. *
  1495. * Objects are "memorized" in a different way, using a special "marked" flag
  1496. * on the object itself, which is set when an object is observed or detected.
  1497. * This allows objects to be "memorized" independant of the terrain features.
  1498. *
  1499. * The "update_view()" function is an extremely important function. It is
  1500. * called only when the player moves, significant terrain changes, or the
  1501. * player's blindness or torch radius changes. Note that when the player
  1502. * is resting, or performing any repeated actions (like digging, disarming,
  1503. * farming, etc), there is no need to call the "update_view()" function, so
  1504. * even if it was not very efficient, this would really only matter when the
  1505. * player was "running" through the dungeon. It sets the "CAVE_VIEW" flag
  1506. * on every cave grid in the player's field of view, and maintains an array
  1507. * of all such grids in the global "view_g" array. It also checks the torch
  1508. * radius of the player, and sets the "CAVE_SEEN" flag for every grid which
  1509. * is in the "field of view" of the player and which is also "illuminated",
  1510. * either by the players torch (if any) or by any permanent light source.
  1511. * It could use and help maintain information about multiple light sources,
  1512. * which would be helpful in a multi-player version of Angband.
  1513. *
  1514. * The "update_view()" function maintains the special "view_g" array, which
  1515. * contains exactly those grids which have the "CAVE_VIEW" flag set. This
  1516. * array is used by "update_view()" to (only) memorize grids which become
  1517. * newly "seen", and to (only) redraw grids whose "seen" value changes, which
  1518. * allows the use of some interesting (and very efficient) "special lighting
  1519. * effects". In addition, this array could be used elsewhere to quickly scan
  1520. * through all the grids which are in the player's field of view.
  1521. *
  1522. * Note that the "update_view()" function allows, among other things, a room
  1523. * to be "partially" seen as the player approaches it, with a growing cone
  1524. * of floor appearing as the player gets closer to the door. Also, by not
  1525. * turning on the "memorize perma-lit grids" option, the player will only
  1526. * "see" those floor grids which are actually in line of sight. And best
  1527. * of all, you can now activate the special lighting effects to indicate
  1528. * which grids are actually in the player's field of view by using dimmer
  1529. * colors for grids which are not in the player's field of view, and/or to
  1530. * indicate which grids are illuminated only by the player's torch by using
  1531. * the color yellow for those grids.
  1532. *
  1533. * The old "update_view()" algorithm uses the special "CAVE_EASY" flag as a
  1534. * temporary internal flag to mark those grids which are not only in view,
  1535. * but which are also "easily" in line of sight of the player. This flag
  1536. * is actually just the "CAVE_SEEN" flag, and the "update_view()" function
  1537. * makes sure to clear it for all old "CAVE_SEEN" grids, and then use it in
  1538. * the algorithm as "CAVE_EASY", and then clear it for all "CAVE_EASY" grids,
  1539. * and then reset it as appropriate for all new "CAVE_SEEN" grids. This is
  1540. * kind of messy, but it works. The old algorithm may disappear eventually.
  1541. *
  1542. * The new "update_view()" algorithm uses a faster and more mathematically
  1543. * correct algorithm, assisted by a large machine generated static array, to
  1544. * determine the "CAVE_VIEW" and "CAVE_SEEN" flags simultaneously. See below.
  1545. *
  1546. * It seems as though slight modifications to the "update_view()" functions
  1547. * would allow us to determine "reverse" line-of-sight as well as "normal"
  1548. * line-of-sight", which would allow monsters to have a more "correct" way
  1549. * to determine if they can "see" the player, since right now, they "cheat"
  1550. * somewhat and assume that if the player has "line of sight" to them, then
  1551. * they can "pretend" that they have "line of sight" to the player. But if
  1552. * such a change was attempted, the monsters would actually start to exhibit
  1553. * some undesirable behavior, such as "freezing" near the entrances to long
  1554. * hallways containing the player, and code would have to be added to make
  1555. * the monsters move around even if the player was not detectable, and to
  1556. * "remember" where the player was last seen, to avoid looking stupid.
  1557. *
  1558. * Note that the "CAVE_GLOW" flag means that a grid is permanently lit in
  1559. * some way. However, for the player to "see" the grid, as determined by
  1560. * the "CAVE_SEEN" flag, the player must not be blind, the grid must have
  1561. * the "CAVE_VIEW" flag set, and if the grid is a "wall" grid, and it is
  1562. * not lit by the player's torch, then it must touch a grid which does not
  1563. * have the "CAVE_WALL" flag set, but which does have both the "CAVE_GLOW"
  1564. * and "CAVE_VIEW" flags set. This last part about wall grids is induced
  1565. * by the semantics of "CAVE_GLOW" as applied to wall grids, and checking
  1566. * the technical requirements can be very expensive, especially since the
  1567. * grid may be touching some "illegal" grids. Luckily, it is more or less
  1568. * correct to restrict the "touching" grids from the eight "possible" grids
  1569. * to the (at most) three grids which are touching the grid, and which are
  1570. * closer to the player than the grid itself, which eliminates more than
  1571. * half of the work, including all of the potentially "illegal" grids, if
  1572. * at most one of the three grids is a "diagonal" grid. In addition, in
  1573. * almost every situation, it is possible to ignore the "CAVE_VIEW" flag
  1574. * on these three "touching" grids, for a variety of technical reasons.
  1575. * Finally, note that in most situations, it is only necessary to check
  1576. * a single "touching" grid, in fact, the grid which is strictly closest
  1577. * to the player of all the touching grids, and in fact, it is normally
  1578. * only necessary to check the "CAVE_GLOW" flag of that grid, again, for
  1579. * various technical reasons. However, one of the situations which does
  1580. * not work with this last reduction is the very common one in which the
  1581. * player approaches an illuminated room from a dark hallway, in which the
  1582. * two wall grids which form the "entrance" to the room would not be marked
  1583. * as "CAVE_SEEN", since of the three "touching" grids nearer to the player
  1584. * than each wall grid, only the farthest of these grids is itself marked
  1585. * "CAVE_GLOW".
  1586. *
  1587. *
  1588. * Here are some pictures of the legal "light source" radius values, in
  1589. * which the numbers indicate the "order" in which the grids could have
  1590. * been calculated, if desired. Note that the code will work with larger
  1591. * radiuses, though currently yields such a radius, and the game would
  1592. * become slower in some situations if it did.
  1593. *<pre>
  1594. * Rad=0 Rad=1 Rad=2 Rad=3
  1595. * No-Light Torch,etc Lantern Artifacts
  1596. *
  1597. * 333
  1598. * 333 43334
  1599. * 212 32123 3321233
  1600. * @ 1@1 31@13 331@133
  1601. * 212 32123 3321233
  1602. * 333 43334
  1603. * 333
  1604. *</pre>
  1605. *
  1606. * Here is an illustration of the two different "update_view()" algorithms,
  1607. * in which the grids marked "%" are pillars, and the grids marked "?" are
  1608. * not in line of sight of the player.
  1609. *
  1610. *<pre>
  1611. * Sample situation
  1612. *
  1613. * #####################
  1614. * ############.%.%.%.%#
  1615. * #...@..#####........#
  1616. * #............%.%.%.%#
  1617. * #......#####........#
  1618. * ############........#
  1619. * #####################
  1620. *
  1621. *
  1622. * New Algorithm Old Algorithm
  1623. *
  1624. * ########????????????? ########?????????????
  1625. * #...@..#????????????? #...@..#?????????????
  1626. * #...........????????? #.........???????????
  1627. * #......#####.....???? #......####??????????
  1628. * ########?????????...# ########?????????????
  1629. *
  1630. * ########????????????? ########?????????????
  1631. * #.@....#????????????? #.@....#?????????????
  1632. * #............%??????? #...........?????????
  1633. * #......#####........? #......#####?????????
  1634. * ########??????????..# ########?????????????
  1635. *
  1636. * ########????????????? ########?????%???????
  1637. * #......#####........# #......#####..???????
  1638. * #.@..........%??????? #.@..........%???????
  1639. * #......#####........# #......#####..???????
  1640. * ########????????????? ########?????????????
  1641. *
  1642. * ########??????????..# ########?????????????
  1643. * #......#####........? #......#####?????????
  1644. * #............%??????? #...........?????????
  1645. * #.@....#????????????? #.@....#?????????????
  1646. * ########????????????? ########?????????????
  1647. *
  1648. * ########?????????%??? ########?????????????
  1649. * #......#####.....???? #......####??????????
  1650. * #...........????????? #.........???????????
  1651. * #...@..#????????????? #...@..#?????????????
  1652. * ########????????????? ########?????????????
  1653. </pre>
  1654. */
  1655. /**
  1656. * Forget the "CAVE_VIEW" grids, redrawing as needed
  1657. */
  1658. void forget_view(void)
  1659. {
  1660. int x, y;
  1661. for (y = 0; y < ARENA_HGT; y++) {
  1662. for (x = 0; x < ARENA_WID; x++) {
  1663. if (!cave_has(cave_info[y][x], CAVE_VIEW))
  1664. continue;
  1665. cave_off(cave_info[y][x], CAVE_VIEW);
  1666. cave_off(cave_info[y][x], CAVE_SEEN);
  1667. light_spot(y, x);
  1668. }
  1669. }
  1670. }
  1671. /**
  1672. * Calculate the complete field of view using a new algorithm
  1673. *
  1674. * If "view_g" and "temp_g" were global pointers to arrays of grids, as
  1675. * opposed to actual arrays of grids, then we could be more efficient by
  1676. * using "pointer swapping".
  1677. *
  1678. * Note the following idiom, which is used in the function below.
  1679. * This idiom processes each "octant" of the field of view, in a
  1680. * clockwise manner, starting with the east strip, south side,
  1681. * and for each octant, allows a simple calculation to set "g"
  1682. * equal to the proper grids, relative to "pg", in the octant.
  1683. *
  1684. * for (o2 = 0; o2 < 16; o2 += 2)
  1685. * ...
  1686. * g = pg + *((s16b*)(((byte*)(p))+o2));
  1687. * ...
  1688. *
  1689. *
  1690. * Normally, vision along the major axes is more likely than vision
  1691. * along the diagonal axes, so we check the bits corresponding to
  1692. * the lines of sight near the major axes first.
  1693. *
  1694. * We use the "temp_g" array (and the "CAVE_TEMP" flag) to keep track of
  1695. * which grids were previously marked "CAVE_SEEN", since only those grids
  1696. * whose "CAVE_SEEN" value changes during this routine must be redrawn.
  1697. *
  1698. * This function is now responsible for maintaining the "CAVE_SEEN"
  1699. * flags as well as the "CAVE_VIEW" flags, which is good, because
  1700. * the only grids which normally need to be memorized and/or redrawn
  1701. * are the ones whose "CAVE_SEEN" flag changes during this routine.
  1702. *
  1703. * Basically, this function divides the "octagon of view" into octants of
  1704. * grids (where grids on the main axes and diagonal axes are "shared" by
  1705. * two octants), and processes each octant one at a time, processing each
  1706. * octant one grid at a time, processing only those grids which "might" be
  1707. * viewable, and setting the "CAVE_VIEW" flag for each grid for which there
  1708. * is an (unobstructed) line of sight from the center of the player grid to
  1709. * any internal point in the grid (and collecting these "CAVE_VIEW" grids
  1710. * into the "view_g" array), and setting the "CAVE_SEEN" flag for the grid
  1711. * if, in addition, the grid is "illuminated" in some way.
  1712. *
  1713. * This function relies on a theorem (suggested and proven by Mat Hostetter)
  1714. * which states that in each octant of a field of view, a given grid will
  1715. * be "intersected" by one or more unobstructed "lines of sight" from the
  1716. * center of the player grid if and only if it is "intersected" by at least
  1717. * one such unobstructed "line of sight" which passes directly through some
  1718. * corner of some grid in the octant which is not shared by any other octant.
  1719. * The proof is based on the fact that there are at least three significant
  1720. * lines of sight involving any non-shared grid in any octant, one which
  1721. * intersects the grid and passes though the corner of the grid closest to
  1722. * the player, and two which "brush" the grid, passing through the "outer"
  1723. * corners of the grid, and that any line of sight which intersects a grid
  1724. * without passing through the corner of a grid in the octant can be "slid"
  1725. * slowly towards the corner of the grid closest to the player, until it
  1726. * either reaches it or until it brushes the corner of another grid which
  1727. * is closer to the player, and in either case, the existanc of a suitable
  1728. * line of sight is thus demonstrated.
  1729. *
  1730. * It turns out that in each octant of the radius 20 "octagon of view",
  1731. * there are 161 grids (with 128 not shared by any other octant), and there
  1732. * are exactly 126 distinct "lines of sight" passing from the center of the
  1733. * player grid through any corner of any non-shared grid in the octant. To
  1734. * determine if a grid is "viewable" by the player, therefore, you need to
  1735. * simply show that one of these 126 lines of sight intersects the grid but
  1736. * does not intersect any wall grid closer to the player. So we simply use
  1737. * a bit vector with 126 bits to represent the set of interesting lines of
  1738. * sight which have not yet been obstructed by wall grids, and then we scan
  1739. * all the grids in the octant, moving outwards from the player grid. For
  1740. * each grid, if any of the lines of sight which intersect that grid have not
  1741. * yet been obstructed, then the grid is viewable. Furthermore, if the grid
  1742. * is a wall grid, then all of the lines of sight which intersect the grid
  1743. * should be marked as obstructed for future reference. Also, we only need
  1744. * to check those grids for whom at least one of the "parents" was a viewable
  1745. * non-wall grid, where the parents include the two grids touching the grid
  1746. * but closer to the player grid (one adjacent, and one diagonal). For the
  1747. * bit vector, we simply use 4 32-bit integers. All of the static values
  1748. * which are needed by this function are stored in the large "vinfo" array
  1749. * (above), which is machine generated by another program. XXX XXX XXX
  1750. *
  1751. * Hack -- The queue must be able to hold more than VINFO_MAX_GRIDS grids
  1752. * because the grids at the edge of the field of view use "grid zero" as
  1753. * their children, and the queue must be able to hold several of these
  1754. * special grids. Because the actual number of required grids is bizarre,
  1755. * we simply allocate twice as many as we would normally need. XXX XXX XXX
  1756. */
  1757. static void mark_wasseen(void)
  1758. {
  1759. int x, y;
  1760. /* Save the old "view" grids for later */
  1761. for (y = 0; y < ARENA_HGT; y++) {
  1762. for (x = 0; x < ARENA_WID; x++) {
  1763. if (cave_has(cave_info[y][x], CAVE_SEEN))
  1764. cave_on(cave_info[y][x], CAVE_TEMP);
  1765. cave_off(cave_info[y][x], CAVE_VIEW);
  1766. cave_off(cave_info[y][x], CAVE_SEEN);
  1767. }
  1768. }
  1769. }
  1770. static void update_one(int y, int x, int blind)
  1771. {
  1772. if (blind)
  1773. cave_off(cave_info[y][x], CAVE_SEEN);
  1774. /* Square went from unseen -> seen */
  1775. if (cave_has(cave_info[y][x], CAVE_SEEN) &&
  1776. !cave_has(cave_info[y][x], CAVE_TEMP)) {
  1777. note_spot(y, x);
  1778. light_spot(y, x);
  1779. }
  1780. /* Square went from seen -> unseen */
  1781. if (!cave_has(cave_info[y][x], CAVE_SEEN) &&
  1782. cave_has(cave_info[y][x], CAVE_TEMP))
  1783. light_spot(y, x);
  1784. cave_off(cave_info[y][x], CAVE_TEMP);
  1785. }
  1786. /**
  1787. * True if the square is a wall square (impedes the player's los).
  1788. *
  1789. */
  1790. bool cave_iswall(int y, int x)
  1791. {
  1792. /* Terrain */
  1793. feature_type *f_ptr;
  1794. if (!in_bounds(y, x))
  1795. return FALSE;
  1796. f_ptr = &f_info[cave_feat[y][x]];
  1797. return !tf_has(f_ptr->flags, TF_LOS);
  1798. }
  1799. static void become_viewable(int y, int x, int lit, int py, int px)
  1800. {
  1801. int xc = x;
  1802. int yc = y;
  1803. if (cave_has(cave_info[y][x], CAVE_VIEW))
  1804. return;
  1805. cave_on(cave_info[y][x], CAVE_VIEW);
  1806. if (lit)
  1807. cave_on(cave_info[y][x], CAVE_SEEN);
  1808. if (cave_has(cave_info[y][x], CAVE_GLOW)) {
  1809. if (cave_iswall(y, x)) {
  1810. /* For walls, move a bit towards the player.
  1811. * TODO(elly): huh? why?
  1812. */
  1813. xc = (x < px) ? (x + 1) : (x > px) ? (x - 1) : x;
  1814. yc = (y < py) ? (y + 1) : (y > py) ? (y - 1) : y;
  1815. }
  1816. if (cave_has(cave_info[yc][xc], CAVE_GLOW))
  1817. cave_on(cave_info[y][x], CAVE_SEEN);
  1818. }
  1819. }
  1820. static void update_view_one(int y, int x, int radius, int py, int px)
  1821. {
  1822. int xc = x;
  1823. int yc = y;
  1824. int d = distance(y, x, py, px);
  1825. int lit = d < radius;
  1826. if (d > MAX_SIGHT)
  1827. return;
  1828. /* Special case for wall lighting. If we are a wall and the square in
  1829. * the direction of the player is in LOS, we are in LOS. This avoids
  1830. * situations like:
  1831. * #1#############
  1832. * #............@#
  1833. * ###############
  1834. * where the wall cell marked '1' would not be lit because the LOS
  1835. * algorithm runs into the adjacent wall cell.
  1836. */
  1837. if (cave_iswall(y, x)) {
  1838. int dx = x - px;
  1839. int dy = y - py;
  1840. int ax = ABS(dx);
  1841. int ay = ABS(dy);
  1842. int sx = dx > 0 ? 1 : -1;
  1843. int sy = dy > 0 ? 1 : -1;
  1844. xc = (x < px) ? (x + 1) : (x > px) ? (x - 1) : x;
  1845. yc = (y < py) ? (y + 1) : (y > py) ? (y - 1) : y;
  1846. /* Check that the cell we're trying to steal LOS from isn't a
  1847. * wall. If we don't do this, double-thickness walls will have
  1848. * both sides visible.
  1849. */
  1850. if (cave_iswall(yc, xc)) {
  1851. xc = x;
  1852. yc = y;
  1853. }
  1854. /* Check that we got here via the 'knight's move' rule. If so,
  1855. * don't steal LOS. */
  1856. if (ax == 2 && ay == 1) {
  1857. if (!cave_iswall(y, x - sx) && cave_iswall(y - sy, x - sx)) {
  1858. xc = x;
  1859. yc = y;
  1860. }
  1861. } else if (ax == 1 && ay == 2) {
  1862. if (cave_iswall(y - sy, x) && cave_iswall(y - sy, x - sx)) {
  1863. xc = x;
  1864. yc = y;
  1865. }
  1866. }
  1867. }
  1868. if (los(py, px, yc, xc))
  1869. become_viewable(y, x, lit, py, px);
  1870. }
  1871. void update_view(void)
  1872. {
  1873. int x, y;
  1874. int radius;
  1875. mark_wasseen();
  1876. /* Extract "radius" value */
  1877. if ((player_has(PF_UNLIGHT) || p_ptr->state.darkness)
  1878. && (p_ptr->cur_light <= 0))
  1879. radius = 2;
  1880. else
  1881. radius = p_ptr->cur_light;
  1882. /* Handle real light */
  1883. if (radius > 0)
  1884. ++radius;
  1885. /* Assume we can view the player grid */
  1886. cave_on(cave_info[p_ptr->py][p_ptr->px], CAVE_VIEW);
  1887. if (radius > 0 || cave_has(cave_info[p_ptr->py][p_ptr->px], CAVE_GLOW))
  1888. cave_on(cave_info[p_ptr->py][p_ptr->px], CAVE_SEEN);
  1889. /* View squares we have LOS to */
  1890. for (y = 0; y < ARENA_HGT; y++)
  1891. for (x = 0; x < ARENA_WID; x++)
  1892. update_view_one(y, x, radius, p_ptr->py, p_ptr->px);
  1893. /*** Step 3 -- Complete the algorithm ***/
  1894. for (y = 0; y < ARENA_HGT; y++)
  1895. for (x = 0; x < ARENA_WID; x++)
  1896. update_one(y, x, p_ptr->timed[TMD_BLIND]);
  1897. }
  1898. /**
  1899. * Every so often, the character makes enough noise that nearby
  1900. * monsters can use it to home in on him.
  1901. *
  1902. * Fill in the "cave_cost" field of every grid that the player can
  1903. * reach with the number of steps needed to reach that grid. This
  1904. * also yields the route distance of the player from every grid.
  1905. *
  1906. * Monsters use this information by moving to adjacent grids with
  1907. * lower flow costs, thereby homing in on the player even though
  1908. * twisty tunnels and mazes. Monsters can also run away from loud
  1909. * noises.
  1910. *
  1911. * The biggest limitation of this code is that it does not easily
  1912. * allow for alternate ways around doors (not all monsters can handle
  1913. * doors) and lava/water (many monsters are not allowed to enter
  1914. * water, lava, or both).
  1915. *
  1916. * The flow table is three-dimensional. The first dimension allows the
  1917. * table to both store and overwrite grids safely. The second indicates
  1918. * whether this value is that for x or for y. The third is the number
  1919. * of grids able to be stored at any flow distance.
  1920. */
  1921. void update_noise(void)
  1922. {
  1923. int cost;
  1924. int route_distance = 0;
  1925. int i, d;
  1926. int y, x, y2, x2;
  1927. int last_index;
  1928. int grid_count = 0;
  1929. int dist;
  1930. bool full = FALSE;
  1931. /* Note where we get information from, and where we overwrite */
  1932. int this_cycle = 0;
  1933. int next_cycle = 1;
  1934. byte flow_table[2][2][8 * NOISE_STRENGTH];
  1935. /* The character's grid has no flow info. Do a full rebuild. */
  1936. if (cave_cost[p_ptr->py][p_ptr->px] == 0)
  1937. full = TRUE;
  1938. /* Determine when to rebuild, update, or do nothing */
  1939. if (!full) {
  1940. dist = ABS(p_ptr->py - flow_center_y);
  1941. if (ABS(p_ptr->px - flow_center_x) > dist)
  1942. dist = ABS(p_ptr->px - flow_center_x);
  1943. /*
  1944. * Character is far enough away from the previous flow center -
  1945. * do a full rebuild.
  1946. */
  1947. if (dist >= 15)
  1948. full = TRUE;
  1949. else {
  1950. /* Get axis distance to center of last update */
  1951. dist = ABS(p_ptr->py - update_center_y);
  1952. if (ABS(p_ptr->px - update_center_x) > dist)
  1953. dist = ABS(p_ptr->px - update_center_x);
  1954. /*
  1955. * We probably cannot decrease the center cost any more.
  1956. * We should assume that we have to do a full rebuild.
  1957. */
  1958. if (cost_at_center - (dist + 5) <= 0)
  1959. full = TRUE;
  1960. /* Less than five grids away from last update */
  1961. else if (dist < 5) {
  1962. /* We're in LOS of the last update - don't update again */
  1963. if (los
  1964. (p_ptr->py, p_ptr->px, update_center_y,
  1965. update_center_x))
  1966. return;
  1967. /* We're not in LOS - update */
  1968. else
  1969. full = FALSE;
  1970. }
  1971. /* Always update if at least five grids away */
  1972. else
  1973. full = FALSE;
  1974. }
  1975. }
  1976. /* Update */
  1977. if (!full) {
  1978. bool found = FALSE;
  1979. /* Start at the character's location */
  1980. flow_table[this_cycle][0][0] = p_ptr->py;
  1981. flow_table[this_cycle][1][0] = p_ptr->px;
  1982. grid_count = 1;
  1983. /* Erase outwards until we hit the previous update center */
  1984. for (cost = 0; cost <= NOISE_STRENGTH; cost++) {
  1985. /*
  1986. * Keep track of the route distance to the previous
  1987. * update center.
  1988. */
  1989. route_distance++;
  1990. /* Get the number of grids we'll be looking at */
  1991. last_index = grid_count;
  1992. /* Clear the grid count */
  1993. grid_count = 0;
  1994. /* Get each valid entry in the flow table in turn */
  1995. for (i = 0; i < last_index; i++) {
  1996. /* Get this grid */
  1997. y = flow_table[this_cycle][0][i];
  1998. x = flow_table[this_cycle][1][i];
  1999. /* Look at all adjacent grids */
  2000. for (d = 0; d < 8; d++) {
  2001. /* Child location */
  2002. y2 = y + ddy_ddd[d];
  2003. x2 = x + ddx_ddd[d];
  2004. /* Check Bounds */
  2005. if (!in_bounds(y2, x2))
  2006. continue;
  2007. /* Ignore illegal grids */
  2008. if (cave_cost[y2][x2] == 0)
  2009. continue;
  2010. /* Ignore previously erased grids */
  2011. if (cave_cost[y2][x2] == 255)
  2012. continue;
  2013. /* Erase previous info, mark grid */
  2014. cave_cost[y2][x2] = 255;
  2015. /* Store this grid in the flow table */
  2016. flow_table[next_cycle][0][grid_count] = y2;
  2017. flow_table[next_cycle][1][grid_count] = x2;
  2018. /* Increment number of grids stored */
  2019. grid_count++;
  2020. /* If this is the previous update center, we can stop */
  2021. if ((y2 == update_center_y) && (x2 == update_center_x))
  2022. found = TRUE;
  2023. }
  2024. }
  2025. /* Stop when we find the previous update center. */
  2026. if (found)
  2027. break;
  2028. /* Swap write and read portions of the table */
  2029. if (this_cycle == 0) {
  2030. this_cycle = 1;
  2031. next_cycle = 0;
  2032. } else {
  2033. this_cycle = 0;
  2034. next_cycle = 1;
  2035. }
  2036. }
  2037. /*
  2038. * Reduce the flow cost assigned to the new center grid by
  2039. * enough to maintain the correct cost slope out to the range
  2040. * we have to update the flow.
  2041. */
  2042. cost_at_center -= route_distance;
  2043. /* We can't reduce the center cost any more. Do a full rebuild. */
  2044. if (cost_at_center < 0)
  2045. full = TRUE;
  2046. else {
  2047. /* Store the new update center */
  2048. update_center_y = p_ptr->py;
  2049. update_center_x = p_ptr->px;
  2050. }
  2051. }
  2052. /* Full rebuild */
  2053. if (full) {
  2054. /*
  2055. * Set the initial cost to 100; updates will progressively
  2056. * lower this value. When it reaches zero, another full
  2057. * rebuild has to be done.
  2058. */
  2059. cost_at_center = 100;
  2060. /* Save the new noise epicenter */
  2061. flow_center_y = p_ptr->py;
  2062. flow_center_x = p_ptr->px;
  2063. update_center_y = p_ptr->py;
  2064. update_center_x = p_ptr->px;
  2065. /* Erase all of the current flow (noise) information */
  2066. for (y = 0; y < ARENA_HGT; y++) {
  2067. for (x = 0; x < ARENA_WID; x++) {
  2068. cave_cost[y][x] = 0;
  2069. }
  2070. }
  2071. }
  2072. /*** Update or rebuild the flow ***/
  2073. /* Store base cost at the character location */
  2074. cave_cost[p_ptr->py][p_ptr->px] = cost_at_center;
  2075. /* Store this grid in the flow table, note that we've done so */
  2076. flow_table[this_cycle][0][0] = p_ptr->py;
  2077. flow_table[this_cycle][1][0] = p_ptr->px;
  2078. grid_count = 1;
  2079. /* Extend the noise burst out to its limits */
  2080. for (cost = cost_at_center + 1;
  2081. cost <= cost_at_center + NOISE_STRENGTH; cost++) {
  2082. /* Get the number of grids we'll be looking at */
  2083. last_index = grid_count;
  2084. /* Stop if we've run out of work to do */
  2085. if (last_index == 0)
  2086. break;
  2087. /* Clear the grid count */
  2088. grid_count = 0;
  2089. /* Get each valid entry in the flow table in turn. */
  2090. for (i = 0; i < last_index; i++) {
  2091. /* Get this grid */
  2092. y = flow_table[this_cycle][0][i];
  2093. x = flow_table[this_cycle][1][i];
  2094. /* Look at all adjacent grids */
  2095. for (d = 0; d < 8; d++) {
  2096. /* Child location */
  2097. y2 = y + ddy_ddd[d];
  2098. x2 = x + ddx_ddd[d];
  2099. /* Check Bounds */
  2100. if (!in_bounds(y2, x2))
  2101. continue;
  2102. /* When doing a rebuild... */
  2103. if (full) {
  2104. /* Ignore previously marked grids */
  2105. if (cave_cost[y2][x2])
  2106. continue;
  2107. /* Ignore walls. Do not ignore rubble. */
  2108. if (tf_has
  2109. (f_info[cave_feat[y2][x2]].flags, TF_NO_NOISE))
  2110. continue;
  2111. }
  2112. /* When doing an update... */
  2113. else {
  2114. /* Ignore all but specially marked grids */
  2115. if (cave_cost[y2][x2] != 255)
  2116. continue;
  2117. }
  2118. /* Store cost at this location */
  2119. cave_cost[y2][x2] = cost;
  2120. /* Store this grid in the flow table */
  2121. flow_table[next_cycle][0][grid_count] = y2;
  2122. flow_table[next_cycle][1][grid_count] = x2;
  2123. /* Increment number of grids stored */
  2124. grid_count++;
  2125. }
  2126. }
  2127. /* Swap write and read portions of the table */
  2128. if (this_cycle == 0) {
  2129. this_cycle = 1;
  2130. next_cycle = 0;
  2131. } else {
  2132. this_cycle = 0;
  2133. next_cycle = 1;
  2134. }
  2135. }
  2136. }
  2137. /**
  2138. * Characters leave scent trails for perceptive monsters to track.
  2139. *
  2140. * Smell is rather more limited than sound. Many creatures cannot use
  2141. * it at all, it doesn't extend very far outwards from the character's
  2142. * current position, and monsters can use it to home in the character,
  2143. * but not to run away from him.
  2144. *
  2145. * Smell is valued according to age. When a character takes his turn,
  2146. * scent is aged by one, and new scent of the current age is laid down.
  2147. * Speedy characters leave more scent, true, but it also ages faster,
  2148. * which makes it harder to hunt them down.
  2149. *
  2150. * Whenever the age count loops, most of the scent trail is erased and
  2151. * the age of the remainder is recalculated.
  2152. */
  2153. void update_smell(void)
  2154. {
  2155. int i, j;
  2156. int y, x;
  2157. int py = p_ptr->py;
  2158. int px = p_ptr->px;
  2159. feature_type *f_ptr = NULL;
  2160. /* Create a table that controls the spread of scent */
  2161. int scent_adjust[5][5] = {
  2162. {250, 2, 2, 2, 250},
  2163. {2, 1, 1, 1, 2},
  2164. {2, 1, 0, 1, 2},
  2165. {2, 1, 1, 1, 2},
  2166. {250, 2, 2, 2, 250},
  2167. };
  2168. /* Scent becomes "younger" */
  2169. scent_when--;
  2170. /* Loop the age and adjust scent values when necessary */
  2171. if (scent_when <= 0) {
  2172. /* Scan the entire dungeon */
  2173. for (y = 0; y < ARENA_HGT; y++) {
  2174. for (x = 0; x < ARENA_WID; x++) {
  2175. /* Ignore non-existent scent */
  2176. if (cave_when[y][x] == 0)
  2177. continue;
  2178. /* Erase the earlier part of the previous cycle */
  2179. if (cave_when[y][x] > SMELL_STRENGTH)
  2180. cave_when[y][x] = 0;
  2181. /* Reset the ages of the most recent scent */
  2182. else
  2183. cave_when[y][x] =
  2184. 250 - SMELL_STRENGTH + cave_when[y][x];
  2185. }
  2186. }
  2187. /* Reset the age value */
  2188. scent_when = 250 - SMELL_STRENGTH;
  2189. }
  2190. /* Lay down new scent */
  2191. for (i = 0; i < 5; i++) {
  2192. for (j = 0; j < 5; j++) {
  2193. /* Translate table to map grids */
  2194. y = i + py - 2;
  2195. x = j + px - 2;
  2196. /* Check Bounds */
  2197. if (!in_bounds(y, x))
  2198. continue;
  2199. /* Get the feature */
  2200. f_ptr = &f_info[cave_feat[y][x]];
  2201. /* Walls, water, and lava cannot hold scent. */
  2202. if (tf_has(f_ptr->flags, TF_NO_SCENT)) {
  2203. continue;
  2204. }
  2205. /* Grid must not be blocked by walls from the character */
  2206. if (!los(p_ptr->py, p_ptr->px, y, x))
  2207. continue;
  2208. /* Note grids that are too far away */
  2209. if (scent_adjust[i][j] == 250)
  2210. continue;
  2211. /* Mark the grid with new scent */
  2212. cave_when[y][x] = scent_when + scent_adjust[i][j];
  2213. }
  2214. }
  2215. }
  2216. /**
  2217. * Map around a given point, or the current panel (plus some)
  2218. * ala "magic mapping". Staffs of magic mapping map more than
  2219. * rods do, because staffs affect larger areas in general.
  2220. *
  2221. * We must never attempt to map the outer dungeon walls, or we
  2222. * might induce illegal cave grid references.
  2223. */
  2224. void map_area(int y, int x, bool extended)
  2225. {
  2226. int i, y_c, x_c;
  2227. int rad = DETECT_RAD_DEFAULT;
  2228. if (extended)
  2229. rad += 10;
  2230. /* Map around a location, if given. */
  2231. if ((y) && (x)) {
  2232. y_c = y;
  2233. x_c = x;
  2234. }
  2235. /* Normally, pick an area to map around the player */
  2236. else {
  2237. y_c = p_ptr->py;
  2238. x_c = p_ptr->px;
  2239. }
  2240. /* Scan the maximal area of mapping */
  2241. for (y = y_c - rad; y <= y_c + rad; y++) {
  2242. for (x = x_c - rad; x <= x_c + rad; x++) {
  2243. feature_type *f_ptr = &f_info[cave_feat[y][x]];
  2244. /* Ignore "illegal" locations */
  2245. if (!in_bounds(y, x))
  2246. continue;
  2247. /* Enforce a "circular" area */
  2248. if (distance(y_c, x_c, y, x) > rad)
  2249. continue;
  2250. /* All passable grids are checked */
  2251. if (tf_has(f_ptr->flags, TF_PASSABLE)) {
  2252. /* Memorize interesting features */
  2253. if (!tf_has(f_ptr->flags, TF_FLOOR) ||
  2254. tf_has(f_ptr->flags, TF_INTERESTING)) {
  2255. /* Memorize the object */
  2256. cave_on(cave_info[y][x], CAVE_MARK);
  2257. }
  2258. /* Memorize known walls */
  2259. for (i = 0; i < 8; i++) {
  2260. int yy = y + ddy_ddd[i];
  2261. int xx = x + ddx_ddd[i];
  2262. /* All blockages are checked */
  2263. f_ptr = &f_info[cave_feat[yy][xx]];
  2264. if (!tf_has(f_ptr->flags, TF_LOS)) {
  2265. /* Memorize the walls */
  2266. cave_on(cave_info[yy][xx], CAVE_MARK);
  2267. }
  2268. }
  2269. }
  2270. }
  2271. }
  2272. /* Redraw map */
  2273. p_ptr->redraw |= (PR_MAP);
  2274. }
  2275. /**
  2276. * Light up the dungeon using "claravoyance"
  2277. *
  2278. * This function "illuminates" every grid in the dungeon, memorizes all
  2279. * "objects", memorizes all grids as with magic mapping, and, under the
  2280. * standard option settings (view_perma_grids but not view_torch_grids)
  2281. * memorizes all floor grids too.
  2282. *
  2283. * In Oangband, greater and lesser vaults only become fully known if the
  2284. * player has accessed this function from the debug commands. Otherwise,
  2285. * they act like magically mapped permenantly lit rooms.
  2286. *
  2287. * Note that if "view_perma_grids" is not set, we do not memorize floor
  2288. * grids, since this would defeat the purpose of "view_perma_grids", not
  2289. * that anyone seems to play without this option.
  2290. *
  2291. * Note that if "view_torch_grids" is set, we do not memorize floor grids,
  2292. * since this would prevent the use of "view_torch_grids" as a method to
  2293. * keep track of what grids have been observed directly.
  2294. */
  2295. void wiz_light(bool wizard)
  2296. {
  2297. int i, y, x;
  2298. /* Memorize objects */
  2299. for (i = 1; i < o_max; i++) {
  2300. object_type *o_ptr = &o_list[i];
  2301. /* Skip dead objects */
  2302. if (!o_ptr->k_idx)
  2303. continue;
  2304. /* Skip held objects */
  2305. if (o_ptr->held_m_idx)
  2306. continue;
  2307. /* Skip objects in vaults, if not a wizard. */
  2308. if ((wizard == FALSE)
  2309. && cave_has(cave_info[o_ptr->iy][o_ptr->ix], CAVE_ICKY))
  2310. continue;
  2311. /* Memorize */
  2312. o_ptr->marked = TRUE;
  2313. }
  2314. /* Scan all normal grids */
  2315. for (y = 1; y < ARENA_HGT - 1; y++) {
  2316. /* Scan all normal grids */
  2317. for (x = 1; x < ARENA_WID - 1; x++) {
  2318. feature_type *f_ptr = &f_info[cave_feat[y][x]];
  2319. /* Process all passable grids (or all grids, if a wizard) */
  2320. if (tf_has(f_ptr->flags, TF_PASSABLE)) {
  2321. /* Paranoia -- stay in bounds */
  2322. if (!in_bounds_fully(y, x))
  2323. continue;
  2324. /* Scan the grid and all neighbors */
  2325. for (i = 0; i < 9; i++) {
  2326. int yy = y + ddy_ddd[i];
  2327. int xx = x + ddx_ddd[i];
  2328. f_ptr = &f_info[cave_feat[yy][xx]];
  2329. /* Perma-light the grid (always) */
  2330. cave_on(cave_info[yy][xx], CAVE_GLOW);
  2331. /* If not a wizard, do not mark passable grids in vaults */
  2332. if ((!wizard)
  2333. && cave_has(cave_info[yy][xx], CAVE_ICKY)) {
  2334. if (tf_has(f_ptr->flags, TF_PASSABLE))
  2335. continue;
  2336. }
  2337. /* Memorize features other than ordinary floor */
  2338. if (!tf_has(f_ptr->flags, TF_FLOOR) ||
  2339. cave_visible_trap(yy, xx)) {
  2340. /* Memorize the grid */
  2341. cave_on(cave_info[yy][xx], CAVE_MARK);
  2342. }
  2343. /* Optionally, memorize floors immediately */
  2344. else if (OPT(view_perma_grids)
  2345. && !OPT(view_torch_grids)) {
  2346. /* Memorize the grid */
  2347. cave_on(cave_info[yy][xx], CAVE_MARK);
  2348. }
  2349. }
  2350. }
  2351. }
  2352. }
  2353. /* Fully update the visuals */
  2354. p_ptr->update |= (PU_FORGET_VIEW | PU_UPDATE_VIEW | PU_MONSTERS);
  2355. /* Redraw whole map, monster list */
  2356. p_ptr->redraw |= (PR_MAP | PR_MONLIST | PR_ITEMLIST);
  2357. }
  2358. /**
  2359. * Forget the dungeon map (ala "Thinking of Maud...").
  2360. */
  2361. void wiz_dark(void)
  2362. {
  2363. int i, y, x;
  2364. /* Forget every grid */
  2365. for (y = 0; y < ARENA_HGT; y++) {
  2366. for (x = 0; x < ARENA_WID; x++) {
  2367. /* Process the grid */
  2368. cave_off(cave_info[y][x], CAVE_MARK);
  2369. cave_off(cave_info[y][x], CAVE_DTRAP);
  2370. }
  2371. }
  2372. /* Forget all objects */
  2373. for (i = 1; i < o_max; i++) {
  2374. object_type *o_ptr = &o_list[i];
  2375. /* Skip dead objects */
  2376. if (!o_ptr->k_idx)
  2377. continue;
  2378. /* Skip held objects */
  2379. if (o_ptr->held_m_idx)
  2380. continue;
  2381. /* Forget the object */
  2382. o_ptr->marked = FALSE;
  2383. }
  2384. /* Fully update the visuals */
  2385. p_ptr->update |= (PU_FORGET_VIEW | PU_UPDATE_VIEW | PU_MONSTERS);
  2386. /* Redraw whole map, monster list */
  2387. p_ptr->redraw |= (PR_MAP | PR_MONLIST | PR_ITEMLIST);
  2388. }
  2389. /**
  2390. * Light or Darken the world
  2391. */
  2392. void illuminate(void)
  2393. {
  2394. int y, x;
  2395. /* Apply light or darkness */
  2396. for (y = 0; y < ARENA_HGT; y++) {
  2397. for (x = 0; x < ARENA_WID; x++) {
  2398. /* Grids outside town walls */
  2399. if ((cave_feat[y][x] == FEAT_PERM_SOLID) && !p_ptr->danger) {
  2400. /* Darken the grid */
  2401. cave_off(cave_info[y][x], CAVE_GLOW);
  2402. /* Hack -- Forget grids */
  2403. if (OPT(view_perma_grids)) {
  2404. cave_off(cave_info[y][x], CAVE_MARK);
  2405. }
  2406. }
  2407. /* Special case of shops */
  2408. else if (cave_feat[y][x] == FEAT_PERM_EXTRA) {
  2409. /* Illuminate the grid */
  2410. cave_on(cave_info[y][x], CAVE_GLOW);
  2411. /* Memorize the grid */
  2412. cave_on(cave_info[y][x], CAVE_MARK);
  2413. }
  2414. /* Viewable grids (light) */
  2415. else if (is_daylight) {
  2416. /* Illuminate the grid */
  2417. cave_on(cave_info[y][x], CAVE_GLOW);
  2418. }
  2419. /* Viewable grids (dark) */
  2420. else {
  2421. /* Darken the grid */
  2422. cave_off(cave_info[y][x], CAVE_GLOW);
  2423. }
  2424. }
  2425. }
  2426. /* Fully update the visuals */
  2427. p_ptr->update |= (PU_FORGET_VIEW | PU_UPDATE_VIEW | PU_MONSTERS);
  2428. /* Redraw map, monster list */
  2429. p_ptr->redraw |= (PR_MAP | PR_MONLIST | PR_ITEMLIST);
  2430. }
  2431. /**
  2432. * Change the "feat" flag for a grid, and notice/redraw the grid.
  2433. */
  2434. void cave_set_feat(int y, int x, int feat)
  2435. {
  2436. /* Change the feature */
  2437. cave_feat[y][x] = feat;
  2438. /* Notice/Redraw */
  2439. if (character_dungeon) {
  2440. /* Notice */
  2441. note_spot(y, x);
  2442. /* Redraw */
  2443. light_spot(y, x);
  2444. }
  2445. }
  2446. /**
  2447. * Determine the path taken by a projection.
  2448. *
  2449. * The projection will always start from the grid (y1,x1), and will travel
  2450. * towards the grid (y2,x2), touching one grid per unit of distance along
  2451. * the major axis, and stopping when it enters the destination grid or a
  2452. * wall grid, or has travelled the maximum legal distance of "range".
  2453. *
  2454. * Note that "distance" in this function (as in the update_view() code)
  2455. * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
  2456. * actually has an "octagon of projection" not a "circle of projection".
  2457. *
  2458. * The path grids are saved into the grid array pointed to by "gp", and
  2459. * there should be room for at least "range" grids in "gp". Note that
  2460. * due to the way in which distance is calculated, this function normally
  2461. * uses fewer than "range" grids for the projection path, so the result
  2462. * of this function should never be compared directly to "range". Note
  2463. * that the initial grid (y1,x1) is never saved into the grid array, not
  2464. * even if the initial grid is also the final grid. XXX XXX XXX
  2465. *
  2466. * The "flg" flags can be used to modify the behavior of this function.
  2467. *
  2468. * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
  2469. * semantics as they do for the "project" function, namely, that the path
  2470. * will stop as soon as it hits a monster, or that the path will continue
  2471. * through the destination grid, respectively.
  2472. *
  2473. * The "PROJECT_JUMP" flag, which for the project() function means to
  2474. * start at a special grid (which makes no sense in this function), means
  2475. * that the path should be "angled" slightly if needed to avoid any wall
  2476. * grids, allowing the player to "target" any grid which is in "view".
  2477. * This flag is non-trivial and has not yet been implemented, but could
  2478. * perhaps make use of the "vinfo" array (above). XXX XXX XXX
  2479. *
  2480. * This function returns the number of grids (if any) in the path. This
  2481. * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
  2482. *
  2483. * This algorithm is similar to, but slightly different from, the one used
  2484. * by update_view_los(), and very different from the one used by los().
  2485. */
  2486. int project_path(u16b * gp, int range, int y1, int x1, int y2, int x2,
  2487. int flg)
  2488. {
  2489. int y, x;
  2490. int n = 0;
  2491. int k = 0;
  2492. /* Absolute */
  2493. int ay, ax;
  2494. /* Offsets */
  2495. int sy, sx;
  2496. /* Fractions */
  2497. int frac;
  2498. /* Scale factors */
  2499. int full, half;
  2500. /* Slope */
  2501. int m;
  2502. bool blocked = FALSE;
  2503. /* No path necessary (or allowed) */
  2504. if ((x1 == x2) && (y1 == y2))
  2505. return (0);
  2506. /* Analyze "dy" */
  2507. if (y2 < y1) {
  2508. ay = (y1 - y2);
  2509. sy = -1;
  2510. } else {
  2511. ay = (y2 - y1);
  2512. sy = 1;
  2513. }
  2514. /* Analyze "dx" */
  2515. if (x2 < x1) {
  2516. ax = (x1 - x2);
  2517. sx = -1;
  2518. } else {
  2519. ax = (x2 - x1);
  2520. sx = 1;
  2521. }
  2522. /* Number of "units" in one "half" grid */
  2523. half = (ay * ax);
  2524. /* Number of "units" in one "full" grid */
  2525. full = half << 1;
  2526. /* Vertical */
  2527. if (ay > ax) {
  2528. /* Start at tile edge */
  2529. frac = ax * ax;
  2530. /* Let m = ((dx/dy) * full) = (dx * dx * 2) = (frac * 2) */
  2531. m = frac << 1;
  2532. /* Start */
  2533. y = y1 + sy;
  2534. x = x1;
  2535. /* Create the projection path */
  2536. while (1) {
  2537. /* Save grid */
  2538. gp[n++] = GRID(y, x);
  2539. /* Hack -- Check maximum range */
  2540. if ((n + (k >> 1)) >= range)
  2541. break;
  2542. /* Sometimes stop at destination grid */
  2543. if (!(flg & (PROJECT_THRU))) {
  2544. if ((x == x2) && (y == y2))
  2545. break;
  2546. }
  2547. /* Always stop at non-initial wall grids */
  2548. if ((n > 0) && !cave_project(y, x))
  2549. break;
  2550. /* Sometimes stop at non-initial monsters/players */
  2551. if (flg & (PROJECT_STOP)) {
  2552. if ((n > 0) && (cave_m_idx[y][x] != 0))
  2553. break;
  2554. }
  2555. /* Sometimes notice non-initial monsters/players */
  2556. if (flg & (PROJECT_CHCK)) {
  2557. if ((n > 0) && (cave_m_idx[y][x] != 0))
  2558. blocked = TRUE;
  2559. }
  2560. /* Slant */
  2561. if (m) {
  2562. /* Advance (X) part 1 */
  2563. frac += m;
  2564. /* Horizontal change */
  2565. if (frac >= half) {
  2566. /* Advance (X) part 2 */
  2567. x += sx;
  2568. /* Advance (X) part 3 */
  2569. frac -= full;
  2570. /* Track distance */
  2571. k++;
  2572. }
  2573. }
  2574. /* Advance (Y) */
  2575. y += sy;
  2576. }
  2577. }
  2578. /* Horizontal */
  2579. else if (ax > ay) {
  2580. /* Start at tile edge */
  2581. frac = ay * ay;
  2582. /* Let m = ((dy/dx) * full) = (dy * dy * 2) = (frac * 2) */
  2583. m = frac << 1;
  2584. /* Start */
  2585. y = y1;
  2586. x = x1 + sx;
  2587. /* Create the projection path */
  2588. while (1) {
  2589. /* Save grid */
  2590. gp[n++] = GRID(y, x);
  2591. /* Hack -- Check maximum range */
  2592. if ((n + (k >> 1)) >= range)
  2593. break;
  2594. /* Sometimes stop at destination grid */
  2595. if (!(flg & (PROJECT_THRU))) {
  2596. if ((x == x2) && (y == y2))
  2597. break;
  2598. }
  2599. /* Always stop at non-initial wall grids */
  2600. if ((n > 0) && !cave_project(y, x))
  2601. break;
  2602. /* Sometimes stop at non-initial monsters/players */
  2603. if (flg & (PROJECT_STOP)) {
  2604. if ((n > 0) && (cave_m_idx[y][x] != 0))
  2605. break;
  2606. }
  2607. /* Sometimes notice non-initial monsters/players */
  2608. if (flg & (PROJECT_CHCK)) {
  2609. if ((n > 0) && (cave_m_idx[y][x] != 0))
  2610. blocked = TRUE;
  2611. }
  2612. /* Slant */
  2613. if (m) {
  2614. /* Advance (Y) part 1 */
  2615. frac += m;
  2616. /* Vertical change */
  2617. if (frac >= half) {
  2618. /* Advance (Y) part 2 */
  2619. y += sy;
  2620. /* Advance (Y) part 3 */
  2621. frac -= full;
  2622. /* Track distance */
  2623. k++;
  2624. }
  2625. }
  2626. /* Advance (X) */
  2627. x += sx;
  2628. }
  2629. }
  2630. /* Diagonal */
  2631. else {
  2632. /* Start */
  2633. y = y1 + sy;
  2634. x = x1 + sx;
  2635. /* Create the projection path */
  2636. while (1) {
  2637. /* Save grid */
  2638. gp[n++] = GRID(y, x);
  2639. /* Hack -- Check maximum range */
  2640. if ((n + (n >> 1)) >= range)
  2641. break;
  2642. /* Sometimes stop at destination grid */
  2643. if (!(flg & (PROJECT_THRU))) {
  2644. if ((x == x2) && (y == y2))
  2645. break;
  2646. }
  2647. /* Always stop at non-initial wall grids */
  2648. if ((n > 0) && !cave_project(y, x))
  2649. break;
  2650. /* Sometimes stop at non-initial monsters/players */
  2651. if (flg & (PROJECT_STOP)) {
  2652. if ((n > 0) && (cave_m_idx[y][x] != 0))
  2653. break;
  2654. }
  2655. /* Sometimes notice non-initial monsters/players */
  2656. if (flg & (PROJECT_CHCK)) {
  2657. if ((n > 0) && (cave_m_idx[y][x] != 0))
  2658. blocked = TRUE;
  2659. }
  2660. /* Advance (Y) */
  2661. y += sy;
  2662. /* Advance (X) */
  2663. x += sx;
  2664. }
  2665. }
  2666. /* Length */
  2667. if (blocked)
  2668. return (-n);
  2669. else
  2670. return (n);
  2671. }
  2672. /**
  2673. * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
  2674. * at the final destination, using the project_path() function to check
  2675. * the projection path.
  2676. *
  2677. * Accept projection flags, and pass them onto project_path().
  2678. *
  2679. * Note that no grid is ever projectable() from itself.
  2680. *
  2681. * This function is used to determine if the player can (easily) target
  2682. * a given grid, if a monster can target the player, and if a clear shot
  2683. * exists from monster to player.
  2684. */
  2685. byte projectable(int y1, int x1, int y2, int x2, int flg)
  2686. {
  2687. int y, x;
  2688. int grid_n = 0;
  2689. u16b grid_g[512];
  2690. feature_type *f_ptr;
  2691. /* Check the projection path */
  2692. grid_n = project_path(grid_g, MAX_RANGE, y1, x1, y2, x2, flg);
  2693. /* No grid is ever projectable from itself */
  2694. if (!grid_n)
  2695. return (FALSE);
  2696. /* Final grid. As grid_n may be negative, use absolute value. */
  2697. y = GRID_Y(grid_g[ABS(grid_n) - 1]);
  2698. x = GRID_X(grid_g[ABS(grid_n) - 1]);
  2699. /* May not end in an unrequested grid */
  2700. if ((y != y2) || (x != x2))
  2701. return (PROJECT_NO);
  2702. /* Must end in a passable grid. */
  2703. f_ptr = &f_info[cave_feat[y][x]];
  2704. if (!tf_has(f_ptr->flags, TF_PASSABLE))
  2705. return (PROJECT_NO);
  2706. /* Promise a clear bolt shot if we have verified that there is one */
  2707. if ((flg & (PROJECT_STOP)) || (flg & (PROJECT_CHCK))) {
  2708. /* Positive value for grid_n mean no obstacle was found. */
  2709. if (grid_n > 0)
  2710. return (PROJECT_CLEAR);
  2711. }
  2712. /* Assume projectable, but make no promises about clear shots */
  2713. return (PROJECT_NOT_CLEAR);
  2714. }
  2715. /**
  2716. * Standard "find me a location" function
  2717. *
  2718. * Obtains a legal location within the given distance of the initial
  2719. * location, and with los() from the source to destination location.
  2720. *
  2721. * This function is often called from inside a loop which searches for
  2722. * locations while increasing the "d" distance.
  2723. *
  2724. * Currently the "m" parameter is unused.
  2725. */
  2726. void scatter(int *yp, int *xp, int y, int x, int d, int m)
  2727. {
  2728. int nx, ny;
  2729. /* Unused */
  2730. m = m;
  2731. /* Pick a location */
  2732. while (TRUE) {
  2733. /* Pick a new location */
  2734. ny = rand_spread(y, d);
  2735. nx = rand_spread(x, d);
  2736. /* Ignore annoying locations */
  2737. if (!in_bounds_fully(y, x))
  2738. continue;
  2739. /* Ignore "excessively distant" locations */
  2740. if ((d > 1) && (distance(y, x, ny, nx) > d))
  2741. continue;
  2742. /* Require "line of sight" */
  2743. if (los(y, x, ny, nx))
  2744. break;
  2745. }
  2746. /* Save the location */
  2747. (*yp) = ny;
  2748. (*xp) = nx;
  2749. }
  2750. /**
  2751. * Track a new monster
  2752. */
  2753. void health_track(int m_idx)
  2754. {
  2755. /* Track a new guy */
  2756. p_ptr->health_who = m_idx;
  2757. /* Redraw (later) */
  2758. p_ptr->redraw |= (PR_HEALTH | PR_MON_MANA);
  2759. }
  2760. /**
  2761. * Hack -- track the given monster race
  2762. */
  2763. void monster_race_track(int r_idx)
  2764. {
  2765. /* Save this monster ID */
  2766. p_ptr->monster_race_idx = r_idx;
  2767. /* Window stuff */
  2768. p_ptr->redraw |= (PR_MONSTER);
  2769. }
  2770. /**
  2771. * Hack -- track the given object kind
  2772. */
  2773. void track_object(int item)
  2774. {
  2775. p_ptr->object_idx = item;
  2776. p_ptr->object_kind_idx = 0;
  2777. p_ptr->redraw |= (PR_OBJECT);
  2778. }
  2779. void track_object_kind(int k_idx)
  2780. {
  2781. p_ptr->object_idx = 0;
  2782. p_ptr->object_kind_idx = k_idx;
  2783. p_ptr->redraw |= (PR_OBJECT);
  2784. }
  2785. /**
  2786. * Something has happened to disturb the player.
  2787. *
  2788. * The first arg indicates a major disturbance, which affects search.
  2789. *
  2790. * The second arg is currently unused, but could induce output flush.
  2791. *
  2792. * All disturbance cancels repeated commands, resting, and running.
  2793. */
  2794. void disturb(int stop_search, int unused_flag)
  2795. {
  2796. /* Unused parameter */
  2797. (void) unused_flag;
  2798. /* Cancel repeated commands */
  2799. cmd_cancel_repeat();
  2800. /* Cancel Resting */
  2801. if (p_ptr->resting) {
  2802. /* Cancel */
  2803. p_ptr->resting = 0;
  2804. /* Redraw the state (later) */
  2805. p_ptr->redraw |= (PR_STATE);
  2806. }
  2807. /* Cancel running */
  2808. if (p_ptr->running) {
  2809. /* Cancel */
  2810. p_ptr->running = 0;
  2811. /* Recenter the panel when running stops */
  2812. if (OPT(center_player))
  2813. verify_panel();
  2814. /* Calculate torch radius */
  2815. p_ptr->update |= (PU_TORCH);
  2816. }
  2817. /* Cancel searching if requested */
  2818. if (stop_search && p_ptr->searching) {
  2819. /* Cancel */
  2820. p_ptr->searching = FALSE;
  2821. /* Recalculate bonuses */
  2822. p_ptr->update |= (PU_BONUS);
  2823. /* Redraw the state */
  2824. p_ptr->redraw |= (PR_STATE);
  2825. }
  2826. /* Flush the input if requested */
  2827. if (OPT(flush_disturb))
  2828. flush();
  2829. }
  2830. /**
  2831. * Hack -- Check if a level is a "quest" level
  2832. */
  2833. bool is_quest(int stage)
  2834. {
  2835. /* Is Morgoth dead? */
  2836. if (p_ptr->total_winner)
  2837. return (FALSE);
  2838. /* Is it level 100? */
  2839. if (chunk_list[stage].z_pos == 100)
  2840. return (TRUE);
  2841. /* No, then */
  2842. return (FALSE);
  2843. }