OSDN Git Service

Merge remote-tracking branch 'remotes/hengbandosx/english-mind-edits' into feature...
[hengband/hengband.git] / src / monster-floor / monster-lite.c
1 #include "monster-floor/monster-lite.h"
2 #include "core/player-update-types.h"
3 #include "dungeon/dungeon-flag-types.h"
4 #include "dungeon/dungeon.h"
5 #include "floor/cave.h"
6 #include "grid/feature-flag-types.h"
7 #include "grid/grid.h"
8 #include "monster-floor/monster-lite-util.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags7.h"
11 #include "monster/monster-status.h"
12 #include "player/special-defense-types.h"
13 #include "system/floor-type-definition.h"
14 #include "system/monster-type-definition.h"
15 #include "view/display-messages.h"
16 #include "world/world.h"
17
18 /*!
19  * @brief モンスターによる光量状態更新 / Add a square to the changes array
20  * @param subject_ptr 主観となるクリーチャーの参照ポインタ
21  * @param y Y座標
22  * @param x X座標
23  */
24 static void update_monster_lite(player_type *subject_ptr, const POSITION y, const POSITION x, monster_lite_type *ml_ptr)
25 {
26     grid_type *g_ptr;
27     int dpf, d;
28     POSITION midpoint;
29     g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
30     if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW)
31         return;
32
33     if (!cave_los_grid(g_ptr)) {
34         if (((y < subject_ptr->y) && (y > ml_ptr->mon_fy)) || ((y > subject_ptr->y) && (y < ml_ptr->mon_fy))) {
35             dpf = subject_ptr->y - ml_ptr->mon_fy;
36             d = y - ml_ptr->mon_fy;
37             midpoint = ml_ptr->mon_fx + ((subject_ptr->x - ml_ptr->mon_fx) * ABS(d)) / ABS(dpf);
38             if (x < midpoint) {
39                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1))
40                     return;
41             } else if (x > midpoint) {
42                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1))
43                     return;
44             } else if (ml_ptr->mon_invis)
45                 return;
46         }
47
48         if (((x < subject_ptr->x) && (x > ml_ptr->mon_fx)) || ((x > subject_ptr->x) && (x < ml_ptr->mon_fx))) {
49             dpf = subject_ptr->x - ml_ptr->mon_fx;
50             d = x - ml_ptr->mon_fx;
51             midpoint = ml_ptr->mon_fy + ((subject_ptr->y - ml_ptr->mon_fy) * ABS(d)) / ABS(dpf);
52             if (y < midpoint) {
53                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x))
54                     return;
55             } else if (y > midpoint) {
56                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x))
57                     return;
58             } else if (ml_ptr->mon_invis)
59                 return;
60         }
61     }
62
63     if (!(g_ptr->info & CAVE_MNDK)) {
64         tmp_pos.x[tmp_pos.n] = x;
65         tmp_pos.y[tmp_pos.n] = y;
66         tmp_pos.n++;
67     } else {
68         g_ptr->info &= ~(CAVE_MNDK);
69     }
70
71     g_ptr->info |= CAVE_MNLT;
72 }
73
74 /*
75  * Add a square to the changes array
76  */
77 static void update_monster_dark(player_type *subject_ptr, const POSITION y, const POSITION x, monster_lite_type *ml_ptr)
78 {
79     grid_type *g_ptr;
80     int midpoint, dpf, d;
81     g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
82     if ((g_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW)
83         return;
84
85     if (!cave_los_grid(g_ptr) && !cave_has_flag_grid(g_ptr, FF_PROJECT)) {
86         if (((y < subject_ptr->y) && (y > ml_ptr->mon_fy)) || ((y > subject_ptr->y) && (y < ml_ptr->mon_fy))) {
87             dpf = subject_ptr->y - ml_ptr->mon_fy;
88             d = y - ml_ptr->mon_fy;
89             midpoint = ml_ptr->mon_fx + ((subject_ptr->x - ml_ptr->mon_fx) * ABS(d)) / ABS(dpf);
90             if (x < midpoint) {
91                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1) && !cave_has_flag_bold(subject_ptr->current_floor_ptr, y, x + 1, FF_PROJECT))
92                     return;
93             } else if (x > midpoint) {
94                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1) && !cave_has_flag_bold(subject_ptr->current_floor_ptr, y, x - 1, FF_PROJECT))
95                     return;
96             } else if (ml_ptr->mon_invis)
97                 return;
98         }
99
100         if (((x < subject_ptr->x) && (x > ml_ptr->mon_fx)) || ((x > subject_ptr->x) && (x < ml_ptr->mon_fx))) {
101             dpf = subject_ptr->x - ml_ptr->mon_fx;
102             d = x - ml_ptr->mon_fx;
103             midpoint = ml_ptr->mon_fy + ((subject_ptr->y - ml_ptr->mon_fy) * ABS(d)) / ABS(dpf);
104             if (y < midpoint) {
105                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x) && !cave_has_flag_bold(subject_ptr->current_floor_ptr, y + 1, x, FF_PROJECT))
106                     return;
107             } else if (y > midpoint) {
108                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x) && !cave_has_flag_bold(subject_ptr->current_floor_ptr, y - 1, x, FF_PROJECT))
109                     return;
110             } else if (ml_ptr->mon_invis)
111                 return;
112         }
113     }
114
115     tmp_pos.x[tmp_pos.n] = x;
116     tmp_pos.y[tmp_pos.n] = y;
117     tmp_pos.n++;
118     g_ptr->info |= CAVE_MNDK;
119 }
120
121 /*
122  * todo player-status からのみ呼ばれている。しかしあちらは行数が酷いので要調整
123  * Update squares illuminated or darkened by monsters.
124  * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
125  * updating.  Only squares in view of the player, whos state
126  * changes are drawn via lite_spot().
127  */
128 void update_mon_lite(player_type *subject_ptr)
129 {
130     void (*add_mon_lite)(player_type *, const POSITION, const POSITION, monster_lite_type *);
131     int dis_lim = ((d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !subject_ptr->see_nocto) ? (MAX_SIGHT / 2 + 1) : (MAX_SIGHT + 3);
132     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
133     for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
134         grid_type *g_ptr;
135         g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
136         g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
137         g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
138     }
139
140     tmp_pos.n = 0;
141     if (!current_world_ptr->timewalk_m_idx) {
142         monster_type *m_ptr;
143         monster_race *r_ptr;
144         for (int i = 1; i < floor_ptr->m_max; i++) {
145             m_ptr = &floor_ptr->m_list[i];
146             r_ptr = &r_info[m_ptr->r_idx];
147             if (!monster_is_valid(m_ptr) || (m_ptr->cdis > dis_lim))
148                 continue;
149
150             int rad = 0;
151             if (r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_SELF_LITE_1))
152                 rad++;
153
154             if (r_ptr->flags7 & (RF7_HAS_LITE_2 | RF7_SELF_LITE_2))
155                 rad += 2;
156
157             if (r_ptr->flags7 & (RF7_HAS_DARK_1 | RF7_SELF_DARK_1))
158                 rad--;
159
160             if (r_ptr->flags7 & (RF7_HAS_DARK_2 | RF7_SELF_DARK_2))
161                 rad -= 2;
162
163             if (!rad)
164                 continue;
165
166             int f_flag;
167             if (rad > 0) {
168                 if (!(r_ptr->flags7 & (RF7_SELF_LITE_1 | RF7_SELF_LITE_2))
169                     && (monster_csleep_remaining(m_ptr) || (!floor_ptr->dun_level && is_daytime()) || subject_ptr->phase_out))
170                     continue;
171
172                 if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
173                     rad = 1;
174
175                 add_mon_lite = update_monster_lite;
176                 f_flag = FF_LOS;
177             } else {
178                 if (!(r_ptr->flags7 & (RF7_SELF_DARK_1 | RF7_SELF_DARK_2)) && (monster_csleep_remaining(m_ptr) || (!floor_ptr->dun_level && !is_daytime())))
179                     continue;
180
181                 add_mon_lite = update_monster_dark;
182                 f_flag = FF_PROJECT;
183                 rad = -rad;
184             }
185
186             monster_lite_type tmp_ml;
187             monster_lite_type *ml_ptr = initialize_monster_lite_type(floor_ptr, &tmp_ml, m_ptr);
188             add_mon_lite(subject_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx, ml_ptr);
189             add_mon_lite(subject_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx, ml_ptr);
190             add_mon_lite(subject_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx, ml_ptr);
191             add_mon_lite(subject_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx + 1, ml_ptr);
192             add_mon_lite(subject_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx - 1, ml_ptr);
193             add_mon_lite(subject_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 1, ml_ptr);
194             add_mon_lite(subject_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 1, ml_ptr);
195             add_mon_lite(subject_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 1, ml_ptr);
196             add_mon_lite(subject_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 1, ml_ptr);
197             if (rad < 2)
198                 continue;
199
200             grid_type *g_ptr;
201             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx, f_flag)) {
202                 add_mon_lite(subject_ptr, ml_ptr->mon_fy + 2, ml_ptr->mon_fx + 1, ml_ptr);
203                 add_mon_lite(subject_ptr, ml_ptr->mon_fy + 2, ml_ptr->mon_fx, ml_ptr);
204                 add_mon_lite(subject_ptr, ml_ptr->mon_fy + 2, ml_ptr->mon_fx - 1, ml_ptr);
205                 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy + 2][ml_ptr->mon_fx];
206                 if ((rad == 3) && cave_has_flag_grid(g_ptr, f_flag)) {
207                     add_mon_lite(subject_ptr, ml_ptr->mon_fy + 3, ml_ptr->mon_fx + 1, ml_ptr);
208                     add_mon_lite(subject_ptr, ml_ptr->mon_fy + 3, ml_ptr->mon_fx, ml_ptr);
209                     add_mon_lite(subject_ptr, ml_ptr->mon_fy + 3, ml_ptr->mon_fx - 1, ml_ptr);
210                 }
211             }
212
213             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx, f_flag)) {
214                 add_mon_lite(subject_ptr, ml_ptr->mon_fy - 2, ml_ptr->mon_fx + 1, ml_ptr);
215                 add_mon_lite(subject_ptr, ml_ptr->mon_fy - 2, ml_ptr->mon_fx, ml_ptr);
216                 add_mon_lite(subject_ptr, ml_ptr->mon_fy - 2, ml_ptr->mon_fx - 1, ml_ptr);
217                 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy - 2][ml_ptr->mon_fx];
218                 if ((rad == 3) && cave_has_flag_grid(g_ptr, f_flag)) {
219                     add_mon_lite(subject_ptr, ml_ptr->mon_fy - 3, ml_ptr->mon_fx + 1, ml_ptr);
220                     add_mon_lite(subject_ptr, ml_ptr->mon_fy - 3, ml_ptr->mon_fx, ml_ptr);
221                     add_mon_lite(subject_ptr, ml_ptr->mon_fy - 3, ml_ptr->mon_fx - 1, ml_ptr);
222                 }
223             }
224
225             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx + 1, f_flag)) {
226                 add_mon_lite(subject_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 2, ml_ptr);
227                 add_mon_lite(subject_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx + 2, ml_ptr);
228                 add_mon_lite(subject_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 2, ml_ptr);
229                 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy][ml_ptr->mon_fx + 2];
230                 if ((rad == 3) && cave_has_flag_grid(g_ptr, f_flag)) {
231                     add_mon_lite(subject_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 3, ml_ptr);
232                     add_mon_lite(subject_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx + 3, ml_ptr);
233                     add_mon_lite(subject_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 3, ml_ptr);
234                 }
235             }
236
237             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx - 1, f_flag)) {
238                 add_mon_lite(subject_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 2, ml_ptr);
239                 add_mon_lite(subject_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx - 2, ml_ptr);
240                 add_mon_lite(subject_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 2, ml_ptr);
241                 g_ptr = &floor_ptr->grid_array[ml_ptr->mon_fy][ml_ptr->mon_fx - 2];
242                 if ((rad == 3) && cave_has_flag_grid(g_ptr, f_flag)) {
243                     add_mon_lite(subject_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 3, ml_ptr);
244                     add_mon_lite(subject_ptr, ml_ptr->mon_fy, ml_ptr->mon_fx - 3, ml_ptr);
245                     add_mon_lite(subject_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 3, ml_ptr);
246                 }
247             }
248
249             if (rad != 3)
250                 continue;
251
252             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx + 1, f_flag))
253                 add_mon_lite(subject_ptr, ml_ptr->mon_fy + 2, ml_ptr->mon_fx + 2, ml_ptr);
254
255             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy + 1, ml_ptr->mon_fx - 1, f_flag))
256                 add_mon_lite(subject_ptr, ml_ptr->mon_fy + 2, ml_ptr->mon_fx - 2, ml_ptr);
257
258             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx + 1, f_flag))
259                 add_mon_lite(subject_ptr, ml_ptr->mon_fy - 2, ml_ptr->mon_fx + 2, ml_ptr);
260
261             if (cave_has_flag_bold(subject_ptr->current_floor_ptr, ml_ptr->mon_fy - 1, ml_ptr->mon_fx - 1, f_flag))
262                 add_mon_lite(subject_ptr, ml_ptr->mon_fy - 2, ml_ptr->mon_fx - 2, ml_ptr);
263         }
264     }
265
266     s16b end_temp = tmp_pos.n;
267     for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
268         POSITION fx = floor_ptr->mon_lite_x[i];
269         POSITION fy = floor_ptr->mon_lite_y[i];
270         grid_type *g_ptr;
271         g_ptr = &floor_ptr->grid_array[fy][fx];
272         if (g_ptr->info & CAVE_TEMP) {
273             if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
274                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
275         } else if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
276             cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
277
278         tmp_pos.x[tmp_pos.n] = fx;
279         tmp_pos.y[tmp_pos.n] = fy;
280         tmp_pos.n++;
281     }
282
283     floor_ptr->mon_lite_n = 0;
284     for (int i = 0; i < end_temp; i++) {
285         POSITION fx = tmp_pos.x[i];
286         POSITION fy = tmp_pos.y[i];
287         grid_type *g_ptr;
288         g_ptr = &floor_ptr->grid_array[fy][fx];
289         if (g_ptr->info & CAVE_MNLT) {
290             if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
291                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
292         } else if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
293             cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
294
295         floor_ptr->mon_lite_x[floor_ptr->mon_lite_n] = fx;
296         floor_ptr->mon_lite_y[floor_ptr->mon_lite_n] = fy;
297         floor_ptr->mon_lite_n++;
298     }
299
300     for (int i = end_temp; i < tmp_pos.n; i++)
301         floor_ptr->grid_array[tmp_pos.y[i]][tmp_pos.x[i]].info &= ~(CAVE_TEMP | CAVE_XTRA);
302
303     tmp_pos.n = 0;
304     subject_ptr->update |= PU_DELAY_VIS;
305     subject_ptr->monlite = (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_MNLT) != 0;
306     if (!(subject_ptr->special_defense & NINJA_S_STEALTH)) {
307         subject_ptr->old_monlite = subject_ptr->monlite;
308         return;
309     }
310
311     if (subject_ptr->old_monlite == subject_ptr->monlite) {
312         subject_ptr->old_monlite = subject_ptr->monlite;
313         return;
314     }
315
316     if (subject_ptr->monlite)
317         msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow becomes thin."));
318     else
319         msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow is restored to its original darkness."));
320
321     subject_ptr->old_monlite = subject_ptr->monlite;
322 }
323
324 /*!
325  * @brief 画面切り替え等でモンスターの灯りを消去する
326  * @param floor_ptr 現在フロアへの参照ポインタ
327  * @return なし
328  */
329 void clear_mon_lite(floor_type *floor_ptr)
330 {
331     for (int i = 0; i < floor_ptr->mon_lite_n; i++) {
332         grid_type *g_ptr;
333         g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
334         g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
335     }
336
337     floor_ptr->mon_lite_n = 0;
338 }