OSDN Git Service

Merge pull request #765 from sikabane-works/release/3.0.0Alpha17
[hengbandforosx/hengbandosx.git] / src / view / display-map.cpp
1 #include "view/display-map.h"
2 #include "autopick/autopick-finder.h"
3 #include "autopick/autopick-methods-table.h"
4 #include "floor/cave.h"
5 #include "game-option/map-screen-options.h"
6 #include "game-option/special-options.h"
7 #include "grid/feature.h"
8 #include "grid/grid.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster-race/race-flags2.h"
12 #include "object/object-info.h"
13 #include "object/object-kind.h"
14 #include "object/object-mark-types.h"
15 #include "system/floor-type-definition.h"
16 #include "term/term-color-types.h"
17 #include "util/bit-flags-calculator.h"
18 #include "window/main-window-util.h"
19 #include "world/world.h"
20
21 byte display_autopick; /*!< 自動拾い状態の設定フラグ */
22
23 /* 一般的にオブジェクトシンボルとして扱われる記号を定義する(幻覚処理向け) /  Hack -- Legal object codes */
24 char image_object_hack[MAX_IMAGE_OBJECT_HACK] = "?/|\\\"!$()_-=[]{},~";
25
26 /* 一般的にモンスターシンボルとして扱われる記号を定義する(幻覚処理向け) / Hack -- Legal monster codes */
27 char image_monster_hack[MAX_IMAGE_MONSTER_HACK] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
28
29 /*!
30  * @brief オブジェクトの表示を幻覚状態に差し替える / Hallucinatory object
31  * @param ap 本来の色
32  * @param cp 本来のシンボル
33  * @return なし
34  */
35 static void image_object(TERM_COLOR *ap, SYMBOL_CODE *cp)
36 {
37     if (use_graphics) {
38         object_kind *k_ptr = &k_info[randint1(max_k_idx - 1)];
39         *cp = k_ptr->x_char;
40         *ap = k_ptr->x_attr;
41         return;
42     }
43
44     size_t n = sizeof(image_object_hack) - 1;
45     *cp = image_object_hack[randint0(n)];
46     *ap = randint1(15);
47 }
48
49 /*!
50  * @brief モンスターの表示を幻覚状態に差し替える / Mega-Hack -- Hallucinatory monster
51  * @param ap 本来の色
52  * @param cp 本来のシンボル
53  * @return なし
54  */
55 static void image_monster(TERM_COLOR *ap, SYMBOL_CODE *cp)
56 {
57     if (use_graphics) {
58         monster_race *r_ptr = &r_info[randint1(max_r_idx - 1)];
59         *cp = r_ptr->x_char;
60         *ap = r_ptr->x_attr;
61         return;
62     }
63
64     *cp = (one_in_(25) ? image_object_hack[randint0(sizeof(image_object_hack) - 1)] : image_monster_hack[randint0(sizeof(image_monster_hack) - 1)]);
65     *ap = randint1(15);
66 }
67
68 /*!
69  * @brief オブジェクト&モンスターの表示を幻覚状態に差し替える / Hack -- Random hallucination
70  * @param ap 本来の色
71  * @param cp 本来のシンボル
72  * @return なし
73  */
74 static void image_random(TERM_COLOR *ap, SYMBOL_CODE *cp)
75 {
76     if (randint0(100) < 75) {
77         image_monster(ap, cp);
78     } else {
79         image_object(ap, cp);
80     }
81 }
82
83 /*!
84  * @brief マップに表示されるべき地形(壁)かどうかを判定する
85  * @param floor_ptr 階の情報への参照ポインタ
86  * @param f_ptr 地形の情報への参照ポインタ
87  * @param y グリッドy座標
88  * @param x グリッドx座標
89  * @return 表示されるべきならtrue、そうでないならfalse
90  * @details
91  * 周り全てが壁に囲まれている壁についてはオプション状態による。
92  * 1か所でも空きがあるか、壁ではない地形、金を含む地形、永久岩は表示。
93  */
94 static bool is_revealed_wall(floor_type *floor_ptr, feature_type *f_ptr, POSITION y, POSITION x)
95 {
96     if (view_hidden_walls) {
97         if (view_unsafe_walls)
98             return TRUE;
99         if (none_bits(floor_ptr->grid_array[y][x].info, CAVE_UNSAFE))
100             return TRUE;
101     }
102
103     if (!has_flag(f_ptr->flags, FF_WALL) || has_flag(f_ptr->flags, FF_HAS_GOLD))
104         return TRUE;
105
106     if (in_bounds(floor_ptr, y, x) && has_flag(f_ptr->flags, FF_PERMANENT))
107         return TRUE;
108
109     int n = 0;
110     for (int i = 0; i < 8; i++) {
111         int dy = y + ddy_cdd[i];
112         int dx = x + ddx_cdd[i];
113         if (!in_bounds(floor_ptr, dy, dx)) {
114             n++;
115             continue;
116         }
117
118         FEAT_IDX f_idx = floor_ptr->grid_array[dy][dx].feat;
119         feature_type *n_ptr = &f_info[f_idx];
120         if (has_flag(n_ptr->flags, FF_WALL))
121             n++;
122     }
123
124     return (n != 8);
125 }
126
127 /*!
128  * @brief 指定した座標の地形の表示属性を取得する / Extract the attr/char to display at the given (legal) map location
129  * @param player_ptr プレイヤー情報への参照ポインタ
130  * @param y 階の中のy座標
131  * @param x 階の中のy座標
132  * @param ap 文字色属性
133  * @param cp 文字種属性
134  * @param tap 文字色属性(タイル)
135  * @param tcp 文字種属性(タイル)
136  * @return なし
137  */
138 void map_info(player_type *player_ptr, POSITION y, POSITION x, TERM_COLOR *ap, SYMBOL_CODE *cp, TERM_COLOR *tap, SYMBOL_CODE *tcp)
139 {
140     floor_type *floor_ptr = player_ptr->current_floor_ptr;
141     grid_type *g_ptr = &floor_ptr->grid_array[y][x];
142     OBJECT_IDX this_o_idx, next_o_idx = 0;
143     FEAT_IDX feat = get_feat_mimic(g_ptr);
144     feature_type *f_ptr = &f_info[feat];
145     TERM_COLOR a;
146     SYMBOL_CODE c;
147     if (!has_flag(f_ptr->flags, FF_REMEMBER)) {
148         if (!player_ptr->blind
149             && ((g_ptr->info & (CAVE_MARK | CAVE_LITE | CAVE_MNLT))
150                 || ((g_ptr->info & CAVE_VIEW) && (((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW) || player_ptr->see_nocto)))) {
151             a = f_ptr->x_attr[F_LIT_STANDARD];
152             c = f_ptr->x_char[F_LIT_STANDARD];
153             if (player_ptr->wild_mode) {
154                 if (view_special_lite && !is_daytime()) {
155                     a = f_ptr->x_attr[F_LIT_DARK];
156                     c = f_ptr->x_char[F_LIT_DARK];
157                 }
158             } else if (darkened_grid(player_ptr, g_ptr)) {
159                 feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
160                 f_ptr = &f_info[feat];
161                 a = f_ptr->x_attr[F_LIT_STANDARD];
162                 c = f_ptr->x_char[F_LIT_STANDARD];
163             } else if (view_special_lite) {
164                 if (g_ptr->info & (CAVE_LITE | CAVE_MNLT)) {
165                     if (view_yellow_lite) {
166                         a = f_ptr->x_attr[F_LIT_LITE];
167                         c = f_ptr->x_char[F_LIT_LITE];
168                     }
169                 } else if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW) {
170                     a = f_ptr->x_attr[F_LIT_DARK];
171                     c = f_ptr->x_char[F_LIT_DARK];
172                 } else if (!(g_ptr->info & CAVE_VIEW)) {
173                     if (view_bright_lite) {
174                         a = f_ptr->x_attr[F_LIT_DARK];
175                         c = f_ptr->x_char[F_LIT_DARK];
176                     }
177                 }
178             }
179         } else {
180             feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
181             f_ptr = &f_info[feat];
182             a = f_ptr->x_attr[F_LIT_STANDARD];
183             c = f_ptr->x_char[F_LIT_STANDARD];
184         }
185     } else {
186         if (g_ptr->info & CAVE_MARK && is_revealed_wall(floor_ptr, f_ptr, y, x)) {
187             a = f_ptr->x_attr[F_LIT_STANDARD];
188             c = f_ptr->x_char[F_LIT_STANDARD];
189             if (player_ptr->wild_mode) {
190                 if (view_granite_lite && (player_ptr->blind || !is_daytime())) {
191                     a = f_ptr->x_attr[F_LIT_DARK];
192                     c = f_ptr->x_char[F_LIT_DARK];
193                 }
194             } else if (darkened_grid(player_ptr, g_ptr) && !player_ptr->blind) {
195                 if (has_flag(f_ptr->flags, FF_LOS) && has_flag(f_ptr->flags, FF_PROJECT)) {
196                     feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
197                     f_ptr = &f_info[feat];
198                     a = f_ptr->x_attr[F_LIT_STANDARD];
199                     c = f_ptr->x_char[F_LIT_STANDARD];
200                 } else if (view_granite_lite && view_bright_lite) {
201                     a = f_ptr->x_attr[F_LIT_DARK];
202                     c = f_ptr->x_char[F_LIT_DARK];
203                 }
204             } else if (view_granite_lite) {
205                 if (player_ptr->blind) {
206                     a = f_ptr->x_attr[F_LIT_DARK];
207                     c = f_ptr->x_char[F_LIT_DARK];
208                 } else if (g_ptr->info & (CAVE_LITE | CAVE_MNLT)) {
209                     if (view_yellow_lite) {
210                         a = f_ptr->x_attr[F_LIT_LITE];
211                         c = f_ptr->x_char[F_LIT_LITE];
212                     }
213                 } else if (view_bright_lite) {
214                     if (!(g_ptr->info & CAVE_VIEW)) {
215                         a = f_ptr->x_attr[F_LIT_DARK];
216                         c = f_ptr->x_char[F_LIT_DARK];
217                     } else if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW) {
218                         a = f_ptr->x_attr[F_LIT_DARK];
219                         c = f_ptr->x_char[F_LIT_DARK];
220                     } else if (!has_flag(f_ptr->flags, FF_LOS) && !check_local_illumination(player_ptr, y, x)) {
221                         a = f_ptr->x_attr[F_LIT_DARK];
222                         c = f_ptr->x_char[F_LIT_DARK];
223                     }
224                 }
225             }
226         } else {
227             feat = (view_unsafe_grids && (g_ptr->info & CAVE_UNSAFE)) ? feat_undetected : feat_none;
228             f_ptr = &f_info[feat];
229             a = f_ptr->x_attr[F_LIT_STANDARD];
230             c = f_ptr->x_char[F_LIT_STANDARD];
231         }
232     }
233
234     if (feat_priority == -1)
235         feat_priority = f_ptr->priority;
236
237     (*tap) = a;
238     (*tcp) = c;
239     (*ap) = a;
240     (*cp) = c;
241
242     if (player_ptr->image && one_in_(256))
243         image_random(ap, cp);
244
245     for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) {
246         object_type *o_ptr;
247         o_ptr = &floor_ptr->o_list[this_o_idx];
248         next_o_idx = o_ptr->next_o_idx;
249         if (!(o_ptr->marked & OM_FOUND))
250             continue;
251
252         if (display_autopick) {
253             byte act;
254
255             match_autopick = find_autopick_list(player_ptr, o_ptr);
256             if (match_autopick == -1)
257                 continue;
258
259             act = autopick_list[match_autopick].action;
260
261             if ((act & DO_DISPLAY) && (act & display_autopick)) {
262                 autopick_obj = o_ptr;
263             } else {
264                 match_autopick = -1;
265                 continue;
266             }
267         }
268
269         (*cp) = object_char(o_ptr);
270         (*ap) = object_attr(o_ptr);
271         feat_priority = 20;
272         if (player_ptr->image)
273             image_object(ap, cp);
274
275         break;
276     }
277
278     if (g_ptr->m_idx && display_autopick != 0) {
279         set_term_color(player_ptr, y, x, ap, cp);
280         return;
281     }
282
283     monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
284     if (!m_ptr->ml) {
285         set_term_color(player_ptr, y, x, ap, cp);
286         return;
287     }
288
289     monster_race *r_ptr = &r_info[m_ptr->ap_r_idx];
290     feat_priority = 30;
291     if (player_ptr->image) {
292         if ((r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) == (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) {
293             /* Do nothing */
294         } else {
295             image_monster(ap, cp);
296         }
297
298         set_term_color(player_ptr, y, x, ap, cp);
299         return;
300     }
301
302     a = r_ptr->x_attr;
303     c = r_ptr->x_char;
304     if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_SHAPECHANGER | RF1_ATTR_CLEAR | RF1_ATTR_MULTI | RF1_ATTR_SEMIRAND))) {
305         *ap = a;
306         *cp = c;
307         set_term_color(player_ptr, y, x, ap, cp);
308         return;
309     }
310
311     if ((r_ptr->flags1 & (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) == (RF1_CHAR_CLEAR | RF1_ATTR_CLEAR)) {
312         set_term_color(player_ptr, y, x, ap, cp);
313         return;
314     }
315
316     if ((r_ptr->flags1 & RF1_ATTR_CLEAR) && (*ap != TERM_DARK) && !use_graphics) {
317         /* Do nothing */
318     } else if ((r_ptr->flags1 & RF1_ATTR_MULTI) && !use_graphics) {
319         if (r_ptr->flags2 & RF2_ATTR_ANY)
320             *ap = randint1(15);
321         else
322             switch (randint1(7)) {
323             case 1:
324                 *ap = TERM_RED;
325                 break;
326             case 2:
327                 *ap = TERM_L_RED;
328                 break;
329             case 3:
330                 *ap = TERM_WHITE;
331                 break;
332             case 4:
333                 *ap = TERM_L_GREEN;
334                 break;
335             case 5:
336                 *ap = TERM_BLUE;
337                 break;
338             case 6:
339                 *ap = TERM_L_DARK;
340                 break;
341             case 7:
342                 *ap = TERM_GREEN;
343                 break;
344             }
345     } else if ((r_ptr->flags1 & RF1_ATTR_SEMIRAND) && !use_graphics) {
346         *ap = g_ptr->m_idx % 15 + 1;
347     } else {
348         *ap = a;
349     }
350
351     if ((r_ptr->flags1 & RF1_CHAR_CLEAR) && (*cp != ' ') && !use_graphics) {
352         set_term_color(player_ptr, y, x, ap, cp);
353         return;
354     }
355
356     if (r_ptr->flags1 & RF1_SHAPECHANGER) {
357         if (use_graphics) {
358             monster_race *tmp_r_ptr = &r_info[randint1(max_r_idx - 1)];
359             *cp = tmp_r_ptr->x_char;
360             *ap = tmp_r_ptr->x_attr;
361         } else {
362             *cp = (one_in_(25) ? image_object_hack[randint0(sizeof(image_object_hack) - 1)] : image_monster_hack[randint0(sizeof(image_monster_hack) - 1)]);
363         }
364
365         set_term_color(player_ptr, y, x, ap, cp);
366         return;
367     }
368
369     *cp = c;
370     set_term_color(player_ptr, y, x, ap, cp);
371 }