• R/O
  • HTTP
  • SSH
  • HTTPS

hengband: Commit

変愚蛮怒のメインリポジトリです


Commit MetaInfo

Revisionfbc7d72e51a476002e6f67176f26f873575c32b9 (tree)
Time2019-02-22 13:30:21
Authordeskull <deskull@user...>
Commiterdeskull

Log Message

[Refactor] #37353 cave.c を grid.c に統合。 / Integrate cave.c to grid.c.

Change Summary

Incremental Difference

--- a/Hengband_vcs2017/Hengband/Hengband.vcxproj
+++ b/Hengband_vcs2017/Hengband/Hengband.vcxproj
@@ -139,7 +139,6 @@
139139 <ClCompile Include="..\..\src\avatar.c" />
140140 <ClCompile Include="..\..\src\birth.c" />
141141 <ClCompile Include="..\..\src\bldg.c" />
142- <ClCompile Include="..\..\src\cave.c" />
143142 <ClCompile Include="..\..\src\chest.c" />
144143 <ClCompile Include="..\..\src\chuukei.c" />
145144 <ClCompile Include="..\..\src\cmd-activate.c" />
--- a/src/cave.c
+++ /dev/null
@@ -1,4969 +0,0 @@
1-/*!
2- * @file grid_array.c
3- * @brief ダンジョンの基礎部分実装(主にマスの実装) / low level dungeon routines -BEN-
4- * @date 2013/12/30
5- * @author
6- * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
7- *\n
8- * This software may be copied and distributed for educational, research,\n
9- * and not for profit purposes provided that this copyright and statement\n
10- * are included in all such copies. Other copyrights may also apply.\n
11- * \n
12- * Support for Adam Bolt's tileset, lighting and transparency effects\n
13- * by Robert Ruehlmann (rr9@angband.org)\n
14- * \n
15- * 2013 Deskull Doxygen向けのコメント整理\n
16- */
17-
18-
19-#include "angband.h"
20-#include "world.h"
21-#include "projection.h"
22-#include "object-hook.h"
23-
24-static byte display_autopick; /*!< 自動拾い状態の設定フラグ */
25-static int match_autopick;
26-static object_type *autopick_obj; /*!< 各種自動拾い処理時に使うオブジェクトポインタ */
27-static int feat_priority; /*!< マップ縮小表示時に表示すべき地形の優先度を保管する */
28-
29-/*!
30- * @brief 2点間の距離をニュートン・ラプソン法で算出する / Distance between two points via Newton-Raphson technique
31- * @param y1 1点目のy座標
32- * @param x1 1点目のx座標
33- * @param y2 2点目のy座標
34- * @param x2 2点目のx座標
35- * @return 2点間の距離
36- */
37-POSITION distance (POSITION y1, POSITION x1, POSITION y2, POSITION x2)
38-{
39- POSITION dy = (y1 > y2) ? (y1 - y2) : (y2 - y1);
40- POSITION dx = (x1 > x2) ? (x1 - x2) : (x2 - x1);
41-
42- /* Squared distance */
43- POSITION target = (dy * dy) + (dx * dx);
44-
45- /* Approximate distance: hypot(dy,dx) = max(dy,dx) + min(dy,dx) / 2 */
46- POSITION d = (dy > dx) ? (dy + (dx>>1)) : (dx + (dy>>1));
47-
48- POSITION err;
49-
50- /* Simple case */
51- if (!dy || !dx) return d;
52-
53- while (1)
54- {
55- /* Approximate error */
56- err = (target - d * d) / (2 * d);
57-
58- /* No error - we are done */
59- if (!err) break;
60-
61- /* Adjust distance */
62- d += err;
63- }
64-
65- return d;
66-}
67-
68-/*!
69- * @brief 地形が罠持ちであるかの判定を行う。 / Return TRUE if the given feature is a trap
70- * @param feat 地形情報のID
71- * @return 罠持ちの地形ならばTRUEを返す。
72- */
73-bool is_trap(FEAT_IDX feat)
74-{
75- return have_flag(f_info[feat].flags, FF_TRAP);
76-}
77-
78-/*!
79- * @brief マスに看破済みの罠があるかの判定を行う。 / Return TRUE if the given grid is a known trap
80- * @param g_ptr マス構造体の参照ポインタ
81- * @return 看破済みの罠があるならTRUEを返す。
82- */
83-bool is_known_trap(grid_type *g_ptr)
84-{
85- if (!g_ptr->mimic && !cave_have_flag_grid(g_ptr, FF_SECRET) &&
86- is_trap(g_ptr->feat)) return TRUE;
87- else
88- return FALSE;
89-}
90-
91-/*!
92- * @brief 地形が閉じたドアであるかの判定を行う。 / Return TRUE if the given grid is a closed door
93- * @param feat 地形情報のID
94- * @return 閉じたドアのある地形ならばTRUEを返す。
95- */
96-bool is_closed_door(FEAT_IDX feat)
97-{
98- feature_type *f_ptr = &f_info[feat];
99-
100- return (have_flag(f_ptr->flags, FF_OPEN) || have_flag(f_ptr->flags, FF_BASH)) &&
101- !have_flag(f_ptr->flags, FF_MOVE);
102-}
103-
104-/*!
105- * @brief マスに隠されたドアがあるかの判定を行う。 / Return TRUE if the given grid is a hidden closed door
106- * @param g_ptr マス構造体の参照ポインタ
107- * @return 隠されたドアがあるならTRUEを返す。
108- */
109-bool is_hidden_door(grid_type *g_ptr)
110-{
111- if ((g_ptr->mimic || cave_have_flag_grid(g_ptr, FF_SECRET)) &&
112- is_closed_door(g_ptr->feat))
113- return TRUE;
114- else
115- return FALSE;
116-}
117-
118-/*!
119- * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
120- * @param y1 始点のy座標
121- * @param x1 始点のx座標
122- * @param y2 終点のy座標
123- * @param x2 終点のx座標
124- * @return LOSが通っているならTRUEを返す。
125- * @details
126- * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall,\n
127- * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.\n
128- *\n
129- * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
130- *\n
131- * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
132- * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line\n
133- * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
134- *\n
135- * We assume that the "mathematical corner" of a non-floor tile does not\n
136- * block line of sight.\n
137- *\n
138- * Because this function uses (short) ints for all calculations, overflow may\n
139- * occur if dx and dy exceed 90.\n
140- *\n
141- * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
142- * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
143- * we can use integer arithmetic.\n
144- *\n
145- * We travel from start to finish along the longer axis, starting at the border\n
146- * between the first and second tiles, where the y offset = .5 * slope, taking\n
147- * into account the scale factor. See below.\n
148- *\n
149- * Also note that this function and the "move towards target" code do NOT\n
150- * share the same properties. Thus, you can see someone, target them, and\n
151- * then fire a bolt at them, but the bolt may hit a wall, not them. However\n,
152- * by clever choice of target locations, you can sometimes throw a "curve".\n
153- *\n
154- * Note that "line of sight" is not "reflexive" in all cases.\n
155- *\n
156- * Use the "projectable()" routine to test "spell/missile line of sight".\n
157- *\n
158- * Use the "update_view()" function to determine player line-of-sight.\n
159- */
160-bool los(POSITION y1, POSITION x1, POSITION y2, POSITION x2)
161-{
162- /* Delta */
163- POSITION dx, dy;
164-
165- /* Absolute */
166- POSITION ax, ay;
167-
168- /* Signs */
169- POSITION sx, sy;
170-
171- /* Fractions */
172- POSITION qx, qy;
173-
174- /* Scanners */
175- POSITION tx, ty;
176-
177- /* Scale factors */
178- POSITION f1, f2;
179-
180- /* Slope, or 1/Slope, of LOS */
181- POSITION m;
182-
183-
184- /* Extract the offset */
185- dy = y2 - y1;
186- dx = x2 - x1;
187-
188- /* Extract the absolute offset */
189- ay = ABS(dy);
190- ax = ABS(dx);
191-
192-
193- /* Handle adjacent (or identical) grids */
194- if ((ax < 2) && (ay < 2)) return TRUE;
195-
196-
197- /* Paranoia -- require "safe" origin */
198- /* if (!in_bounds(y1, x1)) return FALSE; */
199- /* if (!in_bounds(y2, x2)) return FALSE; */
200-
201-
202- /* Directly South/North */
203- if (!dx)
204- {
205- /* South -- check for walls */
206- if (dy > 0)
207- {
208- for (ty = y1 + 1; ty < y2; ty++)
209- {
210- if (!cave_los_bold(ty, x1)) return FALSE;
211- }
212- }
213-
214- /* North -- check for walls */
215- else
216- {
217- for (ty = y1 - 1; ty > y2; ty--)
218- {
219- if (!cave_los_bold(ty, x1)) return FALSE;
220- }
221- }
222-
223- /* Assume los */
224- return TRUE;
225- }
226-
227- /* Directly East/West */
228- if (!dy)
229- {
230- /* East -- check for walls */
231- if (dx > 0)
232- {
233- for (tx = x1 + 1; tx < x2; tx++)
234- {
235- if (!cave_los_bold(y1, tx)) return FALSE;
236- }
237- }
238-
239- /* West -- check for walls */
240- else
241- {
242- for (tx = x1 - 1; tx > x2; tx--)
243- {
244- if (!cave_los_bold(y1, tx)) return FALSE;
245- }
246- }
247-
248- /* Assume los */
249- return TRUE;
250- }
251-
252-
253- /* Extract some signs */
254- sx = (dx < 0) ? -1 : 1;
255- sy = (dy < 0) ? -1 : 1;
256-
257-
258- /* Vertical "knights" */
259- if (ax == 1)
260- {
261- if (ay == 2)
262- {
263- if (cave_los_bold(y1 + sy, x1)) return TRUE;
264- }
265- }
266-
267- /* Horizontal "knights" */
268- else if (ay == 1)
269- {
270- if (ax == 2)
271- {
272- if (cave_los_bold(y1, x1 + sx)) return TRUE;
273- }
274- }
275-
276-
277- /* Calculate scale factor div 2 */
278- f2 = (ax * ay);
279-
280- /* Calculate scale factor */
281- f1 = f2 << 1;
282-
283-
284- /* Travel horizontally */
285- if (ax >= ay)
286- {
287- /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
288- qy = ay * ay;
289- m = qy << 1;
290-
291- tx = x1 + sx;
292-
293- /* Consider the special case where slope == 1. */
294- if (qy == f2)
295- {
296- ty = y1 + sy;
297- qy -= f1;
298- }
299- else
300- {
301- ty = y1;
302- }
303-
304- /* Note (below) the case (qy == f2), where */
305- /* the LOS exactly meets the corner of a tile. */
306- while (x2 - tx)
307- {
308- if (!cave_los_bold(ty, tx)) return FALSE;
309-
310- qy += m;
311-
312- if (qy < f2)
313- {
314- tx += sx;
315- }
316- else if (qy > f2)
317- {
318- ty += sy;
319- if (!cave_los_bold(ty, tx)) return FALSE;
320- qy -= f1;
321- tx += sx;
322- }
323- else
324- {
325- ty += sy;
326- qy -= f1;
327- tx += sx;
328- }
329- }
330- }
331-
332- /* Travel vertically */
333- else
334- {
335- /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
336- qx = ax * ax;
337- m = qx << 1;
338-
339- ty = y1 + sy;
340-
341- if (qx == f2)
342- {
343- tx = x1 + sx;
344- qx -= f1;
345- }
346- else
347- {
348- tx = x1;
349- }
350-
351- /* Note (below) the case (qx == f2), where */
352- /* the LOS exactly meets the corner of a tile. */
353- while (y2 - ty)
354- {
355- if (!cave_los_bold(ty, tx)) return FALSE;
356-
357- qx += m;
358-
359- if (qx < f2)
360- {
361- ty += sy;
362- }
363- else if (qx > f2)
364- {
365- tx += sx;
366- if (!cave_los_bold(ty, tx)) return FALSE;
367- qx -= f1;
368- ty += sy;
369- }
370- else
371- {
372- tx += sx;
373- qx -= f1;
374- ty += sy;
375- }
376- }
377- }
378-
379- /* Assume los */
380- return TRUE;
381-}
382-
383-#define COMPLEX_WALL_ILLUMINATION /*!< 照明状態を壁により影響を受ける、より複雑な判定に切り替えるマクロ */
384-
385-
386-/*!
387- * @brief 指定された座標のマスが現在照らされているかを返す。 / Check for "local" illumination
388- * @param y y座標
389- * @param x x座標
390- * @return 指定された座標に照明がかかっているならTRUEを返す。。
391- */
392-static bool check_local_illumination(POSITION y, POSITION x)
393-{
394- /* Hack -- move towards player */
395- POSITION yy = (y < p_ptr->y) ? (y + 1) : (y > p_ptr->y) ? (y - 1) : y;
396- POSITION xx = (x < p_ptr->x) ? (x + 1) : (x > p_ptr->x) ? (x - 1) : x;
397-
398- /* Check for "local" illumination */
399-
400-#ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
401-
402- /* Check for "complex" illumination */
403- if ((feat_supports_los(get_feat_mimic(&grid_array[yy][xx])) &&
404- (grid_array[yy][xx].info & CAVE_GLOW)) ||
405- (feat_supports_los(get_feat_mimic(&grid_array[y][xx])) &&
406- (grid_array[y][xx].info & CAVE_GLOW)) ||
407- (feat_supports_los(get_feat_mimic(&grid_array[yy][x])) &&
408- (grid_array[yy][x].info & CAVE_GLOW)))
409- {
410- return TRUE;
411- }
412- else return FALSE;
413-
414-#else /* COMPLEX_WALL_ILLUMINATION */
415-
416- /* Check for "simple" illumination */
417- return (grid_array[yy][xx].info & CAVE_GLOW) ? TRUE : FALSE;
418-
419-#endif /* COMPLEX_WALL_ILLUMINATION */
420-}
421-
422-
423-/*! 対象座標のマスの照明状態を更新する際の補助処理マクロ */
424-#define update_local_illumination_aux(Y, X) \
425-{ \
426- if (player_has_los_bold((Y), (X))) \
427- { \
428- /* Update the monster */ \
429- if (grid_array[(Y)][(X)].m_idx) update_monster(grid_array[(Y)][(X)].m_idx, FALSE); \
430-\
431- /* Notice and redraw */ \
432- note_spot((Y), (X)); \
433- lite_spot((Y), (X)); \
434- } \
435-}
436-
437-/*!
438- * @brief 指定された座標の照明状態を更新する / Update "local" illumination
439- * @param y y座標
440- * @param x x座標
441- * @return なし
442- */
443-void update_local_illumination(POSITION y, POSITION x)
444-{
445- int i;
446- POSITION yy, xx;
447-
448- if (!in_bounds(y, x)) return;
449-
450-#ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
451-
452- if ((y != p_ptr->y) && (x != p_ptr->x))
453- {
454- yy = (y < p_ptr->y) ? (y - 1) : (y + 1);
455- xx = (x < p_ptr->x) ? (x - 1) : (x + 1);
456- update_local_illumination_aux(yy, xx);
457- update_local_illumination_aux(y, xx);
458- update_local_illumination_aux(yy, x);
459- }
460- else if (x != p_ptr->x) /* y == p_ptr->y */
461- {
462- xx = (x < p_ptr->x) ? (x - 1) : (x + 1);
463- for (i = -1; i <= 1; i++)
464- {
465- yy = y + i;
466- update_local_illumination_aux(yy, xx);
467- }
468- yy = y - 1;
469- update_local_illumination_aux(yy, x);
470- yy = y + 1;
471- update_local_illumination_aux(yy, x);
472- }
473- else if (y != p_ptr->y) /* x == p_ptr->x */
474- {
475- yy = (y < p_ptr->y) ? (y - 1) : (y + 1);
476- for (i = -1; i <= 1; i++)
477- {
478- xx = x + i;
479- update_local_illumination_aux(yy, xx);
480- }
481- xx = x - 1;
482- update_local_illumination_aux(y, xx);
483- xx = x + 1;
484- update_local_illumination_aux(y, xx);
485- }
486- else /* Player's grid */
487- {
488- for (i = 0; i < 8; i++)
489- {
490- yy = y + ddy_cdd[i];
491- xx = x + ddx_cdd[i];
492- update_local_illumination_aux(yy, xx);
493- }
494- }
495-
496-#else /* COMPLEX_WALL_ILLUMINATION */
497-
498- if ((y != p_ptr->y) && (x != p_ptr->x))
499- {
500- yy = (y < p_ptr->y) ? (y - 1) : (y + 1);
501- xx = (x < p_ptr->x) ? (x - 1) : (x + 1);
502- update_local_illumination_aux(yy, xx);
503- }
504- else if (x != p_ptr->x) /* y == p_ptr->y */
505- {
506- xx = (x < p_ptr->x) ? (x - 1) : (x + 1);
507- for (i = -1; i <= 1; i++)
508- {
509- yy = y + i;
510- update_local_illumination_aux(yy, xx);
511- }
512- }
513- else if (y != p_ptr->y) /* x == p_ptr->x */
514- {
515- yy = (y < p_ptr->y) ? (y - 1) : (y + 1);
516- for (i = -1; i <= 1; i++)
517- {
518- xx = x + i;
519- update_local_illumination_aux(yy, xx);
520- }
521- }
522- else /* Player's grid */
523- {
524- for (i = 0; i < 8; i++)
525- {
526- yy = y + ddy_cdd[i];
527- xx = x + ddx_cdd[i];
528- update_local_illumination_aux(yy, xx);
529- }
530- }
531-
532-#endif /* COMPLEX_WALL_ILLUMINATION */
533-}
534-
535-
536-/*!
537- * @brief 指定された座標をプレイヤーが視覚に収められるかを返す。 / Can the player "see" the given grid in detail?
538- * @param y y座標
539- * @param x x座標
540- * @return 視覚に収められる状態ならTRUEを返す
541- * @details
542- * He must have vision, illumination, and line of sight.\n
543- * \n
544- * Note -- "CAVE_LITE" is only set if the "torch" has "los()".\n
545- * So, given "CAVE_LITE", we know that the grid is "fully visible".\n
546- *\n
547- * Note that "CAVE_GLOW" makes little sense for a wall, since it would mean\n
548- * that a wall is visible from any direction. That would be odd. Except\n
549- * under wizard light, which might make sense. Thus, for walls, we require\n
550- * not only that they be "CAVE_GLOW", but also, that they be adjacent to a\n
551- * grid which is not only "CAVE_GLOW", but which is a non-wall, and which is\n
552- * in line of sight of the player.\n
553- *\n
554- * This extra check is expensive, but it provides a more "correct" semantics.\n
555- *\n
556- * Note that we should not run this check on walls which are "outer walls" of\n
557- * the dungeon, or we will induce a memory fault, but actually verifying all\n
558- * of the locations would be extremely expensive.\n
559- *\n
560- * Thus, to speed up the function, we assume that all "perma-walls" which are\n
561- * "CAVE_GLOW" are "illuminated" from all sides. This is correct for all cases\n
562- * except "vaults" and the "buildings" in town. But the town is a hack anyway,\n
563- * and the player has more important things on his mind when he is attacking a\n
564- * monster vault. It is annoying, but an extremely important optimization.\n
565- *\n
566- * Note that "glowing walls" are only considered to be "illuminated" if the\n
567- * grid which is next to the wall in the direction of the player is also a\n
568- * "glowing" grid. This prevents the player from being able to "see" the\n
569- * walls of illuminated rooms from a corridor outside the room.\n
570- */
571-bool player_can_see_bold(POSITION y, POSITION x)
572-{
573- grid_type *g_ptr;
574-
575- /* Blind players see nothing */
576- if (p_ptr->blind) return FALSE;
577-
578- g_ptr = &grid_array[y][x];
579-
580- /* Note that "torch-lite" yields "illumination" */
581- if (g_ptr->info & (CAVE_LITE | CAVE_MNLT)) return TRUE;
582-
583- /* Require line of sight to the grid */
584- if (!player_has_los_bold(y, x)) return FALSE;
585-
586- /* Noctovision of Ninja */
587- if (p_ptr->see_nocto) return TRUE;
588-
589- /* Require "perma-lite" of the grid */
590- if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW) return FALSE;
591-
592- /* Feature code (applying "mimic" field) */
593- /* Floors are simple */
594- if (feat_supports_los(get_feat_mimic(g_ptr))) return TRUE;
595-
596- /* Check for "local" illumination */
597- return check_local_illumination(y, x);
598-}
599-
600-/*!
601- * @brief 指定された座標をプレイヤー収められていない状態かどうか / Returns true if the player's grid is dark
602- * @return 視覚に収められていないならTRUEを返す
603- * @details player_can_see_bold()関数の返り値の否定を返している。
604- */
605-bool no_lite(void)
606-{
607- return (!player_can_see_bold(p_ptr->y, p_ptr->x));
608-}
609-
610-
611-/*!
612- * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
613- * @param y y座標
614- * @param x x座標
615- * @return 各種の変更が可能ならTRUEを返す。
616- * @details
617- * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
618- */
619-bool cave_valid_bold(POSITION y, POSITION x)
620-{
621- grid_type *g_ptr = &grid_array[y][x];
622- OBJECT_IDX this_o_idx, next_o_idx = 0;
623-
624- /* Forbid perma-grids */
625- if (cave_perma_grid(g_ptr)) return (FALSE);
626-
627- /* Check objects */
628- for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
629- {
630- object_type *o_ptr;
631- o_ptr = &o_list[this_o_idx];
632-
633- /* Acquire next object */
634- next_o_idx = o_ptr->next_o_idx;
635-
636- /* Forbid artifact grids */
637- if (object_is_artifact(o_ptr)) return (FALSE);
638- }
639-
640- /* Accept */
641- return (TRUE);
642-}
643-
644-
645-
646-
647-/*!
648- * 一般的にモンスターシンボルとして扱われる記号を定義する(幻覚処理向け) / Hack -- Legal monster codes
649- */
650-static char image_monster_hack[] = \
651-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
652-
653-/*!
654- * 一般的にオブジェクトシンボルとして扱われる記号を定義する(幻覚処理向け) / Hack -- Legal object codes
655- */
656-static char image_object_hack[] = "?/|\\\"!$()_-=[]{},~";
657-
658-/*!
659- * @brief モンスターの表示を幻覚状態に差し替える / Mega-Hack -- Hallucinatory monster
660- * @param ap 本来の色
661- * @param cp 本来のシンボル
662- * @return なし
663- */
664-static void image_monster(TERM_COLOR *ap, SYMBOL_CODE *cp)
665-{
666- /* Random symbol from set above */
667- if (use_graphics)
668- {
669- monster_race *r_ptr = &r_info[randint1(max_r_idx - 1)];
670-
671- *cp = r_ptr->x_char;
672- *ap = r_ptr->x_attr;
673- }
674- else
675- /* Text mode */
676- {
677- *cp = (one_in_(25) ?
678- image_object_hack[randint0(sizeof(image_object_hack) - 1)] :
679- image_monster_hack[randint0(sizeof(image_monster_hack) - 1)]);
680-
681- /* Random color */
682- *ap = randint1(15);
683- }
684-}
685-
686-/*!
687- * @brief オブジェクトの表示を幻覚状態に差し替える / Hallucinatory object
688- * @param ap 本来の色
689- * @param cp 本来のシンボル
690- * @return なし
691- */
692-static void image_object(TERM_COLOR *ap, SYMBOL_CODE *cp)
693-{
694- if (use_graphics)
695- {
696- object_kind *k_ptr = &k_info[randint1(max_k_idx-1)];
697-
698- *cp = k_ptr->x_char;
699- *ap = k_ptr->x_attr;
700- }
701- else
702- {
703- int n = sizeof(image_object_hack) - 1;
704-
705- *cp = image_object_hack[randint0(n)];
706-
707- /* Random color */
708- *ap = randint1(15);
709- }
710-}
711-
712-
713-/*!
714- * @brief オブジェクト&モンスターの表示を幻覚状態に差し替える / Hack -- Random hallucination
715- * @param ap 本来の色
716- * @param cp 本来のシンボル
717- * @return なし
718- */
719-static void image_random(TERM_COLOR *ap, SYMBOL_CODE *cp)
720-{
721- /* Normally, assume monsters */
722- if (randint0(100) < 75)
723- {
724- image_monster(ap, cp);
725- }
726-
727- /* Otherwise, assume objects */
728- else
729- {
730- image_object(ap, cp);
731- }
732-}
733-
734-/*!
735- * 照明の表現を行うための色合いの関係を{暗闇時, 照明時} で定義する /
736- * This array lists the effects of "brightness" on various "base" colours.\n
737- *\n
738- * This is used to do dynamic lighting effects in ascii :-)\n
739- * At the moment, only the various "floor" tiles are affected.\n
740- *\n
741- * The layout of the array is [x][0] = light and [x][1] = dark.\n
742- */
743-static TERM_COLOR lighting_colours[16][2] =
744-{
745- /* TERM_DARK */
746- {TERM_L_DARK, TERM_DARK},
747-
748- /* TERM_WHITE */
749- {TERM_YELLOW, TERM_SLATE},
750-
751- /* TERM_SLATE */
752- {TERM_WHITE, TERM_L_DARK},
753-
754- /* TERM_ORANGE */
755- {TERM_L_UMBER, TERM_UMBER},
756-
757- /* TERM_RED */
758- {TERM_RED, TERM_RED},
759-
760- /* TERM_GREEN */
761- {TERM_L_GREEN, TERM_GREEN},
762-
763- /* TERM_BLUE */
764- {TERM_BLUE, TERM_BLUE},
765-
766- /* TERM_UMBER */
767- {TERM_L_UMBER, TERM_RED},
768-
769- /* TERM_L_DARK */
770- {TERM_SLATE, TERM_L_DARK},
771-
772- /* TERM_L_WHITE */
773- {TERM_WHITE, TERM_SLATE},
774-
775- /* TERM_VIOLET */
776- {TERM_L_RED, TERM_BLUE},
777-
778- /* TERM_YELLOW */
779- {TERM_YELLOW, TERM_ORANGE},
780-
781- /* TERM_L_RED */
782- {TERM_L_RED, TERM_L_RED},
783-
784- /* TERM_L_GREEN */
785- {TERM_L_GREEN, TERM_GREEN},
786-
787- /* TERM_L_BLUE */
788- {TERM_L_BLUE, TERM_L_BLUE},
789-
790- /* TERM_L_UMBER */
791- {TERM_L_UMBER, TERM_UMBER}
792-};
793-
794-/*!
795- * @brief 調査中
796- * @todo コメントを付加すること
797- */
798-void apply_default_feat_lighting(TERM_COLOR f_attr[F_LIT_MAX], SYMBOL_CODE f_char[F_LIT_MAX])
799-{
800- TERM_COLOR s_attr = f_attr[F_LIT_STANDARD];
801- SYMBOL_CODE s_char = f_char[F_LIT_STANDARD];
802- int i;
803-
804- if (is_ascii_graphics(s_attr)) /* For ASCII */
805- {
806- f_attr[F_LIT_LITE] = lighting_colours[s_attr & 0x0f][0];
807- f_attr[F_LIT_DARK] = lighting_colours[s_attr & 0x0f][1];
808- for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) f_char[i] = s_char;
809- }
810- else /* For tile graphics */
811- {
812- for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) f_attr[i] = s_attr;
813- f_char[F_LIT_LITE] = s_char + 2;
814- f_char[F_LIT_DARK] = s_char + 1;
815- }
816-}
817-
818-
819-/*!
820- * モンスターにより照明が消されている地形か否かを判定する。 / Is this grid "darkened" by monster?
821- */
822-#define darkened_grid(C) \
823- ((((C)->info & (CAVE_VIEW | CAVE_LITE | CAVE_MNLT | CAVE_MNDK)) == (CAVE_VIEW | CAVE_MNDK)) && \
824- !p_ptr->see_nocto)
825-
826-
827-/*!
828- * @brief Mコマンドによる縮小マップの表示を行う / Extract the attr/char to display at the given (legal) map location
829- * @details
830- * Basically, we "paint" the chosen attr/char in several passes, starting\n
831- * with any known "terrain features" (defaulting to darkness), then adding\n
832- * any known "objects", and finally, adding any known "monsters". This\n
833- * is not the fastest method but since most of the calls to this function\n
834- * are made for grids with no monsters or objects, it is fast enough.\n
835- *\n
836- * Note that this function, if used on the grid containing the "player",\n
837- * will return the attr/char of the grid underneath the player, and not\n
838- * the actual player attr/char itself, allowing a lot of optimization\n
839- * in various "display" functions.\n
840- *\n
841- * Note that the "zero" entry in the feature/object/monster arrays are\n
842- * used to provide "special" attr/char codes, with "monster zero" being\n
843- * used for the player attr/char, "object zero" being used for the "stack"\n
844- * attr/char, and "feature zero" being used for the "nothing" attr/char,\n
845- * though this function makes use of only "feature zero".\n
846- *\n
847- * Note that monsters can have some "special" flags, including "ATTR_MULTI",\n
848- * which means their color changes, and "ATTR_CLEAR", which means they take\n
849- * the color of whatever is under them, and "CHAR_CLEAR", which means that\n
850- * they take the symbol of whatever is under them. Technically, the flag\n
851- * "CHAR_MULTI" is supposed to indicate that a monster looks strange when\n
852- * examined, but this flag is currently ignored.\n
853- *\n
854- * Currently, we do nothing with multi-hued objects, because there are\n
855- * not any. If there were, they would have to set "shimmer_objects"\n
856- * when they were created, and then new "shimmer" code in "dungeon.c"\n
857- * would have to be created handle the "shimmer" effect, and the code\n
858- * in "grid_array.c" would have to be updated to create the shimmer effect.\n
859- *\n
860- * Note the effects of hallucination. Objects always appear as random\n
861- * "objects", monsters as random "monsters", and normal grids occasionally\n
862- * appear as random "monsters" or "objects", but note that these random\n
863- * "monsters" and "objects" are really just "colored ascii symbols".\n
864- *\n
865- * Note that "floors" and "invisible traps" (and "zero" features) are\n
866- * drawn as "floors" using a special check for optimization purposes,\n
867- * and these are the only features which get drawn using the special\n
868- * lighting effects activated by "view_special_lite".\n
869- *\n
870- * Note the use of the "mimic" field in the "terrain feature" processing,\n
871- * which allows any feature to "pretend" to be another feature. This is\n
872- * used to "hide" secret doors, and to make all "doors" appear the same,\n
873- * and all "walls" appear the same, and "hidden" treasure stay hidden.\n
874- * It is possible to use this field to make a feature "look" like a floor,\n
875- * but the "special lighting effects" for floors will not be used.\n
876- *\n
877- * Note the use of the new "terrain feature" information. Note that the\n
878- * assumption that all interesting "objects" and "terrain features" are\n
879- * memorized allows extremely optimized processing below. Note the use\n
880- * of separate flags on objects to mark them as memorized allows a grid\n
881- * to have memorized "terrain" without granting knowledge of any object\n
882- * which may appear in that grid.\n
883- *\n
884- * Note the efficient code used to determine if a "floor" grid is\n
885- * "memorized" or "viewable" by the player, where the test for the\n
886- * grid being "viewable" is based on the facts that (1) the grid\n
887- * must be "lit" (torch-lit or perma-lit), (2) the grid must be in\n
888- * line of sight, and (3) the player must not be blind, and uses the\n
889- * assumption that all torch-lit grids are in line of sight.\n
890- *\n
891- * Note that floors (and invisible traps) are the only grids which are\n
892- * not memorized when seen, so only these grids need to check to see if\n
893- * the grid is "viewable" to the player (if it is not memorized). Since\n
894- * most non-memorized grids are in fact walls, this induces *massive*\n
895- * efficiency, at the cost of *forcing* the memorization of non-floor\n
896- * grids when they are first seen. Note that "invisible traps" are\n
897- * always treated exactly like "floors", which prevents "cheating".\n
898- *\n
899- * Note the "special lighting effects" which can be activated for floor\n
900- * grids using the "view_special_lite" option (for "white" floor grids),\n
901- * causing certain grids to be displayed using special colors. If the\n
902- * player is "blind", we will use "dark gray", else if the grid is lit\n
903- * by the torch, and the "view_yellow_lite" option is set, we will use\n
904- * "yellow", else if the grid is "dark", we will use "dark gray", else\n
905- * if the grid is not "viewable", and the "view_bright_lite" option is\n
906- * set, and the we will use "slate" (gray). We will use "white" for all\n
907- * other cases, in particular, for illuminated viewable floor grids.\n
908- *\n
909- * Note the "special lighting effects" which can be activated for wall\n
910- * grids using the "view_granite_lite" option (for "white" wall grids),\n
911- * causing certain grids to be displayed using special colors. If the\n
912- * player is "blind", we will use "dark gray", else if the grid is lit\n
913- * by the torch, and the "view_yellow_lite" option is set, we will use\n
914- * "yellow", else if the "view_bright_lite" option is set, and the grid\n
915- * is not "viewable", or is "dark", or is glowing, but not when viewed\n
916- * from the player's current location, we will use "slate" (gray). We\n
917- * will use "white" for all other cases, in particular, for correctly\n
918- * illuminated viewable wall grids.\n
919- *\n
920- * Note that, when "view_granite_lite" is set, we use an inline version\n
921- * of the "player_can_see_bold()" function to check the "viewability" of\n
922- * grids when the "view_bright_lite" option is set, and we do NOT use\n
923- * any special colors for "dark" wall grids, since this would allow the\n
924- * player to notice the walls of illuminated rooms from a hallway that\n
925- * happened to run beside the room. The alternative, by the way, would\n
926- * be to prevent the generation of hallways next to rooms, but this\n
927- * would still allow problems when digging towards a room.\n
928- *\n
929- * Note that bizarre things must be done when the "attr" and/or "char"\n
930- * codes have the "high-bit" set, since these values are used to encode\n
931- * various "special" pictures in some versions, and certain situations,\n
932- * such as "multi-hued" or "clear" monsters, cause the attr/char codes\n
933- * to be "scrambled" in various ways.\n
934- *\n
935- * Note that eventually we may use the "&" symbol for embedded treasure,\n
936- * and use the "*" symbol to indicate multiple objects, though this will\n
937- * have to wait for Angband 2.8.0 or later. Note that currently, this\n
938- * is not important, since only one object or terrain feature is allowed\n
939- * in each grid. If needed, "k_info[0]" will hold the "stack" attr/char.\n
940- *\n
941- * Note the assumption that doing "x_ptr = &x_info[x]" plus a few of\n
942- * "x_ptr->xxx", is quicker than "x_info[x].xxx", if this is incorrect\n
943- * then a whole lot of code should be changed... XXX XXX\n
944- */
945-void map_info(POSITION y, POSITION x, TERM_COLOR *ap, SYMBOL_CODE *cp, TERM_COLOR *tap, SYMBOL_CODE *tcp)
946-{
947- /* Get the grid_array */
948- grid_type *g_ptr = &grid_array[y][x];
949-
950- OBJECT_IDX this_o_idx, next_o_idx = 0;
951-
952- /* Feature code (applying "mimic" field) */
953- FEAT_IDX feat = get_feat_mimic(g_ptr);
954-
955- /* Access floor */
956- feature_type *f_ptr = &f_info[feat];
957-
958- TERM_COLOR a;
959- SYMBOL_CODE c;
960-
961- /* Boring grids (floors, etc) */
962- if (!have_flag(f_ptr->flags, FF_REMEMBER))
963- {
964- /*
965- * Handle Memorized or visible floor
966- *
967- * No visual when blinded.
968- * (to prevent strange effects on darkness breath)
969- * otherwise,
970- * - Can see grids with CAVE_MARK.
971- * - Can see grids with CAVE_LITE or CAVE_MNLT.
972- * (Such grids also have CAVE_VIEW)
973- * - Can see grids with CAVE_VIEW unless darkened by monsters.
974- */
975- if (!p_ptr->blind &&
976- ((g_ptr->info & (CAVE_MARK | CAVE_LITE | CAVE_MNLT)) ||
977- ((g_ptr->info & CAVE_VIEW) && (((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) || p_ptr->see_nocto))))
978- {
979- /* Normal attr/char */
980- a = f_ptr->x_attr[F_LIT_STANDARD];
981- c = f_ptr->x_char[F_LIT_STANDARD];
982-
983- if (p_ptr->wild_mode)
984- {
985- /* Special lighting effects */
986- /* Handle "night" */
987- if (view_special_lite && !is_daytime())
988- {
989- /* Use a darkened colour/tile */
990- a = f_ptr->x_attr[F_LIT_DARK];
991- c = f_ptr->x_char[F_LIT_DARK];
992- }
993- }
994-
995- /* Mega-Hack -- Handle "in-sight" and "darkened" grids */
996- else if (darkened_grid(g_ptr))
997- {
998- /* Unsafe grid -- idea borrowed from Unangband */
999- feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
1000-
1001- /* Access darkness */
1002- f_ptr = &f_info[feat];
1003-
1004- /* Char and attr of darkness */
1005- a = f_ptr->x_attr[F_LIT_STANDARD];
1006- c = f_ptr->x_char[F_LIT_STANDARD];
1007- }
1008-
1009- /* Special lighting effects */
1010- else if (view_special_lite)
1011- {
1012- /* Handle "torch-lit" grids */
1013- if (g_ptr->info & (CAVE_LITE | CAVE_MNLT))
1014- {
1015- /* Torch lite */
1016- if (view_yellow_lite)
1017- {
1018- /* Use a brightly lit colour/tile */
1019- a = f_ptr->x_attr[F_LIT_LITE];
1020- c = f_ptr->x_char[F_LIT_LITE];
1021- }
1022- }
1023-
1024- /* Handle "dark" grids */
1025- else if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
1026- {
1027- /* Use a darkened colour/tile */
1028- a = f_ptr->x_attr[F_LIT_DARK];
1029- c = f_ptr->x_char[F_LIT_DARK];
1030- }
1031-
1032- /* Handle "out-of-sight" grids */
1033- else if (!(g_ptr->info & CAVE_VIEW))
1034- {
1035- /* Special flag */
1036- if (view_bright_lite)
1037- {
1038- /* Use a darkened colour/tile */
1039- a = f_ptr->x_attr[F_LIT_DARK];
1040- c = f_ptr->x_char[F_LIT_DARK];
1041- }
1042- }
1043- }
1044- }
1045-
1046- /* Unknown */
1047- else
1048- {
1049- /* Unsafe grid -- idea borrowed from Unangband */
1050- feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
1051-
1052- /* Access darkness */
1053- f_ptr = &f_info[feat];
1054-
1055- /* Normal attr/char */
1056- a = f_ptr->x_attr[F_LIT_STANDARD];
1057- c = f_ptr->x_char[F_LIT_STANDARD];
1058- }
1059- }
1060-
1061- /* Interesting grids (non-floors) */
1062- else
1063- {
1064- /* Memorized grids */
1065- if (g_ptr->info & CAVE_MARK)
1066- {
1067- /* Normal attr/char */
1068- a = f_ptr->x_attr[F_LIT_STANDARD];
1069- c = f_ptr->x_char[F_LIT_STANDARD];
1070-
1071- if (p_ptr->wild_mode)
1072- {
1073- /* Special lighting effects */
1074- /* Handle "blind" or "night" */
1075- if (view_granite_lite && (p_ptr->blind || !is_daytime()))
1076- {
1077- /* Use a darkened colour/tile */
1078- a = f_ptr->x_attr[F_LIT_DARK];
1079- c = f_ptr->x_char[F_LIT_DARK];
1080- }
1081- }
1082-
1083- /* Mega-Hack -- Handle "in-sight" and "darkened" grids */
1084- else if (darkened_grid(g_ptr) && !p_ptr->blind)
1085- {
1086- if (have_flag(f_ptr->flags, FF_LOS) && have_flag(f_ptr->flags, FF_PROJECT))
1087- {
1088- /* Unsafe grid -- idea borrowed from Unangband */
1089- feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
1090-
1091- /* Access darkness */
1092- f_ptr = &f_info[feat];
1093-
1094- /* Char and attr of darkness */
1095- a = f_ptr->x_attr[F_LIT_STANDARD];
1096- c = f_ptr->x_char[F_LIT_STANDARD];
1097- }
1098- else if (view_granite_lite && view_bright_lite)
1099- {
1100- /* Use a darkened colour/tile */
1101- a = f_ptr->x_attr[F_LIT_DARK];
1102- c = f_ptr->x_char[F_LIT_DARK];
1103- }
1104- }
1105-
1106- /* Special lighting effects */
1107- else if (view_granite_lite)
1108- {
1109- /* Handle "blind" */
1110- if (p_ptr->blind)
1111- {
1112- /* Use a darkened colour/tile */
1113- a = f_ptr->x_attr[F_LIT_DARK];
1114- c = f_ptr->x_char[F_LIT_DARK];
1115- }
1116-
1117- /* Handle "torch-lit" grids */
1118- else if (g_ptr->info & (CAVE_LITE | CAVE_MNLT))
1119- {
1120- /* Torch lite */
1121- if (view_yellow_lite)
1122- {
1123- /* Use a brightly lit colour/tile */
1124- a = f_ptr->x_attr[F_LIT_LITE];
1125- c = f_ptr->x_char[F_LIT_LITE];
1126- }
1127- }
1128-
1129- /* Handle "view_bright_lite" */
1130- else if (view_bright_lite)
1131- {
1132- /* Not viewable */
1133- if (!(g_ptr->info & CAVE_VIEW))
1134- {
1135- /* Use a darkened colour/tile */
1136- a = f_ptr->x_attr[F_LIT_DARK];
1137- c = f_ptr->x_char[F_LIT_DARK];
1138- }
1139-
1140- /* Not glowing */
1141- else if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
1142- {
1143- /* Use a darkened colour/tile */
1144- a = f_ptr->x_attr[F_LIT_DARK];
1145- c = f_ptr->x_char[F_LIT_DARK];
1146- }
1147-
1148- /* Not glowing correctly */
1149- else if (!have_flag(f_ptr->flags, FF_LOS) && !check_local_illumination(y, x))
1150- {
1151- /* Use a darkened colour/tile */
1152- a = f_ptr->x_attr[F_LIT_DARK];
1153- c = f_ptr->x_char[F_LIT_DARK];
1154- }
1155- }
1156- }
1157- }
1158-
1159- /* Unknown */
1160- else
1161- {
1162- /* Unsafe grid -- idea borrowed from Unangband */
1163- feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
1164-
1165- /* Access feature */
1166- f_ptr = &f_info[feat];
1167-
1168- /* Normal attr/char */
1169- a = f_ptr->x_attr[F_LIT_STANDARD];
1170- c = f_ptr->x_char[F_LIT_STANDARD];
1171- }
1172- }
1173-
1174- if (feat_priority == -1) feat_priority = f_ptr->priority;
1175-
1176- /* Save the terrain info for the transparency effects */
1177- (*tap) = a;
1178- (*tcp) = c;
1179-
1180- /* Save the info */
1181- (*ap) = a;
1182- (*cp) = c;
1183-
1184- /* Hack -- rare random hallucination, except on outer dungeon walls */
1185- if (p_ptr->image)
1186- {
1187- if (one_in_(256))
1188- {
1189- /* Hallucinate */
1190- image_random(ap, cp);
1191- }
1192- }
1193-
1194- /* Objects */
1195- for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1196- {
1197- object_type *o_ptr;
1198- o_ptr = &o_list[this_o_idx];
1199-
1200- /* Acquire next object */
1201- next_o_idx = o_ptr->next_o_idx;
1202-
1203- /* Memorized objects */
1204- if (o_ptr->marked & OM_FOUND)
1205- {
1206- if (display_autopick)
1207- {
1208- byte act;
1209-
1210- match_autopick = is_autopick(o_ptr);
1211- if(match_autopick == -1)
1212- continue;
1213-
1214- act = autopick_list[match_autopick].action;
1215-
1216- if ((act & DO_DISPLAY) && (act & display_autopick))
1217- {
1218- autopick_obj = o_ptr;
1219- }
1220- else
1221- {
1222- match_autopick = -1;
1223- continue;
1224- }
1225- }
1226- /* Normal char */
1227- (*cp) = object_char(o_ptr);
1228-
1229- /* Normal attr */
1230- (*ap) = object_attr(o_ptr);
1231-
1232- feat_priority = 20;
1233-
1234- /* Hack -- hallucination */
1235- if (p_ptr->image) image_object(ap, cp);
1236-
1237- break;
1238- }
1239- }
1240-
1241-
1242- /* Handle monsters */
1243- if (g_ptr->m_idx && display_autopick == 0 )
1244- {
1245- monster_type *m_ptr = &m_list[g_ptr->m_idx];
1246-
1247- /* Visible monster */
1248- if (m_ptr->ml)
1249- {
1250- monster_race *r_ptr = &r_info[m_ptr->ap_r_idx];
1251-
1252- feat_priority = 30;
1253-
1254- /* Hallucination */
1255- if (p_ptr->image)
1256- {
1257- /*
1258- * Monsters with both CHAR_CLEAR and ATTR_CLEAR
1259- * flags are always unseen.
1260- */
1261- if ((r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) == (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR))
1262- {
1263- /* Do nothing */
1264- }
1265- else
1266- {
1267- /* Hallucinatory monster */
1268- image_monster(ap, cp);
1269- }
1270- }
1271- else
1272- {
1273- /* Monster attr/char */
1274- a = r_ptr->x_attr;
1275- c = r_ptr->x_char;
1276-
1277- /* Normal monsters */
1278- if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_SHAPECHANGER | RF1_ATTR_CLEAR
1279- | RF1_ATTR_MULTI | RF1_ATTR_SEMIRAND)))
1280- {
1281- /* Desired monster attr/char */
1282- *ap = a;
1283- *cp = c;
1284- }
1285-
1286- /*
1287- * Monsters with both CHAR_CLEAR and ATTR_CLEAR
1288- * flags are always unseen.
1289- */
1290- else if ((r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) == (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR))
1291- {
1292- /* Do nothing */
1293- }
1294-
1295- else
1296- {
1297- /*** Monster's attr ***/
1298- if ((r_ptr->flags1 & RF1_ATTR_CLEAR) && (*ap != TERM_DARK) && !use_graphics)
1299- {
1300- /* Clear-attr */
1301- /* Do nothing */
1302- }
1303- else if ((r_ptr->flags1 & RF1_ATTR_MULTI) && !use_graphics)
1304- {
1305- /* Multi-hued attr */
1306- if (r_ptr->flags2 & RF2_ATTR_ANY) *ap = randint1(15);
1307- else switch (randint1(7))
1308- {
1309- case 1: *ap = TERM_RED; break;
1310- case 2: *ap = TERM_L_RED; break;
1311- case 3: *ap = TERM_WHITE; break;
1312- case 4: *ap = TERM_L_GREEN; break;
1313- case 5: *ap = TERM_BLUE; break;
1314- case 6: *ap = TERM_L_DARK; break;
1315- case 7: *ap = TERM_GREEN; break;
1316- }
1317- }
1318- else if ((r_ptr->flags1 & RF1_ATTR_SEMIRAND) && !use_graphics)
1319- {
1320- /* Use semi-random attr (usually mimics' colors vary) */
1321- *ap = g_ptr->m_idx % 15 + 1;
1322- }
1323- else
1324- {
1325- /* Normal case */
1326- *ap = a;
1327- }
1328-
1329- /*** Monster's char ***/
1330- if ((r_ptr->flags1 & RF1_CHAR_CLEAR) && (*cp != ' ') && !use_graphics)
1331- {
1332- /* Clear-char */
1333- /* Do nothing */
1334- }
1335- else if (r_ptr->flags1 & RF1_SHAPECHANGER)
1336- {
1337- if (use_graphics)
1338- {
1339- monster_race *tmp_r_ptr = &r_info[randint1(max_r_idx - 1)];
1340- *cp = tmp_r_ptr->x_char;
1341- *ap = tmp_r_ptr->x_attr;
1342- }
1343- else
1344- {
1345- *cp = (one_in_(25) ?
1346- image_object_hack[randint0(sizeof(image_object_hack) - 1)] :
1347- image_monster_hack[randint0(sizeof(image_monster_hack) - 1)]);
1348- }
1349- }
1350- else
1351- {
1352- /* Normal case */
1353- *cp = c;
1354- }
1355- }
1356- }
1357- }
1358- }
1359-
1360- /* Handle "player" */
1361- if (player_bold(y, x))
1362- {
1363- monster_race *r_ptr = &r_info[0];
1364- *ap = r_ptr->x_attr;
1365- *cp = r_ptr->x_char;
1366- feat_priority = 31;
1367- }
1368-}
1369-
1370-
1371-/*
1372- * Calculate panel colum of a location in the map
1373- */
1374-static int panel_col_of(int col)
1375-{
1376- col -= panel_col_min;
1377- if (use_bigtile) col *= 2;
1378- return col + 13;
1379-}
1380-
1381-
1382-/*
1383- * Moves the cursor to a given MAP (y,x) location
1384- */
1385-void move_cursor_relative(int row, int col)
1386-{
1387- /* Real co-ords convert to screen positions */
1388- row -= panel_row_prt;
1389-
1390- /* Go there */
1391- Term_gotoxy(panel_col_of(col), row);
1392-}
1393-
1394-
1395-
1396-/*
1397- * Place an attr/char pair at the given map coordinate, if legal.
1398- */
1399-void print_rel(SYMBOL_CODE c, TERM_COLOR a, TERM_LEN y, TERM_LEN x)
1400-{
1401- /* Only do "legal" locations */
1402- if (panel_contains(y, x))
1403- {
1404- /* Hack -- fake monochrome */
1405- if (!use_graphics)
1406- {
1407- if (world_monster) a = TERM_DARK;
1408- else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
1409- else if (p_ptr->wraith_form) a = TERM_L_DARK;
1410- }
1411-
1412- /* Draw the char using the attr */
1413- Term_queue_bigchar(panel_col_of(x), y-panel_row_prt, a, c, 0, 0);
1414- }
1415-}
1416-
1417-
1418-
1419-
1420-
1421-/*
1422- * Memorize interesting viewable object/features in the given grid
1423- *
1424- * This function should only be called on "legal" grids.
1425- *
1426- * This function will memorize the object and/or feature in the given
1427- * grid, if they are (1) viewable and (2) interesting. Note that all
1428- * objects are interesting, all terrain features except floors (and
1429- * invisible traps) are interesting, and floors (and invisible traps)
1430- * are interesting sometimes (depending on various options involving
1431- * the illumination of floor grids).
1432- *
1433- * The automatic memorization of all objects and non-floor terrain
1434- * features as soon as they are displayed allows incredible amounts
1435- * of optimization in various places, especially "map_info()".
1436- *
1437- * Note that the memorization of objects is completely separate from
1438- * the memorization of terrain features, preventing annoying floor
1439- * memorization when a detected object is picked up from a dark floor,
1440- * and object memorization when an object is dropped into a floor grid
1441- * which is memorized but out-of-sight.
1442- *
1443- * This function should be called every time the "memorization" of
1444- * a grid (or the object in a grid) is called into question, such
1445- * as when an object is created in a grid, when a terrain feature
1446- * "changes" from "floor" to "non-floor", when any grid becomes
1447- * "illuminated" or "viewable", and when a "floor" grid becomes
1448- * "torch-lit".
1449- *
1450- * Note the relatively efficient use of this function by the various
1451- * "update_view()" and "update_lite()" calls, to allow objects and
1452- * terrain features to be memorized (and drawn) whenever they become
1453- * viewable or illuminated in any way, but not when they "maintain"
1454- * or "lose" their previous viewability or illumination.
1455- *
1456- * Note the butchered "internal" version of "player_can_see_bold()",
1457- * optimized primarily for the most common cases, that is, for the
1458- * non-marked floor grids.
1459- */
1460-void note_spot(POSITION y, POSITION x)
1461-{
1462- grid_type *g_ptr = &grid_array[y][x];
1463- OBJECT_IDX this_o_idx, next_o_idx = 0;
1464-
1465- /* Blind players see nothing */
1466- if (p_ptr->blind) return;
1467-
1468- /* Analyze non-torch-lit grids */
1469- if (!(g_ptr->info & (CAVE_LITE | CAVE_MNLT)))
1470- {
1471- /* Require line of sight to the grid */
1472- if (!(g_ptr->info & (CAVE_VIEW))) return;
1473-
1474- /* Require "perma-lite" of the grid */
1475- if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
1476- {
1477- /* Not Ninja */
1478- if (!p_ptr->see_nocto) return;
1479- }
1480- }
1481-
1482-
1483- /* Hack -- memorize objects */
1484- for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1485- {
1486- object_type *o_ptr = &o_list[this_o_idx];
1487-
1488- /* Acquire next object */
1489- next_o_idx = o_ptr->next_o_idx;
1490-
1491- /* Memorize objects */
1492- o_ptr->marked |= OM_FOUND;
1493- }
1494-
1495-
1496- /* Hack -- memorize grids */
1497- if (!(g_ptr->info & (CAVE_MARK)))
1498- {
1499- /* Feature code (applying "mimic" field) */
1500- feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)];
1501-
1502- /* Memorize some "boring" grids */
1503- if (!have_flag(f_ptr->flags, FF_REMEMBER))
1504- {
1505- /* Option -- memorize all torch-lit floors */
1506- if (view_torch_grids &&
1507- ((g_ptr->info & (CAVE_LITE | CAVE_MNLT)) || p_ptr->see_nocto))
1508- {
1509- g_ptr->info |= (CAVE_MARK);
1510- }
1511-
1512- /* Option -- memorize all perma-lit floors */
1513- else if (view_perma_grids && ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW))
1514- {
1515- g_ptr->info |= (CAVE_MARK);
1516- }
1517- }
1518-
1519- /* Memorize normal grids */
1520- else if (have_flag(f_ptr->flags, FF_LOS))
1521- {
1522- g_ptr->info |= (CAVE_MARK);
1523- }
1524-
1525- /* Memorize torch-lit walls */
1526- else if (g_ptr->info & (CAVE_LITE | CAVE_MNLT))
1527- {
1528- g_ptr->info |= (CAVE_MARK);
1529- }
1530-
1531- /* Memorize walls seen by noctovision of Ninja */
1532- else if (p_ptr->see_nocto)
1533- {
1534- g_ptr->info |= (CAVE_MARK);
1535- }
1536-
1537- /* Memorize certain non-torch-lit wall grids */
1538- else if (check_local_illumination(y, x))
1539- {
1540- g_ptr->info |= (CAVE_MARK);
1541- }
1542- }
1543-
1544- /* Memorize terrain of the grid */
1545- g_ptr->info |= (CAVE_KNOWN);
1546-}
1547-
1548-
1549-void display_dungeon(void)
1550-{
1551- TERM_LEN x, y;
1552- TERM_COLOR a;
1553- SYMBOL_CODE c;
1554-
1555- TERM_COLOR ta = 0;
1556- SYMBOL_CODE tc = '\0';
1557-
1558- for (x = p_ptr->x - Term->wid / 2 + 1; x <= p_ptr->x + Term->wid / 2; x++)
1559- {
1560- for (y = p_ptr->y - Term->hgt / 2 + 1; y <= p_ptr->y + Term->hgt / 2; y++)
1561- {
1562- if (in_bounds2(y, x))
1563- {
1564-
1565- /* Examine the grid */
1566- map_info(y, x, &a, &c, &ta, &tc);
1567-
1568- /* Hack -- fake monochrome */
1569- if (!use_graphics)
1570- {
1571- if (world_monster) a = TERM_DARK;
1572- else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
1573- else if (p_ptr->wraith_form) a = TERM_L_DARK;
1574- }
1575-
1576- /* Hack -- Queue it */
1577- Term_queue_char(x - p_ptr->x + Term->wid / 2 - 1, y - p_ptr->y + Term->hgt / 2 - 1, a, c, ta, tc);
1578- }
1579- else
1580- {
1581- /* Clear out-of-bound tiles */
1582-
1583- /* Access darkness */
1584- feature_type *f_ptr = &f_info[feat_none];
1585-
1586- /* Normal attr */
1587- a = f_ptr->x_attr[F_LIT_STANDARD];
1588-
1589- /* Normal char */
1590- c = f_ptr->x_char[F_LIT_STANDARD];
1591-
1592- /* Hack -- Queue it */
1593- Term_queue_char(x - p_ptr->x + Term->wid / 2 - 1, y - p_ptr->y + Term->hgt / 2 - 1, a, c, ta, tc);
1594- }
1595- }
1596- }
1597-}
1598-
1599-
1600-/*
1601- * Redraw (on the screen) a given MAP location
1602- *
1603- * This function should only be called on "legal" grids
1604- */
1605-void lite_spot(POSITION y, POSITION x)
1606-{
1607- /* Redraw if on screen */
1608- if (panel_contains(y, x) && in_bounds2(y, x))
1609- {
1610- TERM_COLOR a;
1611- SYMBOL_CODE c;
1612-
1613- TERM_COLOR ta;
1614- SYMBOL_CODE tc;
1615-
1616- /* Examine the grid */
1617- map_info(y, x, &a, &c, &ta, &tc);
1618-
1619- /* Hack -- fake monochrome */
1620- if (!use_graphics)
1621- {
1622- if (world_monster) a = TERM_DARK;
1623- else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
1624- else if (p_ptr->wraith_form) a = TERM_L_DARK;
1625- }
1626-
1627- /* Hack -- Queue it */
1628- Term_queue_bigchar(panel_col_of(x), y-panel_row_prt, a, c, ta, tc);
1629-
1630- /* Update sub-windows */
1631- p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1632- }
1633-}
1634-
1635-
1636-/*
1637- * Prints the map of the dungeon
1638- *
1639- * Note that, for efficiency, we contain an "optimized" version
1640- * of both "lite_spot()" and "print_rel()", and that we use the
1641- * "lite_spot()" function to display the player grid, if needed.
1642- */
1643-void prt_map(void)
1644-{
1645- POSITION x, y;
1646- int v;
1647-
1648- /* map bounds */
1649- POSITION xmin, xmax, ymin, ymax;
1650-
1651- TERM_LEN wid, hgt;
1652-
1653- Term_get_size(&wid, &hgt);
1654-
1655- /* Remove map offset */
1656- wid -= COL_MAP + 2;
1657- hgt -= ROW_MAP + 2;
1658-
1659- /* Access the cursor state */
1660- (void)Term_get_cursor(&v);
1661-
1662- /* Hide the cursor */
1663- (void)Term_set_cursor(0);
1664-
1665- /* Get bounds */
1666- xmin = (0 < panel_col_min) ? panel_col_min : 0;
1667- xmax = (cur_wid - 1 > panel_col_max) ? panel_col_max : cur_wid - 1;
1668- ymin = (0 < panel_row_min) ? panel_row_min : 0;
1669- ymax = (cur_hgt - 1 > panel_row_max) ? panel_row_max : cur_hgt - 1;
1670-
1671- /* Bottom section of screen */
1672- for (y = 1; y <= ymin - panel_row_prt; y++)
1673- {
1674- /* Erase the section */
1675- Term_erase(COL_MAP, y, wid);
1676- }
1677-
1678- /* Top section of screen */
1679- for (y = ymax - panel_row_prt; y <= hgt; y++)
1680- {
1681- /* Erase the section */
1682- Term_erase(COL_MAP, y, wid);
1683- }
1684-
1685- /* Dump the map */
1686- for (y = ymin; y <= ymax; y++)
1687- {
1688- /* Scan the columns of row "y" */
1689- for (x = xmin; x <= xmax; x++)
1690- {
1691- TERM_COLOR a;
1692- SYMBOL_CODE c;
1693-
1694- TERM_COLOR ta;
1695- SYMBOL_CODE tc;
1696-
1697- /* Determine what is there */
1698- map_info(y, x, &a, &c, &ta, &tc);
1699-
1700- /* Hack -- fake monochrome */
1701- if (!use_graphics)
1702- {
1703- if (world_monster) a = TERM_DARK;
1704- else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
1705- else if (p_ptr->wraith_form) a = TERM_L_DARK;
1706- }
1707-
1708- /* Efficiency -- Redraw that grid of the map */
1709- Term_queue_bigchar(panel_col_of(x), y-panel_row_prt, a, c, ta, tc);
1710- }
1711- }
1712-
1713- /* Display player */
1714- lite_spot(p_ptr->y, p_ptr->x);
1715-
1716- /* Restore the cursor */
1717- (void)Term_set_cursor(v);
1718-}
1719-
1720-
1721-
1722-/*
1723- * print project path
1724- */
1725-void prt_path(POSITION y, POSITION x)
1726-{
1727- int i;
1728- int path_n;
1729- u16b path_g[512];
1730- byte_hack default_color = TERM_SLATE;
1731-
1732- if (!display_path) return;
1733- if (-1 == project_length)
1734- return;
1735-
1736- /* Get projection path */
1737- path_n = project_path(path_g, (project_length ? project_length : MAX_RANGE), p_ptr->y, p_ptr->x, y, x, PROJECT_PATH|PROJECT_THRU);
1738-
1739- p_ptr->redraw |= (PR_MAP);
1740- handle_stuff();
1741-
1742- /* Draw path */
1743- for (i = 0; i < path_n; i++)
1744- {
1745- POSITION ny = GRID_Y(path_g[i]);
1746- POSITION nx = GRID_X(path_g[i]);
1747- grid_type *g_ptr = &grid_array[ny][nx];
1748-
1749- if (panel_contains(ny, nx))
1750- {
1751- TERM_COLOR a = default_color;
1752- char c;
1753-
1754- TERM_COLOR ta = default_color;
1755- char tc = '*';
1756-
1757- if (g_ptr->m_idx && m_list[g_ptr->m_idx].ml)
1758- {
1759- /* Determine what is there */
1760- map_info(ny, nx, &a, &c, &ta, &tc);
1761-
1762- if (!is_ascii_graphics(a))
1763- a = default_color;
1764- else if (c == '.' && (a == TERM_WHITE || a == TERM_L_WHITE))
1765- a = default_color;
1766- else if (a == default_color)
1767- a = TERM_WHITE;
1768- }
1769-
1770- if (!use_graphics)
1771- {
1772- if (world_monster) a = TERM_DARK;
1773- else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
1774- else if (p_ptr->wraith_form) a = TERM_L_DARK;
1775- }
1776-
1777- c = '*';
1778-
1779- /* Hack -- Queue it */
1780- Term_queue_bigchar(panel_col_of(nx), ny-panel_row_prt, a, c, ta, tc);
1781- }
1782-
1783- /* Known Wall */
1784- if ((g_ptr->info & CAVE_MARK) && !cave_have_flag_grid(g_ptr, FF_PROJECT)) break;
1785-
1786- /* Change color */
1787- if (nx == x && ny == y) default_color = TERM_L_DARK;
1788- }
1789-}
1790-
1791-
1792-static concptr simplify_list[][2] =
1793-{
1794-#ifdef JP
1795- {"の魔法書", ""},
1796- {NULL, NULL}
1797-#else
1798- {"^Ring of ", "="},
1799- {"^Amulet of ", "\""},
1800- {"^Scroll of ", "?"},
1801- {"^Scroll titled ", "?"},
1802- {"^Wand of " , "-"},
1803- {"^Rod of " , "-"},
1804- {"^Staff of " , "_"},
1805- {"^Potion of ", "!"},
1806- {" Spellbook ",""},
1807- {"^Book of ", ""},
1808- {" Magic [", "["},
1809- {" Book [", "["},
1810- {" Arts [", "["},
1811- {"^Set of ", ""},
1812- {"^Pair of ", ""},
1813- {NULL, NULL}
1814-#endif
1815-};
1816-
1817-static void display_shortened_item_name(object_type *o_ptr, int y)
1818-{
1819- char buf[MAX_NLEN];
1820- char *c = buf;
1821- int len = 0;
1822- TERM_COLOR attr;
1823-
1824- object_desc(buf, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NAME_ONLY));
1825- attr = tval_to_attr[o_ptr->tval % 128];
1826-
1827- if (p_ptr->image)
1828- {
1829- attr = TERM_WHITE;
1830- strcpy(buf, _("何か奇妙な物", "something strange"));
1831- }
1832-
1833- for (c = buf; *c; c++)
1834- {
1835- int i;
1836- for (i = 0; simplify_list[i][1]; i++)
1837- {
1838- concptr org_w = simplify_list[i][0];
1839-
1840- if (*org_w == '^')
1841- {
1842- if (c == buf)
1843- org_w++;
1844- else
1845- continue;
1846- }
1847-
1848- if (!strncmp(c, org_w, strlen(org_w)))
1849- {
1850- char *s = c;
1851- concptr tmp = simplify_list[i][1];
1852- while (*tmp)
1853- *s++ = *tmp++;
1854- tmp = c + strlen(org_w);
1855- while (*tmp)
1856- *s++ = *tmp++;
1857- *s = '\0';
1858- }
1859- }
1860- }
1861-
1862- c = buf;
1863- len = 0;
1864- /* 半角 12 文字分で切る */
1865- while(*c)
1866- {
1867-#ifdef JP
1868- if(iskanji(*c))
1869- {
1870- if(len + 2 > 12) break;
1871- c+=2;
1872- len+=2;
1873- }
1874- else
1875-#endif
1876- {
1877- if(len + 1 > 12) break;
1878- c++;
1879- len++;
1880- }
1881- }
1882- *c='\0';
1883- Term_putstr(0, y, 12, attr, buf);
1884-}
1885-
1886-/*
1887- * Display a "small-scale" map of the dungeon in the active Term
1888- */
1889-void display_map(int *cy, int *cx)
1890-{
1891- int i, j, x, y;
1892-
1893- TERM_COLOR ta;
1894- SYMBOL_CODE tc;
1895-
1896- byte tp;
1897-
1898- TERM_COLOR **bigma;
1899- SYMBOL_CODE **bigmc;
1900- byte **bigmp;
1901-
1902- TERM_COLOR **ma;
1903- SYMBOL_CODE **mc;
1904- byte **mp;
1905-
1906- /* Save lighting effects */
1907- bool old_view_special_lite = view_special_lite;
1908- bool old_view_granite_lite = view_granite_lite;
1909-
1910- TERM_LEN hgt, wid, yrat, xrat;
1911-
1912- int **match_autopick_yx;
1913- object_type ***object_autopick_yx;
1914-
1915- Term_get_size(&wid, &hgt);
1916- hgt -= 2;
1917- wid -= 14;
1918- if (use_bigtile) wid /= 2;
1919-
1920- yrat = (cur_hgt + hgt - 1) / hgt;
1921- xrat = (cur_wid + wid - 1) / wid;
1922-
1923- /* Disable lighting effects */
1924- view_special_lite = FALSE;
1925- view_granite_lite = FALSE;
1926-
1927- /* Allocate the maps */
1928- C_MAKE(ma, (hgt + 2), TERM_COLOR *);
1929- C_MAKE(mc, (hgt + 2), char_ptr);
1930- C_MAKE(mp, (hgt + 2), byte_ptr);
1931- C_MAKE(match_autopick_yx, (hgt + 2), sint_ptr);
1932- C_MAKE(object_autopick_yx, (hgt + 2), object_type **);
1933-
1934- /* Allocate and wipe each line map */
1935- for (y = 0; y < (hgt + 2); y++)
1936- {
1937- /* Allocate one row each array */
1938- C_MAKE(ma[y], (wid + 2), TERM_COLOR);
1939- C_MAKE(mc[y], (wid + 2), char);
1940- C_MAKE(mp[y], (wid + 2), byte);
1941- C_MAKE(match_autopick_yx[y], (wid + 2), int);
1942- C_MAKE(object_autopick_yx[y], (wid + 2), object_type *);
1943-
1944- for (x = 0; x < wid + 2; ++x)
1945- {
1946- match_autopick_yx[y][x] = -1;
1947- object_autopick_yx[y][x] = NULL;
1948-
1949- /* Nothing here */
1950- ma[y][x] = TERM_WHITE;
1951- mc[y][x] = ' ';
1952-
1953- /* No priority */
1954- mp[y][x] = 0;
1955- }
1956- }
1957-
1958- /* Allocate the maps */
1959- C_MAKE(bigma, (cur_hgt + 2), TERM_COLOR *);
1960- C_MAKE(bigmc, (cur_hgt + 2), char_ptr);
1961- C_MAKE(bigmp, (cur_hgt + 2), byte_ptr);
1962-
1963- /* Allocate and wipe each line map */
1964- for (y = 0; y < (cur_hgt + 2); y++)
1965- {
1966- /* Allocate one row each array */
1967- C_MAKE(bigma[y], (cur_wid + 2), TERM_COLOR);
1968- C_MAKE(bigmc[y], (cur_wid + 2), char);
1969- C_MAKE(bigmp[y], (cur_wid + 2), byte);
1970-
1971- for (x = 0; x < cur_wid + 2; ++x)
1972- {
1973- /* Nothing here */
1974- bigma[y][x] = TERM_WHITE;
1975- bigmc[y][x] = ' ';
1976-
1977- /* No priority */
1978- bigmp[y][x] = 0;
1979- }
1980- }
1981-
1982- /* Fill in the map */
1983- for (i = 0; i < cur_wid; ++i)
1984- {
1985- for (j = 0; j < cur_hgt; ++j)
1986- {
1987- x = i / xrat + 1;
1988- y = j / yrat + 1;
1989-
1990- match_autopick=-1;
1991- autopick_obj=NULL;
1992- feat_priority = -1;
1993-
1994- /* Extract the current attr/char at that map location */
1995- map_info(j, i, &ta, &tc, &ta, &tc);
1996-
1997- /* Extract the priority */
1998- tp = (byte_hack)feat_priority;
1999-
2000- if(match_autopick!=-1
2001- && (match_autopick_yx[y][x] == -1
2002- || match_autopick_yx[y][x] > match_autopick))
2003- {
2004- match_autopick_yx[y][x] = match_autopick;
2005- object_autopick_yx[y][x] = autopick_obj;
2006- tp = 0x7f;
2007- }
2008-
2009- /* Save the char, attr and priority */
2010- bigmc[j+1][i+1] = tc;
2011- bigma[j+1][i+1] = ta;
2012- bigmp[j+1][i+1] = tp;
2013- }
2014- }
2015-
2016- for (j = 0; j < cur_hgt; ++j)
2017- {
2018- for (i = 0; i < cur_wid; ++i)
2019- {
2020- x = i / xrat + 1;
2021- y = j / yrat + 1;
2022-
2023- tc = bigmc[j+1][i+1];
2024- ta = bigma[j+1][i+1];
2025- tp = bigmp[j+1][i+1];
2026-
2027- /* rare feature has more priority */
2028- if (mp[y][x] == tp)
2029- {
2030- int t;
2031- int cnt = 0;
2032-
2033- for (t = 0; t < 8; t++)
2034- {
2035- if (tc == bigmc[j+1+ddy_cdd[t]][i+1+ddx_cdd[t]] &&
2036- ta == bigma[j+1+ddy_cdd[t]][i+1+ddx_cdd[t]])
2037- cnt++;
2038- }
2039- if (cnt <= 4)
2040- tp++;
2041- }
2042-
2043- /* Save "best" */
2044- if (mp[y][x] < tp)
2045- {
2046- /* Save the char, attr and priority */
2047- mc[y][x] = tc;
2048- ma[y][x] = ta;
2049- mp[y][x] = tp;
2050- }
2051- }
2052- }
2053-
2054-
2055- /* Corners */
2056- x = wid + 1;
2057- y = hgt + 1;
2058-
2059- /* Draw the corners */
2060- mc[0][0] = mc[0][x] = mc[y][0] = mc[y][x] = '+';
2061-
2062- /* Draw the horizontal edges */
2063- for (x = 1; x <= wid; x++) mc[0][x] = mc[y][x] = '-';
2064-
2065- /* Draw the vertical edges */
2066- for (y = 1; y <= hgt; y++) mc[y][0] = mc[y][x] = '|';
2067-
2068-
2069- /* Display each map line in order */
2070- for (y = 0; y < hgt + 2; ++y)
2071- {
2072- /* Start a new line */
2073- Term_gotoxy(COL_MAP, y);
2074-
2075- /* Display the line */
2076- for (x = 0; x < wid + 2; ++x)
2077- {
2078- ta = ma[y][x];
2079- tc = mc[y][x];
2080-
2081- /* Hack -- fake monochrome */
2082- if (!use_graphics)
2083- {
2084- if (world_monster) ta = TERM_DARK;
2085- else if (IS_INVULN() || p_ptr->timewalk) ta = TERM_WHITE;
2086- else if (p_ptr->wraith_form) ta = TERM_L_DARK;
2087- }
2088-
2089- /* Add the character */
2090- Term_add_bigch(ta, tc);
2091- }
2092- }
2093-
2094-
2095- for (y = 1; y < hgt + 1; ++y)
2096- {
2097- match_autopick = -1;
2098- for (x = 1; x <= wid; x++){
2099- if (match_autopick_yx[y][x] != -1 &&
2100- (match_autopick > match_autopick_yx[y][x] ||
2101- match_autopick == -1)){
2102- match_autopick = match_autopick_yx[y][x];
2103- autopick_obj = object_autopick_yx[y][x];
2104- }
2105- }
2106-
2107- /* Clear old display */
2108- Term_putstr(0, y, 12, 0, " ");
2109-
2110- if (match_autopick != -1)
2111-#if 1
2112- display_shortened_item_name(autopick_obj, y);
2113-#else
2114- {
2115- char buf[13] = "\0";
2116- strncpy(buf,autopick_list[match_autopick].name,12);
2117- buf[12] = '\0';
2118- put_str(buf,y,0);
2119- }
2120-#endif
2121-
2122- }
2123-
2124- /* Player location */
2125- (*cy) = p_ptr->y / yrat + 1 + ROW_MAP;
2126- if (!use_bigtile)
2127- (*cx) = p_ptr->x / xrat + 1 + COL_MAP;
2128- else
2129- (*cx) = (p_ptr->x / xrat + 1) * 2 + COL_MAP;
2130-
2131- /* Restore lighting effects */
2132- view_special_lite = old_view_special_lite;
2133- view_granite_lite = old_view_granite_lite;
2134-
2135- /* Free each line map */
2136- for (y = 0; y < (hgt + 2); y++)
2137- {
2138- /* Free one row each array */
2139- C_KILL(ma[y], (wid + 2), TERM_COLOR);
2140- C_KILL(mc[y], (wid + 2), SYMBOL_CODE);
2141- C_KILL(mp[y], (wid + 2), byte);
2142- C_KILL(match_autopick_yx[y], (wid + 2), int);
2143- C_KILL(object_autopick_yx[y], (wid + 2), object_type *);
2144- }
2145-
2146- /* Free each line map */
2147- C_KILL(ma, (hgt + 2), TERM_COLOR *);
2148- C_KILL(mc, (hgt + 2), char_ptr);
2149- C_KILL(mp, (hgt + 2), byte_ptr);
2150- C_KILL(match_autopick_yx, (hgt + 2), sint_ptr);
2151- C_KILL(object_autopick_yx, (hgt + 2), object_type **);
2152-
2153- /* Free each line map */
2154- for (y = 0; y < (cur_hgt + 2); y++)
2155- {
2156- /* Free one row each array */
2157- C_KILL(bigma[y], (cur_wid + 2), TERM_COLOR);
2158- C_KILL(bigmc[y], (cur_wid + 2), SYMBOL_CODE);
2159- C_KILL(bigmp[y], (cur_wid + 2), byte);
2160- }
2161-
2162- /* Free each line map */
2163- C_KILL(bigma, (cur_hgt + 2), TERM_COLOR *);
2164- C_KILL(bigmc, (cur_hgt + 2), char_ptr);
2165- C_KILL(bigmp, (cur_hgt + 2), byte_ptr);
2166-}
2167-
2168-
2169-/*
2170- * Display a "small-scale" map of the dungeon for the player
2171- *
2172- * Currently, the "player" is displayed on the map.
2173- */
2174-void do_cmd_view_map(void)
2175-{
2176- int cy, cx;
2177-
2178- screen_save();
2179-
2180- prt(_("お待ち下さい...", "Please wait..."), 0, 0);
2181-
2182- Term_fresh();
2183- Term_clear();
2184-
2185- display_autopick = 0;
2186-
2187- /* Display the map */
2188- display_map(&cy, &cx);
2189-
2190- /* Wait for it */
2191- if(max_autopick && !p_ptr->wild_mode)
2192- {
2193- display_autopick = ITEM_DISPLAY;
2194-
2195- while (1)
2196- {
2197- int i;
2198- byte flag;
2199-
2200- int wid, hgt, row_message;
2201-
2202- Term_get_size(&wid, &hgt);
2203- row_message = hgt - 1;
2204-
2205- put_str(_("何かキーを押してください('M':拾う 'N':放置 'D':M+N 'K':壊すアイテムを表示)",
2206- " Hit M, N(for ~), K(for !), or D(same as M+N) to display auto-picker items."), row_message, 1);
2207-
2208- /* Hilite the player */
2209- move_cursor(cy, cx);
2210-
2211- i = inkey();
2212-
2213- if ('M' == i)
2214- flag = (DO_AUTOPICK | DO_QUERY_AUTOPICK);
2215- else if ('N' == i)
2216- flag = DONT_AUTOPICK;
2217- else if ('K' == i)
2218- flag = DO_AUTODESTROY;
2219- else if ('D' == i)
2220- flag = (DO_AUTOPICK | DO_QUERY_AUTOPICK | DONT_AUTOPICK);
2221- else
2222- break;
2223-
2224- Term_fresh();
2225-
2226- if (~display_autopick & flag)
2227- display_autopick |= flag;
2228- else
2229- display_autopick &= ~flag;
2230- /* Display the map */
2231- display_map(&cy, &cx);
2232- }
2233-
2234- display_autopick = 0;
2235-
2236- }
2237- else
2238- {
2239- put_str(_("何かキーを押すとゲームに戻ります", "Hit any key to continue"), 23, 30);
2240- /* Hilite the player */
2241- move_cursor(cy, cx);
2242- /* Get any key */
2243- inkey();
2244- }
2245- screen_load();
2246-}
2247-
2248-
2249-
2250-
2251-
2252-/*
2253- * Some comments on the grid flags. -BEN-
2254- *
2255- *
2256- * One of the major bottlenecks in previous versions of Angband was in
2257- * the calculation of "line of sight" from the player to various grids,
2258- * such as monsters. This was such a nasty bottleneck that a lot of
2259- * silly things were done to reduce the dependancy on "line of sight",
2260- * for example, you could not "see" any grids in a lit room until you
2261- * actually entered the room, and there were all kinds of bizarre grid
2262- * flags to enable this behavior. This is also why the "call light"
2263- * spells always lit an entire room.
2264- *
2265- * The code below provides functions to calculate the "field of view"
2266- * for the player, which, once calculated, provides extremely fast
2267- * calculation of "line of sight from the player", and to calculate
2268- * the "field of torch lite", which, again, once calculated, provides
2269- * extremely fast calculation of "which grids are lit by the player's
2270- * lite source". In addition to marking grids as "GRID_VIEW" and/or
2271- * "GRID_LITE", as appropriate, these functions maintain an array for
2272- * each of these two flags, each array containing the locations of all
2273- * of the grids marked with the appropriate flag, which can be used to
2274- * very quickly scan through all of the grids in a given set.
2275- *
2276- * To allow more "semantically valid" field of view semantics, whenever
2277- * the field of view (or the set of torch lit grids) changes, all of the
2278- * grids in the field of view (or the set of torch lit grids) are "drawn"
2279- * so that changes in the world will become apparent as soon as possible.
2280- * This has been optimized so that only grids which actually "change" are
2281- * redrawn, using the "temp" array and the "GRID_TEMP" flag to keep track
2282- * of the grids which are entering or leaving the relevent set of grids.
2283- *
2284- * These new methods are so efficient that the old nasty code was removed.
2285- *
2286- * Note that there is no reason to "update" the "viewable space" unless
2287- * the player "moves", or walls/doors are created/destroyed, and there
2288- * is no reason to "update" the "torch lit grids" unless the field of
2289- * view changes, or the "light radius" changes. This means that when
2290- * the player is resting, or digging, or doing anything that does not
2291- * involve movement or changing the state of the dungeon, there is no
2292- * need to update the "view" or the "lite" regions, which is nice.
2293- *
2294- * Note that the calls to the nasty "los()" function have been reduced
2295- * to a bare minimum by the use of the new "field of view" calculations.
2296- *
2297- * I wouldn't be surprised if slight modifications to the "update_view()"
2298- * function would allow us to determine "reverse line-of-sight" as well
2299- * as "normal line-of-sight", which would allow monsters to use a more
2300- * "correct" calculation to determine if they can "see" the player. For
2301- * now, monsters simply "cheat" somewhat and assume that if the player
2302- * has "line of sight" to the monster, then the monster can "pretend"
2303- * that it has "line of sight" to the player.
2304- *
2305- *
2306- * The "update_lite()" function maintains the "CAVE_LITE" flag for each
2307- * grid and maintains an array of all "CAVE_LITE" grids.
2308- *
2309- * This set of grids is the complete set of all grids which are lit by
2310- * the players light source, which allows the "player_can_see_bold()"
2311- * function to work very quickly.
2312- *
2313- * Note that every "CAVE_LITE" grid is also a "CAVE_VIEW" grid, and in
2314- * fact, the player (unless blind) can always "see" all grids which are
2315- * marked as "CAVE_LITE", unless they are "off screen".
2316- *
2317- *
2318- * The "update_view()" function maintains the "CAVE_VIEW" flag for each
2319- * grid and maintains an array of all "CAVE_VIEW" grids.
2320- *
2321- * This set of grids is the complete set of all grids within line of sight
2322- * of the player, allowing the "player_has_los_bold()" macro to work very
2323- * quickly.
2324- *
2325- *
2326- * The current "update_view()" algorithm uses the "CAVE_XTRA" flag as a
2327- * temporary internal flag to mark those grids which are not only in view,
2328- * but which are also "easily" in line of sight of the player. This flag
2329- * is always cleared when we are done.
2330- *
2331- *
2332- * The current "update_lite()" and "update_view()" algorithms use the
2333- * "CAVE_TEMP" flag, and the array of grids which are marked as "CAVE_TEMP",
2334- * to keep track of which grids were previously marked as "CAVE_LITE" or
2335- * "CAVE_VIEW", which allows us to optimize the "screen updates".
2336- *
2337- * The "CAVE_TEMP" flag, and the array of "CAVE_TEMP" grids, is also used
2338- * for various other purposes, such as spreading lite or darkness during
2339- * "lite_room()" / "unlite_room()", and for calculating monster flow.
2340- *
2341- *
2342- * Any grid can be marked as "CAVE_GLOW" which means that the grid itself is
2343- * in some way permanently lit. However, for the player to "see" anything
2344- * in the grid, as determined by "player_can_see()", the player must not be
2345- * blind, the grid must be marked as "CAVE_VIEW", and, in addition, "wall"
2346- * grids, even if marked as "perma lit", are only illuminated if they touch
2347- * a grid which is not a wall and is marked both "CAVE_GLOW" and "CAVE_VIEW".
2348- *
2349- *
2350- * To simplify various things, a grid may be marked as "CAVE_MARK", meaning
2351- * that even if the player cannot "see" the grid, he "knows" the terrain in
2352- * that grid. This is used to "remember" walls/doors/stairs/floors when they
2353- * are "seen" or "detected", and also to "memorize" floors, after "wiz_lite()",
2354- * or when one of the "memorize floor grids" options induces memorization.
2355- *
2356- * Objects are "memorized" in a different way, using a special "marked" flag
2357- * on the object itself, which is set when an object is observed or detected.
2358- *
2359- *
2360- * A grid may be marked as "CAVE_ROOM" which means that it is part of a "room",
2361- * and should be illuminated by "lite room" and "darkness" spells.
2362- *
2363- *
2364- * A grid may be marked as "CAVE_ICKY" which means it is part of a "vault",
2365- * and should be unavailable for "teleportation" destinations.
2366- *
2367- *
2368- * The "view_perma_grids" allows the player to "memorize" every perma-lit grid
2369- * which is observed, and the "view_torch_grids" allows the player to memorize
2370- * every torch-lit grid. The player will always memorize important walls,
2371- * doors, stairs, and other terrain features, as well as any "detected" grids.
2372- *
2373- * Note that the new "update_view()" method allows, among other things, a room
2374- * to be "partially" seen as the player approaches it, with a growing cone of
2375- * floor appearing as the player gets closer to the door. Also, by not turning
2376- * on the "memorize perma-lit grids" option, the player will only "see" those
2377- * floor grids which are actually in line of sight.
2378- *
2379- * And my favorite "plus" is that you can now use a special option to draw the
2380- * "floors" in the "viewable region" brightly (actually, to draw the *other*
2381- * grids dimly), providing a "pretty" effect as the player runs around, and
2382- * to efficiently display the "torch lite" in a special color.
2383- *
2384- *
2385- * Some comments on the "update_view()" algorithm...
2386- *
2387- * The algorithm is very fast, since it spreads "obvious" grids very quickly,
2388- * and only has to call "los()" on the borderline cases. The major axes/diags
2389- * even terminate early when they hit walls. I need to find a quick way
2390- * to "terminate" the other scans.
2391- *
2392- * Note that in the worst case (a big empty area with say 5% scattered walls),
2393- * each of the 1500 or so nearby grids is checked once, most of them getting
2394- * an "instant" rating, and only a small portion requiring a call to "los()".
2395- *
2396- * The only time that the algorithm appears to be "noticeably" too slow is
2397- * when running, and this is usually only important in town, since the town
2398- * provides about the worst scenario possible, with large open regions and
2399- * a few scattered obstructions. There is a special "efficiency" option to
2400- * allow the player to reduce his field of view in town, if needed.
2401- *
2402- * In the "best" case (say, a normal stretch of corridor), the algorithm
2403- * makes one check for each viewable grid, and makes no calls to "los()".
2404- * So running in corridors is very fast, and if a lot of monsters are
2405- * nearby, it is much faster than the old methods.
2406- *
2407- * Note that resting, most normal commands, and several forms of running,
2408- * plus all commands executed near large groups of monsters, are strictly
2409- * more efficient with "update_view()" that with the old "compute los() on
2410- * demand" method, primarily because once the "field of view" has been
2411- * calculated, it does not have to be recalculated until the player moves
2412- * (or a wall or door is created or destroyed).
2413- *
2414- * Note that we no longer have to do as many "los()" checks, since once the
2415- * "view" region has been built, very few things cause it to be "changed"
2416- * (player movement, and the opening/closing of doors, changes in wall status).
2417- * Note that door/wall changes are only relevant when the door/wall itself is
2418- * in the "view" region.
2419- *
2420- * The algorithm seems to only call "los()" from zero to ten times, usually
2421- * only when coming down a corridor into a room, or standing in a room, just
2422- * misaligned with a corridor. So if, say, there are five "nearby" monsters,
2423- * we will be reducing the calls to "los()".
2424- *
2425- * I am thinking in terms of an algorithm that "walks" from the central point
2426- * out to the maximal "distance", at each point, determining the "view" code
2427- * (above). For each grid not on a major axis or diagonal, the "view" code
2428- * depends on the "cave_los_bold()" and "view" of exactly two other grids
2429- * (the one along the nearest diagonal, and the one next to that one, see
2430- * "update_view_aux()"...).
2431- *
2432- * We "memorize" the viewable space array, so that at the cost of under 3000
2433- * bytes, we reduce the time taken by "forget_view()" to one assignment for
2434- * each grid actually in the "viewable space". And for another 3000 bytes,
2435- * we prevent "erase + redraw" ineffiencies via the "seen" set. These bytes
2436- * are also used by other routines, thus reducing the cost to almost nothing.
2437- *
2438- * A similar thing is done for "forget_lite()" in which case the savings are
2439- * much less, but save us from doing bizarre maintenance checking.
2440- *
2441- * In the worst "normal" case (in the middle of the town), the reachable space
2442- * actually reaches to more than half of the largest possible "circle" of view,
2443- * or about 800 grids, and in the worse case (in the middle of a dungeon level
2444- * where all the walls have been removed), the reachable space actually reaches
2445- * the theoretical maximum size of just under 1500 grids.
2446- *
2447- * Each grid G examines the "state" of two (?) other (adjacent) grids, G1 & G2.
2448- * If G1 is lite, G is lite. Else if G2 is lite, G is half. Else if G1 and G2
2449- * are both half, G is half. Else G is dark. It only takes 2 (or 4) bits to
2450- * "name" a grid, so (for MAX_RAD of 20) we could use 1600 bytes, and scan the
2451- * entire possible space (including initialization) in one step per grid. If
2452- * we do the "clearing" as a separate step (and use an array of "view" grids),
2453- * then the clearing will take as many steps as grids that were viewed, and the
2454- * algorithm will be able to "stop" scanning at various points.
2455- * Oh, and outside of the "torch radius", only "lite" grids need to be scanned.
2456- */
2457-
2458-
2459-
2460-
2461-
2462-
2463-
2464-
2465-/*
2466- * Actually erase the entire "lite" array, redrawing every grid
2467- */
2468-void forget_lite(void)
2469-{
2470- int i, x, y;
2471-
2472- /* None to forget */
2473- if (!lite_n) return;
2474-
2475- /* Clear them all */
2476- for (i = 0; i < lite_n; i++)
2477- {
2478- y = lite_y[i];
2479- x = lite_x[i];
2480-
2481- /* Forget "LITE" flag */
2482- grid_array[y][x].info &= ~(CAVE_LITE);
2483-
2484- /* lite_spot(y, x); Perhaps don't need? */
2485- }
2486-
2487- /* None left */
2488- lite_n = 0;
2489-}
2490-
2491-
2492-/*
2493- * For delayed visual update
2494- */
2495-#define cave_note_and_redraw_later(C,Y,X) \
2496-{\
2497- (C)->info |= CAVE_NOTE; \
2498- cave_redraw_later((C), (Y), (X)); \
2499-}
2500-
2501-
2502-/*
2503- * For delayed visual update
2504- */
2505-#define cave_redraw_later(C,Y,X) \
2506-{\
2507- if (!((C)->info & CAVE_REDRAW)) \
2508- { \
2509- (C)->info |= CAVE_REDRAW; \
2510- redraw_y[redraw_n] = (Y); \
2511- redraw_x[redraw_n++] = (X); \
2512- } \
2513-}
2514-
2515-
2516-/*
2517- * This macro allows us to efficiently add a grid to the "lite" array,
2518- * note that we are never called for illegal grids, or for grids which
2519- * have already been placed into the "lite" array, and we are never
2520- * called when the "lite" array is full.
2521- */
2522-#define cave_lite_hack(Y,X) \
2523-{\
2524- if (!(grid_array[Y][X].info & (CAVE_LITE))) \
2525- { \
2526- grid_array[Y][X].info |= (CAVE_LITE); \
2527- lite_y[lite_n] = (Y); \
2528- lite_x[lite_n++] = (X); \
2529- } \
2530-}
2531-
2532-
2533-/*
2534- * Update the set of grids "illuminated" by the player's lite.
2535- *
2536- * This routine needs to use the results of "update_view()"
2537- *
2538- * Note that "blindness" does NOT affect "torch lite". Be careful!
2539- *
2540- * We optimize most lites (all non-artifact lites) by using "obvious"
2541- * facts about the results of "small" lite radius, and we attempt to
2542- * list the "nearby" grids before the more "distant" ones in the
2543- * array of torch-lit grids.
2544- *
2545- * We assume that "radius zero" lite is in fact no lite at all.
2546- *
2547- * Torch Lantern Artifacts
2548- * (etc)
2549- * ***
2550- * *** *****
2551- * *** ***** *******
2552- * *@* **@** ***@***
2553- * *** ***** *******
2554- * *** *****
2555- * ***
2556- */
2557-void update_lite(void)
2558-{
2559- int i;
2560- POSITION x, y, min_x, max_x, min_y, max_y;
2561- int p = p_ptr->cur_lite;
2562- grid_type *g_ptr;
2563-
2564- /*** Special case ***/
2565-
2566-#if 0
2567- /* Hack -- Player has no lite */
2568- if (p <= 0)
2569- {
2570- /* Forget the old lite */
2571- /* forget_lite(); Perhaps don't need? */
2572-
2573- /* Add it to later visual update */
2574- cave_redraw_later(&grid_array[p_ptr->y][p_ptr->x], p_ptr->y, p_ptr->x);
2575- }
2576-#endif
2577-
2578- /*** Save the old "lite" grids for later ***/
2579-
2580- /* Clear them all */
2581- for (i = 0; i < lite_n; i++)
2582- {
2583- y = lite_y[i];
2584- x = lite_x[i];
2585-
2586- /* Mark the grid as not "lite" */
2587- grid_array[y][x].info &= ~(CAVE_LITE);
2588-
2589- /* Mark the grid as "seen" */
2590- grid_array[y][x].info |= (CAVE_TEMP);
2591-
2592- /* Add it to the "seen" set */
2593- temp_y[temp_n] = y;
2594- temp_x[temp_n] = x;
2595- temp_n++;
2596- }
2597-
2598- /* None left */
2599- lite_n = 0;
2600-
2601-
2602- /*** Collect the new "lite" grids ***/
2603-
2604- /* Radius 1 -- torch radius */
2605- if (p >= 1)
2606- {
2607- /* Player grid */
2608- cave_lite_hack(p_ptr->y, p_ptr->x);
2609-
2610- /* Adjacent grid */
2611- cave_lite_hack(p_ptr->y+1, p_ptr->x);
2612- cave_lite_hack(p_ptr->y-1, p_ptr->x);
2613- cave_lite_hack(p_ptr->y, p_ptr->x+1);
2614- cave_lite_hack(p_ptr->y, p_ptr->x-1);
2615-
2616- /* Diagonal grids */
2617- cave_lite_hack(p_ptr->y+1, p_ptr->x+1);
2618- cave_lite_hack(p_ptr->y+1, p_ptr->x-1);
2619- cave_lite_hack(p_ptr->y-1, p_ptr->x+1);
2620- cave_lite_hack(p_ptr->y-1, p_ptr->x-1);
2621- }
2622-
2623- /* Radius 2 -- lantern radius */
2624- if (p >= 2)
2625- {
2626- /* South of the player */
2627- if (cave_los_bold(p_ptr->y + 1, p_ptr->x))
2628- {
2629- cave_lite_hack(p_ptr->y+2, p_ptr->x);
2630- cave_lite_hack(p_ptr->y+2, p_ptr->x+1);
2631- cave_lite_hack(p_ptr->y+2, p_ptr->x-1);
2632- }
2633-
2634- /* North of the player */
2635- if (cave_los_bold(p_ptr->y - 1, p_ptr->x))
2636- {
2637- cave_lite_hack(p_ptr->y-2, p_ptr->x);
2638- cave_lite_hack(p_ptr->y-2, p_ptr->x+1);
2639- cave_lite_hack(p_ptr->y-2, p_ptr->x-1);
2640- }
2641-
2642- /* East of the player */
2643- if (cave_los_bold(p_ptr->y, p_ptr->x + 1))
2644- {
2645- cave_lite_hack(p_ptr->y, p_ptr->x+2);
2646- cave_lite_hack(p_ptr->y+1, p_ptr->x+2);
2647- cave_lite_hack(p_ptr->y-1, p_ptr->x+2);
2648- }
2649-
2650- /* West of the player */
2651- if (cave_los_bold(p_ptr->y, p_ptr->x - 1))
2652- {
2653- cave_lite_hack(p_ptr->y, p_ptr->x-2);
2654- cave_lite_hack(p_ptr->y+1, p_ptr->x-2);
2655- cave_lite_hack(p_ptr->y-1, p_ptr->x-2);
2656- }
2657- }
2658-
2659- /* Radius 3+ -- artifact radius */
2660- if (p >= 3)
2661- {
2662- int d;
2663-
2664- /* Paranoia -- see "LITE_MAX" */
2665- if (p > 14) p = 14;
2666-
2667- /* South-East of the player */
2668- if (cave_los_bold(p_ptr->y + 1, p_ptr->x + 1))
2669- {
2670- cave_lite_hack(p_ptr->y+2, p_ptr->x+2);
2671- }
2672-
2673- /* South-West of the player */
2674- if (cave_los_bold(p_ptr->y + 1, p_ptr->x - 1))
2675- {
2676- cave_lite_hack(p_ptr->y+2, p_ptr->x-2);
2677- }
2678-
2679- /* North-East of the player */
2680- if (cave_los_bold(p_ptr->y - 1, p_ptr->x + 1))
2681- {
2682- cave_lite_hack(p_ptr->y-2, p_ptr->x+2);
2683- }
2684-
2685- /* North-West of the player */
2686- if (cave_los_bold(p_ptr->y - 1, p_ptr->x - 1))
2687- {
2688- cave_lite_hack(p_ptr->y-2, p_ptr->x-2);
2689- }
2690-
2691- /* Maximal north */
2692- min_y = p_ptr->y - p;
2693- if (min_y < 0) min_y = 0;
2694-
2695- /* Maximal south */
2696- max_y = p_ptr->y + p;
2697- if (max_y > cur_hgt-1) max_y = cur_hgt-1;
2698-
2699- /* Maximal west */
2700- min_x = p_ptr->x - p;
2701- if (min_x < 0) min_x = 0;
2702-
2703- /* Maximal east */
2704- max_x = p_ptr->x + p;
2705- if (max_x > cur_wid-1) max_x = cur_wid-1;
2706-
2707- /* Scan the maximal box */
2708- for (y = min_y; y <= max_y; y++)
2709- {
2710- for (x = min_x; x <= max_x; x++)
2711- {
2712- int dy = (p_ptr->y > y) ? (p_ptr->y - y) : (y - p_ptr->y);
2713- int dx = (p_ptr->x > x) ? (p_ptr->x - x) : (x - p_ptr->x);
2714-
2715- /* Skip the "central" grids (above) */
2716- if ((dy <= 2) && (dx <= 2)) continue;
2717-
2718- /* Hack -- approximate the distance */
2719- d = (dy > dx) ? (dy + (dx>>1)) : (dx + (dy>>1));
2720-
2721- /* Skip distant grids */
2722- if (d > p) continue;
2723-
2724- /* Viewable, nearby, grids get "torch lit" */
2725- if (grid_array[y][x].info & CAVE_VIEW)
2726- {
2727- /* This grid is "torch lit" */
2728- cave_lite_hack(y, x);
2729- }
2730- }
2731- }
2732- }
2733-
2734-
2735- /*** Complete the algorithm ***/
2736-
2737- /* Draw the new grids */
2738- for (i = 0; i < lite_n; i++)
2739- {
2740- y = lite_y[i];
2741- x = lite_x[i];
2742-
2743- g_ptr = &grid_array[y][x];
2744-
2745- /* Update fresh grids */
2746- if (g_ptr->info & (CAVE_TEMP)) continue;
2747-
2748- /* Add it to later visual update */
2749- cave_note_and_redraw_later(g_ptr, y, x);
2750- }
2751-
2752- /* Clear them all */
2753- for (i = 0; i < temp_n; i++)
2754- {
2755- y = temp_y[i];
2756- x = temp_x[i];
2757-
2758- g_ptr = &grid_array[y][x];
2759-
2760- /* No longer in the array */
2761- g_ptr->info &= ~(CAVE_TEMP);
2762-
2763- /* Update stale grids */
2764- if (g_ptr->info & (CAVE_LITE)) continue;
2765-
2766- /* Add it to later visual update */
2767- cave_redraw_later(g_ptr, y, x);
2768- }
2769-
2770- /* None left */
2771- temp_n = 0;
2772-
2773- /* Mega-Hack -- Visual update later */
2774- p_ptr->update |= (PU_DELAY_VIS);
2775-}
2776-
2777-
2778-static bool mon_invis;
2779-static POSITION mon_fy, mon_fx;
2780-
2781-/*
2782- * Add a square to the changes array
2783- */
2784-static void mon_lite_hack(POSITION y, POSITION x)
2785-{
2786- grid_type *g_ptr;
2787- int dpf, d;
2788- POSITION midpoint;
2789-
2790- /* We trust this grid is in bounds */
2791- /* if (!in_bounds2(y, x)) return; */
2792-
2793- g_ptr = &grid_array[y][x];
2794-
2795- /* Want a unlit square in view of the player */
2796- if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW) return;
2797-
2798- if (!cave_los_grid(g_ptr))
2799- {
2800- /* Hack -- Prevent monster lite leakage in walls */
2801-
2802- /* Horizontal walls between player and a monster */
2803- if (((y < p_ptr->y) && (y > mon_fy)) || ((y > p_ptr->y) && (y < mon_fy)))
2804- {
2805- dpf = p_ptr->y - mon_fy;
2806- d = y - mon_fy;
2807- midpoint = mon_fx + ((p_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
2808-
2809- /* Only first wall viewed from mid-x is lit */
2810- if (x < midpoint)
2811- {
2812- if (!cave_los_bold(y, x + 1)) return;
2813- }
2814- else if (x > midpoint)
2815- {
2816- if (!cave_los_bold(y, x - 1)) return;
2817- }
2818-
2819- /* Hack XXX XXX - Is it a wall and monster not in LOS? */
2820- else if (mon_invis) return;
2821- }
2822-
2823- /* Vertical walls between player and a monster */
2824- if (((x < p_ptr->x) && (x > mon_fx)) || ((x > p_ptr->x) && (x < mon_fx)))
2825- {
2826- dpf = p_ptr->x - mon_fx;
2827- d = x - mon_fx;
2828- midpoint = mon_fy + ((p_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
2829-
2830- /* Only first wall viewed from mid-y is lit */
2831- if (y < midpoint)
2832- {
2833- if (!cave_los_bold(y + 1, x)) return;
2834- }
2835- else if (y > midpoint)
2836- {
2837- if (!cave_los_bold(y - 1, x)) return;
2838- }
2839-
2840- /* Hack XXX XXX - Is it a wall and monster not in LOS? */
2841- else if (mon_invis) return;
2842- }
2843- }
2844-
2845- /* We trust temp_n does not exceed TEMP_MAX */
2846-
2847- /* New grid */
2848- if (!(g_ptr->info & CAVE_MNDK))
2849- {
2850- /* Save this square */
2851- temp_x[temp_n] = x;
2852- temp_y[temp_n] = y;
2853- temp_n++;
2854- }
2855-
2856- /* Darkened grid */
2857- else
2858- {
2859- /* No longer dark */
2860- g_ptr->info &= ~(CAVE_MNDK);
2861- }
2862-
2863- /* Light it */
2864- g_ptr->info |= CAVE_MNLT;
2865-}
2866-
2867-
2868-/*
2869- * Add a square to the changes array
2870- */
2871-static void mon_dark_hack(POSITION y, POSITION x)
2872-{
2873- grid_type *g_ptr;
2874- int midpoint, dpf, d;
2875-
2876- /* We trust this grid is in bounds */
2877- /* if (!in_bounds2(y, x)) return; */
2878-
2879- g_ptr = &grid_array[y][x];
2880-
2881- /* Want a unlit and undarkened square in view of the player */
2882- if ((g_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW) return;
2883-
2884- if (!cave_los_grid(g_ptr) && !cave_have_flag_grid(g_ptr, FF_PROJECT))
2885- {
2886- /* Hack -- Prevent monster dark lite leakage in walls */
2887-
2888- /* Horizontal walls between player and a monster */
2889- if (((y < p_ptr->y) && (y > mon_fy)) || ((y > p_ptr->y) && (y < mon_fy)))
2890- {
2891- dpf = p_ptr->y - mon_fy;
2892- d = y - mon_fy;
2893- midpoint = mon_fx + ((p_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
2894-
2895- /* Only first wall viewed from mid-x is lit */
2896- if (x < midpoint)
2897- {
2898- if (!cave_los_bold(y, x + 1) && !cave_have_flag_bold(y, x + 1, FF_PROJECT)) return;
2899- }
2900- else if (x > midpoint)
2901- {
2902- if (!cave_los_bold(y, x - 1) && !cave_have_flag_bold(y, x - 1, FF_PROJECT)) return;
2903- }
2904-
2905- /* Hack XXX XXX - Is it a wall and monster not in LOS? */
2906- else if (mon_invis) return;
2907- }
2908-
2909- /* Vertical walls between player and a monster */
2910- if (((x < p_ptr->x) && (x > mon_fx)) || ((x > p_ptr->x) && (x < mon_fx)))
2911- {
2912- dpf = p_ptr->x - mon_fx;
2913- d = x - mon_fx;
2914- midpoint = mon_fy + ((p_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
2915-
2916- /* Only first wall viewed from mid-y is lit */
2917- if (y < midpoint)
2918- {
2919- if (!cave_los_bold(y + 1, x) && !cave_have_flag_bold(y + 1, x, FF_PROJECT)) return;
2920- }
2921- else if (y > midpoint)
2922- {
2923- if (!cave_los_bold(y - 1, x) && !cave_have_flag_bold(y - 1, x, FF_PROJECT)) return;
2924- }
2925-
2926- /* Hack XXX XXX - Is it a wall and monster not in LOS? */
2927- else if (mon_invis) return;
2928- }
2929- }
2930-
2931- /* We trust temp_n does not exceed TEMP_MAX */
2932-
2933- /* Save this square */
2934- temp_x[temp_n] = x;
2935- temp_y[temp_n] = y;
2936- temp_n++;
2937-
2938- /* Darken it */
2939- g_ptr->info |= CAVE_MNDK;
2940-}
2941-
2942-
2943-/*
2944- * Update squares illuminated or darkened by monsters.
2945- *
2946- * Hack - use the CAVE_ROOM flag (renamed to be CAVE_MNLT) to
2947- * denote squares illuminated by monsters.
2948- *
2949- * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
2950- * updating. Only squares in view of the player, whos state
2951- * changes are drawn via lite_spot().
2952- */
2953-void update_mon_lite(void)
2954-{
2955- int i, rad;
2956- grid_type *g_ptr;
2957-
2958- POSITION fx, fy;
2959- void (*add_mon_lite)(POSITION, POSITION);
2960- int f_flag;
2961-
2962- s16b end_temp;
2963-
2964- /* Non-Ninja player in the darkness */
2965- int dis_lim = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !p_ptr->see_nocto) ?
2966- (MAX_SIGHT / 2 + 1) : (MAX_SIGHT + 3);
2967-
2968- /* Clear all monster lit squares */
2969- for (i = 0; i < mon_lite_n; i++)
2970- {
2971- /* Point to grid */
2972- g_ptr = &grid_array[mon_lite_y[i]][mon_lite_x[i]];
2973-
2974- /* Set temp or xtra flag */
2975- g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
2976-
2977- /* Clear monster illumination flag */
2978- g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
2979- }
2980-
2981- /* Empty temp list of new squares to lite up */
2982- temp_n = 0;
2983-
2984- /* If a monster stops time, don't process */
2985- if (!world_monster)
2986- {
2987- monster_type *m_ptr;
2988- monster_race *r_ptr;
2989-
2990- /* Loop through monsters, adding newly lit squares to changes list */
2991- for (i = 1; i < m_max; i++)
2992- {
2993- m_ptr = &m_list[i];
2994- r_ptr = &r_info[m_ptr->r_idx];
2995-
2996- /* Skip dead monsters */
2997- if (!m_ptr->r_idx) continue;
2998-
2999- /* Is it too far away? */
3000- if (m_ptr->cdis > dis_lim) continue;
3001-
3002- /* Get lite radius */
3003- rad = 0;
3004-
3005- /* Note the radii are cumulative */
3006- if (r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_SELF_LITE_1)) rad++;
3007- if (r_ptr->flags7 & (RF7_HAS_LITE_2 | RF7_SELF_LITE_2)) rad += 2;
3008- if (r_ptr->flags7 & (RF7_HAS_DARK_1 | RF7_SELF_DARK_1)) rad--;
3009- if (r_ptr->flags7 & (RF7_HAS_DARK_2 | RF7_SELF_DARK_2)) rad -= 2;
3010-
3011- /* Exit if has no light */
3012- if (!rad) continue;
3013- else if (rad > 0)
3014- {
3015- if (!(r_ptr->flags7 & (RF7_SELF_LITE_1 | RF7_SELF_LITE_2)) && (MON_CSLEEP(m_ptr) || (!dun_level && is_daytime()) || p_ptr->inside_battle)) continue;
3016- if (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS) rad = 1;
3017- add_mon_lite = mon_lite_hack;
3018- f_flag = FF_LOS;
3019- }
3020- else
3021- {
3022- if (!(r_ptr->flags7 & (RF7_SELF_DARK_1 | RF7_SELF_DARK_2)) && (MON_CSLEEP(m_ptr) || (!dun_level && !is_daytime()))) continue;
3023- add_mon_lite = mon_dark_hack;
3024- f_flag = FF_PROJECT;
3025- rad = -rad; /* Use absolute value */
3026- }
3027-
3028- /* Access the location */
3029- mon_fx = m_ptr->fx;
3030- mon_fy = m_ptr->fy;
3031-
3032- /* Is the monster visible? */
3033- mon_invis = !(grid_array[mon_fy][mon_fx].info & CAVE_VIEW);
3034-
3035- /* The square it is on */
3036- add_mon_lite(mon_fy, mon_fx);
3037-
3038- /* Adjacent squares */
3039- add_mon_lite(mon_fy + 1, mon_fx);
3040- add_mon_lite(mon_fy - 1, mon_fx);
3041- add_mon_lite(mon_fy, mon_fx + 1);
3042- add_mon_lite(mon_fy, mon_fx - 1);
3043- add_mon_lite(mon_fy + 1, mon_fx + 1);
3044- add_mon_lite(mon_fy + 1, mon_fx - 1);
3045- add_mon_lite(mon_fy - 1, mon_fx + 1);
3046- add_mon_lite(mon_fy - 1, mon_fx - 1);
3047-
3048- /* Radius 2 */
3049- if (rad >= 2)
3050- {
3051- /* South of the monster */
3052- if (cave_have_flag_bold(mon_fy + 1, mon_fx, f_flag))
3053- {
3054- add_mon_lite(mon_fy + 2, mon_fx + 1);
3055- add_mon_lite(mon_fy + 2, mon_fx);
3056- add_mon_lite(mon_fy + 2, mon_fx - 1);
3057-
3058- g_ptr = &grid_array[mon_fy + 2][mon_fx];
3059-
3060- /* Radius 3 */
3061- if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
3062- {
3063- add_mon_lite(mon_fy + 3, mon_fx + 1);
3064- add_mon_lite(mon_fy + 3, mon_fx);
3065- add_mon_lite(mon_fy + 3, mon_fx - 1);
3066- }
3067- }
3068-
3069- /* North of the monster */
3070- if (cave_have_flag_bold(mon_fy - 1, mon_fx, f_flag))
3071- {
3072- add_mon_lite(mon_fy - 2, mon_fx + 1);
3073- add_mon_lite(mon_fy - 2, mon_fx);
3074- add_mon_lite(mon_fy - 2, mon_fx - 1);
3075-
3076- g_ptr = &grid_array[mon_fy - 2][mon_fx];
3077-
3078- /* Radius 3 */
3079- if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
3080- {
3081- add_mon_lite(mon_fy - 3, mon_fx + 1);
3082- add_mon_lite(mon_fy - 3, mon_fx);
3083- add_mon_lite(mon_fy - 3, mon_fx - 1);
3084- }
3085- }
3086-
3087- /* East of the monster */
3088- if (cave_have_flag_bold(mon_fy, mon_fx + 1, f_flag))
3089- {
3090- add_mon_lite(mon_fy + 1, mon_fx + 2);
3091- add_mon_lite(mon_fy, mon_fx + 2);
3092- add_mon_lite(mon_fy - 1, mon_fx + 2);
3093-
3094- g_ptr = &grid_array[mon_fy][mon_fx + 2];
3095-
3096- /* Radius 3 */
3097- if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
3098- {
3099- add_mon_lite(mon_fy + 1, mon_fx + 3);
3100- add_mon_lite(mon_fy, mon_fx + 3);
3101- add_mon_lite(mon_fy - 1, mon_fx + 3);
3102- }
3103- }
3104-
3105- /* West of the monster */
3106- if (cave_have_flag_bold(mon_fy, mon_fx - 1, f_flag))
3107- {
3108- add_mon_lite(mon_fy + 1, mon_fx - 2);
3109- add_mon_lite(mon_fy, mon_fx - 2);
3110- add_mon_lite(mon_fy - 1, mon_fx - 2);
3111-
3112- g_ptr = &grid_array[mon_fy][mon_fx - 2];
3113-
3114- /* Radius 3 */
3115- if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
3116- {
3117- add_mon_lite(mon_fy + 1, mon_fx - 3);
3118- add_mon_lite(mon_fy, mon_fx - 3);
3119- add_mon_lite(mon_fy - 1, mon_fx - 3);
3120- }
3121- }
3122- }
3123-
3124- /* Radius 3 */
3125- if (rad == 3)
3126- {
3127- /* South-East of the monster */
3128- if (cave_have_flag_bold(mon_fy + 1, mon_fx + 1, f_flag))
3129- {
3130- add_mon_lite(mon_fy + 2, mon_fx + 2);
3131- }
3132-
3133- /* South-West of the monster */
3134- if (cave_have_flag_bold(mon_fy + 1, mon_fx - 1, f_flag))
3135- {
3136- add_mon_lite(mon_fy + 2, mon_fx - 2);
3137- }
3138-
3139- /* North-East of the monster */
3140- if (cave_have_flag_bold(mon_fy - 1, mon_fx + 1, f_flag))
3141- {
3142- add_mon_lite(mon_fy - 2, mon_fx + 2);
3143- }
3144-
3145- /* North-West of the monster */
3146- if (cave_have_flag_bold(mon_fy - 1, mon_fx - 1, f_flag))
3147- {
3148- add_mon_lite(mon_fy - 2, mon_fx - 2);
3149- }
3150- }
3151- }
3152- }
3153-
3154- /* Save end of list of new squares */
3155- end_temp = temp_n;
3156-
3157- /*
3158- * Look at old set flags to see if there are any changes.
3159- */
3160- for (i = 0; i < mon_lite_n; i++)
3161- {
3162- fx = mon_lite_x[i];
3163- fy = mon_lite_y[i];
3164-
3165- /* We trust this grid is in bounds */
3166-
3167- /* Point to grid */
3168- g_ptr = &grid_array[fy][fx];
3169-
3170- if (g_ptr->info & CAVE_TEMP) /* Pervious lit */
3171- {
3172- /* It it no longer lit? */
3173- if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
3174- {
3175- /* It is now unlit */
3176- /* Add it to later visual update */
3177- cave_note_and_redraw_later(g_ptr, fy, fx);
3178- }
3179- }
3180- else /* Pervious darkened */
3181- {
3182- /* It it no longer darken? */
3183- if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
3184- {
3185- /* It is now undarken */
3186- /* Add it to later visual update */
3187- cave_note_and_redraw_later(g_ptr, fy, fx);
3188- }
3189- }
3190-
3191- /* Add to end of temp array */
3192- temp_x[temp_n] = fx;
3193- temp_y[temp_n] = fy;
3194- temp_n++;
3195- }
3196-
3197- /* Clear the lite array */
3198- mon_lite_n = 0;
3199-
3200- /* Copy the temp array into the lit array lighting the new squares. */
3201- for (i = 0; i < end_temp; i++)
3202- {
3203- fx = temp_x[i];
3204- fy = temp_y[i];
3205-
3206- /* We trust this grid is in bounds */
3207-
3208- /* Point to grid */
3209- g_ptr = &grid_array[fy][fx];
3210-
3211- if (g_ptr->info & CAVE_MNLT) /* Lit */
3212- {
3213- /* The is the square newly lit and visible? */
3214- if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
3215- {
3216- /* It is now lit */
3217- /* Add it to later visual update */
3218- cave_note_and_redraw_later(g_ptr, fy, fx);
3219- }
3220- }
3221- else /* Darkened */
3222- {
3223- /* The is the square newly darkened and visible? */
3224- if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
3225- {
3226- /* It is now darkened */
3227- /* Add it to later visual update */
3228- cave_note_and_redraw_later(g_ptr, fy, fx);
3229- }
3230- }
3231-
3232- /* Save in the monster lit or darkened array */
3233- mon_lite_x[mon_lite_n] = fx;
3234- mon_lite_y[mon_lite_n] = fy;
3235- mon_lite_n++;
3236- }
3237-
3238- /* Clear the temp flag for the old lit or darken grids */
3239- for (i = end_temp; i < temp_n; i++)
3240- {
3241- /* We trust this grid is in bounds */
3242-
3243- grid_array[temp_y[i]][temp_x[i]].info &= ~(CAVE_TEMP | CAVE_XTRA);
3244- }
3245-
3246- /* Finished with temp_n */
3247- temp_n = 0;
3248-
3249- /* Mega-Hack -- Visual update later */
3250- p_ptr->update |= (PU_DELAY_VIS);
3251-
3252- p_ptr->monlite = (grid_array[p_ptr->y][p_ptr->x].info & CAVE_MNLT) ? TRUE : FALSE;
3253-
3254- if (p_ptr->special_defense & NINJA_S_STEALTH)
3255- {
3256- if (p_ptr->old_monlite != p_ptr->monlite)
3257- {
3258- if (p_ptr->monlite)
3259- {
3260- msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow become thin."));
3261- }
3262- else
3263- {
3264- msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow restored its original darkness."));
3265- }
3266- }
3267- }
3268- p_ptr->old_monlite = p_ptr->monlite;
3269-}
3270-
3271-void clear_mon_lite(void)
3272-{
3273- int i;
3274- grid_type *g_ptr;
3275-
3276- /* Clear all monster lit squares */
3277- for (i = 0; i < mon_lite_n; i++)
3278- {
3279- /* Point to grid */
3280- g_ptr = &grid_array[mon_lite_y[i]][mon_lite_x[i]];
3281-
3282- /* Clear monster illumination flag */
3283- g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
3284- }
3285-
3286- /* Empty the array */
3287- mon_lite_n = 0;
3288-}
3289-
3290-
3291-
3292-/*
3293- * Clear the viewable space
3294- */
3295-void forget_view(void)
3296-{
3297- int i;
3298-
3299- grid_type *g_ptr;
3300-
3301- /* None to forget */
3302- if (!view_n) return;
3303-
3304- /* Clear them all */
3305- for (i = 0; i < view_n; i++)
3306- {
3307- POSITION y = view_y[i];
3308- POSITION x = view_x[i];
3309- g_ptr = &grid_array[y][x];
3310-
3311- /* Forget that the grid is viewable */
3312- g_ptr->info &= ~(CAVE_VIEW);
3313-
3314- /* if (!panel_contains(y, x)) continue; */
3315-
3316- /* Update the screen */
3317- /* lite_spot(y, x); Perhaps don't need? */
3318- }
3319-
3320- /* None left */
3321- view_n = 0;
3322-}
3323-
3324-
3325-
3326-/*
3327- * This macro allows us to efficiently add a grid to the "view" array,
3328- * note that we are never called for illegal grids, or for grids which
3329- * have already been placed into the "view" array, and we are never
3330- * called when the "view" array is full.
3331- */
3332-#define cave_view_hack(C,Y,X) \
3333-{\
3334- if (!((C)->info & (CAVE_VIEW))){\
3335- (C)->info |= (CAVE_VIEW); \
3336- view_y[view_n] = (Y); \
3337- view_x[view_n] = (X); \
3338- view_n++;}\
3339-}
3340-
3341-
3342-
3343-/*
3344- * Helper function for "update_view()" below
3345- *
3346- * We are checking the "viewability" of grid (y,x) by the player.
3347- *
3348- * This function assumes that (y,x) is legal (i.e. on the map).
3349- *
3350- * Grid (y1,x1) is on the "diagonal" between (p_ptr->y,p_ptr->x) and (y,x)
3351- * Grid (y2,x2) is "adjacent", also between (p_ptr->y,p_ptr->x) and (y,x).
3352- *
3353- * Note that we are using the "CAVE_XTRA" field for marking grids as
3354- * "easily viewable". This bit is cleared at the end of "update_view()".
3355- *
3356- * This function adds (y,x) to the "viewable set" if necessary.
3357- *
3358- * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
3359- */
3360-static bool update_view_aux(POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
3361-{
3362- bool f1, f2, v1, v2, z1, z2, wall;
3363-
3364- grid_type *g_ptr;
3365-
3366- grid_type *g1_c_ptr;
3367- grid_type *g2_c_ptr;
3368-
3369- /* Access the grids */
3370- g1_c_ptr = &grid_array[y1][x1];
3371- g2_c_ptr = &grid_array[y2][x2];
3372-
3373-
3374- /* Check for walls */
3375- f1 = (cave_los_grid(g1_c_ptr));
3376- f2 = (cave_los_grid(g2_c_ptr));
3377-
3378- /* Totally blocked by physical walls */
3379- if (!f1 && !f2) return (TRUE);
3380-
3381-
3382- /* Check for visibility */
3383- v1 = (f1 && (g1_c_ptr->info & (CAVE_VIEW)));
3384- v2 = (f2 && (g2_c_ptr->info & (CAVE_VIEW)));
3385-
3386- /* Totally blocked by "unviewable neighbors" */
3387- if (!v1 && !v2) return (TRUE);
3388-
3389- g_ptr = &grid_array[y][x];
3390-
3391-
3392- /* Check for walls */
3393- wall = (!cave_los_grid(g_ptr));
3394-
3395-
3396- /* Check the "ease" of visibility */
3397- z1 = (v1 && (g1_c_ptr->info & (CAVE_XTRA)));
3398- z2 = (v2 && (g2_c_ptr->info & (CAVE_XTRA)));
3399-
3400- /* Hack -- "easy" plus "easy" yields "easy" */
3401- if (z1 && z2)
3402- {
3403- g_ptr->info |= (CAVE_XTRA);
3404-
3405- cave_view_hack(g_ptr, y, x);
3406-
3407- return (wall);
3408- }
3409-
3410- /* Hack -- primary "easy" yields "viewed" */
3411- if (z1)
3412- {
3413- cave_view_hack(g_ptr, y, x);
3414-
3415- return (wall);
3416- }
3417-
3418- /* Hack -- "view" plus "view" yields "view" */
3419- if (v1 && v2)
3420- {
3421- /* g_ptr->info |= (CAVE_XTRA); */
3422-
3423- cave_view_hack(g_ptr, y, x);
3424-
3425- return (wall);
3426- }
3427-
3428-
3429- /* Mega-Hack -- the "los()" function works poorly on walls */
3430- if (wall)
3431- {
3432- cave_view_hack(g_ptr, y, x);
3433-
3434- return (wall);
3435- }
3436-
3437-
3438- /* Hack -- check line of sight */
3439- if (los(p_ptr->y, p_ptr->x, y, x))
3440- {
3441- cave_view_hack(g_ptr, y, x);
3442-
3443- return (wall);
3444- }
3445-
3446-
3447- /* Assume no line of sight. */
3448- return (TRUE);
3449-}
3450-
3451-
3452-
3453-/*
3454- * Calculate the viewable space
3455- *
3456- * 1: Process the player
3457- * 1a: The player is always (easily) viewable
3458- * 2: Process the diagonals
3459- * 2a: The diagonals are (easily) viewable up to the first wall
3460- * 2b: But never go more than 2/3 of the "full" distance
3461- * 3: Process the main axes
3462- * 3a: The main axes are (easily) viewable up to the first wall
3463- * 3b: But never go more than the "full" distance
3464- * 4: Process sequential "strips" in each of the eight octants
3465- * 4a: Each strip runs along the previous strip
3466- * 4b: The main axes are "previous" to the first strip
3467- * 4c: Process both "sides" of each "direction" of each strip
3468- * 4c1: Each side aborts as soon as possible
3469- * 4c2: Each side tells the next strip how far it has to check
3470- *
3471- * Note that the octant processing involves some pretty interesting
3472- * observations involving when a grid might possibly be viewable from
3473- * a given grid, and on the order in which the strips are processed.
3474- *
3475- * Note the use of the mathematical facts shown below, which derive
3476- * from the fact that (1 < sqrt(2) < 1.5), and that the length of the
3477- * hypotenuse of a right triangle is primarily determined by the length
3478- * of the longest side, when one side is small, and is strictly less
3479- * than one-and-a-half times as long as the longest side when both of
3480- * the sides are large.
3481- *
3482- * if (manhatten(dy,dx) < R) then (hypot(dy,dx) < R)
3483- * if (manhatten(dy,dx) > R*3/2) then (hypot(dy,dx) > R)
3484- *
3485- * hypot(dy,dx) is approximated by (dx+dy+MAX(dx,dy)) / 2
3486- *
3487- * These observations are important because the calculation of the actual
3488- * value of "hypot(dx,dy)" is extremely expensive, involving square roots,
3489- * while for small values (up to about 20 or so), the approximations above
3490- * are correct to within an error of at most one grid or so.
3491- *
3492- * Observe the use of "full" and "over" in the code below, and the use of
3493- * the specialized calculation involving "limit", all of which derive from
3494- * the observations given above. Basically, we note that the "circle" of
3495- * view is completely contained in an "octagon" whose bounds are easy to
3496- * determine, and that only a few steps are needed to derive the actual
3497- * bounds of the circle given the bounds of the octagon.
3498- *
3499- * Note that by skipping all the grids in the corners of the octagon, we
3500- * place an upper limit on the number of grids in the field of view, given
3501- * that "full" is never more than 20. Of the 1681 grids in the "square" of
3502- * view, only about 1475 of these are in the "octagon" of view, and even
3503- * fewer are in the "circle" of view, so 1500 or 1536 is more than enough
3504- * entries to completely contain the actual field of view.
3505- *
3506- * Note also the care taken to prevent "running off the map". The use of
3507- * explicit checks on the "validity" of the "diagonal", and the fact that
3508- * the loops are never allowed to "leave" the map, lets "update_view_aux()"
3509- * use the optimized "cave_los_bold()" macro, and to avoid the overhead
3510- * of multiple checks on the validity of grids.
3511- *
3512- * Note the "optimizations" involving the "se","sw","ne","nw","es","en",
3513- * "ws","wn" variables. They work like this: While travelling down the
3514- * south-bound strip just to the east of the main south axis, as soon as
3515- * we get to a grid which does not "transmit" viewing, if all of the strips
3516- * preceding us (in this case, just the main axis) had terminated at or before
3517- * the same point, then we can stop, and reset the "max distance" to ourself.
3518- * So, each strip (named by major axis plus offset, thus "se" in this case)
3519- * maintains a "blockage" variable, initialized during the main axis step,
3520- * and checks it whenever a blockage is observed. After processing each
3521- * strip as far as the previous strip told us to process, the next strip is
3522- * told not to go farther than the current strip's farthest viewable grid,
3523- * unless open space is still available. This uses the "k" variable.
3524- *
3525- * Note the use of "inline" macros for efficiency. The "cave_los_grid()"
3526- * macro is a replacement for "cave_los_bold()" which takes a pointer to
3527- * a grid instead of its location. The "cave_view_hack()" macro is a
3528- * chunk of code which adds the given location to the "view" array if it
3529- * is not already there, using both the actual location and a pointer to
3530- * the grid. See above.
3531- *
3532- * By the way, the purpose of this code is to reduce the dependancy on the
3533- * "los()" function which is slow, and, in some cases, not very accurate.
3534- *
3535- * It is very possible that I am the only person who fully understands this
3536- * function, and for that I am truly sorry, but efficiency was very important
3537- * and the "simple" version of this function was just not fast enough. I am
3538- * more than willing to replace this function with a simpler one, if it is
3539- * equally efficient, and especially willing if the new function happens to
3540- * derive "reverse-line-of-sight" at the same time, since currently monsters
3541- * just use an optimized hack of "you see me, so I see you", and then use the
3542- * actual "projectable()" function to check spell attacks.
3543- */
3544-void update_view(void)
3545-{
3546- int n, m, d, k, z;
3547- POSITION y, x;
3548-
3549- int se, sw, ne, nw, es, en, ws, wn;
3550-
3551- int full, over;
3552-
3553- POSITION y_max = cur_hgt - 1;
3554- POSITION x_max = cur_wid - 1;
3555-
3556- grid_type *g_ptr;
3557-
3558- /*** Initialize ***/
3559-
3560- /* Optimize */
3561- if (view_reduce_view && !dun_level)
3562- {
3563- /* Full radius (10) */
3564- full = MAX_SIGHT / 2;
3565-
3566- /* Octagon factor (15) */
3567- over = MAX_SIGHT * 3 / 4;
3568- }
3569-
3570- /* Normal */
3571- else
3572- {
3573- /* Full radius (20) */
3574- full = MAX_SIGHT;
3575-
3576- /* Octagon factor (30) */
3577- over = MAX_SIGHT * 3 / 2;
3578- }
3579-
3580-
3581- /*** Step 0 -- Begin ***/
3582-
3583- /* Save the old "view" grids for later */
3584- for (n = 0; n < view_n; n++)
3585- {
3586- y = view_y[n];
3587- x = view_x[n];
3588- g_ptr = &grid_array[y][x];
3589-
3590- /* Mark the grid as not in "view" */
3591- g_ptr->info &= ~(CAVE_VIEW);
3592-
3593- /* Mark the grid as "seen" */
3594- g_ptr->info |= (CAVE_TEMP);
3595-
3596- /* Add it to the "seen" set */
3597- temp_y[temp_n] = y;
3598- temp_x[temp_n] = x;
3599- temp_n++;
3600- }
3601-
3602- /* Start over with the "view" array */
3603- view_n = 0;
3604-
3605- /*** Step 1 -- adjacent grids ***/
3606-
3607- /* Now start on the player */
3608- y = p_ptr->y;
3609- x = p_ptr->x;
3610- g_ptr = &grid_array[y][x];
3611-
3612- /* Assume the player grid is easily viewable */
3613- g_ptr->info |= (CAVE_XTRA);
3614-
3615- /* Assume the player grid is viewable */
3616- cave_view_hack(g_ptr, y, x);
3617-
3618-
3619- /*** Step 2 -- Major Diagonals ***/
3620-
3621- /* Hack -- Limit */
3622- z = full * 2 / 3;
3623-
3624- /* Scan south-east */
3625- for (d = 1; d <= z; d++)
3626- {
3627- g_ptr = &grid_array[y+d][x+d];
3628- g_ptr->info |= (CAVE_XTRA);
3629- cave_view_hack(g_ptr, y+d, x+d);
3630- if (!cave_los_grid(g_ptr)) break;
3631- }
3632-
3633- /* Scan south-west */
3634- for (d = 1; d <= z; d++)
3635- {
3636- g_ptr = &grid_array[y+d][x-d];
3637- g_ptr->info |= (CAVE_XTRA);
3638- cave_view_hack(g_ptr, y+d, x-d);
3639- if (!cave_los_grid(g_ptr)) break;
3640- }
3641-
3642- /* Scan north-east */
3643- for (d = 1; d <= z; d++)
3644- {
3645- g_ptr = &grid_array[y-d][x+d];
3646- g_ptr->info |= (CAVE_XTRA);
3647- cave_view_hack(g_ptr, y-d, x+d);
3648- if (!cave_los_grid(g_ptr)) break;
3649- }
3650-
3651- /* Scan north-west */
3652- for (d = 1; d <= z; d++)
3653- {
3654- g_ptr = &grid_array[y-d][x-d];
3655- g_ptr->info |= (CAVE_XTRA);
3656- cave_view_hack(g_ptr, y-d, x-d);
3657- if (!cave_los_grid(g_ptr)) break;
3658- }
3659-
3660- /*** Step 3 -- major axes ***/
3661-
3662- /* Scan south */
3663- for (d = 1; d <= full; d++)
3664- {
3665- g_ptr = &grid_array[y+d][x];
3666- g_ptr->info |= (CAVE_XTRA);
3667- cave_view_hack(g_ptr, y+d, x);
3668- if (!cave_los_grid(g_ptr)) break;
3669- }
3670-
3671- /* Initialize the "south strips" */
3672- se = sw = d;
3673-
3674- /* Scan north */
3675- for (d = 1; d <= full; d++)
3676- {
3677- g_ptr = &grid_array[y-d][x];
3678- g_ptr->info |= (CAVE_XTRA);
3679- cave_view_hack(g_ptr, y-d, x);
3680- if (!cave_los_grid(g_ptr)) break;
3681- }
3682-
3683- /* Initialize the "north strips" */
3684- ne = nw = d;
3685-
3686- /* Scan east */
3687- for (d = 1; d <= full; d++)
3688- {
3689- g_ptr = &grid_array[y][x+d];
3690- g_ptr->info |= (CAVE_XTRA);
3691- cave_view_hack(g_ptr, y, x+d);
3692- if (!cave_los_grid(g_ptr)) break;
3693- }
3694-
3695- /* Initialize the "east strips" */
3696- es = en = d;
3697-
3698- /* Scan west */
3699- for (d = 1; d <= full; d++)
3700- {
3701- g_ptr = &grid_array[y][x-d];
3702- g_ptr->info |= (CAVE_XTRA);
3703- cave_view_hack(g_ptr, y, x-d);
3704- if (!cave_los_grid(g_ptr)) break;
3705- }
3706-
3707- /* Initialize the "west strips" */
3708- ws = wn = d;
3709-
3710-
3711- /*** Step 4 -- Divide each "octant" into "strips" ***/
3712-
3713- /* Now check each "diagonal" (in parallel) */
3714- for (n = 1; n <= over / 2; n++)
3715- {
3716- POSITION ypn, ymn, xpn, xmn;
3717-
3718- /* Acquire the "bounds" of the maximal circle */
3719- z = over - n - n;
3720- if (z > full - n) z = full - n;
3721- while ((z + n + (n>>1)) > full) z--;
3722-
3723-
3724- /* Access the four diagonal grids */
3725- ypn = y + n;
3726- ymn = y - n;
3727- xpn = x + n;
3728- xmn = x - n;
3729-
3730-
3731- /* South strip */
3732- if (ypn < y_max)
3733- {
3734- /* Maximum distance */
3735- m = MIN(z, y_max - ypn);
3736-
3737- /* East side */
3738- if ((xpn <= x_max) && (n < se))
3739- {
3740- /* Scan */
3741- for (k = n, d = 1; d <= m; d++)
3742- {
3743- /* Check grid "d" in strip "n", notice "blockage" */
3744- if (update_view_aux(ypn+d, xpn, ypn+d-1, xpn-1, ypn+d-1, xpn))
3745- {
3746- if (n + d >= se) break;
3747- }
3748-
3749- /* Track most distant "non-blockage" */
3750- else
3751- {
3752- k = n + d;
3753- }
3754- }
3755-
3756- /* Limit the next strip */
3757- se = k + 1;
3758- }
3759-
3760- /* West side */
3761- if ((xmn >= 0) && (n < sw))
3762- {
3763- /* Scan */
3764- for (k = n, d = 1; d <= m; d++)
3765- {
3766- /* Check grid "d" in strip "n", notice "blockage" */
3767- if (update_view_aux(ypn+d, xmn, ypn+d-1, xmn+1, ypn+d-1, xmn))
3768- {
3769- if (n + d >= sw) break;
3770- }
3771-
3772- /* Track most distant "non-blockage" */
3773- else
3774- {
3775- k = n + d;
3776- }
3777- }
3778-
3779- /* Limit the next strip */
3780- sw = k + 1;
3781- }
3782- }
3783-
3784-
3785- /* North strip */
3786- if (ymn > 0)
3787- {
3788- /* Maximum distance */
3789- m = MIN(z, ymn);
3790-
3791- /* East side */
3792- if ((xpn <= x_max) && (n < ne))
3793- {
3794- /* Scan */
3795- for (k = n, d = 1; d <= m; d++)
3796- {
3797- /* Check grid "d" in strip "n", notice "blockage" */
3798- if (update_view_aux(ymn-d, xpn, ymn-d+1, xpn-1, ymn-d+1, xpn))
3799- {
3800- if (n + d >= ne) break;
3801- }
3802-
3803- /* Track most distant "non-blockage" */
3804- else
3805- {
3806- k = n + d;
3807- }
3808- }
3809-
3810- /* Limit the next strip */
3811- ne = k + 1;
3812- }
3813-
3814- /* West side */
3815- if ((xmn >= 0) && (n < nw))
3816- {
3817- /* Scan */
3818- for (k = n, d = 1; d <= m; d++)
3819- {
3820- /* Check grid "d" in strip "n", notice "blockage" */
3821- if (update_view_aux(ymn-d, xmn, ymn-d+1, xmn+1, ymn-d+1, xmn))
3822- {
3823- if (n + d >= nw) break;
3824- }
3825-
3826- /* Track most distant "non-blockage" */
3827- else
3828- {
3829- k = n + d;
3830- }
3831- }
3832-
3833- /* Limit the next strip */
3834- nw = k + 1;
3835- }
3836- }
3837-
3838-
3839- /* East strip */
3840- if (xpn < x_max)
3841- {
3842- /* Maximum distance */
3843- m = MIN(z, x_max - xpn);
3844-
3845- /* South side */
3846- if ((ypn <= x_max) && (n < es))
3847- {
3848- /* Scan */
3849- for (k = n, d = 1; d <= m; d++)
3850- {
3851- /* Check grid "d" in strip "n", notice "blockage" */
3852- if (update_view_aux(ypn, xpn+d, ypn-1, xpn+d-1, ypn, xpn+d-1))
3853- {
3854- if (n + d >= es) break;
3855- }
3856-
3857- /* Track most distant "non-blockage" */
3858- else
3859- {
3860- k = n + d;
3861- }
3862- }
3863-
3864- /* Limit the next strip */
3865- es = k + 1;
3866- }
3867-
3868- /* North side */
3869- if ((ymn >= 0) && (n < en))
3870- {
3871- /* Scan */
3872- for (k = n, d = 1; d <= m; d++)
3873- {
3874- /* Check grid "d" in strip "n", notice "blockage" */
3875- if (update_view_aux(ymn, xpn+d, ymn+1, xpn+d-1, ymn, xpn+d-1))
3876- {
3877- if (n + d >= en) break;
3878- }
3879-
3880- /* Track most distant "non-blockage" */
3881- else
3882- {
3883- k = n + d;
3884- }
3885- }
3886-
3887- /* Limit the next strip */
3888- en = k + 1;
3889- }
3890- }
3891-
3892-
3893- /* West strip */
3894- if (xmn > 0)
3895- {
3896- /* Maximum distance */
3897- m = MIN(z, xmn);
3898-
3899- /* South side */
3900- if ((ypn <= y_max) && (n < ws))
3901- {
3902- /* Scan */
3903- for (k = n, d = 1; d <= m; d++)
3904- {
3905- /* Check grid "d" in strip "n", notice "blockage" */
3906- if (update_view_aux(ypn, xmn-d, ypn-1, xmn-d+1, ypn, xmn-d+1))
3907- {
3908- if (n + d >= ws) break;
3909- }
3910-
3911- /* Track most distant "non-blockage" */
3912- else
3913- {
3914- k = n + d;
3915- }
3916- }
3917-
3918- /* Limit the next strip */
3919- ws = k + 1;
3920- }
3921-
3922- /* North side */
3923- if ((ymn >= 0) && (n < wn))
3924- {
3925- /* Scan */
3926- for (k = n, d = 1; d <= m; d++)
3927- {
3928- /* Check grid "d" in strip "n", notice "blockage" */
3929- if (update_view_aux(ymn, xmn-d, ymn+1, xmn-d+1, ymn, xmn-d+1))
3930- {
3931- if (n + d >= wn) break;
3932- }
3933-
3934- /* Track most distant "non-blockage" */
3935- else
3936- {
3937- k = n + d;
3938- }
3939- }
3940-
3941- /* Limit the next strip */
3942- wn = k + 1;
3943- }
3944- }
3945- }
3946-
3947-
3948- /*** Step 5 -- Complete the algorithm ***/
3949-
3950- /* Update all the new grids */
3951- for (n = 0; n < view_n; n++)
3952- {
3953- y = view_y[n];
3954- x = view_x[n];
3955- g_ptr = &grid_array[y][x];
3956-
3957- /* Clear the "CAVE_XTRA" flag */
3958- g_ptr->info &= ~(CAVE_XTRA);
3959-
3960- /* Update only newly viewed grids */
3961- if (g_ptr->info & (CAVE_TEMP)) continue;
3962-
3963- /* Add it to later visual update */
3964- cave_note_and_redraw_later(g_ptr, y, x);
3965- }
3966-
3967- /* Wipe the old grids, update as needed */
3968- for (n = 0; n < temp_n; n++)
3969- {
3970- y = temp_y[n];
3971- x = temp_x[n];
3972- g_ptr = &grid_array[y][x];
3973-
3974- /* No longer in the array */
3975- g_ptr->info &= ~(CAVE_TEMP);
3976-
3977- /* Update only non-viewable grids */
3978- if (g_ptr->info & (CAVE_VIEW)) continue;
3979-
3980- /* Add it to later visual update */
3981- cave_redraw_later(g_ptr, y, x);
3982- }
3983-
3984- /* None left */
3985- temp_n = 0;
3986-
3987- /* Mega-Hack -- Visual update later */
3988- p_ptr->update |= (PU_DELAY_VIS);
3989-}
3990-
3991-
3992-/*
3993- * Mega-Hack -- Delayed visual update
3994- * Only used if update_view(), update_lite() or update_mon_lite() was called
3995- */
3996-void delayed_visual_update(void)
3997-{
3998- int i;
3999- POSITION y, x;
4000- grid_type *g_ptr;
4001-
4002- /* Update needed grids */
4003- for (i = 0; i < redraw_n; i++)
4004- {
4005- y = redraw_y[i];
4006- x = redraw_x[i];
4007- g_ptr = &grid_array[y][x];
4008-
4009- /* Update only needed grids (prevent multiple updating) */
4010- if (!(g_ptr->info & CAVE_REDRAW)) continue;
4011-
4012- /* If required, note */
4013- if (g_ptr->info & CAVE_NOTE) note_spot(y, x);
4014-
4015- lite_spot(y, x);
4016-
4017- /* Hack -- Visual update of monster on this grid */
4018- if (g_ptr->m_idx) update_monster(g_ptr->m_idx, FALSE);
4019-
4020- /* No longer in the array */
4021- g_ptr->info &= ~(CAVE_NOTE | CAVE_REDRAW);
4022- }
4023-
4024- /* None left */
4025- redraw_n = 0;
4026-}
4027-
4028-
4029-/*
4030- * Hack -- forget the "flow" information
4031- */
4032-void forget_flow(void)
4033-{
4034- POSITION x, y;
4035-
4036- /* Check the entire dungeon */
4037- for (y = 0; y < cur_hgt; y++)
4038- {
4039- for (x = 0; x < cur_wid; x++)
4040- {
4041- /* Forget the old data */
4042- grid_array[y][x].dist = 0;
4043- grid_array[y][x].cost = 0;
4044- grid_array[y][x].when = 0;
4045- }
4046- }
4047-}
4048-
4049-
4050-/*
4051- * Hack - speed up the update_flow algorithm by only doing
4052- * it everytime the player moves out of LOS of the last
4053- * "way-point".
4054- */
4055-static POSITION flow_x = 0;
4056-static POSITION flow_y = 0;
4057-
4058-
4059-
4060-/*
4061- * Hack -- fill in the "cost" field of every grid that the player
4062- * can "reach" with the number of steps needed to reach that grid.
4063- * This also yields the "distance" of the player from every grid.
4064- *
4065- * In addition, mark the "when" of the grids that can reach
4066- * the player with the incremented value of "flow_n".
4067- *
4068- * Hack -- use the "seen" array as a "circular queue".
4069- *
4070- * We do not need a priority queue because the cost from grid
4071- * to grid is always "one" and we process them in order.
4072- */
4073-void update_flow(void)
4074-{
4075- POSITION x, y;
4076- DIRECTION d;
4077- int flow_head = 1;
4078- int flow_tail = 0;
4079-
4080- /* Paranoia -- make sure the array is empty */
4081- if (temp_n) return;
4082-
4083- /* The last way-point is on the map */
4084- if (running && in_bounds(flow_y, flow_x))
4085- {
4086- /* The way point is in sight - do not update. (Speedup) */
4087- if (grid_array[flow_y][flow_x].info & CAVE_VIEW) return;
4088- }
4089-
4090- /* Erase all of the current flow information */
4091- for (y = 0; y < cur_hgt; y++)
4092- {
4093- for (x = 0; x < cur_wid; x++)
4094- {
4095- grid_array[y][x].cost = 0;
4096- grid_array[y][x].dist = 0;
4097- }
4098- }
4099-
4100- /* Save player position */
4101- flow_y = p_ptr->y;
4102- flow_x = p_ptr->x;
4103-
4104- /* Add the player's grid to the queue */
4105- temp_y[0] = p_ptr->y;
4106- temp_x[0] = p_ptr->x;
4107-
4108- /* Now process the queue */
4109- while (flow_head != flow_tail)
4110- {
4111- int ty, tx;
4112-
4113- /* Extract the next entry */
4114- ty = temp_y[flow_tail];
4115- tx = temp_x[flow_tail];
4116-
4117- /* Forget that entry */
4118- if (++flow_tail == TEMP_MAX) flow_tail = 0;
4119-
4120- /* Add the "children" */
4121- for (d = 0; d < 8; d++)
4122- {
4123- int old_head = flow_head;
4124- byte_hack m = grid_array[ty][tx].cost + 1;
4125- byte_hack n = grid_array[ty][tx].dist + 1;
4126- grid_type *g_ptr;
4127-
4128- /* Child location */
4129- y = ty + ddy_ddd[d];
4130- x = tx + ddx_ddd[d];
4131-
4132- /* Ignore player's grid */
4133- if (player_bold(y, x)) continue;
4134-
4135- g_ptr = &grid_array[y][x];
4136-
4137- if (is_closed_door(g_ptr->feat)) m += 3;
4138-
4139- /* Ignore "pre-stamped" entries */
4140- if (g_ptr->dist != 0 && g_ptr->dist <= n && g_ptr->cost <= m) continue;
4141-
4142- /* Ignore "walls" and "rubble" */
4143- if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
4144-
4145- /* Save the flow cost */
4146- if (g_ptr->cost == 0 || g_ptr->cost > m) g_ptr->cost = m;
4147- if (g_ptr->dist == 0 || g_ptr->dist > n) g_ptr->dist = n;
4148-
4149- /* Hack -- limit flow depth */
4150- if (n == MONSTER_FLOW_DEPTH) continue;
4151-
4152- /* Enqueue that entry */
4153- temp_y[flow_head] = y;
4154- temp_x[flow_head] = x;
4155-
4156- /* Advance the queue */
4157- if (++flow_head == TEMP_MAX) flow_head = 0;
4158-
4159- /* Hack -- notice overflow by forgetting new entry */
4160- if (flow_head == flow_tail) flow_head = old_head;
4161- }
4162- }
4163-}
4164-
4165-
4166-static int scent_when = 0;
4167-
4168-/*
4169- * Characters leave scent trails for perceptive monsters to track.
4170- *
4171- * Smell is rather more limited than sound. Many creatures cannot use
4172- * it at all, it doesn't extend very far outwards from the character's
4173- * current position, and monsters can use it to home in the character,
4174- * but not to run away from him.
4175- *
4176- * Smell is valued according to age. When a character takes his turn,
4177- * scent is aged by one, and new scent of the current age is laid down.
4178- * Speedy characters leave more scent, true, but it also ages faster,
4179- * which makes it harder to hunt them down.
4180- *
4181- * Whenever the age count loops, most of the scent trail is erased and
4182- * the age of the remainder is recalculated.
4183- */
4184-void update_smell(void)
4185-{
4186- POSITION i, j;
4187- POSITION y, x;
4188-
4189- /* Create a table that controls the spread of scent */
4190- const int scent_adjust[5][5] =
4191- {
4192- { -1, 0, 0, 0,-1 },
4193- { 0, 1, 1, 1, 0 },
4194- { 0, 1, 2, 1, 0 },
4195- { 0, 1, 1, 1, 0 },
4196- { -1, 0, 0, 0,-1 },
4197- };
4198-
4199- /* Loop the age and adjust scent values when necessary */
4200- if (++scent_when == 254)
4201- {
4202- /* Scan the entire dungeon */
4203- for (y = 0; y < cur_hgt; y++)
4204- {
4205- for (x = 0; x < cur_wid; x++)
4206- {
4207- int w = grid_array[y][x].when;
4208- grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
4209- }
4210- }
4211-
4212- /* Restart */
4213- scent_when = 126;
4214- }
4215-
4216-
4217- /* Lay down new scent */
4218- for (i = 0; i < 5; i++)
4219- {
4220- for (j = 0; j < 5; j++)
4221- {
4222- grid_type *g_ptr;
4223-
4224- /* Translate table to map grids */
4225- y = i + p_ptr->y - 2;
4226- x = j + p_ptr->x - 2;
4227-
4228- /* Check Bounds */
4229- if (!in_bounds(y, x)) continue;
4230-
4231- g_ptr = &grid_array[y][x];
4232-
4233- /* Walls, water, and lava cannot hold scent. */
4234- if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
4235-
4236- /* Grid must not be blocked by walls from the character */
4237- if (!player_has_los_bold(y, x)) continue;
4238-
4239- /* Note grids that are too far away */
4240- if (scent_adjust[i][j] == -1) continue;
4241-
4242- /* Mark the grid with new scent */
4243- g_ptr->when = scent_when + scent_adjust[i][j];
4244- }
4245- }
4246-}
4247-
4248-
4249-/*
4250- * Hack -- map the current panel (plus some) ala "magic mapping"
4251- */
4252-void map_area(POSITION range)
4253-{
4254- int i;
4255- POSITION x, y;
4256- grid_type *g_ptr;
4257- FEAT_IDX feat;
4258- feature_type *f_ptr;
4259-
4260- if (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS) range /= 3;
4261-
4262- /* Scan that area */
4263- for (y = 1; y < cur_hgt - 1; y++)
4264- {
4265- for (x = 1; x < cur_wid - 1; x++)
4266- {
4267- if (distance(p_ptr->y, p_ptr->x, y, x) > range) continue;
4268-
4269- g_ptr = &grid_array[y][x];
4270-
4271- /* Memorize terrain of the grid */
4272- g_ptr->info |= (CAVE_KNOWN);
4273-
4274- /* Feature code (applying "mimic" field) */
4275- feat = get_feat_mimic(g_ptr);
4276- f_ptr = &f_info[feat];
4277-
4278- /* All non-walls are "checked" */
4279- if (!have_flag(f_ptr->flags, FF_WALL))
4280- {
4281- /* Memorize normal features */
4282- if (have_flag(f_ptr->flags, FF_REMEMBER))
4283- {
4284- /* Memorize the object */
4285- g_ptr->info |= (CAVE_MARK);
4286- }
4287-
4288- /* Memorize known walls */
4289- for (i = 0; i < 8; i++)
4290- {
4291- g_ptr = &grid_array[y + ddy_ddd[i]][x + ddx_ddd[i]];
4292-
4293- /* Feature code (applying "mimic" field) */
4294- feat = get_feat_mimic(g_ptr);
4295- f_ptr = &f_info[feat];
4296-
4297- /* Memorize walls (etc) */
4298- if (have_flag(f_ptr->flags, FF_REMEMBER))
4299- {
4300- /* Memorize the walls */
4301- g_ptr->info |= (CAVE_MARK);
4302- }
4303- }
4304- }
4305- }
4306- }
4307-
4308- p_ptr->redraw |= (PR_MAP);
4309-
4310- p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
4311-}
4312-
4313-
4314-/*
4315- * Change the "feat" flag for a grid, and notice/redraw the grid
4316- */
4317-void cave_set_feat(POSITION y, POSITION x, FEAT_IDX feat)
4318-{
4319- grid_type *g_ptr = &grid_array[y][x];
4320- feature_type *f_ptr = &f_info[feat];
4321- bool old_los, old_mirror;
4322-
4323- if (!character_dungeon)
4324- {
4325- /* Clear mimic type */
4326- g_ptr->mimic = 0;
4327-
4328- /* Change the feature */
4329- g_ptr->feat = feat;
4330-
4331- /* Hack -- glow the GLOW terrain */
4332- if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
4333- {
4334- DIRECTION i;
4335- POSITION yy, xx;
4336-
4337- for (i = 0; i < 9; i++)
4338- {
4339- yy = y + ddy_ddd[i];
4340- xx = x + ddx_ddd[i];
4341- if (!in_bounds2(yy, xx)) continue;
4342- grid_array[yy][xx].info |= CAVE_GLOW;
4343- }
4344- }
4345-
4346- return;
4347- }
4348-
4349- old_los = cave_have_flag_bold(y, x, FF_LOS);
4350- old_mirror = is_mirror_grid(g_ptr);
4351-
4352- /* Clear mimic type */
4353- g_ptr->mimic = 0;
4354-
4355- /* Change the feature */
4356- g_ptr->feat = feat;
4357-
4358- /* Remove flag for mirror/glyph */
4359- g_ptr->info &= ~(CAVE_OBJECT);
4360-
4361- if (old_mirror && (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
4362- {
4363- g_ptr->info &= ~(CAVE_GLOW);
4364- if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
4365-
4366- update_local_illumination(y, x);
4367- }
4368-
4369- /* Check for change to boring grid */
4370- if (!have_flag(f_ptr->flags, FF_REMEMBER)) g_ptr->info &= ~(CAVE_MARK);
4371- if (g_ptr->m_idx) update_monster(g_ptr->m_idx, FALSE);
4372-
4373- note_spot(y, x);
4374-
4375- lite_spot(y, x);
4376-
4377- /* Check if los has changed */
4378- if (old_los ^ have_flag(f_ptr->flags, FF_LOS))
4379- {
4380-
4381-#ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
4382-
4383- update_local_illumination(y, x);
4384-
4385-#endif /* COMPLEX_WALL_ILLUMINATION */
4386-
4387- /* Update the visuals */
4388- p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS);
4389- }
4390-
4391- /* Hack -- glow the GLOW terrain */
4392- if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
4393- {
4394- DIRECTION i;
4395- POSITION yy, xx;
4396- grid_type *cc_ptr;
4397-
4398- for (i = 0; i < 9; i++)
4399- {
4400- yy = y + ddy_ddd[i];
4401- xx = x + ddx_ddd[i];
4402- if (!in_bounds2(yy, xx)) continue;
4403- cc_ptr = &grid_array[yy][xx];
4404- cc_ptr->info |= CAVE_GLOW;
4405-
4406- if (player_has_los_grid(cc_ptr))
4407- {
4408- if (cc_ptr->m_idx) update_monster(cc_ptr->m_idx, FALSE);
4409-
4410- note_spot(yy, xx);
4411-
4412- lite_spot(yy, xx);
4413- }
4414-
4415- update_local_illumination(yy, xx);
4416- }
4417-
4418- if (p_ptr->special_defense & NINJA_S_STEALTH)
4419- {
4420- if (grid_array[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(FALSE);
4421- }
4422- }
4423-}
4424-
4425-
4426-FEAT_IDX conv_dungeon_feat(FEAT_IDX newfeat)
4427-{
4428- feature_type *f_ptr = &f_info[newfeat];
4429-
4430- if (have_flag(f_ptr->flags, FF_CONVERT))
4431- {
4432- switch (f_ptr->subtype)
4433- {
4434- case CONVERT_TYPE_FLOOR:
4435- return feat_ground_type[randint0(100)];
4436- case CONVERT_TYPE_WALL:
4437- return feat_wall_type[randint0(100)];
4438- case CONVERT_TYPE_INNER:
4439- return feat_wall_inner;
4440- case CONVERT_TYPE_OUTER:
4441- return feat_wall_outer;
4442- case CONVERT_TYPE_SOLID:
4443- return feat_wall_solid;
4444- case CONVERT_TYPE_STREAM1:
4445- return d_info[p_ptr->dungeon_idx].stream1;
4446- case CONVERT_TYPE_STREAM2:
4447- return d_info[p_ptr->dungeon_idx].stream2;
4448- default:
4449- return newfeat;
4450- }
4451- }
4452- else return newfeat;
4453-}
4454-
4455-
4456-/*
4457- * Take a feature, determine what that feature becomes
4458- * through applying the given action.
4459- */
4460-FEAT_IDX feat_state(FEAT_IDX feat, int action)
4461-{
4462- feature_type *f_ptr = &f_info[feat];
4463- int i;
4464-
4465- /* Get the new feature */
4466- for (i = 0; i < MAX_FEAT_STATES; i++)
4467- {
4468- if (f_ptr->state[i].action == action) return conv_dungeon_feat(f_ptr->state[i].result);
4469- }
4470-
4471- if (have_flag(f_ptr->flags, FF_PERMANENT)) return feat;
4472-
4473- return (feature_action_flags[action] & FAF_DESTROY) ? conv_dungeon_feat(f_ptr->destroyed) : feat;
4474-}
4475-
4476-/*
4477- * Takes a location and action and changes the feature at that
4478- * location through applying the given action.
4479- */
4480-void cave_alter_feat(POSITION y, POSITION x, int action)
4481-{
4482- /* Set old feature */
4483- FEAT_IDX oldfeat = grid_array[y][x].feat;
4484-
4485- /* Get the new feat */
4486- FEAT_IDX newfeat = feat_state(oldfeat, action);
4487-
4488- /* No change */
4489- if (newfeat == oldfeat) return;
4490-
4491- /* Set the new feature */
4492- cave_set_feat(y, x, newfeat);
4493-
4494- if (!(feature_action_flags[action] & FAF_NO_DROP))
4495- {
4496- feature_type *old_f_ptr = &f_info[oldfeat];
4497- feature_type *f_ptr = &f_info[newfeat];
4498- bool found = FALSE;
4499-
4500- /* Handle gold */
4501- if (have_flag(old_f_ptr->flags, FF_HAS_GOLD) && !have_flag(f_ptr->flags, FF_HAS_GOLD))
4502- {
4503- /* Place some gold */
4504- place_gold(y, x);
4505- found = TRUE;
4506- }
4507-
4508- /* Handle item */
4509- if (have_flag(old_f_ptr->flags, FF_HAS_ITEM) && !have_flag(f_ptr->flags, FF_HAS_ITEM) && (randint0(100) < (15 - dun_level / 2)))
4510- {
4511- /* Place object */
4512- place_object(y, x, 0L);
4513- found = TRUE;
4514- }
4515-
4516- if (found && character_dungeon && player_can_see_bold(y, x))
4517- {
4518- msg_print(_("何かを発見した!", "You have found something!"));
4519- }
4520- }
4521-
4522- if (feature_action_flags[action] & FAF_CRASH_GLASS)
4523- {
4524- feature_type *old_f_ptr = &f_info[oldfeat];
4525-
4526- if (have_flag(old_f_ptr->flags, FF_GLASS) && character_dungeon)
4527- {
4528- project(PROJECT_WHO_GLASS_SHARDS, 1, y, x, MIN(dun_level, 100) / 4, GF_SHARDS,
4529- (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_HIDE | PROJECT_JUMP | PROJECT_NO_HANGEKI), -1);
4530- }
4531- }
4532-}
4533-
4534-
4535-/* Remove a mirror */
4536-void remove_mirror(POSITION y, POSITION x)
4537-{
4538- grid_type *g_ptr = &grid_array[y][x];
4539-
4540- /* Remove the mirror */
4541- g_ptr->info &= ~(CAVE_OBJECT);
4542- g_ptr->mimic = 0;
4543-
4544- if (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
4545- {
4546- g_ptr->info &= ~(CAVE_GLOW);
4547- if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
4548- if (g_ptr->m_idx) update_monster(g_ptr->m_idx, FALSE);
4549-
4550- update_local_illumination(y, x);
4551- }
4552-
4553- note_spot(y, x);
4554-
4555- lite_spot(y, x);
4556-}
4557-
4558-
4559-/*
4560- * Return TRUE if there is a mirror on the grid.
4561- */
4562-bool is_mirror_grid(grid_type *g_ptr)
4563-{
4564- if ((g_ptr->info & CAVE_OBJECT) && have_flag(f_info[g_ptr->mimic].flags, FF_MIRROR))
4565- return TRUE;
4566- else
4567- return FALSE;
4568-}
4569-
4570-
4571-/*
4572- * Return TRUE if there is a mirror on the grid.
4573- */
4574-bool is_glyph_grid(grid_type *g_ptr)
4575-{
4576- if ((g_ptr->info & CAVE_OBJECT) && have_flag(f_info[g_ptr->mimic].flags, FF_GLYPH))
4577- return TRUE;
4578- else
4579- return FALSE;
4580-}
4581-
4582-
4583-/*
4584- * Return TRUE if there is a mirror on the grid.
4585- */
4586-bool is_explosive_rune_grid(grid_type *g_ptr)
4587-{
4588- if ((g_ptr->info & CAVE_OBJECT) && have_flag(f_info[g_ptr->mimic].flags, FF_MINOR_GLYPH))
4589- return TRUE;
4590- else
4591- return FALSE;
4592-}
4593-
4594-
4595-/*
4596- * Calculate "incremental motion". Used by project() and shoot().
4597- * Assumes that (*y,*x) lies on the path from (y1,x1) to (y2,x2).
4598- */
4599-void mmove2(POSITION *y, POSITION *x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
4600-{
4601- POSITION dy, dx, dist, shift;
4602-
4603- /* Extract the distance travelled */
4604- dy = (*y < y1) ? y1 - *y : *y - y1;
4605- dx = (*x < x1) ? x1 - *x : *x - x1;
4606-
4607- /* Number of steps */
4608- dist = (dy > dx) ? dy : dx;
4609-
4610- /* We are calculating the next location */
4611- dist++;
4612-
4613-
4614- /* Calculate the total distance along each axis */
4615- dy = (y2 < y1) ? (y1 - y2) : (y2 - y1);
4616- dx = (x2 < x1) ? (x1 - x2) : (x2 - x1);
4617-
4618- /* Paranoia -- Hack -- no motion */
4619- if (!dy && !dx) return;
4620-
4621-
4622- /* Move mostly vertically */
4623- if (dy > dx)
4624- {
4625- /* Extract a shift factor */
4626- shift = (dist * dx + (dy - 1) / 2) / dy;
4627-
4628- /* Sometimes move along the minor axis */
4629- (*x) = (x2 < x1) ? (x1 - shift) : (x1 + shift);
4630-
4631- /* Always move along major axis */
4632- (*y) = (y2 < y1) ? (y1 - dist) : (y1 + dist);
4633- }
4634-
4635- /* Move mostly horizontally */
4636- else
4637- {
4638- /* Extract a shift factor */
4639- shift = (dist * dy + (dx - 1) / 2) / dx;
4640-
4641- /* Sometimes move along the minor axis */
4642- (*y) = (y2 < y1) ? (y1 - shift) : (y1 + shift);
4643-
4644- /* Always move along major axis */
4645- (*x) = (x2 < x1) ? (x1 - dist) : (x1 + dist);
4646- }
4647-}
4648-
4649-
4650-
4651-/*
4652- * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
4653- * at the final destination, assuming no monster gets in the way.
4654- *
4655- * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
4656- */
4657-bool projectable(POSITION y1, POSITION x1, POSITION y2, POSITION x2)
4658-{
4659- POSITION y, x;
4660-
4661- int grid_n = 0;
4662- u16b grid_g[512];
4663-
4664- /* Check the projection path */
4665- grid_n = project_path(grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
4666-
4667- /* Identical grid */
4668- if (!grid_n) return TRUE;
4669-
4670- /* Final grid */
4671- y = GRID_Y(grid_g[grid_n - 1]);
4672- x = GRID_X(grid_g[grid_n - 1]);
4673-
4674- /* May not end in an unrequested grid */
4675- if ((y != y2) || (x != x2)) return (FALSE);
4676-
4677- /* Assume okay */
4678- return (TRUE);
4679-}
4680-
4681-
4682-/*
4683- * Standard "find me a location" function
4684- *
4685- * Obtains a legal location within the given distance of the initial
4686- * location, and with "los()" from the source to destination location.
4687- *
4688- * This function is often called from inside a loop which searches for
4689- * locations while increasing the "d" distance.
4690- *
4691- * Currently the "m" parameter is unused.
4692- */
4693-void scatter(POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION d, BIT_FLAGS mode)
4694-{
4695- POSITION nx, ny;
4696-
4697- /* Pick a location */
4698- while (TRUE)
4699- {
4700- /* Pick a new location */
4701- ny = rand_spread(y, d);
4702- nx = rand_spread(x, d);
4703-
4704- /* Ignore annoying locations */
4705- if (!in_bounds(ny, nx)) continue;
4706-
4707- /* Ignore "excessively distant" locations */
4708- if ((d > 1) && (distance(y, x, ny, nx) > d)) continue;
4709-
4710- if (mode & PROJECT_LOS)
4711- {
4712- if(los(y, x, ny, nx)) break;
4713- }
4714- else
4715- {
4716- if(projectable(y, x, ny, nx)) break;
4717- }
4718-
4719- }
4720-
4721- /* Save the location */
4722- (*yp) = ny;
4723- (*xp) = nx;
4724-}
4725-
4726-
4727-
4728-
4729-/*
4730- * Track a new monster
4731- */
4732-void health_track(MONSTER_IDX m_idx)
4733-{
4734- /* Mount monster is already tracked */
4735- if (m_idx && m_idx == p_ptr->riding) return;
4736-
4737- /* Track a new guy */
4738- p_ptr->health_who = m_idx;
4739-
4740- /* Redraw (later) */
4741- p_ptr->redraw |= (PR_HEALTH);
4742-}
4743-
4744-
4745-
4746-/*
4747- * Hack -- track the given monster race
4748- */
4749-void monster_race_track(MONRACE_IDX r_idx)
4750-{
4751- /* Save this monster ID */
4752- p_ptr->monster_race_idx = r_idx;
4753-
4754- p_ptr->window |= (PW_MONSTER);
4755-}
4756-
4757-
4758-
4759-/*
4760- * Hack -- track the given object kind
4761- */
4762-void object_kind_track(KIND_OBJECT_IDX k_idx)
4763-{
4764- /* Save this monster ID */
4765- p_ptr->object_kind_idx = k_idx;
4766-
4767- p_ptr->window |= (PW_OBJECT);
4768-}
4769-
4770-
4771-
4772-/*
4773- * Something has happened to disturb the player.
4774- *
4775- * The first arg indicates a major disturbance, which affects search.
4776- *
4777- * The second arg is currently unused, but could induce output flush.
4778- *
4779- * All disturbance cancels repeated commands, resting, and running.
4780- */
4781-void disturb(bool stop_search, bool stop_travel)
4782-{
4783-#ifndef TRAVEL
4784- /* Unused */
4785- stop_travel = stop_travel;
4786-#endif
4787-
4788- /* Cancel auto-commands */
4789- /* command_new = 0; */
4790-
4791- /* Cancel repeated commands */
4792- if (command_rep)
4793- {
4794- /* Cancel */
4795- command_rep = 0;
4796-
4797- /* Redraw the state (later) */
4798- p_ptr->redraw |= (PR_STATE);
4799- }
4800-
4801- /* Cancel Resting */
4802- if ((p_ptr->action == ACTION_REST) || (p_ptr->action == ACTION_FISH) || (stop_search && (p_ptr->action == ACTION_SEARCH)))
4803- {
4804- /* Cancel */
4805- set_action(ACTION_NONE);
4806- }
4807-
4808- /* Cancel running */
4809- if (running)
4810- {
4811- /* Cancel */
4812- running = 0;
4813-
4814- /* Check for new panel if appropriate */
4815- if (center_player && !center_running) verify_panel();
4816-
4817- /* Calculate torch radius */
4818- p_ptr->update |= (PU_TORCH);
4819-
4820- /* Update monster flow */
4821- p_ptr->update |= (PU_FLOW);
4822- }
4823-
4824-#ifdef TRAVEL
4825- if (stop_travel)
4826- {
4827- /* Cancel */
4828- travel.run = 0;
4829-
4830- /* Check for new panel if appropriate */
4831- if (center_player && !center_running) verify_panel();
4832-
4833- /* Calculate torch radius */
4834- p_ptr->update |= (PU_TORCH);
4835- }
4836-#endif
4837-
4838- /* Flush the input if requested */
4839- if (flush_disturb) flush();
4840-}
4841-
4842-
4843-/*
4844- * Glow deep lava and building entrances in the floor
4845- */
4846-void glow_deep_lava_and_bldg(void)
4847-{
4848- POSITION y, x, yy, xx;
4849- DIRECTION i;
4850- grid_type *g_ptr;
4851-
4852- /* Not in the darkness dungeon */
4853- if (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS) return;
4854-
4855- for (y = 0; y < cur_hgt; y++)
4856- {
4857- for (x = 0; x < cur_wid; x++)
4858- {
4859- g_ptr = &grid_array[y][x];
4860-
4861- /* Feature code (applying "mimic" field) */
4862-
4863- if (have_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_GLOW))
4864- {
4865- for (i = 0; i < 9; i++)
4866- {
4867- yy = y + ddy_ddd[i];
4868- xx = x + ddx_ddd[i];
4869- if (!in_bounds2(yy, xx)) continue;
4870- grid_array[yy][xx].info |= CAVE_GLOW;
4871- }
4872- }
4873- }
4874- }
4875-
4876- /* Update the view and lite */
4877- p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
4878-
4879- p_ptr->redraw |= (PR_MAP);
4880-}
4881-
4882-/*!
4883-* @brief 指定されたマスがモンスターのテレポート可能先かどうかを判定する。
4884-* @param m_idx モンスターID
4885-* @param y 移動先Y座標
4886-* @param x 移動先X座標
4887-* @param mode オプション
4888-* @return テレポート先として妥当ならばtrue
4889-*/
4890-bool cave_monster_teleportable_bold(MONSTER_IDX m_idx, POSITION y, POSITION x, BIT_FLAGS mode)
4891-{
4892- monster_type *m_ptr = &m_list[m_idx];
4893- grid_type *g_ptr = &grid_array[y][x];
4894- feature_type *f_ptr = &f_info[g_ptr->feat];
4895-
4896- /* Require "teleportable" space */
4897- if (!have_flag(f_ptr->flags, FF_TELEPORTABLE)) return FALSE;
4898-
4899- if (g_ptr->m_idx && (g_ptr->m_idx != m_idx)) return FALSE;
4900- if (player_bold(y, x)) return FALSE;
4901-
4902- /* Hack -- no teleport onto glyph of warding */
4903- if (is_glyph_grid(g_ptr)) return FALSE;
4904- if (is_explosive_rune_grid(g_ptr)) return FALSE;
4905-
4906- if (!(mode & TELEPORT_PASSIVE))
4907- {
4908- if (!monster_can_cross_terrain(g_ptr->feat, &r_info[m_ptr->r_idx], 0)) return FALSE;
4909- }
4910-
4911- return TRUE;
4912-}
4913-
4914-/*!
4915-* @brief 指定されたマスにプレイヤーがテレポート可能かどうかを判定する。
4916-* @param y 移動先Y座標
4917-* @param x 移動先X座標
4918-* @param mode オプション
4919-* @return テレポート先として妥当ならばtrue
4920-*/
4921-bool cave_player_teleportable_bold(POSITION y, POSITION x, BIT_FLAGS mode)
4922-{
4923- grid_type *g_ptr = &grid_array[y][x];
4924- feature_type *f_ptr = &f_info[g_ptr->feat];
4925-
4926- /* Require "teleportable" space */
4927- if (!have_flag(f_ptr->flags, FF_TELEPORTABLE)) return FALSE;
4928-
4929- /* No magical teleporting into vaults and such */
4930- if (!(mode & TELEPORT_NONMAGICAL) && (g_ptr->info & CAVE_ICKY)) return FALSE;
4931-
4932- if (g_ptr->m_idx && (g_ptr->m_idx != p_ptr->riding)) return FALSE;
4933-
4934- /* don't teleport on a trap. */
4935- if (have_flag(f_ptr->flags, FF_HIT_TRAP)) return FALSE;
4936-
4937- if (!(mode & TELEPORT_PASSIVE))
4938- {
4939- if (!player_can_enter(g_ptr->feat, 0)) return FALSE;
4940-
4941- if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP))
4942- {
4943- if (!p_ptr->levitation && !p_ptr->can_swim) return FALSE;
4944- }
4945-
4946- if (have_flag(f_ptr->flags, FF_LAVA) && !p_ptr->immune_fire && !IS_INVULN())
4947- {
4948- /* Always forbid deep lava */
4949- if (have_flag(f_ptr->flags, FF_DEEP)) return FALSE;
4950-
4951- /* Forbid shallow lava when the player don't have levitation */
4952- if (!p_ptr->levitation) return FALSE;
4953- }
4954-
4955- }
4956-
4957- return TRUE;
4958-}
4959-
4960-/*!
4961- * @brief 地形は開くものであって、かつ開かれているかを返す /
4962- * Attempt to open the given chest at the given location
4963- * @param feat 地形ID
4964- * @return 開いた地形である場合TRUEを返す / Return TRUE if the given feature is an open door
4965- */
4966-bool is_open(FEAT_IDX feat)
4967-{
4968- return have_flag(f_info[feat].flags, FF_CLOSE) && (feat != feat_state(feat, FF_CLOSE));
4969-}
--- a/src/grid.c
+++ b/src/grid.c
@@ -1,18 +1,26 @@
1-/*!
2- * @file grid.c
3- * @brief ダンジョンの生成処理の基幹部分 / low-level dungeon creation primitives
4- * @date 2014/01/04
5- * @author
6- * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
7- *\n
8- * This software may be copied and distributed for educational, research,\n
9- * and not for profit purposes provided that this copyright and statement\n
10- * are included in all such copies. Other copyrights may also apply.\n
11- * \n
12- * 2014 Deskull Doxygen向けのコメント整理\n
13- */
1+
2+ /*!
3+ * @file grid.c
4+ * @brief グリッドの実装 / low level dungeon routines -BEN-
5+ * @date 2013/12/30
6+ * @author
7+ * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
8+ *\n
9+ * This software may be copied and distributed for educational, research,\n
10+ * and not for profit purposes provided that this copyright and statement\n
11+ * are included in all such copies. Other copyrights may also apply.\n
12+ * \n
13+ * Support for Adam Bolt's tileset, lighting and transparency effects\n
14+ * by Robert Ruehlmann (rr9@angband.org)\n
15+ * \n
16+ * 2013 Deskull Doxygen向けのコメント整理\n
17+ */
18+
1419
1520 #include "angband.h"
21+#include "world.h"
22+#include "projection.h"
23+#include "object-hook.h"
1624 #include "generate.h"
1725 #include "grid.h"
1826 #include "trap.h"
@@ -20,6 +28,11 @@
2028 #include "monster.h"
2129 #include "quest.h"
2230
31+static byte display_autopick; /*!< 自動拾い状態の設定フラグ */
32+static int match_autopick;
33+static object_type *autopick_obj; /*!< 各種自動拾い処理時に使うオブジェクトポインタ */
34+static int feat_priority; /*!< マップ縮小表示時に表示すべき地形の優先度を保管する */
35+
2336
2437 /*!
2538 * @brief 新規フロアに入りたてのプレイヤーをランダムな場所に配置する / Returns random co-ordinates for player/monster/object
@@ -777,3 +790,4947 @@ void place_bound_perm_wall(grid_type *g_ptr)
777790 /* Add "solid" perma-wall */
778791 place_solid_perm_grid(g_ptr);
779792 }
793+
794+
795+/*!
796+ * @brief 2点間の距離をニュートン・ラプソン法で算出する / Distance between two points via Newton-Raphson technique
797+ * @param y1 1点目のy座標
798+ * @param x1 1点目のx座標
799+ * @param y2 2点目のy座標
800+ * @param x2 2点目のx座標
801+ * @return 2点間の距離
802+ */
803+POSITION distance(POSITION y1, POSITION x1, POSITION y2, POSITION x2)
804+{
805+ POSITION dy = (y1 > y2) ? (y1 - y2) : (y2 - y1);
806+ POSITION dx = (x1 > x2) ? (x1 - x2) : (x2 - x1);
807+
808+ /* Squared distance */
809+ POSITION target = (dy * dy) + (dx * dx);
810+
811+ /* Approximate distance: hypot(dy,dx) = max(dy,dx) + min(dy,dx) / 2 */
812+ POSITION d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
813+
814+ POSITION err;
815+
816+ /* Simple case */
817+ if (!dy || !dx) return d;
818+
819+ while (1)
820+ {
821+ /* Approximate error */
822+ err = (target - d * d) / (2 * d);
823+
824+ /* No error - we are done */
825+ if (!err) break;
826+
827+ /* Adjust distance */
828+ d += err;
829+ }
830+
831+ return d;
832+}
833+
834+/*!
835+ * @brief 地形が罠持ちであるかの判定を行う。 / Return TRUE if the given feature is a trap
836+ * @param feat 地形情報のID
837+ * @return 罠持ちの地形ならばTRUEを返す。
838+ */
839+bool is_trap(FEAT_IDX feat)
840+{
841+ return have_flag(f_info[feat].flags, FF_TRAP);
842+}
843+
844+/*!
845+ * @brief マスに看破済みの罠があるかの判定を行う。 / Return TRUE if the given grid is a known trap
846+ * @param g_ptr マス構造体の参照ポインタ
847+ * @return 看破済みの罠があるならTRUEを返す。
848+ */
849+bool is_known_trap(grid_type *g_ptr)
850+{
851+ if (!g_ptr->mimic && !cave_have_flag_grid(g_ptr, FF_SECRET) &&
852+ is_trap(g_ptr->feat)) return TRUE;
853+ else
854+ return FALSE;
855+}
856+
857+/*!
858+ * @brief 地形が閉じたドアであるかの判定を行う。 / Return TRUE if the given grid is a closed door
859+ * @param feat 地形情報のID
860+ * @return 閉じたドアのある地形ならばTRUEを返す。
861+ */
862+bool is_closed_door(FEAT_IDX feat)
863+{
864+ feature_type *f_ptr = &f_info[feat];
865+
866+ return (have_flag(f_ptr->flags, FF_OPEN) || have_flag(f_ptr->flags, FF_BASH)) &&
867+ !have_flag(f_ptr->flags, FF_MOVE);
868+}
869+
870+/*!
871+ * @brief マスに隠されたドアがあるかの判定を行う。 / Return TRUE if the given grid is a hidden closed door
872+ * @param g_ptr マス構造体の参照ポインタ
873+ * @return 隠されたドアがあるならTRUEを返す。
874+ */
875+bool is_hidden_door(grid_type *g_ptr)
876+{
877+ if ((g_ptr->mimic || cave_have_flag_grid(g_ptr, FF_SECRET)) &&
878+ is_closed_door(g_ptr->feat))
879+ return TRUE;
880+ else
881+ return FALSE;
882+}
883+
884+/*!
885+ * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
886+ * @param y1 始点のy座標
887+ * @param x1 始点のx座標
888+ * @param y2 終点のy座標
889+ * @param x2 終点のx座標
890+ * @return LOSが通っているならTRUEを返す。
891+ * @details
892+ * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall,\n
893+ * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.\n
894+ *\n
895+ * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
896+ *\n
897+ * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
898+ * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line\n
899+ * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
900+ *\n
901+ * We assume that the "mathematical corner" of a non-floor tile does not\n
902+ * block line of sight.\n
903+ *\n
904+ * Because this function uses (short) ints for all calculations, overflow may\n
905+ * occur if dx and dy exceed 90.\n
906+ *\n
907+ * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
908+ * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
909+ * we can use integer arithmetic.\n
910+ *\n
911+ * We travel from start to finish along the longer axis, starting at the border\n
912+ * between the first and second tiles, where the y offset = .5 * slope, taking\n
913+ * into account the scale factor. See below.\n
914+ *\n
915+ * Also note that this function and the "move towards target" code do NOT\n
916+ * share the same properties. Thus, you can see someone, target them, and\n
917+ * then fire a bolt at them, but the bolt may hit a wall, not them. However\n,
918+ * by clever choice of target locations, you can sometimes throw a "curve".\n
919+ *\n
920+ * Note that "line of sight" is not "reflexive" in all cases.\n
921+ *\n
922+ * Use the "projectable()" routine to test "spell/missile line of sight".\n
923+ *\n
924+ * Use the "update_view()" function to determine player line-of-sight.\n
925+ */
926+bool los(POSITION y1, POSITION x1, POSITION y2, POSITION x2)
927+{
928+ /* Delta */
929+ POSITION dx, dy;
930+
931+ /* Absolute */
932+ POSITION ax, ay;
933+
934+ /* Signs */
935+ POSITION sx, sy;
936+
937+ /* Fractions */
938+ POSITION qx, qy;
939+
940+ /* Scanners */
941+ POSITION tx, ty;
942+
943+ /* Scale factors */
944+ POSITION f1, f2;
945+
946+ /* Slope, or 1/Slope, of LOS */
947+ POSITION m;
948+
949+
950+ /* Extract the offset */
951+ dy = y2 - y1;
952+ dx = x2 - x1;
953+
954+ /* Extract the absolute offset */
955+ ay = ABS(dy);
956+ ax = ABS(dx);
957+
958+
959+ /* Handle adjacent (or identical) grids */
960+ if ((ax < 2) && (ay < 2)) return TRUE;
961+
962+
963+ /* Paranoia -- require "safe" origin */
964+ /* if (!in_bounds(y1, x1)) return FALSE; */
965+ /* if (!in_bounds(y2, x2)) return FALSE; */
966+
967+
968+ /* Directly South/North */
969+ if (!dx)
970+ {
971+ /* South -- check for walls */
972+ if (dy > 0)
973+ {
974+ for (ty = y1 + 1; ty < y2; ty++)
975+ {
976+ if (!cave_los_bold(ty, x1)) return FALSE;
977+ }
978+ }
979+
980+ /* North -- check for walls */
981+ else
982+ {
983+ for (ty = y1 - 1; ty > y2; ty--)
984+ {
985+ if (!cave_los_bold(ty, x1)) return FALSE;
986+ }
987+ }
988+
989+ /* Assume los */
990+ return TRUE;
991+ }
992+
993+ /* Directly East/West */
994+ if (!dy)
995+ {
996+ /* East -- check for walls */
997+ if (dx > 0)
998+ {
999+ for (tx = x1 + 1; tx < x2; tx++)
1000+ {
1001+ if (!cave_los_bold(y1, tx)) return FALSE;
1002+ }
1003+ }
1004+
1005+ /* West -- check for walls */
1006+ else
1007+ {
1008+ for (tx = x1 - 1; tx > x2; tx--)
1009+ {
1010+ if (!cave_los_bold(y1, tx)) return FALSE;
1011+ }
1012+ }
1013+
1014+ /* Assume los */
1015+ return TRUE;
1016+ }
1017+
1018+
1019+ /* Extract some signs */
1020+ sx = (dx < 0) ? -1 : 1;
1021+ sy = (dy < 0) ? -1 : 1;
1022+
1023+
1024+ /* Vertical "knights" */
1025+ if (ax == 1)
1026+ {
1027+ if (ay == 2)
1028+ {
1029+ if (cave_los_bold(y1 + sy, x1)) return TRUE;
1030+ }
1031+ }
1032+
1033+ /* Horizontal "knights" */
1034+ else if (ay == 1)
1035+ {
1036+ if (ax == 2)
1037+ {
1038+ if (cave_los_bold(y1, x1 + sx)) return TRUE;
1039+ }
1040+ }
1041+
1042+
1043+ /* Calculate scale factor div 2 */
1044+ f2 = (ax * ay);
1045+
1046+ /* Calculate scale factor */
1047+ f1 = f2 << 1;
1048+
1049+
1050+ /* Travel horizontally */
1051+ if (ax >= ay)
1052+ {
1053+ /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
1054+ qy = ay * ay;
1055+ m = qy << 1;
1056+
1057+ tx = x1 + sx;
1058+
1059+ /* Consider the special case where slope == 1. */
1060+ if (qy == f2)
1061+ {
1062+ ty = y1 + sy;
1063+ qy -= f1;
1064+ }
1065+ else
1066+ {
1067+ ty = y1;
1068+ }
1069+
1070+ /* Note (below) the case (qy == f2), where */
1071+ /* the LOS exactly meets the corner of a tile. */
1072+ while (x2 - tx)
1073+ {
1074+ if (!cave_los_bold(ty, tx)) return FALSE;
1075+
1076+ qy += m;
1077+
1078+ if (qy < f2)
1079+ {
1080+ tx += sx;
1081+ }
1082+ else if (qy > f2)
1083+ {
1084+ ty += sy;
1085+ if (!cave_los_bold(ty, tx)) return FALSE;
1086+ qy -= f1;
1087+ tx += sx;
1088+ }
1089+ else
1090+ {
1091+ ty += sy;
1092+ qy -= f1;
1093+ tx += sx;
1094+ }
1095+ }
1096+ }
1097+
1098+ /* Travel vertically */
1099+ else
1100+ {
1101+ /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
1102+ qx = ax * ax;
1103+ m = qx << 1;
1104+
1105+ ty = y1 + sy;
1106+
1107+ if (qx == f2)
1108+ {
1109+ tx = x1 + sx;
1110+ qx -= f1;
1111+ }
1112+ else
1113+ {
1114+ tx = x1;
1115+ }
1116+
1117+ /* Note (below) the case (qx == f2), where */
1118+ /* the LOS exactly meets the corner of a tile. */
1119+ while (y2 - ty)
1120+ {
1121+ if (!cave_los_bold(ty, tx)) return FALSE;
1122+
1123+ qx += m;
1124+
1125+ if (qx < f2)
1126+ {
1127+ ty += sy;
1128+ }
1129+ else if (qx > f2)
1130+ {
1131+ tx += sx;
1132+ if (!cave_los_bold(ty, tx)) return FALSE;
1133+ qx -= f1;
1134+ ty += sy;
1135+ }
1136+ else
1137+ {
1138+ tx += sx;
1139+ qx -= f1;
1140+ ty += sy;
1141+ }
1142+ }
1143+ }
1144+
1145+ /* Assume los */
1146+ return TRUE;
1147+}
1148+
1149+#define COMPLEX_WALL_ILLUMINATION /*!< 照明状態を壁により影響を受ける、より複雑な判定に切り替えるマクロ */
1150+
1151+
1152+/*!
1153+ * @brief 指定された座標のマスが現在照らされているかを返す。 / Check for "local" illumination
1154+ * @param y y座標
1155+ * @param x x座標
1156+ * @return 指定された座標に照明がかかっているならTRUEを返す。。
1157+ */
1158+static bool check_local_illumination(POSITION y, POSITION x)
1159+{
1160+ /* Hack -- move towards player */
1161+ POSITION yy = (y < p_ptr->y) ? (y + 1) : (y > p_ptr->y) ? (y - 1) : y;
1162+ POSITION xx = (x < p_ptr->x) ? (x + 1) : (x > p_ptr->x) ? (x - 1) : x;
1163+
1164+ /* Check for "local" illumination */
1165+
1166+#ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
1167+
1168+ /* Check for "complex" illumination */
1169+ if ((feat_supports_los(get_feat_mimic(&grid_array[yy][xx])) &&
1170+ (grid_array[yy][xx].info & CAVE_GLOW)) ||
1171+ (feat_supports_los(get_feat_mimic(&grid_array[y][xx])) &&
1172+ (grid_array[y][xx].info & CAVE_GLOW)) ||
1173+ (feat_supports_los(get_feat_mimic(&grid_array[yy][x])) &&
1174+ (grid_array[yy][x].info & CAVE_GLOW)))
1175+ {
1176+ return TRUE;
1177+ }
1178+ else return FALSE;
1179+
1180+#else /* COMPLEX_WALL_ILLUMINATION */
1181+
1182+ /* Check for "simple" illumination */
1183+ return (grid_array[yy][xx].info & CAVE_GLOW) ? TRUE : FALSE;
1184+
1185+#endif /* COMPLEX_WALL_ILLUMINATION */
1186+}
1187+
1188+
1189+/*! 対象座標のマスの照明状態を更新する際の補助処理マクロ */
1190+#define update_local_illumination_aux(Y, X) \
1191+{ \
1192+ if (player_has_los_bold((Y), (X))) \
1193+ { \
1194+ /* Update the monster */ \
1195+ if (grid_array[(Y)][(X)].m_idx) update_monster(grid_array[(Y)][(X)].m_idx, FALSE); \
1196+\
1197+ /* Notice and redraw */ \
1198+ note_spot((Y), (X)); \
1199+ lite_spot((Y), (X)); \
1200+ } \
1201+}
1202+
1203+/*!
1204+ * @brief 指定された座標の照明状態を更新する / Update "local" illumination
1205+ * @param y y座標
1206+ * @param x x座標
1207+ * @return なし
1208+ */
1209+void update_local_illumination(POSITION y, POSITION x)
1210+{
1211+ int i;
1212+ POSITION yy, xx;
1213+
1214+ if (!in_bounds(y, x)) return;
1215+
1216+#ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
1217+
1218+ if ((y != p_ptr->y) && (x != p_ptr->x))
1219+ {
1220+ yy = (y < p_ptr->y) ? (y - 1) : (y + 1);
1221+ xx = (x < p_ptr->x) ? (x - 1) : (x + 1);
1222+ update_local_illumination_aux(yy, xx);
1223+ update_local_illumination_aux(y, xx);
1224+ update_local_illumination_aux(yy, x);
1225+ }
1226+ else if (x != p_ptr->x) /* y == p_ptr->y */
1227+ {
1228+ xx = (x < p_ptr->x) ? (x - 1) : (x + 1);
1229+ for (i = -1; i <= 1; i++)
1230+ {
1231+ yy = y + i;
1232+ update_local_illumination_aux(yy, xx);
1233+ }
1234+ yy = y - 1;
1235+ update_local_illumination_aux(yy, x);
1236+ yy = y + 1;
1237+ update_local_illumination_aux(yy, x);
1238+ }
1239+ else if (y != p_ptr->y) /* x == p_ptr->x */
1240+ {
1241+ yy = (y < p_ptr->y) ? (y - 1) : (y + 1);
1242+ for (i = -1; i <= 1; i++)
1243+ {
1244+ xx = x + i;
1245+ update_local_illumination_aux(yy, xx);
1246+ }
1247+ xx = x - 1;
1248+ update_local_illumination_aux(y, xx);
1249+ xx = x + 1;
1250+ update_local_illumination_aux(y, xx);
1251+ }
1252+ else /* Player's grid */
1253+ {
1254+ for (i = 0; i < 8; i++)
1255+ {
1256+ yy = y + ddy_cdd[i];
1257+ xx = x + ddx_cdd[i];
1258+ update_local_illumination_aux(yy, xx);
1259+ }
1260+ }
1261+
1262+#else /* COMPLEX_WALL_ILLUMINATION */
1263+
1264+ if ((y != p_ptr->y) && (x != p_ptr->x))
1265+ {
1266+ yy = (y < p_ptr->y) ? (y - 1) : (y + 1);
1267+ xx = (x < p_ptr->x) ? (x - 1) : (x + 1);
1268+ update_local_illumination_aux(yy, xx);
1269+ }
1270+ else if (x != p_ptr->x) /* y == p_ptr->y */
1271+ {
1272+ xx = (x < p_ptr->x) ? (x - 1) : (x + 1);
1273+ for (i = -1; i <= 1; i++)
1274+ {
1275+ yy = y + i;
1276+ update_local_illumination_aux(yy, xx);
1277+ }
1278+ }
1279+ else if (y != p_ptr->y) /* x == p_ptr->x */
1280+ {
1281+ yy = (y < p_ptr->y) ? (y - 1) : (y + 1);
1282+ for (i = -1; i <= 1; i++)
1283+ {
1284+ xx = x + i;
1285+ update_local_illumination_aux(yy, xx);
1286+ }
1287+ }
1288+ else /* Player's grid */
1289+ {
1290+ for (i = 0; i < 8; i++)
1291+ {
1292+ yy = y + ddy_cdd[i];
1293+ xx = x + ddx_cdd[i];
1294+ update_local_illumination_aux(yy, xx);
1295+ }
1296+ }
1297+
1298+#endif /* COMPLEX_WALL_ILLUMINATION */
1299+}
1300+
1301+
1302+/*!
1303+ * @brief 指定された座標をプレイヤーが視覚に収められるかを返す。 / Can the player "see" the given grid in detail?
1304+ * @param y y座標
1305+ * @param x x座標
1306+ * @return 視覚に収められる状態ならTRUEを返す
1307+ * @details
1308+ * He must have vision, illumination, and line of sight.\n
1309+ * \n
1310+ * Note -- "CAVE_LITE" is only set if the "torch" has "los()".\n
1311+ * So, given "CAVE_LITE", we know that the grid is "fully visible".\n
1312+ *\n
1313+ * Note that "CAVE_GLOW" makes little sense for a wall, since it would mean\n
1314+ * that a wall is visible from any direction. That would be odd. Except\n
1315+ * under wizard light, which might make sense. Thus, for walls, we require\n
1316+ * not only that they be "CAVE_GLOW", but also, that they be adjacent to a\n
1317+ * grid which is not only "CAVE_GLOW", but which is a non-wall, and which is\n
1318+ * in line of sight of the player.\n
1319+ *\n
1320+ * This extra check is expensive, but it provides a more "correct" semantics.\n
1321+ *\n
1322+ * Note that we should not run this check on walls which are "outer walls" of\n
1323+ * the dungeon, or we will induce a memory fault, but actually verifying all\n
1324+ * of the locations would be extremely expensive.\n
1325+ *\n
1326+ * Thus, to speed up the function, we assume that all "perma-walls" which are\n
1327+ * "CAVE_GLOW" are "illuminated" from all sides. This is correct for all cases\n
1328+ * except "vaults" and the "buildings" in town. But the town is a hack anyway,\n
1329+ * and the player has more important things on his mind when he is attacking a\n
1330+ * monster vault. It is annoying, but an extremely important optimization.\n
1331+ *\n
1332+ * Note that "glowing walls" are only considered to be "illuminated" if the\n
1333+ * grid which is next to the wall in the direction of the player is also a\n
1334+ * "glowing" grid. This prevents the player from being able to "see" the\n
1335+ * walls of illuminated rooms from a corridor outside the room.\n
1336+ */
1337+bool player_can_see_bold(POSITION y, POSITION x)
1338+{
1339+ grid_type *g_ptr;
1340+
1341+ /* Blind players see nothing */
1342+ if (p_ptr->blind) return FALSE;
1343+
1344+ g_ptr = &grid_array[y][x];
1345+
1346+ /* Note that "torch-lite" yields "illumination" */
1347+ if (g_ptr->info & (CAVE_LITE | CAVE_MNLT)) return TRUE;
1348+
1349+ /* Require line of sight to the grid */
1350+ if (!player_has_los_bold(y, x)) return FALSE;
1351+
1352+ /* Noctovision of Ninja */
1353+ if (p_ptr->see_nocto) return TRUE;
1354+
1355+ /* Require "perma-lite" of the grid */
1356+ if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW) return FALSE;
1357+
1358+ /* Feature code (applying "mimic" field) */
1359+ /* Floors are simple */
1360+ if (feat_supports_los(get_feat_mimic(g_ptr))) return TRUE;
1361+
1362+ /* Check for "local" illumination */
1363+ return check_local_illumination(y, x);
1364+}
1365+
1366+/*!
1367+ * @brief 指定された座標をプレイヤー収められていない状態かどうか / Returns true if the player's grid is dark
1368+ * @return 視覚に収められていないならTRUEを返す
1369+ * @details player_can_see_bold()関数の返り値の否定を返している。
1370+ */
1371+bool no_lite(void)
1372+{
1373+ return (!player_can_see_bold(p_ptr->y, p_ptr->x));
1374+}
1375+
1376+
1377+/*!
1378+ * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
1379+ * @param y y座標
1380+ * @param x x座標
1381+ * @return 各種の変更が可能ならTRUEを返す。
1382+ * @details
1383+ * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
1384+ */
1385+bool cave_valid_bold(POSITION y, POSITION x)
1386+{
1387+ grid_type *g_ptr = &grid_array[y][x];
1388+ OBJECT_IDX this_o_idx, next_o_idx = 0;
1389+
1390+ /* Forbid perma-grids */
1391+ if (cave_perma_grid(g_ptr)) return (FALSE);
1392+
1393+ /* Check objects */
1394+ for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1395+ {
1396+ object_type *o_ptr;
1397+ o_ptr = &o_list[this_o_idx];
1398+
1399+ /* Acquire next object */
1400+ next_o_idx = o_ptr->next_o_idx;
1401+
1402+ /* Forbid artifact grids */
1403+ if (object_is_artifact(o_ptr)) return (FALSE);
1404+ }
1405+
1406+ /* Accept */
1407+ return (TRUE);
1408+}
1409+
1410+
1411+
1412+
1413+/*!
1414+ * 一般的にモンスターシンボルとして扱われる記号を定義する(幻覚処理向け) / Hack -- Legal monster codes
1415+ */
1416+static char image_monster_hack[] = \
1417+"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1418+
1419+/*!
1420+ * 一般的にオブジェクトシンボルとして扱われる記号を定義する(幻覚処理向け) / Hack -- Legal object codes
1421+ */
1422+static char image_object_hack[] = "?/|\\\"!$()_-=[]{},~";
1423+
1424+/*!
1425+ * @brief モンスターの表示を幻覚状態に差し替える / Mega-Hack -- Hallucinatory monster
1426+ * @param ap 本来の色
1427+ * @param cp 本来のシンボル
1428+ * @return なし
1429+ */
1430+static void image_monster(TERM_COLOR *ap, SYMBOL_CODE *cp)
1431+{
1432+ /* Random symbol from set above */
1433+ if (use_graphics)
1434+ {
1435+ monster_race *r_ptr = &r_info[randint1(max_r_idx - 1)];
1436+
1437+ *cp = r_ptr->x_char;
1438+ *ap = r_ptr->x_attr;
1439+ }
1440+ else
1441+ /* Text mode */
1442+ {
1443+ *cp = (one_in_(25) ?
1444+ image_object_hack[randint0(sizeof(image_object_hack) - 1)] :
1445+ image_monster_hack[randint0(sizeof(image_monster_hack) - 1)]);
1446+
1447+ /* Random color */
1448+ *ap = randint1(15);
1449+ }
1450+}
1451+
1452+/*!
1453+ * @brief オブジェクトの表示を幻覚状態に差し替える / Hallucinatory object
1454+ * @param ap 本来の色
1455+ * @param cp 本来のシンボル
1456+ * @return なし
1457+ */
1458+static void image_object(TERM_COLOR *ap, SYMBOL_CODE *cp)
1459+{
1460+ if (use_graphics)
1461+ {
1462+ object_kind *k_ptr = &k_info[randint1(max_k_idx - 1)];
1463+
1464+ *cp = k_ptr->x_char;
1465+ *ap = k_ptr->x_attr;
1466+ }
1467+ else
1468+ {
1469+ int n = sizeof(image_object_hack) - 1;
1470+
1471+ *cp = image_object_hack[randint0(n)];
1472+
1473+ /* Random color */
1474+ *ap = randint1(15);
1475+ }
1476+}
1477+
1478+
1479+/*!
1480+ * @brief オブジェクト&モンスターの表示を幻覚状態に差し替える / Hack -- Random hallucination
1481+ * @param ap 本来の色
1482+ * @param cp 本来のシンボル
1483+ * @return なし
1484+ */
1485+static void image_random(TERM_COLOR *ap, SYMBOL_CODE *cp)
1486+{
1487+ /* Normally, assume monsters */
1488+ if (randint0(100) < 75)
1489+ {
1490+ image_monster(ap, cp);
1491+ }
1492+
1493+ /* Otherwise, assume objects */
1494+ else
1495+ {
1496+ image_object(ap, cp);
1497+ }
1498+}
1499+
1500+/*!
1501+ * 照明の表現を行うための色合いの関係を{暗闇時, 照明時} で定義する /
1502+ * This array lists the effects of "brightness" on various "base" colours.\n
1503+ *\n
1504+ * This is used to do dynamic lighting effects in ascii :-)\n
1505+ * At the moment, only the various "floor" tiles are affected.\n
1506+ *\n
1507+ * The layout of the array is [x][0] = light and [x][1] = dark.\n
1508+ */
1509+static TERM_COLOR lighting_colours[16][2] =
1510+{
1511+ /* TERM_DARK */
1512+ {TERM_L_DARK, TERM_DARK},
1513+
1514+ /* TERM_WHITE */
1515+ {TERM_YELLOW, TERM_SLATE},
1516+
1517+ /* TERM_SLATE */
1518+ {TERM_WHITE, TERM_L_DARK},
1519+
1520+ /* TERM_ORANGE */
1521+ {TERM_L_UMBER, TERM_UMBER},
1522+
1523+ /* TERM_RED */
1524+ {TERM_RED, TERM_RED},
1525+
1526+ /* TERM_GREEN */
1527+ {TERM_L_GREEN, TERM_GREEN},
1528+
1529+ /* TERM_BLUE */
1530+ {TERM_BLUE, TERM_BLUE},
1531+
1532+ /* TERM_UMBER */
1533+ {TERM_L_UMBER, TERM_RED},
1534+
1535+ /* TERM_L_DARK */
1536+ {TERM_SLATE, TERM_L_DARK},
1537+
1538+ /* TERM_L_WHITE */
1539+ {TERM_WHITE, TERM_SLATE},
1540+
1541+ /* TERM_VIOLET */
1542+ {TERM_L_RED, TERM_BLUE},
1543+
1544+ /* TERM_YELLOW */
1545+ {TERM_YELLOW, TERM_ORANGE},
1546+
1547+ /* TERM_L_RED */
1548+ {TERM_L_RED, TERM_L_RED},
1549+
1550+ /* TERM_L_GREEN */
1551+ {TERM_L_GREEN, TERM_GREEN},
1552+
1553+ /* TERM_L_BLUE */
1554+ {TERM_L_BLUE, TERM_L_BLUE},
1555+
1556+ /* TERM_L_UMBER */
1557+ {TERM_L_UMBER, TERM_UMBER}
1558+};
1559+
1560+/*!
1561+ * @brief 調査中
1562+ * @todo コメントを付加すること
1563+ */
1564+void apply_default_feat_lighting(TERM_COLOR f_attr[F_LIT_MAX], SYMBOL_CODE f_char[F_LIT_MAX])
1565+{
1566+ TERM_COLOR s_attr = f_attr[F_LIT_STANDARD];
1567+ SYMBOL_CODE s_char = f_char[F_LIT_STANDARD];
1568+ int i;
1569+
1570+ if (is_ascii_graphics(s_attr)) /* For ASCII */
1571+ {
1572+ f_attr[F_LIT_LITE] = lighting_colours[s_attr & 0x0f][0];
1573+ f_attr[F_LIT_DARK] = lighting_colours[s_attr & 0x0f][1];
1574+ for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) f_char[i] = s_char;
1575+ }
1576+ else /* For tile graphics */
1577+ {
1578+ for (i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) f_attr[i] = s_attr;
1579+ f_char[F_LIT_LITE] = s_char + 2;
1580+ f_char[F_LIT_DARK] = s_char + 1;
1581+ }
1582+}
1583+
1584+
1585+/*!
1586+ * モンスターにより照明が消されている地形か否かを判定する。 / Is this grid "darkened" by monster?
1587+ */
1588+#define darkened_grid(C) \
1589+ ((((C)->info & (CAVE_VIEW | CAVE_LITE | CAVE_MNLT | CAVE_MNDK)) == (CAVE_VIEW | CAVE_MNDK)) && \
1590+ !p_ptr->see_nocto)
1591+
1592+
1593+ /*!
1594+ * @brief Mコマンドによる縮小マップの表示を行う / Extract the attr/char to display at the given (legal) map location
1595+ * @details
1596+ * Basically, we "paint" the chosen attr/char in several passes, starting\n
1597+ * with any known "terrain features" (defaulting to darkness), then adding\n
1598+ * any known "objects", and finally, adding any known "monsters". This\n
1599+ * is not the fastest method but since most of the calls to this function\n
1600+ * are made for grids with no monsters or objects, it is fast enough.\n
1601+ *\n
1602+ * Note that this function, if used on the grid containing the "player",\n
1603+ * will return the attr/char of the grid underneath the player, and not\n
1604+ * the actual player attr/char itself, allowing a lot of optimization\n
1605+ * in various "display" functions.\n
1606+ *\n
1607+ * Note that the "zero" entry in the feature/object/monster arrays are\n
1608+ * used to provide "special" attr/char codes, with "monster zero" being\n
1609+ * used for the player attr/char, "object zero" being used for the "stack"\n
1610+ * attr/char, and "feature zero" being used for the "nothing" attr/char,\n
1611+ * though this function makes use of only "feature zero".\n
1612+ *\n
1613+ * Note that monsters can have some "special" flags, including "ATTR_MULTI",\n
1614+ * which means their color changes, and "ATTR_CLEAR", which means they take\n
1615+ * the color of whatever is under them, and "CHAR_CLEAR", which means that\n
1616+ * they take the symbol of whatever is under them. Technically, the flag\n
1617+ * "CHAR_MULTI" is supposed to indicate that a monster looks strange when\n
1618+ * examined, but this flag is currently ignored.\n
1619+ *\n
1620+ * Currently, we do nothing with multi-hued objects, because there are\n
1621+ * not any. If there were, they would have to set "shimmer_objects"\n
1622+ * when they were created, and then new "shimmer" code in "dungeon.c"\n
1623+ * would have to be created handle the "shimmer" effect, and the code\n
1624+ * in "grid_array.c" would have to be updated to create the shimmer effect.\n
1625+ *\n
1626+ * Note the effects of hallucination. Objects always appear as random\n
1627+ * "objects", monsters as random "monsters", and normal grids occasionally\n
1628+ * appear as random "monsters" or "objects", but note that these random\n
1629+ * "monsters" and "objects" are really just "colored ascii symbols".\n
1630+ *\n
1631+ * Note that "floors" and "invisible traps" (and "zero" features) are\n
1632+ * drawn as "floors" using a special check for optimization purposes,\n
1633+ * and these are the only features which get drawn using the special\n
1634+ * lighting effects activated by "view_special_lite".\n
1635+ *\n
1636+ * Note the use of the "mimic" field in the "terrain feature" processing,\n
1637+ * which allows any feature to "pretend" to be another feature. This is\n
1638+ * used to "hide" secret doors, and to make all "doors" appear the same,\n
1639+ * and all "walls" appear the same, and "hidden" treasure stay hidden.\n
1640+ * It is possible to use this field to make a feature "look" like a floor,\n
1641+ * but the "special lighting effects" for floors will not be used.\n
1642+ *\n
1643+ * Note the use of the new "terrain feature" information. Note that the\n
1644+ * assumption that all interesting "objects" and "terrain features" are\n
1645+ * memorized allows extremely optimized processing below. Note the use\n
1646+ * of separate flags on objects to mark them as memorized allows a grid\n
1647+ * to have memorized "terrain" without granting knowledge of any object\n
1648+ * which may appear in that grid.\n
1649+ *\n
1650+ * Note the efficient code used to determine if a "floor" grid is\n
1651+ * "memorized" or "viewable" by the player, where the test for the\n
1652+ * grid being "viewable" is based on the facts that (1) the grid\n
1653+ * must be "lit" (torch-lit or perma-lit), (2) the grid must be in\n
1654+ * line of sight, and (3) the player must not be blind, and uses the\n
1655+ * assumption that all torch-lit grids are in line of sight.\n
1656+ *\n
1657+ * Note that floors (and invisible traps) are the only grids which are\n
1658+ * not memorized when seen, so only these grids need to check to see if\n
1659+ * the grid is "viewable" to the player (if it is not memorized). Since\n
1660+ * most non-memorized grids are in fact walls, this induces *massive*\n
1661+ * efficiency, at the cost of *forcing* the memorization of non-floor\n
1662+ * grids when they are first seen. Note that "invisible traps" are\n
1663+ * always treated exactly like "floors", which prevents "cheating".\n
1664+ *\n
1665+ * Note the "special lighting effects" which can be activated for floor\n
1666+ * grids using the "view_special_lite" option (for "white" floor grids),\n
1667+ * causing certain grids to be displayed using special colors. If the\n
1668+ * player is "blind", we will use "dark gray", else if the grid is lit\n
1669+ * by the torch, and the "view_yellow_lite" option is set, we will use\n
1670+ * "yellow", else if the grid is "dark", we will use "dark gray", else\n
1671+ * if the grid is not "viewable", and the "view_bright_lite" option is\n
1672+ * set, and the we will use "slate" (gray). We will use "white" for all\n
1673+ * other cases, in particular, for illuminated viewable floor grids.\n
1674+ *\n
1675+ * Note the "special lighting effects" which can be activated for wall\n
1676+ * grids using the "view_granite_lite" option (for "white" wall grids),\n
1677+ * causing certain grids to be displayed using special colors. If the\n
1678+ * player is "blind", we will use "dark gray", else if the grid is lit\n
1679+ * by the torch, and the "view_yellow_lite" option is set, we will use\n
1680+ * "yellow", else if the "view_bright_lite" option is set, and the grid\n
1681+ * is not "viewable", or is "dark", or is glowing, but not when viewed\n
1682+ * from the player's current location, we will use "slate" (gray). We\n
1683+ * will use "white" for all other cases, in particular, for correctly\n
1684+ * illuminated viewable wall grids.\n
1685+ *\n
1686+ * Note that, when "view_granite_lite" is set, we use an inline version\n
1687+ * of the "player_can_see_bold()" function to check the "viewability" of\n
1688+ * grids when the "view_bright_lite" option is set, and we do NOT use\n
1689+ * any special colors for "dark" wall grids, since this would allow the\n
1690+ * player to notice the walls of illuminated rooms from a hallway that\n
1691+ * happened to run beside the room. The alternative, by the way, would\n
1692+ * be to prevent the generation of hallways next to rooms, but this\n
1693+ * would still allow problems when digging towards a room.\n
1694+ *\n
1695+ * Note that bizarre things must be done when the "attr" and/or "char"\n
1696+ * codes have the "high-bit" set, since these values are used to encode\n
1697+ * various "special" pictures in some versions, and certain situations,\n
1698+ * such as "multi-hued" or "clear" monsters, cause the attr/char codes\n
1699+ * to be "scrambled" in various ways.\n
1700+ *\n
1701+ * Note that eventually we may use the "&" symbol for embedded treasure,\n
1702+ * and use the "*" symbol to indicate multiple objects, though this will\n
1703+ * have to wait for Angband 2.8.0 or later. Note that currently, this\n
1704+ * is not important, since only one object or terrain feature is allowed\n
1705+ * in each grid. If needed, "k_info[0]" will hold the "stack" attr/char.\n
1706+ *\n
1707+ * Note the assumption that doing "x_ptr = &x_info[x]" plus a few of\n
1708+ * "x_ptr->xxx", is quicker than "x_info[x].xxx", if this is incorrect\n
1709+ * then a whole lot of code should be changed... XXX XXX\n
1710+ */
1711+void map_info(POSITION y, POSITION x, TERM_COLOR *ap, SYMBOL_CODE *cp, TERM_COLOR *tap, SYMBOL_CODE *tcp)
1712+{
1713+ /* Get the grid_array */
1714+ grid_type *g_ptr = &grid_array[y][x];
1715+
1716+ OBJECT_IDX this_o_idx, next_o_idx = 0;
1717+
1718+ /* Feature code (applying "mimic" field) */
1719+ FEAT_IDX feat = get_feat_mimic(g_ptr);
1720+
1721+ /* Access floor */
1722+ feature_type *f_ptr = &f_info[feat];
1723+
1724+ TERM_COLOR a;
1725+ SYMBOL_CODE c;
1726+
1727+ /* Boring grids (floors, etc) */
1728+ if (!have_flag(f_ptr->flags, FF_REMEMBER))
1729+ {
1730+ /*
1731+ * Handle Memorized or visible floor
1732+ *
1733+ * No visual when blinded.
1734+ * (to prevent strange effects on darkness breath)
1735+ * otherwise,
1736+ * - Can see grids with CAVE_MARK.
1737+ * - Can see grids with CAVE_LITE or CAVE_MNLT.
1738+ * (Such grids also have CAVE_VIEW)
1739+ * - Can see grids with CAVE_VIEW unless darkened by monsters.
1740+ */
1741+ if (!p_ptr->blind &&
1742+ ((g_ptr->info & (CAVE_MARK | CAVE_LITE | CAVE_MNLT)) ||
1743+ ((g_ptr->info & CAVE_VIEW) && (((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) || p_ptr->see_nocto))))
1744+ {
1745+ /* Normal attr/char */
1746+ a = f_ptr->x_attr[F_LIT_STANDARD];
1747+ c = f_ptr->x_char[F_LIT_STANDARD];
1748+
1749+ if (p_ptr->wild_mode)
1750+ {
1751+ /* Special lighting effects */
1752+ /* Handle "night" */
1753+ if (view_special_lite && !is_daytime())
1754+ {
1755+ /* Use a darkened colour/tile */
1756+ a = f_ptr->x_attr[F_LIT_DARK];
1757+ c = f_ptr->x_char[F_LIT_DARK];
1758+ }
1759+ }
1760+
1761+ /* Mega-Hack -- Handle "in-sight" and "darkened" grids */
1762+ else if (darkened_grid(g_ptr))
1763+ {
1764+ /* Unsafe grid -- idea borrowed from Unangband */
1765+ feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
1766+
1767+ /* Access darkness */
1768+ f_ptr = &f_info[feat];
1769+
1770+ /* Char and attr of darkness */
1771+ a = f_ptr->x_attr[F_LIT_STANDARD];
1772+ c = f_ptr->x_char[F_LIT_STANDARD];
1773+ }
1774+
1775+ /* Special lighting effects */
1776+ else if (view_special_lite)
1777+ {
1778+ /* Handle "torch-lit" grids */
1779+ if (g_ptr->info & (CAVE_LITE | CAVE_MNLT))
1780+ {
1781+ /* Torch lite */
1782+ if (view_yellow_lite)
1783+ {
1784+ /* Use a brightly lit colour/tile */
1785+ a = f_ptr->x_attr[F_LIT_LITE];
1786+ c = f_ptr->x_char[F_LIT_LITE];
1787+ }
1788+ }
1789+
1790+ /* Handle "dark" grids */
1791+ else if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
1792+ {
1793+ /* Use a darkened colour/tile */
1794+ a = f_ptr->x_attr[F_LIT_DARK];
1795+ c = f_ptr->x_char[F_LIT_DARK];
1796+ }
1797+
1798+ /* Handle "out-of-sight" grids */
1799+ else if (!(g_ptr->info & CAVE_VIEW))
1800+ {
1801+ /* Special flag */
1802+ if (view_bright_lite)
1803+ {
1804+ /* Use a darkened colour/tile */
1805+ a = f_ptr->x_attr[F_LIT_DARK];
1806+ c = f_ptr->x_char[F_LIT_DARK];
1807+ }
1808+ }
1809+ }
1810+ }
1811+
1812+ /* Unknown */
1813+ else
1814+ {
1815+ /* Unsafe grid -- idea borrowed from Unangband */
1816+ feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
1817+
1818+ /* Access darkness */
1819+ f_ptr = &f_info[feat];
1820+
1821+ /* Normal attr/char */
1822+ a = f_ptr->x_attr[F_LIT_STANDARD];
1823+ c = f_ptr->x_char[F_LIT_STANDARD];
1824+ }
1825+ }
1826+
1827+ /* Interesting grids (non-floors) */
1828+ else
1829+ {
1830+ /* Memorized grids */
1831+ if (g_ptr->info & CAVE_MARK)
1832+ {
1833+ /* Normal attr/char */
1834+ a = f_ptr->x_attr[F_LIT_STANDARD];
1835+ c = f_ptr->x_char[F_LIT_STANDARD];
1836+
1837+ if (p_ptr->wild_mode)
1838+ {
1839+ /* Special lighting effects */
1840+ /* Handle "blind" or "night" */
1841+ if (view_granite_lite && (p_ptr->blind || !is_daytime()))
1842+ {
1843+ /* Use a darkened colour/tile */
1844+ a = f_ptr->x_attr[F_LIT_DARK];
1845+ c = f_ptr->x_char[F_LIT_DARK];
1846+ }
1847+ }
1848+
1849+ /* Mega-Hack -- Handle "in-sight" and "darkened" grids */
1850+ else if (darkened_grid(g_ptr) && !p_ptr->blind)
1851+ {
1852+ if (have_flag(f_ptr->flags, FF_LOS) && have_flag(f_ptr->flags, FF_PROJECT))
1853+ {
1854+ /* Unsafe grid -- idea borrowed from Unangband */
1855+ feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
1856+
1857+ /* Access darkness */
1858+ f_ptr = &f_info[feat];
1859+
1860+ /* Char and attr of darkness */
1861+ a = f_ptr->x_attr[F_LIT_STANDARD];
1862+ c = f_ptr->x_char[F_LIT_STANDARD];
1863+ }
1864+ else if (view_granite_lite && view_bright_lite)
1865+ {
1866+ /* Use a darkened colour/tile */
1867+ a = f_ptr->x_attr[F_LIT_DARK];
1868+ c = f_ptr->x_char[F_LIT_DARK];
1869+ }
1870+ }
1871+
1872+ /* Special lighting effects */
1873+ else if (view_granite_lite)
1874+ {
1875+ /* Handle "blind" */
1876+ if (p_ptr->blind)
1877+ {
1878+ /* Use a darkened colour/tile */
1879+ a = f_ptr->x_attr[F_LIT_DARK];
1880+ c = f_ptr->x_char[F_LIT_DARK];
1881+ }
1882+
1883+ /* Handle "torch-lit" grids */
1884+ else if (g_ptr->info & (CAVE_LITE | CAVE_MNLT))
1885+ {
1886+ /* Torch lite */
1887+ if (view_yellow_lite)
1888+ {
1889+ /* Use a brightly lit colour/tile */
1890+ a = f_ptr->x_attr[F_LIT_LITE];
1891+ c = f_ptr->x_char[F_LIT_LITE];
1892+ }
1893+ }
1894+
1895+ /* Handle "view_bright_lite" */
1896+ else if (view_bright_lite)
1897+ {
1898+ /* Not viewable */
1899+ if (!(g_ptr->info & CAVE_VIEW))
1900+ {
1901+ /* Use a darkened colour/tile */
1902+ a = f_ptr->x_attr[F_LIT_DARK];
1903+ c = f_ptr->x_char[F_LIT_DARK];
1904+ }
1905+
1906+ /* Not glowing */
1907+ else if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
1908+ {
1909+ /* Use a darkened colour/tile */
1910+ a = f_ptr->x_attr[F_LIT_DARK];
1911+ c = f_ptr->x_char[F_LIT_DARK];
1912+ }
1913+
1914+ /* Not glowing correctly */
1915+ else if (!have_flag(f_ptr->flags, FF_LOS) && !check_local_illumination(y, x))
1916+ {
1917+ /* Use a darkened colour/tile */
1918+ a = f_ptr->x_attr[F_LIT_DARK];
1919+ c = f_ptr->x_char[F_LIT_DARK];
1920+ }
1921+ }
1922+ }
1923+ }
1924+
1925+ /* Unknown */
1926+ else
1927+ {
1928+ /* Unsafe grid -- idea borrowed from Unangband */
1929+ feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
1930+
1931+ /* Access feature */
1932+ f_ptr = &f_info[feat];
1933+
1934+ /* Normal attr/char */
1935+ a = f_ptr->x_attr[F_LIT_STANDARD];
1936+ c = f_ptr->x_char[F_LIT_STANDARD];
1937+ }
1938+ }
1939+
1940+ if (feat_priority == -1) feat_priority = f_ptr->priority;
1941+
1942+ /* Save the terrain info for the transparency effects */
1943+ (*tap) = a;
1944+ (*tcp) = c;
1945+
1946+ /* Save the info */
1947+ (*ap) = a;
1948+ (*cp) = c;
1949+
1950+ /* Hack -- rare random hallucination, except on outer dungeon walls */
1951+ if (p_ptr->image)
1952+ {
1953+ if (one_in_(256))
1954+ {
1955+ /* Hallucinate */
1956+ image_random(ap, cp);
1957+ }
1958+ }
1959+
1960+ /* Objects */
1961+ for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1962+ {
1963+ object_type *o_ptr;
1964+ o_ptr = &o_list[this_o_idx];
1965+
1966+ /* Acquire next object */
1967+ next_o_idx = o_ptr->next_o_idx;
1968+
1969+ /* Memorized objects */
1970+ if (o_ptr->marked & OM_FOUND)
1971+ {
1972+ if (display_autopick)
1973+ {
1974+ byte act;
1975+
1976+ match_autopick = is_autopick(o_ptr);
1977+ if (match_autopick == -1)
1978+ continue;
1979+
1980+ act = autopick_list[match_autopick].action;
1981+
1982+ if ((act & DO_DISPLAY) && (act & display_autopick))
1983+ {
1984+ autopick_obj = o_ptr;
1985+ }
1986+ else
1987+ {
1988+ match_autopick = -1;
1989+ continue;
1990+ }
1991+ }
1992+ /* Normal char */
1993+ (*cp) = object_char(o_ptr);
1994+
1995+ /* Normal attr */
1996+ (*ap) = object_attr(o_ptr);
1997+
1998+ feat_priority = 20;
1999+
2000+ /* Hack -- hallucination */
2001+ if (p_ptr->image) image_object(ap, cp);
2002+
2003+ break;
2004+ }
2005+ }
2006+
2007+
2008+ /* Handle monsters */
2009+ if (g_ptr->m_idx && display_autopick == 0)
2010+ {
2011+ monster_type *m_ptr = &m_list[g_ptr->m_idx];
2012+
2013+ /* Visible monster */
2014+ if (m_ptr->ml)
2015+ {
2016+ monster_race *r_ptr = &r_info[m_ptr->ap_r_idx];
2017+
2018+ feat_priority = 30;
2019+
2020+ /* Hallucination */
2021+ if (p_ptr->image)
2022+ {
2023+ /*
2024+ * Monsters with both CHAR_CLEAR and ATTR_CLEAR
2025+ * flags are always unseen.
2026+ */
2027+ if ((r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) == (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR))
2028+ {
2029+ /* Do nothing */
2030+ }
2031+ else
2032+ {
2033+ /* Hallucinatory monster */
2034+ image_monster(ap, cp);
2035+ }
2036+ }
2037+ else
2038+ {
2039+ /* Monster attr/char */
2040+ a = r_ptr->x_attr;
2041+ c = r_ptr->x_char;
2042+
2043+ /* Normal monsters */
2044+ if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_SHAPECHANGER | RF1_ATTR_CLEAR
2045+ | RF1_ATTR_MULTI | RF1_ATTR_SEMIRAND)))
2046+ {
2047+ /* Desired monster attr/char */
2048+ *ap = a;
2049+ *cp = c;
2050+ }
2051+
2052+ /*
2053+ * Monsters with both CHAR_CLEAR and ATTR_CLEAR
2054+ * flags are always unseen.
2055+ */
2056+ else if ((r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) == (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR))
2057+ {
2058+ /* Do nothing */
2059+ }
2060+
2061+ else
2062+ {
2063+ /*** Monster's attr ***/
2064+ if ((r_ptr->flags1 & RF1_ATTR_CLEAR) && (*ap != TERM_DARK) && !use_graphics)
2065+ {
2066+ /* Clear-attr */
2067+ /* Do nothing */
2068+ }
2069+ else if ((r_ptr->flags1 & RF1_ATTR_MULTI) && !use_graphics)
2070+ {
2071+ /* Multi-hued attr */
2072+ if (r_ptr->flags2 & RF2_ATTR_ANY) *ap = randint1(15);
2073+ else switch (randint1(7))
2074+ {
2075+ case 1: *ap = TERM_RED; break;
2076+ case 2: *ap = TERM_L_RED; break;
2077+ case 3: *ap = TERM_WHITE; break;
2078+ case 4: *ap = TERM_L_GREEN; break;
2079+ case 5: *ap = TERM_BLUE; break;
2080+ case 6: *ap = TERM_L_DARK; break;
2081+ case 7: *ap = TERM_GREEN; break;
2082+ }
2083+ }
2084+ else if ((r_ptr->flags1 & RF1_ATTR_SEMIRAND) && !use_graphics)
2085+ {
2086+ /* Use semi-random attr (usually mimics' colors vary) */
2087+ *ap = g_ptr->m_idx % 15 + 1;
2088+ }
2089+ else
2090+ {
2091+ /* Normal case */
2092+ *ap = a;
2093+ }
2094+
2095+ /*** Monster's char ***/
2096+ if ((r_ptr->flags1 & RF1_CHAR_CLEAR) && (*cp != ' ') && !use_graphics)
2097+ {
2098+ /* Clear-char */
2099+ /* Do nothing */
2100+ }
2101+ else if (r_ptr->flags1 & RF1_SHAPECHANGER)
2102+ {
2103+ if (use_graphics)
2104+ {
2105+ monster_race *tmp_r_ptr = &r_info[randint1(max_r_idx - 1)];
2106+ *cp = tmp_r_ptr->x_char;
2107+ *ap = tmp_r_ptr->x_attr;
2108+ }
2109+ else
2110+ {
2111+ *cp = (one_in_(25) ?
2112+ image_object_hack[randint0(sizeof(image_object_hack) - 1)] :
2113+ image_monster_hack[randint0(sizeof(image_monster_hack) - 1)]);
2114+ }
2115+ }
2116+ else
2117+ {
2118+ /* Normal case */
2119+ *cp = c;
2120+ }
2121+ }
2122+ }
2123+ }
2124+ }
2125+
2126+ /* Handle "player" */
2127+ if (player_bold(y, x))
2128+ {
2129+ monster_race *r_ptr = &r_info[0];
2130+ *ap = r_ptr->x_attr;
2131+ *cp = r_ptr->x_char;
2132+ feat_priority = 31;
2133+ }
2134+}
2135+
2136+
2137+/*
2138+ * Calculate panel colum of a location in the map
2139+ */
2140+static int panel_col_of(int col)
2141+{
2142+ col -= panel_col_min;
2143+ if (use_bigtile) col *= 2;
2144+ return col + 13;
2145+}
2146+
2147+
2148+/*
2149+ * Moves the cursor to a given MAP (y,x) location
2150+ */
2151+void move_cursor_relative(int row, int col)
2152+{
2153+ /* Real co-ords convert to screen positions */
2154+ row -= panel_row_prt;
2155+
2156+ /* Go there */
2157+ Term_gotoxy(panel_col_of(col), row);
2158+}
2159+
2160+
2161+
2162+/*
2163+ * Place an attr/char pair at the given map coordinate, if legal.
2164+ */
2165+void print_rel(SYMBOL_CODE c, TERM_COLOR a, TERM_LEN y, TERM_LEN x)
2166+{
2167+ /* Only do "legal" locations */
2168+ if (panel_contains(y, x))
2169+ {
2170+ /* Hack -- fake monochrome */
2171+ if (!use_graphics)
2172+ {
2173+ if (world_monster) a = TERM_DARK;
2174+ else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
2175+ else if (p_ptr->wraith_form) a = TERM_L_DARK;
2176+ }
2177+
2178+ /* Draw the char using the attr */
2179+ Term_queue_bigchar(panel_col_of(x), y - panel_row_prt, a, c, 0, 0);
2180+ }
2181+}
2182+
2183+
2184+
2185+
2186+
2187+/*
2188+ * Memorize interesting viewable object/features in the given grid
2189+ *
2190+ * This function should only be called on "legal" grids.
2191+ *
2192+ * This function will memorize the object and/or feature in the given
2193+ * grid, if they are (1) viewable and (2) interesting. Note that all
2194+ * objects are interesting, all terrain features except floors (and
2195+ * invisible traps) are interesting, and floors (and invisible traps)
2196+ * are interesting sometimes (depending on various options involving
2197+ * the illumination of floor grids).
2198+ *
2199+ * The automatic memorization of all objects and non-floor terrain
2200+ * features as soon as they are displayed allows incredible amounts
2201+ * of optimization in various places, especially "map_info()".
2202+ *
2203+ * Note that the memorization of objects is completely separate from
2204+ * the memorization of terrain features, preventing annoying floor
2205+ * memorization when a detected object is picked up from a dark floor,
2206+ * and object memorization when an object is dropped into a floor grid
2207+ * which is memorized but out-of-sight.
2208+ *
2209+ * This function should be called every time the "memorization" of
2210+ * a grid (or the object in a grid) is called into question, such
2211+ * as when an object is created in a grid, when a terrain feature
2212+ * "changes" from "floor" to "non-floor", when any grid becomes
2213+ * "illuminated" or "viewable", and when a "floor" grid becomes
2214+ * "torch-lit".
2215+ *
2216+ * Note the relatively efficient use of this function by the various
2217+ * "update_view()" and "update_lite()" calls, to allow objects and
2218+ * terrain features to be memorized (and drawn) whenever they become
2219+ * viewable or illuminated in any way, but not when they "maintain"
2220+ * or "lose" their previous viewability or illumination.
2221+ *
2222+ * Note the butchered "internal" version of "player_can_see_bold()",
2223+ * optimized primarily for the most common cases, that is, for the
2224+ * non-marked floor grids.
2225+ */
2226+void note_spot(POSITION y, POSITION x)
2227+{
2228+ grid_type *g_ptr = &grid_array[y][x];
2229+ OBJECT_IDX this_o_idx, next_o_idx = 0;
2230+
2231+ /* Blind players see nothing */
2232+ if (p_ptr->blind) return;
2233+
2234+ /* Analyze non-torch-lit grids */
2235+ if (!(g_ptr->info & (CAVE_LITE | CAVE_MNLT)))
2236+ {
2237+ /* Require line of sight to the grid */
2238+ if (!(g_ptr->info & (CAVE_VIEW))) return;
2239+
2240+ /* Require "perma-lite" of the grid */
2241+ if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
2242+ {
2243+ /* Not Ninja */
2244+ if (!p_ptr->see_nocto) return;
2245+ }
2246+ }
2247+
2248+
2249+ /* Hack -- memorize objects */
2250+ for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
2251+ {
2252+ object_type *o_ptr = &o_list[this_o_idx];
2253+
2254+ /* Acquire next object */
2255+ next_o_idx = o_ptr->next_o_idx;
2256+
2257+ /* Memorize objects */
2258+ o_ptr->marked |= OM_FOUND;
2259+ }
2260+
2261+
2262+ /* Hack -- memorize grids */
2263+ if (!(g_ptr->info & (CAVE_MARK)))
2264+ {
2265+ /* Feature code (applying "mimic" field) */
2266+ feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)];
2267+
2268+ /* Memorize some "boring" grids */
2269+ if (!have_flag(f_ptr->flags, FF_REMEMBER))
2270+ {
2271+ /* Option -- memorize all torch-lit floors */
2272+ if (view_torch_grids &&
2273+ ((g_ptr->info & (CAVE_LITE | CAVE_MNLT)) || p_ptr->see_nocto))
2274+ {
2275+ g_ptr->info |= (CAVE_MARK);
2276+ }
2277+
2278+ /* Option -- memorize all perma-lit floors */
2279+ else if (view_perma_grids && ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW))
2280+ {
2281+ g_ptr->info |= (CAVE_MARK);
2282+ }
2283+ }
2284+
2285+ /* Memorize normal grids */
2286+ else if (have_flag(f_ptr->flags, FF_LOS))
2287+ {
2288+ g_ptr->info |= (CAVE_MARK);
2289+ }
2290+
2291+ /* Memorize torch-lit walls */
2292+ else if (g_ptr->info & (CAVE_LITE | CAVE_MNLT))
2293+ {
2294+ g_ptr->info |= (CAVE_MARK);
2295+ }
2296+
2297+ /* Memorize walls seen by noctovision of Ninja */
2298+ else if (p_ptr->see_nocto)
2299+ {
2300+ g_ptr->info |= (CAVE_MARK);
2301+ }
2302+
2303+ /* Memorize certain non-torch-lit wall grids */
2304+ else if (check_local_illumination(y, x))
2305+ {
2306+ g_ptr->info |= (CAVE_MARK);
2307+ }
2308+ }
2309+
2310+ /* Memorize terrain of the grid */
2311+ g_ptr->info |= (CAVE_KNOWN);
2312+}
2313+
2314+
2315+void display_dungeon(void)
2316+{
2317+ TERM_LEN x, y;
2318+ TERM_COLOR a;
2319+ SYMBOL_CODE c;
2320+
2321+ TERM_COLOR ta = 0;
2322+ SYMBOL_CODE tc = '\0';
2323+
2324+ for (x = p_ptr->x - Term->wid / 2 + 1; x <= p_ptr->x + Term->wid / 2; x++)
2325+ {
2326+ for (y = p_ptr->y - Term->hgt / 2 + 1; y <= p_ptr->y + Term->hgt / 2; y++)
2327+ {
2328+ if (in_bounds2(y, x))
2329+ {
2330+
2331+ /* Examine the grid */
2332+ map_info(y, x, &a, &c, &ta, &tc);
2333+
2334+ /* Hack -- fake monochrome */
2335+ if (!use_graphics)
2336+ {
2337+ if (world_monster) a = TERM_DARK;
2338+ else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
2339+ else if (p_ptr->wraith_form) a = TERM_L_DARK;
2340+ }
2341+
2342+ /* Hack -- Queue it */
2343+ Term_queue_char(x - p_ptr->x + Term->wid / 2 - 1, y - p_ptr->y + Term->hgt / 2 - 1, a, c, ta, tc);
2344+ }
2345+ else
2346+ {
2347+ /* Clear out-of-bound tiles */
2348+
2349+ /* Access darkness */
2350+ feature_type *f_ptr = &f_info[feat_none];
2351+
2352+ /* Normal attr */
2353+ a = f_ptr->x_attr[F_LIT_STANDARD];
2354+
2355+ /* Normal char */
2356+ c = f_ptr->x_char[F_LIT_STANDARD];
2357+
2358+ /* Hack -- Queue it */
2359+ Term_queue_char(x - p_ptr->x + Term->wid / 2 - 1, y - p_ptr->y + Term->hgt / 2 - 1, a, c, ta, tc);
2360+ }
2361+ }
2362+ }
2363+}
2364+
2365+
2366+/*
2367+ * Redraw (on the screen) a given MAP location
2368+ *
2369+ * This function should only be called on "legal" grids
2370+ */
2371+void lite_spot(POSITION y, POSITION x)
2372+{
2373+ /* Redraw if on screen */
2374+ if (panel_contains(y, x) && in_bounds2(y, x))
2375+ {
2376+ TERM_COLOR a;
2377+ SYMBOL_CODE c;
2378+
2379+ TERM_COLOR ta;
2380+ SYMBOL_CODE tc;
2381+
2382+ /* Examine the grid */
2383+ map_info(y, x, &a, &c, &ta, &tc);
2384+
2385+ /* Hack -- fake monochrome */
2386+ if (!use_graphics)
2387+ {
2388+ if (world_monster) a = TERM_DARK;
2389+ else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
2390+ else if (p_ptr->wraith_form) a = TERM_L_DARK;
2391+ }
2392+
2393+ /* Hack -- Queue it */
2394+ Term_queue_bigchar(panel_col_of(x), y - panel_row_prt, a, c, ta, tc);
2395+
2396+ /* Update sub-windows */
2397+ p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
2398+ }
2399+}
2400+
2401+
2402+/*
2403+ * Prints the map of the dungeon
2404+ *
2405+ * Note that, for efficiency, we contain an "optimized" version
2406+ * of both "lite_spot()" and "print_rel()", and that we use the
2407+ * "lite_spot()" function to display the player grid, if needed.
2408+ */
2409+void prt_map(void)
2410+{
2411+ POSITION x, y;
2412+ int v;
2413+
2414+ /* map bounds */
2415+ POSITION xmin, xmax, ymin, ymax;
2416+
2417+ TERM_LEN wid, hgt;
2418+
2419+ Term_get_size(&wid, &hgt);
2420+
2421+ /* Remove map offset */
2422+ wid -= COL_MAP + 2;
2423+ hgt -= ROW_MAP + 2;
2424+
2425+ /* Access the cursor state */
2426+ (void)Term_get_cursor(&v);
2427+
2428+ /* Hide the cursor */
2429+ (void)Term_set_cursor(0);
2430+
2431+ /* Get bounds */
2432+ xmin = (0 < panel_col_min) ? panel_col_min : 0;
2433+ xmax = (cur_wid - 1 > panel_col_max) ? panel_col_max : cur_wid - 1;
2434+ ymin = (0 < panel_row_min) ? panel_row_min : 0;
2435+ ymax = (cur_hgt - 1 > panel_row_max) ? panel_row_max : cur_hgt - 1;
2436+
2437+ /* Bottom section of screen */
2438+ for (y = 1; y <= ymin - panel_row_prt; y++)
2439+ {
2440+ /* Erase the section */
2441+ Term_erase(COL_MAP, y, wid);
2442+ }
2443+
2444+ /* Top section of screen */
2445+ for (y = ymax - panel_row_prt; y <= hgt; y++)
2446+ {
2447+ /* Erase the section */
2448+ Term_erase(COL_MAP, y, wid);
2449+ }
2450+
2451+ /* Dump the map */
2452+ for (y = ymin; y <= ymax; y++)
2453+ {
2454+ /* Scan the columns of row "y" */
2455+ for (x = xmin; x <= xmax; x++)
2456+ {
2457+ TERM_COLOR a;
2458+ SYMBOL_CODE c;
2459+
2460+ TERM_COLOR ta;
2461+ SYMBOL_CODE tc;
2462+
2463+ /* Determine what is there */
2464+ map_info(y, x, &a, &c, &ta, &tc);
2465+
2466+ /* Hack -- fake monochrome */
2467+ if (!use_graphics)
2468+ {
2469+ if (world_monster) a = TERM_DARK;
2470+ else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
2471+ else if (p_ptr->wraith_form) a = TERM_L_DARK;
2472+ }
2473+
2474+ /* Efficiency -- Redraw that grid of the map */
2475+ Term_queue_bigchar(panel_col_of(x), y - panel_row_prt, a, c, ta, tc);
2476+ }
2477+ }
2478+
2479+ /* Display player */
2480+ lite_spot(p_ptr->y, p_ptr->x);
2481+
2482+ /* Restore the cursor */
2483+ (void)Term_set_cursor(v);
2484+}
2485+
2486+
2487+
2488+/*
2489+ * print project path
2490+ */
2491+void prt_path(POSITION y, POSITION x)
2492+{
2493+ int i;
2494+ int path_n;
2495+ u16b path_g[512];
2496+ byte_hack default_color = TERM_SLATE;
2497+
2498+ if (!display_path) return;
2499+ if (-1 == project_length)
2500+ return;
2501+
2502+ /* Get projection path */
2503+ path_n = project_path(path_g, (project_length ? project_length : MAX_RANGE), p_ptr->y, p_ptr->x, y, x, PROJECT_PATH | PROJECT_THRU);
2504+
2505+ p_ptr->redraw |= (PR_MAP);
2506+ handle_stuff();
2507+
2508+ /* Draw path */
2509+ for (i = 0; i < path_n; i++)
2510+ {
2511+ POSITION ny = GRID_Y(path_g[i]);
2512+ POSITION nx = GRID_X(path_g[i]);
2513+ grid_type *g_ptr = &grid_array[ny][nx];
2514+
2515+ if (panel_contains(ny, nx))
2516+ {
2517+ TERM_COLOR a = default_color;
2518+ char c;
2519+
2520+ TERM_COLOR ta = default_color;
2521+ char tc = '*';
2522+
2523+ if (g_ptr->m_idx && m_list[g_ptr->m_idx].ml)
2524+ {
2525+ /* Determine what is there */
2526+ map_info(ny, nx, &a, &c, &ta, &tc);
2527+
2528+ if (!is_ascii_graphics(a))
2529+ a = default_color;
2530+ else if (c == '.' && (a == TERM_WHITE || a == TERM_L_WHITE))
2531+ a = default_color;
2532+ else if (a == default_color)
2533+ a = TERM_WHITE;
2534+ }
2535+
2536+ if (!use_graphics)
2537+ {
2538+ if (world_monster) a = TERM_DARK;
2539+ else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
2540+ else if (p_ptr->wraith_form) a = TERM_L_DARK;
2541+ }
2542+
2543+ c = '*';
2544+
2545+ /* Hack -- Queue it */
2546+ Term_queue_bigchar(panel_col_of(nx), ny - panel_row_prt, a, c, ta, tc);
2547+ }
2548+
2549+ /* Known Wall */
2550+ if ((g_ptr->info & CAVE_MARK) && !cave_have_flag_grid(g_ptr, FF_PROJECT)) break;
2551+
2552+ /* Change color */
2553+ if (nx == x && ny == y) default_color = TERM_L_DARK;
2554+ }
2555+}
2556+
2557+
2558+static concptr simplify_list[][2] =
2559+{
2560+#ifdef JP
2561+ {"の魔法書", ""},
2562+ {NULL, NULL}
2563+#else
2564+ {"^Ring of ", "="},
2565+ {"^Amulet of ", "\""},
2566+ {"^Scroll of ", "?"},
2567+ {"^Scroll titled ", "?"},
2568+ {"^Wand of " , "-"},
2569+ {"^Rod of " , "-"},
2570+ {"^Staff of " , "_"},
2571+ {"^Potion of ", "!"},
2572+ {" Spellbook ",""},
2573+ {"^Book of ", ""},
2574+ {" Magic [", "["},
2575+ {" Book [", "["},
2576+ {" Arts [", "["},
2577+ {"^Set of ", ""},
2578+ {"^Pair of ", ""},
2579+ {NULL, NULL}
2580+#endif
2581+};
2582+
2583+static void display_shortened_item_name(object_type *o_ptr, int y)
2584+{
2585+ char buf[MAX_NLEN];
2586+ char *c = buf;
2587+ int len = 0;
2588+ TERM_COLOR attr;
2589+
2590+ object_desc(buf, o_ptr, (OD_NO_FLAVOR | OD_OMIT_PREFIX | OD_NAME_ONLY));
2591+ attr = tval_to_attr[o_ptr->tval % 128];
2592+
2593+ if (p_ptr->image)
2594+ {
2595+ attr = TERM_WHITE;
2596+ strcpy(buf, _("何か奇妙な物", "something strange"));
2597+ }
2598+
2599+ for (c = buf; *c; c++)
2600+ {
2601+ int i;
2602+ for (i = 0; simplify_list[i][1]; i++)
2603+ {
2604+ concptr org_w = simplify_list[i][0];
2605+
2606+ if (*org_w == '^')
2607+ {
2608+ if (c == buf)
2609+ org_w++;
2610+ else
2611+ continue;
2612+ }
2613+
2614+ if (!strncmp(c, org_w, strlen(org_w)))
2615+ {
2616+ char *s = c;
2617+ concptr tmp = simplify_list[i][1];
2618+ while (*tmp)
2619+ *s++ = *tmp++;
2620+ tmp = c + strlen(org_w);
2621+ while (*tmp)
2622+ *s++ = *tmp++;
2623+ *s = '\0';
2624+ }
2625+ }
2626+ }
2627+
2628+ c = buf;
2629+ len = 0;
2630+ /* 半角 12 文字分で切る */
2631+ while (*c)
2632+ {
2633+#ifdef JP
2634+ if (iskanji(*c))
2635+ {
2636+ if (len + 2 > 12) break;
2637+ c += 2;
2638+ len += 2;
2639+ }
2640+ else
2641+#endif
2642+ {
2643+ if (len + 1 > 12) break;
2644+ c++;
2645+ len++;
2646+ }
2647+ }
2648+ *c = '\0';
2649+ Term_putstr(0, y, 12, attr, buf);
2650+}
2651+
2652+/*
2653+ * Display a "small-scale" map of the dungeon in the active Term
2654+ */
2655+void display_map(int *cy, int *cx)
2656+{
2657+ int i, j, x, y;
2658+
2659+ TERM_COLOR ta;
2660+ SYMBOL_CODE tc;
2661+
2662+ byte tp;
2663+
2664+ TERM_COLOR **bigma;
2665+ SYMBOL_CODE **bigmc;
2666+ byte **bigmp;
2667+
2668+ TERM_COLOR **ma;
2669+ SYMBOL_CODE **mc;
2670+ byte **mp;
2671+
2672+ /* Save lighting effects */
2673+ bool old_view_special_lite = view_special_lite;
2674+ bool old_view_granite_lite = view_granite_lite;
2675+
2676+ TERM_LEN hgt, wid, yrat, xrat;
2677+
2678+ int **match_autopick_yx;
2679+ object_type ***object_autopick_yx;
2680+
2681+ Term_get_size(&wid, &hgt);
2682+ hgt -= 2;
2683+ wid -= 14;
2684+ if (use_bigtile) wid /= 2;
2685+
2686+ yrat = (cur_hgt + hgt - 1) / hgt;
2687+ xrat = (cur_wid + wid - 1) / wid;
2688+
2689+ /* Disable lighting effects */
2690+ view_special_lite = FALSE;
2691+ view_granite_lite = FALSE;
2692+
2693+ /* Allocate the maps */
2694+ C_MAKE(ma, (hgt + 2), TERM_COLOR *);
2695+ C_MAKE(mc, (hgt + 2), char_ptr);
2696+ C_MAKE(mp, (hgt + 2), byte_ptr);
2697+ C_MAKE(match_autopick_yx, (hgt + 2), sint_ptr);
2698+ C_MAKE(object_autopick_yx, (hgt + 2), object_type **);
2699+
2700+ /* Allocate and wipe each line map */
2701+ for (y = 0; y < (hgt + 2); y++)
2702+ {
2703+ /* Allocate one row each array */
2704+ C_MAKE(ma[y], (wid + 2), TERM_COLOR);
2705+ C_MAKE(mc[y], (wid + 2), char);
2706+ C_MAKE(mp[y], (wid + 2), byte);
2707+ C_MAKE(match_autopick_yx[y], (wid + 2), int);
2708+ C_MAKE(object_autopick_yx[y], (wid + 2), object_type *);
2709+
2710+ for (x = 0; x < wid + 2; ++x)
2711+ {
2712+ match_autopick_yx[y][x] = -1;
2713+ object_autopick_yx[y][x] = NULL;
2714+
2715+ /* Nothing here */
2716+ ma[y][x] = TERM_WHITE;
2717+ mc[y][x] = ' ';
2718+
2719+ /* No priority */
2720+ mp[y][x] = 0;
2721+ }
2722+ }
2723+
2724+ /* Allocate the maps */
2725+ C_MAKE(bigma, (cur_hgt + 2), TERM_COLOR *);
2726+ C_MAKE(bigmc, (cur_hgt + 2), char_ptr);
2727+ C_MAKE(bigmp, (cur_hgt + 2), byte_ptr);
2728+
2729+ /* Allocate and wipe each line map */
2730+ for (y = 0; y < (cur_hgt + 2); y++)
2731+ {
2732+ /* Allocate one row each array */
2733+ C_MAKE(bigma[y], (cur_wid + 2), TERM_COLOR);
2734+ C_MAKE(bigmc[y], (cur_wid + 2), char);
2735+ C_MAKE(bigmp[y], (cur_wid + 2), byte);
2736+
2737+ for (x = 0; x < cur_wid + 2; ++x)
2738+ {
2739+ /* Nothing here */
2740+ bigma[y][x] = TERM_WHITE;
2741+ bigmc[y][x] = ' ';
2742+
2743+ /* No priority */
2744+ bigmp[y][x] = 0;
2745+ }
2746+ }
2747+
2748+ /* Fill in the map */
2749+ for (i = 0; i < cur_wid; ++i)
2750+ {
2751+ for (j = 0; j < cur_hgt; ++j)
2752+ {
2753+ x = i / xrat + 1;
2754+ y = j / yrat + 1;
2755+
2756+ match_autopick = -1;
2757+ autopick_obj = NULL;
2758+ feat_priority = -1;
2759+
2760+ /* Extract the current attr/char at that map location */
2761+ map_info(j, i, &ta, &tc, &ta, &tc);
2762+
2763+ /* Extract the priority */
2764+ tp = (byte_hack)feat_priority;
2765+
2766+ if (match_autopick != -1
2767+ && (match_autopick_yx[y][x] == -1
2768+ || match_autopick_yx[y][x] > match_autopick))
2769+ {
2770+ match_autopick_yx[y][x] = match_autopick;
2771+ object_autopick_yx[y][x] = autopick_obj;
2772+ tp = 0x7f;
2773+ }
2774+
2775+ /* Save the char, attr and priority */
2776+ bigmc[j + 1][i + 1] = tc;
2777+ bigma[j + 1][i + 1] = ta;
2778+ bigmp[j + 1][i + 1] = tp;
2779+ }
2780+ }
2781+
2782+ for (j = 0; j < cur_hgt; ++j)
2783+ {
2784+ for (i = 0; i < cur_wid; ++i)
2785+ {
2786+ x = i / xrat + 1;
2787+ y = j / yrat + 1;
2788+
2789+ tc = bigmc[j + 1][i + 1];
2790+ ta = bigma[j + 1][i + 1];
2791+ tp = bigmp[j + 1][i + 1];
2792+
2793+ /* rare feature has more priority */
2794+ if (mp[y][x] == tp)
2795+ {
2796+ int t;
2797+ int cnt = 0;
2798+
2799+ for (t = 0; t < 8; t++)
2800+ {
2801+ if (tc == bigmc[j + 1 + ddy_cdd[t]][i + 1 + ddx_cdd[t]] &&
2802+ ta == bigma[j + 1 + ddy_cdd[t]][i + 1 + ddx_cdd[t]])
2803+ cnt++;
2804+ }
2805+ if (cnt <= 4)
2806+ tp++;
2807+ }
2808+
2809+ /* Save "best" */
2810+ if (mp[y][x] < tp)
2811+ {
2812+ /* Save the char, attr and priority */
2813+ mc[y][x] = tc;
2814+ ma[y][x] = ta;
2815+ mp[y][x] = tp;
2816+ }
2817+ }
2818+ }
2819+
2820+
2821+ /* Corners */
2822+ x = wid + 1;
2823+ y = hgt + 1;
2824+
2825+ /* Draw the corners */
2826+ mc[0][0] = mc[0][x] = mc[y][0] = mc[y][x] = '+';
2827+
2828+ /* Draw the horizontal edges */
2829+ for (x = 1; x <= wid; x++) mc[0][x] = mc[y][x] = '-';
2830+
2831+ /* Draw the vertical edges */
2832+ for (y = 1; y <= hgt; y++) mc[y][0] = mc[y][x] = '|';
2833+
2834+
2835+ /* Display each map line in order */
2836+ for (y = 0; y < hgt + 2; ++y)
2837+ {
2838+ /* Start a new line */
2839+ Term_gotoxy(COL_MAP, y);
2840+
2841+ /* Display the line */
2842+ for (x = 0; x < wid + 2; ++x)
2843+ {
2844+ ta = ma[y][x];
2845+ tc = mc[y][x];
2846+
2847+ /* Hack -- fake monochrome */
2848+ if (!use_graphics)
2849+ {
2850+ if (world_monster) ta = TERM_DARK;
2851+ else if (IS_INVULN() || p_ptr->timewalk) ta = TERM_WHITE;
2852+ else if (p_ptr->wraith_form) ta = TERM_L_DARK;
2853+ }
2854+
2855+ /* Add the character */
2856+ Term_add_bigch(ta, tc);
2857+ }
2858+ }
2859+
2860+
2861+ for (y = 1; y < hgt + 1; ++y)
2862+ {
2863+ match_autopick = -1;
2864+ for (x = 1; x <= wid; x++) {
2865+ if (match_autopick_yx[y][x] != -1 &&
2866+ (match_autopick > match_autopick_yx[y][x] ||
2867+ match_autopick == -1)) {
2868+ match_autopick = match_autopick_yx[y][x];
2869+ autopick_obj = object_autopick_yx[y][x];
2870+ }
2871+ }
2872+
2873+ /* Clear old display */
2874+ Term_putstr(0, y, 12, 0, " ");
2875+
2876+ if (match_autopick != -1)
2877+#if 1
2878+ display_shortened_item_name(autopick_obj, y);
2879+#else
2880+ {
2881+ char buf[13] = "\0";
2882+ strncpy(buf, autopick_list[match_autopick].name, 12);
2883+ buf[12] = '\0';
2884+ put_str(buf, y, 0);
2885+ }
2886+#endif
2887+
2888+ }
2889+
2890+ /* Player location */
2891+ (*cy) = p_ptr->y / yrat + 1 + ROW_MAP;
2892+ if (!use_bigtile)
2893+ (*cx) = p_ptr->x / xrat + 1 + COL_MAP;
2894+ else
2895+ (*cx) = (p_ptr->x / xrat + 1) * 2 + COL_MAP;
2896+
2897+ /* Restore lighting effects */
2898+ view_special_lite = old_view_special_lite;
2899+ view_granite_lite = old_view_granite_lite;
2900+
2901+ /* Free each line map */
2902+ for (y = 0; y < (hgt + 2); y++)
2903+ {
2904+ /* Free one row each array */
2905+ C_KILL(ma[y], (wid + 2), TERM_COLOR);
2906+ C_KILL(mc[y], (wid + 2), SYMBOL_CODE);
2907+ C_KILL(mp[y], (wid + 2), byte);
2908+ C_KILL(match_autopick_yx[y], (wid + 2), int);
2909+ C_KILL(object_autopick_yx[y], (wid + 2), object_type *);
2910+ }
2911+
2912+ /* Free each line map */
2913+ C_KILL(ma, (hgt + 2), TERM_COLOR *);
2914+ C_KILL(mc, (hgt + 2), char_ptr);
2915+ C_KILL(mp, (hgt + 2), byte_ptr);
2916+ C_KILL(match_autopick_yx, (hgt + 2), sint_ptr);
2917+ C_KILL(object_autopick_yx, (hgt + 2), object_type **);
2918+
2919+ /* Free each line map */
2920+ for (y = 0; y < (cur_hgt + 2); y++)
2921+ {
2922+ /* Free one row each array */
2923+ C_KILL(bigma[y], (cur_wid + 2), TERM_COLOR);
2924+ C_KILL(bigmc[y], (cur_wid + 2), SYMBOL_CODE);
2925+ C_KILL(bigmp[y], (cur_wid + 2), byte);
2926+ }
2927+
2928+ /* Free each line map */
2929+ C_KILL(bigma, (cur_hgt + 2), TERM_COLOR *);
2930+ C_KILL(bigmc, (cur_hgt + 2), char_ptr);
2931+ C_KILL(bigmp, (cur_hgt + 2), byte_ptr);
2932+}
2933+
2934+
2935+/*
2936+ * Display a "small-scale" map of the dungeon for the player
2937+ *
2938+ * Currently, the "player" is displayed on the map.
2939+ */
2940+void do_cmd_view_map(void)
2941+{
2942+ int cy, cx;
2943+
2944+ screen_save();
2945+
2946+ prt(_("お待ち下さい...", "Please wait..."), 0, 0);
2947+
2948+ Term_fresh();
2949+ Term_clear();
2950+
2951+ display_autopick = 0;
2952+
2953+ /* Display the map */
2954+ display_map(&cy, &cx);
2955+
2956+ /* Wait for it */
2957+ if (max_autopick && !p_ptr->wild_mode)
2958+ {
2959+ display_autopick = ITEM_DISPLAY;
2960+
2961+ while (1)
2962+ {
2963+ int i;
2964+ byte flag;
2965+
2966+ int wid, hgt, row_message;
2967+
2968+ Term_get_size(&wid, &hgt);
2969+ row_message = hgt - 1;
2970+
2971+ put_str(_("何かキーを押してください('M':拾う 'N':放置 'D':M+N 'K':壊すアイテムを表示)",
2972+ " Hit M, N(for ~), K(for !), or D(same as M+N) to display auto-picker items."), row_message, 1);
2973+
2974+ /* Hilite the player */
2975+ move_cursor(cy, cx);
2976+
2977+ i = inkey();
2978+
2979+ if ('M' == i)
2980+ flag = (DO_AUTOPICK | DO_QUERY_AUTOPICK);
2981+ else if ('N' == i)
2982+ flag = DONT_AUTOPICK;
2983+ else if ('K' == i)
2984+ flag = DO_AUTODESTROY;
2985+ else if ('D' == i)
2986+ flag = (DO_AUTOPICK | DO_QUERY_AUTOPICK | DONT_AUTOPICK);
2987+ else
2988+ break;
2989+
2990+ Term_fresh();
2991+
2992+ if (~display_autopick & flag)
2993+ display_autopick |= flag;
2994+ else
2995+ display_autopick &= ~flag;
2996+ /* Display the map */
2997+ display_map(&cy, &cx);
2998+ }
2999+
3000+ display_autopick = 0;
3001+
3002+ }
3003+ else
3004+ {
3005+ put_str(_("何かキーを押すとゲームに戻ります", "Hit any key to continue"), 23, 30);
3006+ /* Hilite the player */
3007+ move_cursor(cy, cx);
3008+ /* Get any key */
3009+ inkey();
3010+ }
3011+ screen_load();
3012+}
3013+
3014+
3015+
3016+
3017+
3018+/*
3019+ * Some comments on the grid flags. -BEN-
3020+ *
3021+ *
3022+ * One of the major bottlenecks in previous versions of Angband was in
3023+ * the calculation of "line of sight" from the player to various grids,
3024+ * such as monsters. This was such a nasty bottleneck that a lot of
3025+ * silly things were done to reduce the dependancy on "line of sight",
3026+ * for example, you could not "see" any grids in a lit room until you
3027+ * actually entered the room, and there were all kinds of bizarre grid
3028+ * flags to enable this behavior. This is also why the "call light"
3029+ * spells always lit an entire room.
3030+ *
3031+ * The code below provides functions to calculate the "field of view"
3032+ * for the player, which, once calculated, provides extremely fast
3033+ * calculation of "line of sight from the player", and to calculate
3034+ * the "field of torch lite", which, again, once calculated, provides
3035+ * extremely fast calculation of "which grids are lit by the player's
3036+ * lite source". In addition to marking grids as "GRID_VIEW" and/or
3037+ * "GRID_LITE", as appropriate, these functions maintain an array for
3038+ * each of these two flags, each array containing the locations of all
3039+ * of the grids marked with the appropriate flag, which can be used to
3040+ * very quickly scan through all of the grids in a given set.
3041+ *
3042+ * To allow more "semantically valid" field of view semantics, whenever
3043+ * the field of view (or the set of torch lit grids) changes, all of the
3044+ * grids in the field of view (or the set of torch lit grids) are "drawn"
3045+ * so that changes in the world will become apparent as soon as possible.
3046+ * This has been optimized so that only grids which actually "change" are
3047+ * redrawn, using the "temp" array and the "GRID_TEMP" flag to keep track
3048+ * of the grids which are entering or leaving the relevent set of grids.
3049+ *
3050+ * These new methods are so efficient that the old nasty code was removed.
3051+ *
3052+ * Note that there is no reason to "update" the "viewable space" unless
3053+ * the player "moves", or walls/doors are created/destroyed, and there
3054+ * is no reason to "update" the "torch lit grids" unless the field of
3055+ * view changes, or the "light radius" changes. This means that when
3056+ * the player is resting, or digging, or doing anything that does not
3057+ * involve movement or changing the state of the dungeon, there is no
3058+ * need to update the "view" or the "lite" regions, which is nice.
3059+ *
3060+ * Note that the calls to the nasty "los()" function have been reduced
3061+ * to a bare minimum by the use of the new "field of view" calculations.
3062+ *
3063+ * I wouldn't be surprised if slight modifications to the "update_view()"
3064+ * function would allow us to determine "reverse line-of-sight" as well
3065+ * as "normal line-of-sight", which would allow monsters to use a more
3066+ * "correct" calculation to determine if they can "see" the player. For
3067+ * now, monsters simply "cheat" somewhat and assume that if the player
3068+ * has "line of sight" to the monster, then the monster can "pretend"
3069+ * that it has "line of sight" to the player.
3070+ *
3071+ *
3072+ * The "update_lite()" function maintains the "CAVE_LITE" flag for each
3073+ * grid and maintains an array of all "CAVE_LITE" grids.
3074+ *
3075+ * This set of grids is the complete set of all grids which are lit by
3076+ * the players light source, which allows the "player_can_see_bold()"
3077+ * function to work very quickly.
3078+ *
3079+ * Note that every "CAVE_LITE" grid is also a "CAVE_VIEW" grid, and in
3080+ * fact, the player (unless blind) can always "see" all grids which are
3081+ * marked as "CAVE_LITE", unless they are "off screen".
3082+ *
3083+ *
3084+ * The "update_view()" function maintains the "CAVE_VIEW" flag for each
3085+ * grid and maintains an array of all "CAVE_VIEW" grids.
3086+ *
3087+ * This set of grids is the complete set of all grids within line of sight
3088+ * of the player, allowing the "player_has_los_bold()" macro to work very
3089+ * quickly.
3090+ *
3091+ *
3092+ * The current "update_view()" algorithm uses the "CAVE_XTRA" flag as a
3093+ * temporary internal flag to mark those grids which are not only in view,
3094+ * but which are also "easily" in line of sight of the player. This flag
3095+ * is always cleared when we are done.
3096+ *
3097+ *
3098+ * The current "update_lite()" and "update_view()" algorithms use the
3099+ * "CAVE_TEMP" flag, and the array of grids which are marked as "CAVE_TEMP",
3100+ * to keep track of which grids were previously marked as "CAVE_LITE" or
3101+ * "CAVE_VIEW", which allows us to optimize the "screen updates".
3102+ *
3103+ * The "CAVE_TEMP" flag, and the array of "CAVE_TEMP" grids, is also used
3104+ * for various other purposes, such as spreading lite or darkness during
3105+ * "lite_room()" / "unlite_room()", and for calculating monster flow.
3106+ *
3107+ *
3108+ * Any grid can be marked as "CAVE_GLOW" which means that the grid itself is
3109+ * in some way permanently lit. However, for the player to "see" anything
3110+ * in the grid, as determined by "player_can_see()", the player must not be
3111+ * blind, the grid must be marked as "CAVE_VIEW", and, in addition, "wall"
3112+ * grids, even if marked as "perma lit", are only illuminated if they touch
3113+ * a grid which is not a wall and is marked both "CAVE_GLOW" and "CAVE_VIEW".
3114+ *
3115+ *
3116+ * To simplify various things, a grid may be marked as "CAVE_MARK", meaning
3117+ * that even if the player cannot "see" the grid, he "knows" the terrain in
3118+ * that grid. This is used to "remember" walls/doors/stairs/floors when they
3119+ * are "seen" or "detected", and also to "memorize" floors, after "wiz_lite()",
3120+ * or when one of the "memorize floor grids" options induces memorization.
3121+ *
3122+ * Objects are "memorized" in a different way, using a special "marked" flag
3123+ * on the object itself, which is set when an object is observed or detected.
3124+ *
3125+ *
3126+ * A grid may be marked as "CAVE_ROOM" which means that it is part of a "room",
3127+ * and should be illuminated by "lite room" and "darkness" spells.
3128+ *
3129+ *
3130+ * A grid may be marked as "CAVE_ICKY" which means it is part of a "vault",
3131+ * and should be unavailable for "teleportation" destinations.
3132+ *
3133+ *
3134+ * The "view_perma_grids" allows the player to "memorize" every perma-lit grid
3135+ * which is observed, and the "view_torch_grids" allows the player to memorize
3136+ * every torch-lit grid. The player will always memorize important walls,
3137+ * doors, stairs, and other terrain features, as well as any "detected" grids.
3138+ *
3139+ * Note that the new "update_view()" method allows, among other things, a room
3140+ * to be "partially" seen as the player approaches it, with a growing cone of
3141+ * floor appearing as the player gets closer to the door. Also, by not turning
3142+ * on the "memorize perma-lit grids" option, the player will only "see" those
3143+ * floor grids which are actually in line of sight.
3144+ *
3145+ * And my favorite "plus" is that you can now use a special option to draw the
3146+ * "floors" in the "viewable region" brightly (actually, to draw the *other*
3147+ * grids dimly), providing a "pretty" effect as the player runs around, and
3148+ * to efficiently display the "torch lite" in a special color.
3149+ *
3150+ *
3151+ * Some comments on the "update_view()" algorithm...
3152+ *
3153+ * The algorithm is very fast, since it spreads "obvious" grids very quickly,
3154+ * and only has to call "los()" on the borderline cases. The major axes/diags
3155+ * even terminate early when they hit walls. I need to find a quick way
3156+ * to "terminate" the other scans.
3157+ *
3158+ * Note that in the worst case (a big empty area with say 5% scattered walls),
3159+ * each of the 1500 or so nearby grids is checked once, most of them getting
3160+ * an "instant" rating, and only a small portion requiring a call to "los()".
3161+ *
3162+ * The only time that the algorithm appears to be "noticeably" too slow is
3163+ * when running, and this is usually only important in town, since the town
3164+ * provides about the worst scenario possible, with large open regions and
3165+ * a few scattered obstructions. There is a special "efficiency" option to
3166+ * allow the player to reduce his field of view in town, if needed.
3167+ *
3168+ * In the "best" case (say, a normal stretch of corridor), the algorithm
3169+ * makes one check for each viewable grid, and makes no calls to "los()".
3170+ * So running in corridors is very fast, and if a lot of monsters are
3171+ * nearby, it is much faster than the old methods.
3172+ *
3173+ * Note that resting, most normal commands, and several forms of running,
3174+ * plus all commands executed near large groups of monsters, are strictly
3175+ * more efficient with "update_view()" that with the old "compute los() on
3176+ * demand" method, primarily because once the "field of view" has been
3177+ * calculated, it does not have to be recalculated until the player moves
3178+ * (or a wall or door is created or destroyed).
3179+ *
3180+ * Note that we no longer have to do as many "los()" checks, since once the
3181+ * "view" region has been built, very few things cause it to be "changed"
3182+ * (player movement, and the opening/closing of doors, changes in wall status).
3183+ * Note that door/wall changes are only relevant when the door/wall itself is
3184+ * in the "view" region.
3185+ *
3186+ * The algorithm seems to only call "los()" from zero to ten times, usually
3187+ * only when coming down a corridor into a room, or standing in a room, just
3188+ * misaligned with a corridor. So if, say, there are five "nearby" monsters,
3189+ * we will be reducing the calls to "los()".
3190+ *
3191+ * I am thinking in terms of an algorithm that "walks" from the central point
3192+ * out to the maximal "distance", at each point, determining the "view" code
3193+ * (above). For each grid not on a major axis or diagonal, the "view" code
3194+ * depends on the "cave_los_bold()" and "view" of exactly two other grids
3195+ * (the one along the nearest diagonal, and the one next to that one, see
3196+ * "update_view_aux()"...).
3197+ *
3198+ * We "memorize" the viewable space array, so that at the cost of under 3000
3199+ * bytes, we reduce the time taken by "forget_view()" to one assignment for
3200+ * each grid actually in the "viewable space". And for another 3000 bytes,
3201+ * we prevent "erase + redraw" ineffiencies via the "seen" set. These bytes
3202+ * are also used by other routines, thus reducing the cost to almost nothing.
3203+ *
3204+ * A similar thing is done for "forget_lite()" in which case the savings are
3205+ * much less, but save us from doing bizarre maintenance checking.
3206+ *
3207+ * In the worst "normal" case (in the middle of the town), the reachable space
3208+ * actually reaches to more than half of the largest possible "circle" of view,
3209+ * or about 800 grids, and in the worse case (in the middle of a dungeon level
3210+ * where all the walls have been removed), the reachable space actually reaches
3211+ * the theoretical maximum size of just under 1500 grids.
3212+ *
3213+ * Each grid G examines the "state" of two (?) other (adjacent) grids, G1 & G2.
3214+ * If G1 is lite, G is lite. Else if G2 is lite, G is half. Else if G1 and G2
3215+ * are both half, G is half. Else G is dark. It only takes 2 (or 4) bits to
3216+ * "name" a grid, so (for MAX_RAD of 20) we could use 1600 bytes, and scan the
3217+ * entire possible space (including initialization) in one step per grid. If
3218+ * we do the "clearing" as a separate step (and use an array of "view" grids),
3219+ * then the clearing will take as many steps as grids that were viewed, and the
3220+ * algorithm will be able to "stop" scanning at various points.
3221+ * Oh, and outside of the "torch radius", only "lite" grids need to be scanned.
3222+ */
3223+
3224+
3225+
3226+
3227+
3228+
3229+
3230+
3231+ /*
3232+ * Actually erase the entire "lite" array, redrawing every grid
3233+ */
3234+void forget_lite(void)
3235+{
3236+ int i, x, y;
3237+
3238+ /* None to forget */
3239+ if (!lite_n) return;
3240+
3241+ /* Clear them all */
3242+ for (i = 0; i < lite_n; i++)
3243+ {
3244+ y = lite_y[i];
3245+ x = lite_x[i];
3246+
3247+ /* Forget "LITE" flag */
3248+ grid_array[y][x].info &= ~(CAVE_LITE);
3249+
3250+ /* lite_spot(y, x); Perhaps don't need? */
3251+ }
3252+
3253+ /* None left */
3254+ lite_n = 0;
3255+}
3256+
3257+
3258+/*
3259+ * For delayed visual update
3260+ */
3261+#define cave_note_and_redraw_later(C,Y,X) \
3262+{\
3263+ (C)->info |= CAVE_NOTE; \
3264+ cave_redraw_later((C), (Y), (X)); \
3265+}
3266+
3267+
3268+ /*
3269+ * For delayed visual update
3270+ */
3271+#define cave_redraw_later(C,Y,X) \
3272+{\
3273+ if (!((C)->info & CAVE_REDRAW)) \
3274+ { \
3275+ (C)->info |= CAVE_REDRAW; \
3276+ redraw_y[redraw_n] = (Y); \
3277+ redraw_x[redraw_n++] = (X); \
3278+ } \
3279+}
3280+
3281+
3282+ /*
3283+ * This macro allows us to efficiently add a grid to the "lite" array,
3284+ * note that we are never called for illegal grids, or for grids which
3285+ * have already been placed into the "lite" array, and we are never
3286+ * called when the "lite" array is full.
3287+ */
3288+#define cave_lite_hack(Y,X) \
3289+{\
3290+ if (!(grid_array[Y][X].info & (CAVE_LITE))) \
3291+ { \
3292+ grid_array[Y][X].info |= (CAVE_LITE); \
3293+ lite_y[lite_n] = (Y); \
3294+ lite_x[lite_n++] = (X); \
3295+ } \
3296+}
3297+
3298+
3299+ /*
3300+ * Update the set of grids "illuminated" by the player's lite.
3301+ *
3302+ * This routine needs to use the results of "update_view()"
3303+ *
3304+ * Note that "blindness" does NOT affect "torch lite". Be careful!
3305+ *
3306+ * We optimize most lites (all non-artifact lites) by using "obvious"
3307+ * facts about the results of "small" lite radius, and we attempt to
3308+ * list the "nearby" grids before the more "distant" ones in the
3309+ * array of torch-lit grids.
3310+ *
3311+ * We assume that "radius zero" lite is in fact no lite at all.
3312+ *
3313+ * Torch Lantern Artifacts
3314+ * (etc)
3315+ * ***
3316+ * *** *****
3317+ * *** ***** *******
3318+ * *@* **@** ***@***
3319+ * *** ***** *******
3320+ * *** *****
3321+ * ***
3322+ */
3323+void update_lite(void)
3324+{
3325+ int i;
3326+ POSITION x, y, min_x, max_x, min_y, max_y;
3327+ int p = p_ptr->cur_lite;
3328+ grid_type *g_ptr;
3329+
3330+ /*** Special case ***/
3331+
3332+#if 0
3333+ /* Hack -- Player has no lite */
3334+ if (p <= 0)
3335+ {
3336+ /* Forget the old lite */
3337+ /* forget_lite(); Perhaps don't need? */
3338+
3339+ /* Add it to later visual update */
3340+ cave_redraw_later(&grid_array[p_ptr->y][p_ptr->x], p_ptr->y, p_ptr->x);
3341+ }
3342+#endif
3343+
3344+ /*** Save the old "lite" grids for later ***/
3345+
3346+ /* Clear them all */
3347+ for (i = 0; i < lite_n; i++)
3348+ {
3349+ y = lite_y[i];
3350+ x = lite_x[i];
3351+
3352+ /* Mark the grid as not "lite" */
3353+ grid_array[y][x].info &= ~(CAVE_LITE);
3354+
3355+ /* Mark the grid as "seen" */
3356+ grid_array[y][x].info |= (CAVE_TEMP);
3357+
3358+ /* Add it to the "seen" set */
3359+ temp_y[temp_n] = y;
3360+ temp_x[temp_n] = x;
3361+ temp_n++;
3362+ }
3363+
3364+ /* None left */
3365+ lite_n = 0;
3366+
3367+
3368+ /*** Collect the new "lite" grids ***/
3369+
3370+ /* Radius 1 -- torch radius */
3371+ if (p >= 1)
3372+ {
3373+ /* Player grid */
3374+ cave_lite_hack(p_ptr->y, p_ptr->x);
3375+
3376+ /* Adjacent grid */
3377+ cave_lite_hack(p_ptr->y + 1, p_ptr->x);
3378+ cave_lite_hack(p_ptr->y - 1, p_ptr->x);
3379+ cave_lite_hack(p_ptr->y, p_ptr->x + 1);
3380+ cave_lite_hack(p_ptr->y, p_ptr->x - 1);
3381+
3382+ /* Diagonal grids */
3383+ cave_lite_hack(p_ptr->y + 1, p_ptr->x + 1);
3384+ cave_lite_hack(p_ptr->y + 1, p_ptr->x - 1);
3385+ cave_lite_hack(p_ptr->y - 1, p_ptr->x + 1);
3386+ cave_lite_hack(p_ptr->y - 1, p_ptr->x - 1);
3387+ }
3388+
3389+ /* Radius 2 -- lantern radius */
3390+ if (p >= 2)
3391+ {
3392+ /* South of the player */
3393+ if (cave_los_bold(p_ptr->y + 1, p_ptr->x))
3394+ {
3395+ cave_lite_hack(p_ptr->y + 2, p_ptr->x);
3396+ cave_lite_hack(p_ptr->y + 2, p_ptr->x + 1);
3397+ cave_lite_hack(p_ptr->y + 2, p_ptr->x - 1);
3398+ }
3399+
3400+ /* North of the player */
3401+ if (cave_los_bold(p_ptr->y - 1, p_ptr->x))
3402+ {
3403+ cave_lite_hack(p_ptr->y - 2, p_ptr->x);
3404+ cave_lite_hack(p_ptr->y - 2, p_ptr->x + 1);
3405+ cave_lite_hack(p_ptr->y - 2, p_ptr->x - 1);
3406+ }
3407+
3408+ /* East of the player */
3409+ if (cave_los_bold(p_ptr->y, p_ptr->x + 1))
3410+ {
3411+ cave_lite_hack(p_ptr->y, p_ptr->x + 2);
3412+ cave_lite_hack(p_ptr->y + 1, p_ptr->x + 2);
3413+ cave_lite_hack(p_ptr->y - 1, p_ptr->x + 2);
3414+ }
3415+
3416+ /* West of the player */
3417+ if (cave_los_bold(p_ptr->y, p_ptr->x - 1))
3418+ {
3419+ cave_lite_hack(p_ptr->y, p_ptr->x - 2);
3420+ cave_lite_hack(p_ptr->y + 1, p_ptr->x - 2);
3421+ cave_lite_hack(p_ptr->y - 1, p_ptr->x - 2);
3422+ }
3423+ }
3424+
3425+ /* Radius 3+ -- artifact radius */
3426+ if (p >= 3)
3427+ {
3428+ int d;
3429+
3430+ /* Paranoia -- see "LITE_MAX" */
3431+ if (p > 14) p = 14;
3432+
3433+ /* South-East of the player */
3434+ if (cave_los_bold(p_ptr->y + 1, p_ptr->x + 1))
3435+ {
3436+ cave_lite_hack(p_ptr->y + 2, p_ptr->x + 2);
3437+ }
3438+
3439+ /* South-West of the player */
3440+ if (cave_los_bold(p_ptr->y + 1, p_ptr->x - 1))
3441+ {
3442+ cave_lite_hack(p_ptr->y + 2, p_ptr->x - 2);
3443+ }
3444+
3445+ /* North-East of the player */
3446+ if (cave_los_bold(p_ptr->y - 1, p_ptr->x + 1))
3447+ {
3448+ cave_lite_hack(p_ptr->y - 2, p_ptr->x + 2);
3449+ }
3450+
3451+ /* North-West of the player */
3452+ if (cave_los_bold(p_ptr->y - 1, p_ptr->x - 1))
3453+ {
3454+ cave_lite_hack(p_ptr->y - 2, p_ptr->x - 2);
3455+ }
3456+
3457+ /* Maximal north */
3458+ min_y = p_ptr->y - p;
3459+ if (min_y < 0) min_y = 0;
3460+
3461+ /* Maximal south */
3462+ max_y = p_ptr->y + p;
3463+ if (max_y > cur_hgt - 1) max_y = cur_hgt - 1;
3464+
3465+ /* Maximal west */
3466+ min_x = p_ptr->x - p;
3467+ if (min_x < 0) min_x = 0;
3468+
3469+ /* Maximal east */
3470+ max_x = p_ptr->x + p;
3471+ if (max_x > cur_wid - 1) max_x = cur_wid - 1;
3472+
3473+ /* Scan the maximal box */
3474+ for (y = min_y; y <= max_y; y++)
3475+ {
3476+ for (x = min_x; x <= max_x; x++)
3477+ {
3478+ int dy = (p_ptr->y > y) ? (p_ptr->y - y) : (y - p_ptr->y);
3479+ int dx = (p_ptr->x > x) ? (p_ptr->x - x) : (x - p_ptr->x);
3480+
3481+ /* Skip the "central" grids (above) */
3482+ if ((dy <= 2) && (dx <= 2)) continue;
3483+
3484+ /* Hack -- approximate the distance */
3485+ d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
3486+
3487+ /* Skip distant grids */
3488+ if (d > p) continue;
3489+
3490+ /* Viewable, nearby, grids get "torch lit" */
3491+ if (grid_array[y][x].info & CAVE_VIEW)
3492+ {
3493+ /* This grid is "torch lit" */
3494+ cave_lite_hack(y, x);
3495+ }
3496+ }
3497+ }
3498+ }
3499+
3500+
3501+ /*** Complete the algorithm ***/
3502+
3503+ /* Draw the new grids */
3504+ for (i = 0; i < lite_n; i++)
3505+ {
3506+ y = lite_y[i];
3507+ x = lite_x[i];
3508+
3509+ g_ptr = &grid_array[y][x];
3510+
3511+ /* Update fresh grids */
3512+ if (g_ptr->info & (CAVE_TEMP)) continue;
3513+
3514+ /* Add it to later visual update */
3515+ cave_note_and_redraw_later(g_ptr, y, x);
3516+ }
3517+
3518+ /* Clear them all */
3519+ for (i = 0; i < temp_n; i++)
3520+ {
3521+ y = temp_y[i];
3522+ x = temp_x[i];
3523+
3524+ g_ptr = &grid_array[y][x];
3525+
3526+ /* No longer in the array */
3527+ g_ptr->info &= ~(CAVE_TEMP);
3528+
3529+ /* Update stale grids */
3530+ if (g_ptr->info & (CAVE_LITE)) continue;
3531+
3532+ /* Add it to later visual update */
3533+ cave_redraw_later(g_ptr, y, x);
3534+ }
3535+
3536+ /* None left */
3537+ temp_n = 0;
3538+
3539+ /* Mega-Hack -- Visual update later */
3540+ p_ptr->update |= (PU_DELAY_VIS);
3541+}
3542+
3543+
3544+static bool mon_invis;
3545+static POSITION mon_fy, mon_fx;
3546+
3547+/*
3548+ * Add a square to the changes array
3549+ */
3550+static void mon_lite_hack(POSITION y, POSITION x)
3551+{
3552+ grid_type *g_ptr;
3553+ int dpf, d;
3554+ POSITION midpoint;
3555+
3556+ /* We trust this grid is in bounds */
3557+ /* if (!in_bounds2(y, x)) return; */
3558+
3559+ g_ptr = &grid_array[y][x];
3560+
3561+ /* Want a unlit square in view of the player */
3562+ if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW) return;
3563+
3564+ if (!cave_los_grid(g_ptr))
3565+ {
3566+ /* Hack -- Prevent monster lite leakage in walls */
3567+
3568+ /* Horizontal walls between player and a monster */
3569+ if (((y < p_ptr->y) && (y > mon_fy)) || ((y > p_ptr->y) && (y < mon_fy)))
3570+ {
3571+ dpf = p_ptr->y - mon_fy;
3572+ d = y - mon_fy;
3573+ midpoint = mon_fx + ((p_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
3574+
3575+ /* Only first wall viewed from mid-x is lit */
3576+ if (x < midpoint)
3577+ {
3578+ if (!cave_los_bold(y, x + 1)) return;
3579+ }
3580+ else if (x > midpoint)
3581+ {
3582+ if (!cave_los_bold(y, x - 1)) return;
3583+ }
3584+
3585+ /* Hack XXX XXX - Is it a wall and monster not in LOS? */
3586+ else if (mon_invis) return;
3587+ }
3588+
3589+ /* Vertical walls between player and a monster */
3590+ if (((x < p_ptr->x) && (x > mon_fx)) || ((x > p_ptr->x) && (x < mon_fx)))
3591+ {
3592+ dpf = p_ptr->x - mon_fx;
3593+ d = x - mon_fx;
3594+ midpoint = mon_fy + ((p_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
3595+
3596+ /* Only first wall viewed from mid-y is lit */
3597+ if (y < midpoint)
3598+ {
3599+ if (!cave_los_bold(y + 1, x)) return;
3600+ }
3601+ else if (y > midpoint)
3602+ {
3603+ if (!cave_los_bold(y - 1, x)) return;
3604+ }
3605+
3606+ /* Hack XXX XXX - Is it a wall and monster not in LOS? */
3607+ else if (mon_invis) return;
3608+ }
3609+ }
3610+
3611+ /* We trust temp_n does not exceed TEMP_MAX */
3612+
3613+ /* New grid */
3614+ if (!(g_ptr->info & CAVE_MNDK))
3615+ {
3616+ /* Save this square */
3617+ temp_x[temp_n] = x;
3618+ temp_y[temp_n] = y;
3619+ temp_n++;
3620+ }
3621+
3622+ /* Darkened grid */
3623+ else
3624+ {
3625+ /* No longer dark */
3626+ g_ptr->info &= ~(CAVE_MNDK);
3627+ }
3628+
3629+ /* Light it */
3630+ g_ptr->info |= CAVE_MNLT;
3631+}
3632+
3633+
3634+/*
3635+ * Add a square to the changes array
3636+ */
3637+static void mon_dark_hack(POSITION y, POSITION x)
3638+{
3639+ grid_type *g_ptr;
3640+ int midpoint, dpf, d;
3641+
3642+ /* We trust this grid is in bounds */
3643+ /* if (!in_bounds2(y, x)) return; */
3644+
3645+ g_ptr = &grid_array[y][x];
3646+
3647+ /* Want a unlit and undarkened square in view of the player */
3648+ if ((g_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW) return;
3649+
3650+ if (!cave_los_grid(g_ptr) && !cave_have_flag_grid(g_ptr, FF_PROJECT))
3651+ {
3652+ /* Hack -- Prevent monster dark lite leakage in walls */
3653+
3654+ /* Horizontal walls between player and a monster */
3655+ if (((y < p_ptr->y) && (y > mon_fy)) || ((y > p_ptr->y) && (y < mon_fy)))
3656+ {
3657+ dpf = p_ptr->y - mon_fy;
3658+ d = y - mon_fy;
3659+ midpoint = mon_fx + ((p_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
3660+
3661+ /* Only first wall viewed from mid-x is lit */
3662+ if (x < midpoint)
3663+ {
3664+ if (!cave_los_bold(y, x + 1) && !cave_have_flag_bold(y, x + 1, FF_PROJECT)) return;
3665+ }
3666+ else if (x > midpoint)
3667+ {
3668+ if (!cave_los_bold(y, x - 1) && !cave_have_flag_bold(y, x - 1, FF_PROJECT)) return;
3669+ }
3670+
3671+ /* Hack XXX XXX - Is it a wall and monster not in LOS? */
3672+ else if (mon_invis) return;
3673+ }
3674+
3675+ /* Vertical walls between player and a monster */
3676+ if (((x < p_ptr->x) && (x > mon_fx)) || ((x > p_ptr->x) && (x < mon_fx)))
3677+ {
3678+ dpf = p_ptr->x - mon_fx;
3679+ d = x - mon_fx;
3680+ midpoint = mon_fy + ((p_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
3681+
3682+ /* Only first wall viewed from mid-y is lit */
3683+ if (y < midpoint)
3684+ {
3685+ if (!cave_los_bold(y + 1, x) && !cave_have_flag_bold(y + 1, x, FF_PROJECT)) return;
3686+ }
3687+ else if (y > midpoint)
3688+ {
3689+ if (!cave_los_bold(y - 1, x) && !cave_have_flag_bold(y - 1, x, FF_PROJECT)) return;
3690+ }
3691+
3692+ /* Hack XXX XXX - Is it a wall and monster not in LOS? */
3693+ else if (mon_invis) return;
3694+ }
3695+ }
3696+
3697+ /* We trust temp_n does not exceed TEMP_MAX */
3698+
3699+ /* Save this square */
3700+ temp_x[temp_n] = x;
3701+ temp_y[temp_n] = y;
3702+ temp_n++;
3703+
3704+ /* Darken it */
3705+ g_ptr->info |= CAVE_MNDK;
3706+}
3707+
3708+
3709+/*
3710+ * Update squares illuminated or darkened by monsters.
3711+ *
3712+ * Hack - use the CAVE_ROOM flag (renamed to be CAVE_MNLT) to
3713+ * denote squares illuminated by monsters.
3714+ *
3715+ * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
3716+ * updating. Only squares in view of the player, whos state
3717+ * changes are drawn via lite_spot().
3718+ */
3719+void update_mon_lite(void)
3720+{
3721+ int i, rad;
3722+ grid_type *g_ptr;
3723+
3724+ POSITION fx, fy;
3725+ void(*add_mon_lite)(POSITION, POSITION);
3726+ int f_flag;
3727+
3728+ s16b end_temp;
3729+
3730+ /* Non-Ninja player in the darkness */
3731+ int dis_lim = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !p_ptr->see_nocto) ?
3732+ (MAX_SIGHT / 2 + 1) : (MAX_SIGHT + 3);
3733+
3734+ /* Clear all monster lit squares */
3735+ for (i = 0; i < mon_lite_n; i++)
3736+ {
3737+ /* Point to grid */
3738+ g_ptr = &grid_array[mon_lite_y[i]][mon_lite_x[i]];
3739+
3740+ /* Set temp or xtra flag */
3741+ g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
3742+
3743+ /* Clear monster illumination flag */
3744+ g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
3745+ }
3746+
3747+ /* Empty temp list of new squares to lite up */
3748+ temp_n = 0;
3749+
3750+ /* If a monster stops time, don't process */
3751+ if (!world_monster)
3752+ {
3753+ monster_type *m_ptr;
3754+ monster_race *r_ptr;
3755+
3756+ /* Loop through monsters, adding newly lit squares to changes list */
3757+ for (i = 1; i < m_max; i++)
3758+ {
3759+ m_ptr = &m_list[i];
3760+ r_ptr = &r_info[m_ptr->r_idx];
3761+
3762+ /* Skip dead monsters */
3763+ if (!m_ptr->r_idx) continue;
3764+
3765+ /* Is it too far away? */
3766+ if (m_ptr->cdis > dis_lim) continue;
3767+
3768+ /* Get lite radius */
3769+ rad = 0;
3770+
3771+ /* Note the radii are cumulative */
3772+ if (r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_SELF_LITE_1)) rad++;
3773+ if (r_ptr->flags7 & (RF7_HAS_LITE_2 | RF7_SELF_LITE_2)) rad += 2;
3774+ if (r_ptr->flags7 & (RF7_HAS_DARK_1 | RF7_SELF_DARK_1)) rad--;
3775+ if (r_ptr->flags7 & (RF7_HAS_DARK_2 | RF7_SELF_DARK_2)) rad -= 2;
3776+
3777+ /* Exit if has no light */
3778+ if (!rad) continue;
3779+ else if (rad > 0)
3780+ {
3781+ if (!(r_ptr->flags7 & (RF7_SELF_LITE_1 | RF7_SELF_LITE_2)) && (MON_CSLEEP(m_ptr) || (!dun_level && is_daytime()) || p_ptr->inside_battle)) continue;
3782+ if (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS) rad = 1;
3783+ add_mon_lite = mon_lite_hack;
3784+ f_flag = FF_LOS;
3785+ }
3786+ else
3787+ {
3788+ if (!(r_ptr->flags7 & (RF7_SELF_DARK_1 | RF7_SELF_DARK_2)) && (MON_CSLEEP(m_ptr) || (!dun_level && !is_daytime()))) continue;
3789+ add_mon_lite = mon_dark_hack;
3790+ f_flag = FF_PROJECT;
3791+ rad = -rad; /* Use absolute value */
3792+ }
3793+
3794+ /* Access the location */
3795+ mon_fx = m_ptr->fx;
3796+ mon_fy = m_ptr->fy;
3797+
3798+ /* Is the monster visible? */
3799+ mon_invis = !(grid_array[mon_fy][mon_fx].info & CAVE_VIEW);
3800+
3801+ /* The square it is on */
3802+ add_mon_lite(mon_fy, mon_fx);
3803+
3804+ /* Adjacent squares */
3805+ add_mon_lite(mon_fy + 1, mon_fx);
3806+ add_mon_lite(mon_fy - 1, mon_fx);
3807+ add_mon_lite(mon_fy, mon_fx + 1);
3808+ add_mon_lite(mon_fy, mon_fx - 1);
3809+ add_mon_lite(mon_fy + 1, mon_fx + 1);
3810+ add_mon_lite(mon_fy + 1, mon_fx - 1);
3811+ add_mon_lite(mon_fy - 1, mon_fx + 1);
3812+ add_mon_lite(mon_fy - 1, mon_fx - 1);
3813+
3814+ /* Radius 2 */
3815+ if (rad >= 2)
3816+ {
3817+ /* South of the monster */
3818+ if (cave_have_flag_bold(mon_fy + 1, mon_fx, f_flag))
3819+ {
3820+ add_mon_lite(mon_fy + 2, mon_fx + 1);
3821+ add_mon_lite(mon_fy + 2, mon_fx);
3822+ add_mon_lite(mon_fy + 2, mon_fx - 1);
3823+
3824+ g_ptr = &grid_array[mon_fy + 2][mon_fx];
3825+
3826+ /* Radius 3 */
3827+ if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
3828+ {
3829+ add_mon_lite(mon_fy + 3, mon_fx + 1);
3830+ add_mon_lite(mon_fy + 3, mon_fx);
3831+ add_mon_lite(mon_fy + 3, mon_fx - 1);
3832+ }
3833+ }
3834+
3835+ /* North of the monster */
3836+ if (cave_have_flag_bold(mon_fy - 1, mon_fx, f_flag))
3837+ {
3838+ add_mon_lite(mon_fy - 2, mon_fx + 1);
3839+ add_mon_lite(mon_fy - 2, mon_fx);
3840+ add_mon_lite(mon_fy - 2, mon_fx - 1);
3841+
3842+ g_ptr = &grid_array[mon_fy - 2][mon_fx];
3843+
3844+ /* Radius 3 */
3845+ if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
3846+ {
3847+ add_mon_lite(mon_fy - 3, mon_fx + 1);
3848+ add_mon_lite(mon_fy - 3, mon_fx);
3849+ add_mon_lite(mon_fy - 3, mon_fx - 1);
3850+ }
3851+ }
3852+
3853+ /* East of the monster */
3854+ if (cave_have_flag_bold(mon_fy, mon_fx + 1, f_flag))
3855+ {
3856+ add_mon_lite(mon_fy + 1, mon_fx + 2);
3857+ add_mon_lite(mon_fy, mon_fx + 2);
3858+ add_mon_lite(mon_fy - 1, mon_fx + 2);
3859+
3860+ g_ptr = &grid_array[mon_fy][mon_fx + 2];
3861+
3862+ /* Radius 3 */
3863+ if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
3864+ {
3865+ add_mon_lite(mon_fy + 1, mon_fx + 3);
3866+ add_mon_lite(mon_fy, mon_fx + 3);
3867+ add_mon_lite(mon_fy - 1, mon_fx + 3);
3868+ }
3869+ }
3870+
3871+ /* West of the monster */
3872+ if (cave_have_flag_bold(mon_fy, mon_fx - 1, f_flag))
3873+ {
3874+ add_mon_lite(mon_fy + 1, mon_fx - 2);
3875+ add_mon_lite(mon_fy, mon_fx - 2);
3876+ add_mon_lite(mon_fy - 1, mon_fx - 2);
3877+
3878+ g_ptr = &grid_array[mon_fy][mon_fx - 2];
3879+
3880+ /* Radius 3 */
3881+ if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
3882+ {
3883+ add_mon_lite(mon_fy + 1, mon_fx - 3);
3884+ add_mon_lite(mon_fy, mon_fx - 3);
3885+ add_mon_lite(mon_fy - 1, mon_fx - 3);
3886+ }
3887+ }
3888+ }
3889+
3890+ /* Radius 3 */
3891+ if (rad == 3)
3892+ {
3893+ /* South-East of the monster */
3894+ if (cave_have_flag_bold(mon_fy + 1, mon_fx + 1, f_flag))
3895+ {
3896+ add_mon_lite(mon_fy + 2, mon_fx + 2);
3897+ }
3898+
3899+ /* South-West of the monster */
3900+ if (cave_have_flag_bold(mon_fy + 1, mon_fx - 1, f_flag))
3901+ {
3902+ add_mon_lite(mon_fy + 2, mon_fx - 2);
3903+ }
3904+
3905+ /* North-East of the monster */
3906+ if (cave_have_flag_bold(mon_fy - 1, mon_fx + 1, f_flag))
3907+ {
3908+ add_mon_lite(mon_fy - 2, mon_fx + 2);
3909+ }
3910+
3911+ /* North-West of the monster */
3912+ if (cave_have_flag_bold(mon_fy - 1, mon_fx - 1, f_flag))
3913+ {
3914+ add_mon_lite(mon_fy - 2, mon_fx - 2);
3915+ }
3916+ }
3917+ }
3918+ }
3919+
3920+ /* Save end of list of new squares */
3921+ end_temp = temp_n;
3922+
3923+ /*
3924+ * Look at old set flags to see if there are any changes.
3925+ */
3926+ for (i = 0; i < mon_lite_n; i++)
3927+ {
3928+ fx = mon_lite_x[i];
3929+ fy = mon_lite_y[i];
3930+
3931+ /* We trust this grid is in bounds */
3932+
3933+ /* Point to grid */
3934+ g_ptr = &grid_array[fy][fx];
3935+
3936+ if (g_ptr->info & CAVE_TEMP) /* Pervious lit */
3937+ {
3938+ /* It it no longer lit? */
3939+ if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
3940+ {
3941+ /* It is now unlit */
3942+ /* Add it to later visual update */
3943+ cave_note_and_redraw_later(g_ptr, fy, fx);
3944+ }
3945+ }
3946+ else /* Pervious darkened */
3947+ {
3948+ /* It it no longer darken? */
3949+ if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
3950+ {
3951+ /* It is now undarken */
3952+ /* Add it to later visual update */
3953+ cave_note_and_redraw_later(g_ptr, fy, fx);
3954+ }
3955+ }
3956+
3957+ /* Add to end of temp array */
3958+ temp_x[temp_n] = fx;
3959+ temp_y[temp_n] = fy;
3960+ temp_n++;
3961+ }
3962+
3963+ /* Clear the lite array */
3964+ mon_lite_n = 0;
3965+
3966+ /* Copy the temp array into the lit array lighting the new squares. */
3967+ for (i = 0; i < end_temp; i++)
3968+ {
3969+ fx = temp_x[i];
3970+ fy = temp_y[i];
3971+
3972+ /* We trust this grid is in bounds */
3973+
3974+ /* Point to grid */
3975+ g_ptr = &grid_array[fy][fx];
3976+
3977+ if (g_ptr->info & CAVE_MNLT) /* Lit */
3978+ {
3979+ /* The is the square newly lit and visible? */
3980+ if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
3981+ {
3982+ /* It is now lit */
3983+ /* Add it to later visual update */
3984+ cave_note_and_redraw_later(g_ptr, fy, fx);
3985+ }
3986+ }
3987+ else /* Darkened */
3988+ {
3989+ /* The is the square newly darkened and visible? */
3990+ if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
3991+ {
3992+ /* It is now darkened */
3993+ /* Add it to later visual update */
3994+ cave_note_and_redraw_later(g_ptr, fy, fx);
3995+ }
3996+ }
3997+
3998+ /* Save in the monster lit or darkened array */
3999+ mon_lite_x[mon_lite_n] = fx;
4000+ mon_lite_y[mon_lite_n] = fy;
4001+ mon_lite_n++;
4002+ }
4003+
4004+ /* Clear the temp flag for the old lit or darken grids */
4005+ for (i = end_temp; i < temp_n; i++)
4006+ {
4007+ /* We trust this grid is in bounds */
4008+
4009+ grid_array[temp_y[i]][temp_x[i]].info &= ~(CAVE_TEMP | CAVE_XTRA);
4010+ }
4011+
4012+ /* Finished with temp_n */
4013+ temp_n = 0;
4014+
4015+ /* Mega-Hack -- Visual update later */
4016+ p_ptr->update |= (PU_DELAY_VIS);
4017+
4018+ p_ptr->monlite = (grid_array[p_ptr->y][p_ptr->x].info & CAVE_MNLT) ? TRUE : FALSE;
4019+
4020+ if (p_ptr->special_defense & NINJA_S_STEALTH)
4021+ {
4022+ if (p_ptr->old_monlite != p_ptr->monlite)
4023+ {
4024+ if (p_ptr->monlite)
4025+ {
4026+ msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow become thin."));
4027+ }
4028+ else
4029+ {
4030+ msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow restored its original darkness."));
4031+ }
4032+ }
4033+ }
4034+ p_ptr->old_monlite = p_ptr->monlite;
4035+}
4036+
4037+void clear_mon_lite(void)
4038+{
4039+ int i;
4040+ grid_type *g_ptr;
4041+
4042+ /* Clear all monster lit squares */
4043+ for (i = 0; i < mon_lite_n; i++)
4044+ {
4045+ /* Point to grid */
4046+ g_ptr = &grid_array[mon_lite_y[i]][mon_lite_x[i]];
4047+
4048+ /* Clear monster illumination flag */
4049+ g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
4050+ }
4051+
4052+ /* Empty the array */
4053+ mon_lite_n = 0;
4054+}
4055+
4056+
4057+
4058+/*
4059+ * Clear the viewable space
4060+ */
4061+void forget_view(void)
4062+{
4063+ int i;
4064+
4065+ grid_type *g_ptr;
4066+
4067+ /* None to forget */
4068+ if (!view_n) return;
4069+
4070+ /* Clear them all */
4071+ for (i = 0; i < view_n; i++)
4072+ {
4073+ POSITION y = view_y[i];
4074+ POSITION x = view_x[i];
4075+ g_ptr = &grid_array[y][x];
4076+
4077+ /* Forget that the grid is viewable */
4078+ g_ptr->info &= ~(CAVE_VIEW);
4079+
4080+ /* if (!panel_contains(y, x)) continue; */
4081+
4082+ /* Update the screen */
4083+ /* lite_spot(y, x); Perhaps don't need? */
4084+ }
4085+
4086+ /* None left */
4087+ view_n = 0;
4088+}
4089+
4090+
4091+
4092+/*
4093+ * This macro allows us to efficiently add a grid to the "view" array,
4094+ * note that we are never called for illegal grids, or for grids which
4095+ * have already been placed into the "view" array, and we are never
4096+ * called when the "view" array is full.
4097+ */
4098+#define cave_view_hack(C,Y,X) \
4099+{\
4100+ if (!((C)->info & (CAVE_VIEW))){\
4101+ (C)->info |= (CAVE_VIEW); \
4102+ view_y[view_n] = (Y); \
4103+ view_x[view_n] = (X); \
4104+ view_n++;}\
4105+}
4106+
4107+
4108+
4109+ /*
4110+ * Helper function for "update_view()" below
4111+ *
4112+ * We are checking the "viewability" of grid (y,x) by the player.
4113+ *
4114+ * This function assumes that (y,x) is legal (i.e. on the map).
4115+ *
4116+ * Grid (y1,x1) is on the "diagonal" between (p_ptr->y,p_ptr->x) and (y,x)
4117+ * Grid (y2,x2) is "adjacent", also between (p_ptr->y,p_ptr->x) and (y,x).
4118+ *
4119+ * Note that we are using the "CAVE_XTRA" field for marking grids as
4120+ * "easily viewable". This bit is cleared at the end of "update_view()".
4121+ *
4122+ * This function adds (y,x) to the "viewable set" if necessary.
4123+ *
4124+ * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
4125+ */
4126+static bool update_view_aux(POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
4127+{
4128+ bool f1, f2, v1, v2, z1, z2, wall;
4129+
4130+ grid_type *g_ptr;
4131+
4132+ grid_type *g1_c_ptr;
4133+ grid_type *g2_c_ptr;
4134+
4135+ /* Access the grids */
4136+ g1_c_ptr = &grid_array[y1][x1];
4137+ g2_c_ptr = &grid_array[y2][x2];
4138+
4139+
4140+ /* Check for walls */
4141+ f1 = (cave_los_grid(g1_c_ptr));
4142+ f2 = (cave_los_grid(g2_c_ptr));
4143+
4144+ /* Totally blocked by physical walls */
4145+ if (!f1 && !f2) return (TRUE);
4146+
4147+
4148+ /* Check for visibility */
4149+ v1 = (f1 && (g1_c_ptr->info & (CAVE_VIEW)));
4150+ v2 = (f2 && (g2_c_ptr->info & (CAVE_VIEW)));
4151+
4152+ /* Totally blocked by "unviewable neighbors" */
4153+ if (!v1 && !v2) return (TRUE);
4154+
4155+ g_ptr = &grid_array[y][x];
4156+
4157+
4158+ /* Check for walls */
4159+ wall = (!cave_los_grid(g_ptr));
4160+
4161+
4162+ /* Check the "ease" of visibility */
4163+ z1 = (v1 && (g1_c_ptr->info & (CAVE_XTRA)));
4164+ z2 = (v2 && (g2_c_ptr->info & (CAVE_XTRA)));
4165+
4166+ /* Hack -- "easy" plus "easy" yields "easy" */
4167+ if (z1 && z2)
4168+ {
4169+ g_ptr->info |= (CAVE_XTRA);
4170+
4171+ cave_view_hack(g_ptr, y, x);
4172+
4173+ return (wall);
4174+ }
4175+
4176+ /* Hack -- primary "easy" yields "viewed" */
4177+ if (z1)
4178+ {
4179+ cave_view_hack(g_ptr, y, x);
4180+
4181+ return (wall);
4182+ }
4183+
4184+ /* Hack -- "view" plus "view" yields "view" */
4185+ if (v1 && v2)
4186+ {
4187+ /* g_ptr->info |= (CAVE_XTRA); */
4188+
4189+ cave_view_hack(g_ptr, y, x);
4190+
4191+ return (wall);
4192+ }
4193+
4194+
4195+ /* Mega-Hack -- the "los()" function works poorly on walls */
4196+ if (wall)
4197+ {
4198+ cave_view_hack(g_ptr, y, x);
4199+
4200+ return (wall);
4201+ }
4202+
4203+
4204+ /* Hack -- check line of sight */
4205+ if (los(p_ptr->y, p_ptr->x, y, x))
4206+ {
4207+ cave_view_hack(g_ptr, y, x);
4208+
4209+ return (wall);
4210+ }
4211+
4212+
4213+ /* Assume no line of sight. */
4214+ return (TRUE);
4215+}
4216+
4217+
4218+
4219+/*
4220+ * Calculate the viewable space
4221+ *
4222+ * 1: Process the player
4223+ * 1a: The player is always (easily) viewable
4224+ * 2: Process the diagonals
4225+ * 2a: The diagonals are (easily) viewable up to the first wall
4226+ * 2b: But never go more than 2/3 of the "full" distance
4227+ * 3: Process the main axes
4228+ * 3a: The main axes are (easily) viewable up to the first wall
4229+ * 3b: But never go more than the "full" distance
4230+ * 4: Process sequential "strips" in each of the eight octants
4231+ * 4a: Each strip runs along the previous strip
4232+ * 4b: The main axes are "previous" to the first strip
4233+ * 4c: Process both "sides" of each "direction" of each strip
4234+ * 4c1: Each side aborts as soon as possible
4235+ * 4c2: Each side tells the next strip how far it has to check
4236+ *
4237+ * Note that the octant processing involves some pretty interesting
4238+ * observations involving when a grid might possibly be viewable from
4239+ * a given grid, and on the order in which the strips are processed.
4240+ *
4241+ * Note the use of the mathematical facts shown below, which derive
4242+ * from the fact that (1 < sqrt(2) < 1.5), and that the length of the
4243+ * hypotenuse of a right triangle is primarily determined by the length
4244+ * of the longest side, when one side is small, and is strictly less
4245+ * than one-and-a-half times as long as the longest side when both of
4246+ * the sides are large.
4247+ *
4248+ * if (manhatten(dy,dx) < R) then (hypot(dy,dx) < R)
4249+ * if (manhatten(dy,dx) > R*3/2) then (hypot(dy,dx) > R)
4250+ *
4251+ * hypot(dy,dx) is approximated by (dx+dy+MAX(dx,dy)) / 2
4252+ *
4253+ * These observations are important because the calculation of the actual
4254+ * value of "hypot(dx,dy)" is extremely expensive, involving square roots,
4255+ * while for small values (up to about 20 or so), the approximations above
4256+ * are correct to within an error of at most one grid or so.
4257+ *
4258+ * Observe the use of "full" and "over" in the code below, and the use of
4259+ * the specialized calculation involving "limit", all of which derive from
4260+ * the observations given above. Basically, we note that the "circle" of
4261+ * view is completely contained in an "octagon" whose bounds are easy to
4262+ * determine, and that only a few steps are needed to derive the actual
4263+ * bounds of the circle given the bounds of the octagon.
4264+ *
4265+ * Note that by skipping all the grids in the corners of the octagon, we
4266+ * place an upper limit on the number of grids in the field of view, given
4267+ * that "full" is never more than 20. Of the 1681 grids in the "square" of
4268+ * view, only about 1475 of these are in the "octagon" of view, and even
4269+ * fewer are in the "circle" of view, so 1500 or 1536 is more than enough
4270+ * entries to completely contain the actual field of view.
4271+ *
4272+ * Note also the care taken to prevent "running off the map". The use of
4273+ * explicit checks on the "validity" of the "diagonal", and the fact that
4274+ * the loops are never allowed to "leave" the map, lets "update_view_aux()"
4275+ * use the optimized "cave_los_bold()" macro, and to avoid the overhead
4276+ * of multiple checks on the validity of grids.
4277+ *
4278+ * Note the "optimizations" involving the "se","sw","ne","nw","es","en",
4279+ * "ws","wn" variables. They work like this: While travelling down the
4280+ * south-bound strip just to the east of the main south axis, as soon as
4281+ * we get to a grid which does not "transmit" viewing, if all of the strips
4282+ * preceding us (in this case, just the main axis) had terminated at or before
4283+ * the same point, then we can stop, and reset the "max distance" to ourself.
4284+ * So, each strip (named by major axis plus offset, thus "se" in this case)
4285+ * maintains a "blockage" variable, initialized during the main axis step,
4286+ * and checks it whenever a blockage is observed. After processing each
4287+ * strip as far as the previous strip told us to process, the next strip is
4288+ * told not to go farther than the current strip's farthest viewable grid,
4289+ * unless open space is still available. This uses the "k" variable.
4290+ *
4291+ * Note the use of "inline" macros for efficiency. The "cave_los_grid()"
4292+ * macro is a replacement for "cave_los_bold()" which takes a pointer to
4293+ * a grid instead of its location. The "cave_view_hack()" macro is a
4294+ * chunk of code which adds the given location to the "view" array if it
4295+ * is not already there, using both the actual location and a pointer to
4296+ * the grid. See above.
4297+ *
4298+ * By the way, the purpose of this code is to reduce the dependancy on the
4299+ * "los()" function which is slow, and, in some cases, not very accurate.
4300+ *
4301+ * It is very possible that I am the only person who fully understands this
4302+ * function, and for that I am truly sorry, but efficiency was very important
4303+ * and the "simple" version of this function was just not fast enough. I am
4304+ * more than willing to replace this function with a simpler one, if it is
4305+ * equally efficient, and especially willing if the new function happens to
4306+ * derive "reverse-line-of-sight" at the same time, since currently monsters
4307+ * just use an optimized hack of "you see me, so I see you", and then use the
4308+ * actual "projectable()" function to check spell attacks.
4309+ */
4310+void update_view(void)
4311+{
4312+ int n, m, d, k, z;
4313+ POSITION y, x;
4314+
4315+ int se, sw, ne, nw, es, en, ws, wn;
4316+
4317+ int full, over;
4318+
4319+ POSITION y_max = cur_hgt - 1;
4320+ POSITION x_max = cur_wid - 1;
4321+
4322+ grid_type *g_ptr;
4323+
4324+ /*** Initialize ***/
4325+
4326+ /* Optimize */
4327+ if (view_reduce_view && !dun_level)
4328+ {
4329+ /* Full radius (10) */
4330+ full = MAX_SIGHT / 2;
4331+
4332+ /* Octagon factor (15) */
4333+ over = MAX_SIGHT * 3 / 4;
4334+ }
4335+
4336+ /* Normal */
4337+ else
4338+ {
4339+ /* Full radius (20) */
4340+ full = MAX_SIGHT;
4341+
4342+ /* Octagon factor (30) */
4343+ over = MAX_SIGHT * 3 / 2;
4344+ }
4345+
4346+
4347+ /*** Step 0 -- Begin ***/
4348+
4349+ /* Save the old "view" grids for later */
4350+ for (n = 0; n < view_n; n++)
4351+ {
4352+ y = view_y[n];
4353+ x = view_x[n];
4354+ g_ptr = &grid_array[y][x];
4355+
4356+ /* Mark the grid as not in "view" */
4357+ g_ptr->info &= ~(CAVE_VIEW);
4358+
4359+ /* Mark the grid as "seen" */
4360+ g_ptr->info |= (CAVE_TEMP);
4361+
4362+ /* Add it to the "seen" set */
4363+ temp_y[temp_n] = y;
4364+ temp_x[temp_n] = x;
4365+ temp_n++;
4366+ }
4367+
4368+ /* Start over with the "view" array */
4369+ view_n = 0;
4370+
4371+ /*** Step 1 -- adjacent grids ***/
4372+
4373+ /* Now start on the player */
4374+ y = p_ptr->y;
4375+ x = p_ptr->x;
4376+ g_ptr = &grid_array[y][x];
4377+
4378+ /* Assume the player grid is easily viewable */
4379+ g_ptr->info |= (CAVE_XTRA);
4380+
4381+ /* Assume the player grid is viewable */
4382+ cave_view_hack(g_ptr, y, x);
4383+
4384+
4385+ /*** Step 2 -- Major Diagonals ***/
4386+
4387+ /* Hack -- Limit */
4388+ z = full * 2 / 3;
4389+
4390+ /* Scan south-east */
4391+ for (d = 1; d <= z; d++)
4392+ {
4393+ g_ptr = &grid_array[y + d][x + d];
4394+ g_ptr->info |= (CAVE_XTRA);
4395+ cave_view_hack(g_ptr, y + d, x + d);
4396+ if (!cave_los_grid(g_ptr)) break;
4397+ }
4398+
4399+ /* Scan south-west */
4400+ for (d = 1; d <= z; d++)
4401+ {
4402+ g_ptr = &grid_array[y + d][x - d];
4403+ g_ptr->info |= (CAVE_XTRA);
4404+ cave_view_hack(g_ptr, y + d, x - d);
4405+ if (!cave_los_grid(g_ptr)) break;
4406+ }
4407+
4408+ /* Scan north-east */
4409+ for (d = 1; d <= z; d++)
4410+ {
4411+ g_ptr = &grid_array[y - d][x + d];
4412+ g_ptr->info |= (CAVE_XTRA);
4413+ cave_view_hack(g_ptr, y - d, x + d);
4414+ if (!cave_los_grid(g_ptr)) break;
4415+ }
4416+
4417+ /* Scan north-west */
4418+ for (d = 1; d <= z; d++)
4419+ {
4420+ g_ptr = &grid_array[y - d][x - d];
4421+ g_ptr->info |= (CAVE_XTRA);
4422+ cave_view_hack(g_ptr, y - d, x - d);
4423+ if (!cave_los_grid(g_ptr)) break;
4424+ }
4425+
4426+ /*** Step 3 -- major axes ***/
4427+
4428+ /* Scan south */
4429+ for (d = 1; d <= full; d++)
4430+ {
4431+ g_ptr = &grid_array[y + d][x];
4432+ g_ptr->info |= (CAVE_XTRA);
4433+ cave_view_hack(g_ptr, y + d, x);
4434+ if (!cave_los_grid(g_ptr)) break;
4435+ }
4436+
4437+ /* Initialize the "south strips" */
4438+ se = sw = d;
4439+
4440+ /* Scan north */
4441+ for (d = 1; d <= full; d++)
4442+ {
4443+ g_ptr = &grid_array[y - d][x];
4444+ g_ptr->info |= (CAVE_XTRA);
4445+ cave_view_hack(g_ptr, y - d, x);
4446+ if (!cave_los_grid(g_ptr)) break;
4447+ }
4448+
4449+ /* Initialize the "north strips" */
4450+ ne = nw = d;
4451+
4452+ /* Scan east */
4453+ for (d = 1; d <= full; d++)
4454+ {
4455+ g_ptr = &grid_array[y][x + d];
4456+ g_ptr->info |= (CAVE_XTRA);
4457+ cave_view_hack(g_ptr, y, x + d);
4458+ if (!cave_los_grid(g_ptr)) break;
4459+ }
4460+
4461+ /* Initialize the "east strips" */
4462+ es = en = d;
4463+
4464+ /* Scan west */
4465+ for (d = 1; d <= full; d++)
4466+ {
4467+ g_ptr = &grid_array[y][x - d];
4468+ g_ptr->info |= (CAVE_XTRA);
4469+ cave_view_hack(g_ptr, y, x - d);
4470+ if (!cave_los_grid(g_ptr)) break;
4471+ }
4472+
4473+ /* Initialize the "west strips" */
4474+ ws = wn = d;
4475+
4476+
4477+ /*** Step 4 -- Divide each "octant" into "strips" ***/
4478+
4479+ /* Now check each "diagonal" (in parallel) */
4480+ for (n = 1; n <= over / 2; n++)
4481+ {
4482+ POSITION ypn, ymn, xpn, xmn;
4483+
4484+ /* Acquire the "bounds" of the maximal circle */
4485+ z = over - n - n;
4486+ if (z > full - n) z = full - n;
4487+ while ((z + n + (n >> 1)) > full) z--;
4488+
4489+
4490+ /* Access the four diagonal grids */
4491+ ypn = y + n;
4492+ ymn = y - n;
4493+ xpn = x + n;
4494+ xmn = x - n;
4495+
4496+
4497+ /* South strip */
4498+ if (ypn < y_max)
4499+ {
4500+ /* Maximum distance */
4501+ m = MIN(z, y_max - ypn);
4502+
4503+ /* East side */
4504+ if ((xpn <= x_max) && (n < se))
4505+ {
4506+ /* Scan */
4507+ for (k = n, d = 1; d <= m; d++)
4508+ {
4509+ /* Check grid "d" in strip "n", notice "blockage" */
4510+ if (update_view_aux(ypn + d, xpn, ypn + d - 1, xpn - 1, ypn + d - 1, xpn))
4511+ {
4512+ if (n + d >= se) break;
4513+ }
4514+
4515+ /* Track most distant "non-blockage" */
4516+ else
4517+ {
4518+ k = n + d;
4519+ }
4520+ }
4521+
4522+ /* Limit the next strip */
4523+ se = k + 1;
4524+ }
4525+
4526+ /* West side */
4527+ if ((xmn >= 0) && (n < sw))
4528+ {
4529+ /* Scan */
4530+ for (k = n, d = 1; d <= m; d++)
4531+ {
4532+ /* Check grid "d" in strip "n", notice "blockage" */
4533+ if (update_view_aux(ypn + d, xmn, ypn + d - 1, xmn + 1, ypn + d - 1, xmn))
4534+ {
4535+ if (n + d >= sw) break;
4536+ }
4537+
4538+ /* Track most distant "non-blockage" */
4539+ else
4540+ {
4541+ k = n + d;
4542+ }
4543+ }
4544+
4545+ /* Limit the next strip */
4546+ sw = k + 1;
4547+ }
4548+ }
4549+
4550+
4551+ /* North strip */
4552+ if (ymn > 0)
4553+ {
4554+ /* Maximum distance */
4555+ m = MIN(z, ymn);
4556+
4557+ /* East side */
4558+ if ((xpn <= x_max) && (n < ne))
4559+ {
4560+ /* Scan */
4561+ for (k = n, d = 1; d <= m; d++)
4562+ {
4563+ /* Check grid "d" in strip "n", notice "blockage" */
4564+ if (update_view_aux(ymn - d, xpn, ymn - d + 1, xpn - 1, ymn - d + 1, xpn))
4565+ {
4566+ if (n + d >= ne) break;
4567+ }
4568+
4569+ /* Track most distant "non-blockage" */
4570+ else
4571+ {
4572+ k = n + d;
4573+ }
4574+ }
4575+
4576+ /* Limit the next strip */
4577+ ne = k + 1;
4578+ }
4579+
4580+ /* West side */
4581+ if ((xmn >= 0) && (n < nw))
4582+ {
4583+ /* Scan */
4584+ for (k = n, d = 1; d <= m; d++)
4585+ {
4586+ /* Check grid "d" in strip "n", notice "blockage" */
4587+ if (update_view_aux(ymn - d, xmn, ymn - d + 1, xmn + 1, ymn - d + 1, xmn))
4588+ {
4589+ if (n + d >= nw) break;
4590+ }
4591+
4592+ /* Track most distant "non-blockage" */
4593+ else
4594+ {
4595+ k = n + d;
4596+ }
4597+ }
4598+
4599+ /* Limit the next strip */
4600+ nw = k + 1;
4601+ }
4602+ }
4603+
4604+
4605+ /* East strip */
4606+ if (xpn < x_max)
4607+ {
4608+ /* Maximum distance */
4609+ m = MIN(z, x_max - xpn);
4610+
4611+ /* South side */
4612+ if ((ypn <= x_max) && (n < es))
4613+ {
4614+ /* Scan */
4615+ for (k = n, d = 1; d <= m; d++)
4616+ {
4617+ /* Check grid "d" in strip "n", notice "blockage" */
4618+ if (update_view_aux(ypn, xpn + d, ypn - 1, xpn + d - 1, ypn, xpn + d - 1))
4619+ {
4620+ if (n + d >= es) break;
4621+ }
4622+
4623+ /* Track most distant "non-blockage" */
4624+ else
4625+ {
4626+ k = n + d;
4627+ }
4628+ }
4629+
4630+ /* Limit the next strip */
4631+ es = k + 1;
4632+ }
4633+
4634+ /* North side */
4635+ if ((ymn >= 0) && (n < en))
4636+ {
4637+ /* Scan */
4638+ for (k = n, d = 1; d <= m; d++)
4639+ {
4640+ /* Check grid "d" in strip "n", notice "blockage" */
4641+ if (update_view_aux(ymn, xpn + d, ymn + 1, xpn + d - 1, ymn, xpn + d - 1))
4642+ {
4643+ if (n + d >= en) break;
4644+ }
4645+
4646+ /* Track most distant "non-blockage" */
4647+ else
4648+ {
4649+ k = n + d;
4650+ }
4651+ }
4652+
4653+ /* Limit the next strip */
4654+ en = k + 1;
4655+ }
4656+ }
4657+
4658+
4659+ /* West strip */
4660+ if (xmn > 0)
4661+ {
4662+ /* Maximum distance */
4663+ m = MIN(z, xmn);
4664+
4665+ /* South side */
4666+ if ((ypn <= y_max) && (n < ws))
4667+ {
4668+ /* Scan */
4669+ for (k = n, d = 1; d <= m; d++)
4670+ {
4671+ /* Check grid "d" in strip "n", notice "blockage" */
4672+ if (update_view_aux(ypn, xmn - d, ypn - 1, xmn - d + 1, ypn, xmn - d + 1))
4673+ {
4674+ if (n + d >= ws) break;
4675+ }
4676+
4677+ /* Track most distant "non-blockage" */
4678+ else
4679+ {
4680+ k = n + d;
4681+ }
4682+ }
4683+
4684+ /* Limit the next strip */
4685+ ws = k + 1;
4686+ }
4687+
4688+ /* North side */
4689+ if ((ymn >= 0) && (n < wn))
4690+ {
4691+ /* Scan */
4692+ for (k = n, d = 1; d <= m; d++)
4693+ {
4694+ /* Check grid "d" in strip "n", notice "blockage" */
4695+ if (update_view_aux(ymn, xmn - d, ymn + 1, xmn - d + 1, ymn, xmn - d + 1))
4696+ {
4697+ if (n + d >= wn) break;
4698+ }
4699+
4700+ /* Track most distant "non-blockage" */
4701+ else
4702+ {
4703+ k = n + d;
4704+ }
4705+ }
4706+
4707+ /* Limit the next strip */
4708+ wn = k + 1;
4709+ }
4710+ }
4711+ }
4712+
4713+
4714+ /*** Step 5 -- Complete the algorithm ***/
4715+
4716+ /* Update all the new grids */
4717+ for (n = 0; n < view_n; n++)
4718+ {