OSDN Git Service

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