OSDN Git Service

[Refactor] #40477 Separated map-screen-options.c/h from cmd-gameoption.c/h
[hengband/hengband.git] / src / floor / floor-events.c
1 #include "floor/floor-events.h"
2 #include "cmd-io/cmd-dump.h"
3 #include "dungeon/dungeon.h"
4 #include "dungeon/quest.h"
5 #include "floor/floor.h"
6 #include "game-option/map-screen-options.h"
7 #include "grid/grid.h"
8 #include "monster-race/race-flags1.h"
9 #include "monster-race/race-flags7.h"
10 #include "monster/monster-info.h"
11 #include "monster/monster-list.h"
12 #include "monster/monster-status.h"
13 #include "perception/object-perception.h"
14 #include "object-enchant/object-ego.h"
15 #include "object/object-hook.h"
16 #include "object/object-kind.h"
17 #include "object/object-mark-types.h"
18 #include "object/object-value.h"
19 #include "object-enchant/special-object-flags.h"
20 #include "sv-definition/sv-amulet-types.h"
21 #include "sv-definition/sv-protector-types.h"
22 #include "sv-definition/sv-ring-types.h"
23 #include "player/player-effects.h"
24 #include "player/player-move.h"
25 #include "util/util.h"
26 #include "view/display-main-window.h"
27 #include "world/world.h"
28
29 static bool mon_invis;
30 static POSITION mon_fy, mon_fx;
31
32 void day_break(player_type *subject_ptr)
33 {
34         POSITION y, x;
35         msg_print(_("夜が明けた。", "The sun has risen."));
36
37         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
38         if (!subject_ptr->wild_mode)
39         {
40                 /* Hack -- Scan the town */
41                 for (y = 0; y < floor_ptr->height; y++)
42                 {
43                         for (x = 0; x < floor_ptr->width; x++)
44                         {
45                                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
46
47                                 /* Assume lit */
48                                 g_ptr->info |= (CAVE_GLOW);
49
50                                 /* Hack -- Memorize lit grids if allowed */
51                                 if (view_perma_grids) g_ptr->info |= (CAVE_MARK);
52
53                                 note_spot(subject_ptr, y, x);
54                         }
55                 }
56         }
57
58         subject_ptr->update |= (PU_MONSTERS | PU_MON_LITE);
59         subject_ptr->redraw |= (PR_MAP);
60         subject_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
61
62         if (subject_ptr->special_defense & NINJA_S_STEALTH)
63         {
64                 if (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_GLOW) set_superstealth(subject_ptr, FALSE);
65         }
66
67 }
68
69 void night_falls(player_type *subject_ptr)
70 {
71         POSITION y, x;
72         msg_print(_("日が沈んだ。", "The sun has fallen."));
73
74         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
75         if (!subject_ptr->wild_mode)
76         {
77                 /* Hack -- Scan the town */
78                 for (y = 0; y < floor_ptr->height; y++)
79                 {
80                         for (x = 0; x < floor_ptr->width; x++)
81                         {
82                                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
83
84                                 /* Feature code (applying "mimic" field) */
85                                 feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)];
86
87                                 if (!is_mirror_grid(g_ptr) && !have_flag(f_ptr->flags, FF_QUEST_ENTER) &&
88                                         !have_flag(f_ptr->flags, FF_ENTRANCE))
89                                 {
90                                         /* Assume dark */
91                                         g_ptr->info &= ~(CAVE_GLOW);
92
93                                         if (!have_flag(f_ptr->flags, FF_REMEMBER))
94                                         {
95                                                 /* Forget the normal floor grid */
96                                                 g_ptr->info &= ~(CAVE_MARK);
97
98                                                 note_spot(subject_ptr, y, x);
99                                         }
100                                 }
101                         }
102
103                         glow_deep_lava_and_bldg(subject_ptr);
104                 }
105         }
106
107         subject_ptr->update |= (PU_MONSTERS | PU_MON_LITE);
108         subject_ptr->redraw |= (PR_MAP);
109         subject_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
110
111         if (subject_ptr->special_defense & NINJA_S_STEALTH)
112         {
113                 if (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_GLOW) set_superstealth(subject_ptr, FALSE);
114         }
115
116 }
117
118 /*!
119  * @brief 現在フロアに残っている敵モンスターの数を返す /
120  * @return 現在の敵モンスターの数
121  */
122 MONSTER_NUMBER count_all_hostile_monsters(floor_type *floor_ptr)
123 {
124         MONSTER_NUMBER number_mon = 0;
125
126         for (POSITION x = 0; x < floor_ptr->width; ++x)
127         {
128                 for (POSITION y = 0; y < floor_ptr->height; ++y)
129                 {
130                         MONSTER_IDX m_idx = floor_ptr->grid_array[y][x].m_idx;
131
132                         if (m_idx > 0 && is_hostile(&floor_ptr->m_list[m_idx]))
133                         {
134                                 ++number_mon;
135                         }
136                 }
137         }
138
139         return number_mon;
140 }
141
142 /*!
143  * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
144  */
145 #define RATING_BOOST(delta) (delta * delta + 50 * delta)
146
147  /*!
148   * @brief ダンジョンの雰囲気を算出する。
149   * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor
150   * @return 算出されたダンジョンの雰囲気ランク
151   */
152 byte get_dungeon_feeling(floor_type *floor_ptr)
153 {
154         /* Hack -- no feeling in the town */
155         if (!floor_ptr->dun_level) return 0;
156
157         /* Examine each monster */
158         const int base = 10;
159         int rating = 0;
160         for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++)
161         {
162                 monster_type *m_ptr = &floor_ptr->m_list[i];
163                 monster_race *r_ptr;
164                 int delta = 0;
165                 if (!monster_is_valid(m_ptr)) continue;
166
167                 if (is_pet(m_ptr)) continue;
168
169                 r_ptr = &r_info[m_ptr->r_idx];
170
171                 if (r_ptr->flags1 & (RF1_UNIQUE))
172                 {
173                         /* Nearly out-of-depth unique monsters */
174                         if (r_ptr->level + 10 > floor_ptr->dun_level)
175                         {
176                                 /* Boost rating by twice delta-depth */
177                                 delta += (r_ptr->level + 10 - floor_ptr->dun_level) * 2 * base;
178                         }
179                 }
180                 else
181                 {
182                         /* Out-of-depth monsters */
183                         if (r_ptr->level > floor_ptr->dun_level)
184                         {
185                                 /* Boost rating by delta-depth */
186                                 delta += (r_ptr->level - floor_ptr->dun_level) * base;
187                         }
188                 }
189
190                 /* Unusually crowded monsters get a little bit of rating boost */
191                 if (r_ptr->flags1 & RF1_FRIENDS)
192                 {
193                         if (5 <= get_monster_crowd_number(floor_ptr, i)) delta += 1;
194                 }
195                 else
196                 {
197                         if (2 <= get_monster_crowd_number(floor_ptr, i)) delta += 1;
198                 }
199
200
201                 rating += RATING_BOOST(delta);
202         }
203
204         /* Examine each unidentified object */
205         for (MONSTER_IDX i = 1; i < floor_ptr->o_max; i++)
206         {
207                 object_type *o_ptr = &floor_ptr->o_list[i];
208                 object_kind *k_ptr = &k_info[o_ptr->k_idx];
209                 int delta = 0;
210
211                 if (!OBJECT_IS_VALID(o_ptr)) continue;
212
213                 /* Skip known objects */
214                 if (object_is_known(o_ptr))
215                 {
216                         /* Touched? */
217                         if (o_ptr->marked & OM_TOUCHED) continue;
218                 }
219
220                 /* Skip pseudo-known objects */
221                 if (o_ptr->ident & IDENT_SENSE) continue;
222
223                 /* Ego objects */
224                 if (object_is_ego(o_ptr))
225                 {
226                         ego_item_type *e_ptr = &e_info[o_ptr->name2];
227
228                         delta += e_ptr->rating * base;
229                 }
230
231                 /* Artifacts */
232                 if (object_is_artifact(o_ptr))
233                 {
234                         PRICE cost = object_value_real(o_ptr);
235
236                         delta += 10 * base;
237                         if (cost > 10000L) delta += 10 * base;
238                         if (cost > 50000L) delta += 10 * base;
239                         if (cost > 100000L) delta += 10 * base;
240
241                         /* Special feeling */
242                         if (!preserve_mode) return 1;
243                 }
244
245                 if (o_ptr->tval == TV_DRAG_ARMOR) delta += 30 * base;
246                 if (o_ptr->tval == TV_SHIELD && o_ptr->sval == SV_DRAGON_SHIELD) delta += 5 * base;
247                 if (o_ptr->tval == TV_GLOVES && o_ptr->sval == SV_SET_OF_DRAGON_GLOVES) delta += 5 * base;
248                 if (o_ptr->tval == TV_BOOTS && o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE) delta += 5 * base;
249                 if (o_ptr->tval == TV_HELM && o_ptr->sval == SV_DRAGON_HELM) delta += 5 * base;
250                 if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_SPEED && !object_is_cursed(o_ptr)) delta += 25 * base;
251                 if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_LORDLY && !object_is_cursed(o_ptr)) delta += 15 * base;
252                 if (o_ptr->tval == TV_AMULET && o_ptr->sval == SV_AMULET_THE_MAGI && !object_is_cursed(o_ptr)) delta += 15 * base;
253
254                 /* Out-of-depth objects */
255                 if (!object_is_cursed(o_ptr) && !object_is_broken(o_ptr) && k_ptr->level > floor_ptr->dun_level)
256                 {
257                         /* Rating increase */
258                         delta += (k_ptr->level - floor_ptr->dun_level) * base;
259                 }
260
261                 rating += RATING_BOOST(delta);
262         }
263
264
265         if (rating > RATING_BOOST(1000)) return 2;
266         if (rating > RATING_BOOST(800)) return 3;
267         if (rating > RATING_BOOST(600)) return 4;
268         if (rating > RATING_BOOST(400)) return 5;
269         if (rating > RATING_BOOST(300)) return 6;
270         if (rating > RATING_BOOST(200)) return 7;
271         if (rating > RATING_BOOST(100)) return 8;
272         if (rating > RATING_BOOST(0)) return 9;
273         return 10;
274 }
275
276 /*!
277  * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する
278  * / Update dungeon feeling, and announce it if changed
279  * @return なし
280  */
281 void update_dungeon_feeling(player_type *subject_ptr)
282 {
283         /* No feeling on the surface */
284         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
285         if (!floor_ptr->dun_level) return;
286
287         /* No feeling in the arena */
288         if (subject_ptr->phase_out) return;
289
290         /* Extract delay time */
291         int delay = MAX(10, 150 - subject_ptr->skill_fos) * (150 - floor_ptr->dun_level) * TURNS_PER_TICK / 100;
292
293         /* Not yet felt anything */
294         if (current_world_ptr->game_turn < subject_ptr->feeling_turn + delay && !cheat_xtra) return;
295
296         /* Extract quest number (if any) */
297         int quest_num = quest_number(subject_ptr, floor_ptr->dun_level);
298
299         /* No feeling in a quest */
300         if (quest_num &&
301                 (is_fixed_quest_idx(quest_num) &&
302                         !((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT) ||
303                                 !(quest[quest_num].flags & QUEST_FLAG_PRESET)))) return;
304
305
306         /* Get new dungeon feeling */
307         byte new_feeling = get_dungeon_feeling(floor_ptr);
308
309         /* Remember last time updated */
310         subject_ptr->feeling_turn = current_world_ptr->game_turn;
311
312         /* No change */
313         if (subject_ptr->feeling == new_feeling) return;
314
315         /* Dungeon feeling is changed */
316         subject_ptr->feeling = new_feeling;
317
318         /* Announce feeling */
319         do_cmd_feeling(subject_ptr);
320
321         select_floor_music(subject_ptr);
322
323         /* Update the level indicator */
324         subject_ptr->redraw |= (PR_DEPTH);
325
326         if (disturb_minor) disturb(subject_ptr, FALSE, FALSE);
327 }
328
329
330 /*
331  * Glow deep lava and building entrances in the floor
332  */
333 void glow_deep_lava_and_bldg(player_type *subject_ptr)
334 {
335         /* Not in the darkness dungeon */
336         if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) return;
337
338         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
339         for (POSITION y = 0; y < floor_ptr->height; y++)
340         {
341                 for (POSITION x = 0; x < floor_ptr->width; x++)
342                 {
343                         grid_type *g_ptr;
344                         g_ptr = &floor_ptr->grid_array[y][x];
345
346                         if (!have_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_GLOW))
347                                 continue;
348
349                         for (DIRECTION i = 0; i < 9; i++)
350                         {
351                                 POSITION yy = y + ddy_ddd[i];
352                                 POSITION xx = x + ddx_ddd[i];
353                                 if (!in_bounds2(floor_ptr, yy, xx)) continue;
354                                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
355                         }
356                 }
357         }
358
359         subject_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
360         subject_ptr->redraw |= (PR_MAP);
361 }
362
363
364 /*
365  * Actually erase the entire "lite" array, redrawing every grid
366  */
367 void forget_lite(floor_type *floor_ptr)
368 {
369         /* None to forget */
370         if (!floor_ptr->lite_n) return;
371
372         /* Clear them all */
373         for (int i = 0; i < floor_ptr->lite_n; i++)
374         {
375                 POSITION y = floor_ptr->lite_y[i];
376                 POSITION x = floor_ptr->lite_x[i];
377
378                 /* Forget "LITE" flag */
379                 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
380         }
381
382         floor_ptr->lite_n = 0;
383 }
384
385
386 /*
387  * Update the set of grids "illuminated" by the player's lite.
388  *
389  * This routine needs to use the results of "update_view()"
390  *
391  * Note that "blindness" does NOT affect "torch lite".  Be careful!
392  *
393  * We optimize most lites (all non-artifact lites) by using "obvious"
394  * facts about the results of "small" lite radius, and we attempt to
395  * list the "nearby" grids before the more "distant" ones in the
396  * array of torch-lit grids.
397  *
398  * We assume that "radius zero" lite is in fact no lite at all.
399  *
400  *     Torch     Lantern     Artifacts
401  *     (etc)
402  *                              ***
403  *                 ***         *****
404  *      ***       *****       *******
405  *      *@*       **@**       ***@***
406  *      ***       *****       *******
407  *                 ***         *****
408  *                              ***
409  */
410 void update_lite(player_type *subject_ptr)
411 {
412         POSITION p = subject_ptr->cur_lite;
413         grid_type *g_ptr;
414
415         /*** Save the old "lite" grids for later ***/
416
417         /* Clear them all */
418         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
419         for (int i = 0; i < floor_ptr->lite_n; i++)
420         {
421                 POSITION y = floor_ptr->lite_y[i];
422                 POSITION x = floor_ptr->lite_x[i];
423
424                 /* Mark the grid as not "lite" */
425                 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
426
427                 /* Mark the grid as "seen" */
428                 floor_ptr->grid_array[y][x].info |= (CAVE_TEMP);
429
430                 /* Add it to the "seen" set */
431                 tmp_pos.y[tmp_pos.n] = y;
432                 tmp_pos.x[tmp_pos.n] = x;
433                 tmp_pos.n++;
434         }
435
436         /* None left */
437         floor_ptr->lite_n = 0;
438
439
440         /*** Collect the new "lite" grids ***/
441
442         /* Radius 1 -- torch radius */
443         if (p >= 1)
444         {
445                 /* Player grid */
446                 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x);
447
448                 /* Adjacent grid */
449                 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x);
450                 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x);
451                 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 1);
452                 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 1);
453
454                 /* Diagonal grids */
455                 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1);
456                 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1);
457                 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1);
458                 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1);
459         }
460
461         /* Radius 2 -- lantern radius */
462         if (p >= 2)
463         {
464                 /* South of the player */
465                 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x))
466                 {
467                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x);
468                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 1);
469                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 1);
470                 }
471
472                 /* North of the player */
473                 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x))
474                 {
475                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x);
476                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 1);
477                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 1);
478                 }
479
480                 /* East of the player */
481                 if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x + 1))
482                 {
483                         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 2);
484                         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 2);
485                         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 2);
486                 }
487
488                 /* West of the player */
489                 if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x - 1))
490                 {
491                         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 2);
492                         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 2);
493                         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 2);
494                 }
495         }
496
497         /* Radius 3+ -- artifact radius */
498         if (p >= 3)
499         {
500                 int d;
501
502                 /* Paranoia -- see "LITE_MAX" */
503                 if (p > 14) p = 14;
504
505                 /* South-East of the player */
506                 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1))
507                 {
508                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 2);
509                 }
510
511                 /* South-West of the player */
512                 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1))
513                 {
514                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 2);
515                 }
516
517                 /* North-East of the player */
518                 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1))
519                 {
520                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 2);
521                 }
522
523                 /* North-West of the player */
524                 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1))
525                 {
526                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 2);
527                 }
528
529                 /* Maximal north */
530                 POSITION min_y = subject_ptr->y - p;
531                 if (min_y < 0) min_y = 0;
532
533                 /* Maximal south */
534                 POSITION max_y = subject_ptr->y + p;
535                 if (max_y > floor_ptr->height - 1) max_y = floor_ptr->height - 1;
536
537                 /* Maximal west */
538                 POSITION min_x = subject_ptr->x - p;
539                 if (min_x < 0) min_x = 0;
540
541                 /* Maximal east */
542                 POSITION max_x = subject_ptr->x + p;
543                 if (max_x > floor_ptr->width - 1) max_x = floor_ptr->width - 1;
544
545                 /* Scan the maximal box */
546                 for (POSITION y = min_y; y <= max_y; y++)
547                 {
548                         for (POSITION x = min_x; x <= max_x; x++)
549                         {
550                                 int dy = (subject_ptr->y > y) ? (subject_ptr->y - y) : (y - subject_ptr->y);
551                                 int dx = (subject_ptr->x > x) ? (subject_ptr->x - x) : (x - subject_ptr->x);
552
553                                 /* Skip the "central" grids (above) */
554                                 if ((dy <= 2) && (dx <= 2)) continue;
555
556                                 /* Hack -- approximate the distance */
557                                 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
558
559                                 /* Skip distant grids */
560                                 if (d > p) continue;
561
562                                 /* Viewable, nearby, grids get "torch lit" */
563                                 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW)
564                                 {
565                                         /* This grid is "torch lit" */
566                                         cave_lite_hack(floor_ptr, y, x);
567                                 }
568                         }
569                 }
570         }
571
572
573         /*** Complete the algorithm ***/
574
575         /* Draw the new grids */
576         for (int i = 0; i < floor_ptr->lite_n; i++)
577         {
578                 POSITION y = floor_ptr->lite_y[i];
579                 POSITION x = floor_ptr->lite_x[i];
580
581                 g_ptr = &floor_ptr->grid_array[y][x];
582
583                 /* Update fresh grids */
584                 if (g_ptr->info & (CAVE_TEMP)) continue;
585
586                 /* Add it to later visual update */
587                 cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
588         }
589
590         /* Clear them all */
591         for (int i = 0; i < tmp_pos.n; i++)
592         {
593                 POSITION y = tmp_pos.y[i];
594                 POSITION x = tmp_pos.x[i];
595
596                 g_ptr = &floor_ptr->grid_array[y][x];
597
598                 /* No longer in the array */
599                 g_ptr->info &= ~(CAVE_TEMP);
600
601                 /* Update stale grids */
602                 if (g_ptr->info & (CAVE_LITE)) continue;
603
604                 /* Add it to later visual update */
605                 cave_redraw_later(floor_ptr, g_ptr, y, x);
606         }
607
608         tmp_pos.n = 0;
609         subject_ptr->update |= (PU_DELAY_VIS);
610 }
611
612
613 /*
614  * Clear the viewable space
615  */
616 void forget_view(floor_type *floor_ptr)
617 {
618         /* None to forget */
619         if (!floor_ptr->view_n) return;
620
621         /* Clear them all */
622         for (int i = 0; i < floor_ptr->view_n; i++)
623         {
624                 POSITION y = floor_ptr->view_y[i];
625                 POSITION x = floor_ptr->view_x[i];
626                 grid_type *g_ptr;
627                 g_ptr = &floor_ptr->grid_array[y][x];
628
629                 /* Forget that the grid is viewable */
630                 g_ptr->info &= ~(CAVE_VIEW);
631         }
632
633         floor_ptr->view_n = 0;
634 }
635
636
637 /*
638  * Helper function for "update_view()" below
639  *
640  * We are checking the "viewability" of grid (y,x) by the player.
641  *
642  * This function assumes that (y,x) is legal (i.e. on the map).
643  *
644  * Grid (y1,x1) is on the "diagonal" between (subject_ptr->y,subject_ptr->x) and (y,x)
645  * Grid (y2,x2) is "adjacent", also between (subject_ptr->y,subject_ptr->x) and (y,x).
646  *
647  * Note that we are using the "CAVE_XTRA" field for marking grids as
648  * "easily viewable".  This bit is cleared at the end of "update_view()".
649  *
650  * This function adds (y,x) to the "viewable set" if necessary.
651  *
652  * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
653  */
654 static bool update_view_aux(player_type *subject_ptr, POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
655 {
656         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
657         grid_type *g1_c_ptr;
658         grid_type *g2_c_ptr;
659         g1_c_ptr = &floor_ptr->grid_array[y1][x1];
660         g2_c_ptr = &floor_ptr->grid_array[y2][x2];
661
662         /* Check for walls */
663         bool f1 = (cave_los_grid(g1_c_ptr));
664         bool f2 = (cave_los_grid(g2_c_ptr));
665
666         /* Totally blocked by physical walls */
667         if (!f1 && !f2) return TRUE;
668
669         /* Check for visibility */
670         bool v1 = (f1 && (g1_c_ptr->info & (CAVE_VIEW)));
671         bool v2 = (f2 && (g2_c_ptr->info & (CAVE_VIEW)));
672
673         /* Totally blocked by "unviewable neighbors" */
674         if (!v1 && !v2) return TRUE;
675
676         grid_type *g_ptr;
677         g_ptr = &floor_ptr->grid_array[y][x];
678
679         /* Check for walls */
680         bool wall = (!cave_los_grid(g_ptr));
681
682         /* Check the "ease" of visibility */
683         bool z1 = (v1 && (g1_c_ptr->info & (CAVE_XTRA)));
684         bool z2 = (v2 && (g2_c_ptr->info & (CAVE_XTRA)));
685
686         /* Hack -- "easy" plus "easy" yields "easy" */
687         if (z1 && z2)
688         {
689                 g_ptr->info |= (CAVE_XTRA);
690                 cave_view_hack(floor_ptr, g_ptr, y, x);
691                 return wall;
692         }
693
694         /* Hack -- primary "easy" yields "viewed" */
695         if (z1)
696         {
697                 cave_view_hack(floor_ptr, g_ptr, y, x);
698                 return wall;
699         }
700
701         /* Hack -- "view" plus "view" yields "view" */
702         if (v1 && v2)
703         {
704                 cave_view_hack(floor_ptr, g_ptr, y, x);
705                 return wall;
706         }
707
708         /* Mega-Hack -- the "los()" function works poorly on walls */
709         if (wall)
710         {
711                 cave_view_hack(floor_ptr, g_ptr, y, x);
712                 return wall;
713         }
714
715         /* Hack -- check line of sight */
716         if (los(subject_ptr, subject_ptr->y, subject_ptr->x, y, x))
717         {
718                 cave_view_hack(floor_ptr, g_ptr, y, x);
719                 return wall;
720         }
721
722         return TRUE;
723 }
724
725
726 /*
727  * Calculate the viewable space
728  *
729  *  1: Process the player
730  *  1a: The player is always (easily) viewable
731  *  2: Process the diagonals
732  *  2a: The diagonals are (easily) viewable up to the first wall
733  *  2b: But never go more than 2/3 of the "full" distance
734  *  3: Process the main axes
735  *  3a: The main axes are (easily) viewable up to the first wall
736  *  3b: But never go more than the "full" distance
737  *  4: Process sequential "strips" in each of the eight octants
738  *  4a: Each strip runs along the previous strip
739  *  4b: The main axes are "previous" to the first strip
740  *  4c: Process both "sides" of each "direction" of each strip
741  *  4c1: Each side aborts as soon as possible
742  *  4c2: Each side tells the next strip how far it has to check
743  *
744  * Note that the octant processing involves some pretty interesting
745  * observations involving when a grid might possibly be viewable from
746  * a given grid, and on the order in which the strips are processed.
747  *
748  * Note the use of the mathematical facts shown below, which derive
749  * from the fact that (1 < sqrt(2) < 1.5), and that the length of the
750  * hypotenuse of a right triangle is primarily determined by the length
751  * of the longest side, when one side is small, and is strictly less
752  * than one-and-a-half times as long as the longest side when both of
753  * the sides are large.
754  *
755  *   if (manhatten(dy,dx) < R) then (hypot(dy,dx) < R)
756  *   if (manhatten(dy,dx) > R*3/2) then (hypot(dy,dx) > R)
757  *
758  *   hypot(dy,dx) is approximated by (dx+dy+MAX(dx,dy)) / 2
759  *
760  * These observations are important because the calculation of the actual
761  * value of "hypot(dx,dy)" is extremely expensive, involving square roots,
762  * while for small values (up to about 20 or so), the approximations above
763  * are correct to within an error of at most one grid or so.
764  *
765  * Observe the use of "full" and "over" in the code below, and the use of
766  * the specialized calculation involving "limit", all of which derive from
767  * the observations given above.  Basically, we note that the "circle" of
768  * view is completely contained in an "octagon" whose bounds are easy to
769  * determine, and that only a few steps are needed to derive the actual
770  * bounds of the circle given the bounds of the octagon.
771  *
772  * Note that by skipping all the grids in the corners of the octagon, we
773  * place an upper limit on the number of grids in the field of view, given
774  * that "full" is never more than 20.  Of the 1681 grids in the "square" of
775  * view, only about 1475 of these are in the "octagon" of view, and even
776  * fewer are in the "circle" of view, so 1500 or 1536 is more than enough
777  * entries to completely contain the actual field of view.
778  *
779  * Note also the care taken to prevent "running off the map".  The use of
780  * explicit checks on the "validity" of the "diagonal", and the fact that
781  * the loops are never allowed to "leave" the map, lets "update_view_aux()"
782  * use the optimized "cave_los_bold()" macro, and to avoid the overhead
783  * of multiple checks on the validity of grids.
784  *
785  * Note the "optimizations" involving the "se","sw","ne","nw","es","en",
786  * "ws","wn" variables.  They work like this: While travelling down the
787  * south-bound strip just to the east of the main south axis, as soon as
788  * we get to a grid which does not "transmit" viewing, if all of the strips
789  * preceding us (in this case, just the main axis) had terminated at or before
790  * the same point, then we can stop, and reset the "max distance" to ourself.
791  * So, each strip (named by major axis plus offset, thus "se" in this case)
792  * maintains a "blockage" variable, initialized during the main axis step,
793  * and checks it whenever a blockage is observed.  After processing each
794  * strip as far as the previous strip told us to process, the next strip is
795  * told not to go farther than the current strip's farthest viewable grid,
796  * unless open space is still available.  This uses the "k" variable.
797  *
798  * Note the use of "inline" macros for efficiency.  The "cave_los_grid()"
799  * macro is a replacement for "cave_los_bold()" which takes a pointer to
800  * a grid instead of its location.  The "cave_view_hack()" macro is a
801  * chunk of code which adds the given location to the "view" array if it
802  * is not already there, using both the actual location and a pointer to
803  * the grid.  See above.
804  *
805  * By the way, the purpose of this code is to reduce the dependancy on the
806  * "los()" function which is slow, and, in some cases, not very accurate.
807  *
808  * It is very possible that I am the only person who fully understands this
809  * function, and for that I am truly sorry, but efficiency was very important
810  * and the "simple" version of this function was just not fast enough.  I am
811  * more than willing to replace this function with a simpler one, if it is
812  * equally efficient, and especially willing if the new function happens to
813  * derive "reverse-line-of-sight" at the same time, since currently monsters
814  * just use an optimized hack of "you see me, so I see you", and then use the
815  * actual "projectable()" function to check spell attacks.
816  */
817 void update_view(player_type *subject_ptr)
818 {
819         int n, m, d, k, z;
820         POSITION y, x;
821
822         int se, sw, ne, nw, es, en, ws, wn;
823
824         int full, over;
825
826         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
827         POSITION y_max = floor_ptr->height - 1;
828         POSITION x_max = floor_ptr->width - 1;
829
830         grid_type *g_ptr;
831
832         /*** Initialize ***/
833
834         /* Optimize */
835         if (view_reduce_view && !floor_ptr->dun_level)
836         {
837                 /* Full radius (10) */
838                 full = MAX_SIGHT / 2;
839
840                 /* Octagon factor (15) */
841                 over = MAX_SIGHT * 3 / 4;
842         }
843
844         /* Normal */
845         else
846         {
847                 /* Full radius (20) */
848                 full = MAX_SIGHT;
849
850                 /* Octagon factor (30) */
851                 over = MAX_SIGHT * 3 / 2;
852         }
853
854
855         /*** Step 0 -- Begin ***/
856
857         /* Save the old "view" grids for later */
858         for (n = 0; n < floor_ptr->view_n; n++)
859         {
860                 y = floor_ptr->view_y[n];
861                 x = floor_ptr->view_x[n];
862                 g_ptr = &floor_ptr->grid_array[y][x];
863
864                 /* Mark the grid as not in "view" */
865                 g_ptr->info &= ~(CAVE_VIEW);
866
867                 /* Mark the grid as "seen" */
868                 g_ptr->info |= (CAVE_TEMP);
869
870                 /* Add it to the "seen" set */
871                 tmp_pos.y[tmp_pos.n] = y;
872                 tmp_pos.x[tmp_pos.n] = x;
873                 tmp_pos.n++;
874         }
875
876         /* Start over with the "view" array */
877         floor_ptr->view_n = 0;
878
879         /*** Step 1 -- adjacent grids ***/
880
881         /* Now start on the player */
882         y = subject_ptr->y;
883         x = subject_ptr->x;
884         g_ptr = &floor_ptr->grid_array[y][x];
885
886         /* Assume the player grid is easily viewable */
887         g_ptr->info |= (CAVE_XTRA);
888
889         /* Assume the player grid is viewable */
890         cave_view_hack(floor_ptr, g_ptr, y, x);
891
892
893         /*** Step 2 -- Major Diagonals ***/
894
895         /* Hack -- Limit */
896         z = full * 2 / 3;
897
898         /* Scan south-east */
899         for (d = 1; d <= z; d++)
900         {
901                 g_ptr = &floor_ptr->grid_array[y + d][x + d];
902                 g_ptr->info |= (CAVE_XTRA);
903                 cave_view_hack(floor_ptr, g_ptr, y + d, x + d);
904                 if (!cave_los_grid(g_ptr)) break;
905         }
906
907         /* Scan south-west */
908         for (d = 1; d <= z; d++)
909         {
910                 g_ptr = &floor_ptr->grid_array[y + d][x - d];
911                 g_ptr->info |= (CAVE_XTRA);
912                 cave_view_hack(floor_ptr, g_ptr, y + d, x - d);
913                 if (!cave_los_grid(g_ptr)) break;
914         }
915
916         /* Scan north-east */
917         for (d = 1; d <= z; d++)
918         {
919                 g_ptr = &floor_ptr->grid_array[y - d][x + d];
920                 g_ptr->info |= (CAVE_XTRA);
921                 cave_view_hack(floor_ptr, g_ptr, y - d, x + d);
922                 if (!cave_los_grid(g_ptr)) break;
923         }
924
925         /* Scan north-west */
926         for (d = 1; d <= z; d++)
927         {
928                 g_ptr = &floor_ptr->grid_array[y - d][x - d];
929                 g_ptr->info |= (CAVE_XTRA);
930                 cave_view_hack(floor_ptr, g_ptr, y - d, x - d);
931                 if (!cave_los_grid(g_ptr)) break;
932         }
933
934         /*** Step 3 -- major axes ***/
935
936         /* Scan south */
937         for (d = 1; d <= full; d++)
938         {
939                 g_ptr = &floor_ptr->grid_array[y + d][x];
940                 g_ptr->info |= (CAVE_XTRA);
941                 cave_view_hack(floor_ptr, g_ptr, y + d, x);
942                 if (!cave_los_grid(g_ptr)) break;
943         }
944
945         /* Initialize the "south strips" */
946         se = sw = d;
947
948         /* Scan north */
949         for (d = 1; d <= full; d++)
950         {
951                 g_ptr = &floor_ptr->grid_array[y - d][x];
952                 g_ptr->info |= (CAVE_XTRA);
953                 cave_view_hack(floor_ptr, g_ptr, y - d, x);
954                 if (!cave_los_grid(g_ptr)) break;
955         }
956
957         /* Initialize the "north strips" */
958         ne = nw = d;
959
960         /* Scan east */
961         for (d = 1; d <= full; d++)
962         {
963                 g_ptr = &floor_ptr->grid_array[y][x + d];
964                 g_ptr->info |= (CAVE_XTRA);
965                 cave_view_hack(floor_ptr, g_ptr, y, x + d);
966                 if (!cave_los_grid(g_ptr)) break;
967         }
968
969         /* Initialize the "east strips" */
970         es = en = d;
971
972         /* Scan west */
973         for (d = 1; d <= full; d++)
974         {
975                 g_ptr = &floor_ptr->grid_array[y][x - d];
976                 g_ptr->info |= (CAVE_XTRA);
977                 cave_view_hack(floor_ptr, g_ptr, y, x - d);
978                 if (!cave_los_grid(g_ptr)) break;
979         }
980
981         /* Initialize the "west strips" */
982         ws = wn = d;
983
984
985         /*** Step 4 -- Divide each "octant" into "strips" ***/
986
987         /* Now check each "diagonal" (in parallel) */
988         for (n = 1; n <= over / 2; n++)
989         {
990                 POSITION ypn, ymn, xpn, xmn;
991
992                 /* Acquire the "bounds" of the maximal circle */
993                 z = over - n - n;
994                 if (z > full - n) z = full - n;
995                 while ((z + n + (n >> 1)) > full) z--;
996
997                 /* Access the four diagonal grids */
998                 ypn = y + n;
999                 ymn = y - n;
1000                 xpn = x + n;
1001                 xmn = x - n;
1002
1003                 /* South strip */
1004                 if (ypn < y_max)
1005                 {
1006                         /* Maximum distance */
1007                         m = MIN(z, y_max - ypn);
1008
1009                         /* East side */
1010                         if ((xpn <= x_max) && (n < se))
1011                         {
1012                                 /* Scan */
1013                                 for (k = n, d = 1; d <= m; d++)
1014                                 {
1015                                         /* Check grid "d" in strip "n", notice "blockage" */
1016                                         if (update_view_aux(subject_ptr, ypn + d, xpn, ypn + d - 1, xpn - 1, ypn + d - 1, xpn))
1017                                         {
1018                                                 if (n + d >= se) break;
1019                                         }
1020
1021                                         /* Track most distant "non-blockage" */
1022                                         else
1023                                         {
1024                                                 k = n + d;
1025                                         }
1026                                 }
1027
1028                                 /* Limit the next strip */
1029                                 se = k + 1;
1030                         }
1031
1032                         /* West side */
1033                         if ((xmn >= 0) && (n < sw))
1034                         {
1035                                 /* Scan */
1036                                 for (k = n, d = 1; d <= m; d++)
1037                                 {
1038                                         /* Check grid "d" in strip "n", notice "blockage" */
1039                                         if (update_view_aux(subject_ptr, ypn + d, xmn, ypn + d - 1, xmn + 1, ypn + d - 1, xmn))
1040                                         {
1041                                                 if (n + d >= sw) break;
1042                                         }
1043
1044                                         /* Track most distant "non-blockage" */
1045                                         else
1046                                         {
1047                                                 k = n + d;
1048                                         }
1049                                 }
1050
1051                                 /* Limit the next strip */
1052                                 sw = k + 1;
1053                         }
1054                 }
1055
1056                 /* North strip */
1057                 if (ymn > 0)
1058                 {
1059                         /* Maximum distance */
1060                         m = MIN(z, ymn);
1061
1062                         /* East side */
1063                         if ((xpn <= x_max) && (n < ne))
1064                         {
1065                                 /* Scan */
1066                                 for (k = n, d = 1; d <= m; d++)
1067                                 {
1068                                         /* Check grid "d" in strip "n", notice "blockage" */
1069                                         if (update_view_aux(subject_ptr, ymn - d, xpn, ymn - d + 1, xpn - 1, ymn - d + 1, xpn))
1070                                         {
1071                                                 if (n + d >= ne) break;
1072                                         }
1073
1074                                         /* Track most distant "non-blockage" */
1075                                         else
1076                                         {
1077                                                 k = n + d;
1078                                         }
1079                                 }
1080
1081                                 /* Limit the next strip */
1082                                 ne = k + 1;
1083                         }
1084
1085                         /* West side */
1086                         if ((xmn >= 0) && (n < nw))
1087                         {
1088                                 /* Scan */
1089                                 for (k = n, d = 1; d <= m; d++)
1090                                 {
1091                                         /* Check grid "d" in strip "n", notice "blockage" */
1092                                         if (update_view_aux(subject_ptr, ymn - d, xmn, ymn - d + 1, xmn + 1, ymn - d + 1, xmn))
1093                                         {
1094                                                 if (n + d >= nw) break;
1095                                         }
1096
1097                                         /* Track most distant "non-blockage" */
1098                                         else
1099                                         {
1100                                                 k = n + d;
1101                                         }
1102                                 }
1103
1104                                 /* Limit the next strip */
1105                                 nw = k + 1;
1106                         }
1107                 }
1108
1109                 /* East strip */
1110                 if (xpn < x_max)
1111                 {
1112                         /* Maximum distance */
1113                         m = MIN(z, x_max - xpn);
1114
1115                         /* South side */
1116                         if ((ypn <= x_max) && (n < es))
1117                         {
1118                                 /* Scan */
1119                                 for (k = n, d = 1; d <= m; d++)
1120                                 {
1121                                         /* Check grid "d" in strip "n", notice "blockage" */
1122                                         if (update_view_aux(subject_ptr, ypn, xpn + d, ypn - 1, xpn + d - 1, ypn, xpn + d - 1))
1123                                         {
1124                                                 if (n + d >= es) break;
1125                                         }
1126
1127                                         /* Track most distant "non-blockage" */
1128                                         else
1129                                         {
1130                                                 k = n + d;
1131                                         }
1132                                 }
1133
1134                                 /* Limit the next strip */
1135                                 es = k + 1;
1136                         }
1137
1138                         /* North side */
1139                         if ((ymn >= 0) && (n < en))
1140                         {
1141                                 /* Scan */
1142                                 for (k = n, d = 1; d <= m; d++)
1143                                 {
1144                                         /* Check grid "d" in strip "n", notice "blockage" */
1145                                         if (update_view_aux(subject_ptr, ymn, xpn + d, ymn + 1, xpn + d - 1, ymn, xpn + d - 1))
1146                                         {
1147                                                 if (n + d >= en) break;
1148                                         }
1149
1150                                         /* Track most distant "non-blockage" */
1151                                         else
1152                                         {
1153                                                 k = n + d;
1154                                         }
1155                                 }
1156
1157                                 /* Limit the next strip */
1158                                 en = k + 1;
1159                         }
1160                 }
1161
1162                 /* West strip */
1163                 if (xmn > 0)
1164                 {
1165                         /* Maximum distance */
1166                         m = MIN(z, xmn);
1167
1168                         /* South side */
1169                         if ((ypn <= y_max) && (n < ws))
1170                         {
1171                                 /* Scan */
1172                                 for (k = n, d = 1; d <= m; d++)
1173                                 {
1174                                         /* Check grid "d" in strip "n", notice "blockage" */
1175                                         if (update_view_aux(subject_ptr, ypn, xmn - d, ypn - 1, xmn - d + 1, ypn, xmn - d + 1))
1176                                         {
1177                                                 if (n + d >= ws) break;
1178                                         }
1179
1180                                         /* Track most distant "non-blockage" */
1181                                         else
1182                                         {
1183                                                 k = n + d;
1184                                         }
1185                                 }
1186
1187                                 /* Limit the next strip */
1188                                 ws = k + 1;
1189                         }
1190
1191                         /* North side */
1192                         if ((ymn >= 0) && (n < wn))
1193                         {
1194                                 /* Scan */
1195                                 for (k = n, d = 1; d <= m; d++)
1196                                 {
1197                                         /* Check grid "d" in strip "n", notice "blockage" */
1198                                         if (update_view_aux(subject_ptr, ymn, xmn - d, ymn + 1, xmn - d + 1, ymn, xmn - d + 1))
1199                                         {
1200                                                 if (n + d >= wn) break;
1201                                         }
1202
1203                                         /* Track most distant "non-blockage" */
1204                                         else
1205                                         {
1206                                                 k = n + d;
1207                                         }
1208                                 }
1209
1210                                 /* Limit the next strip */
1211                                 wn = k + 1;
1212                         }
1213                 }
1214         }
1215
1216         /*** Step 5 -- Complete the algorithm ***/
1217
1218         /* Update all the new grids */
1219         for (n = 0; n < floor_ptr->view_n; n++)
1220         {
1221                 y = floor_ptr->view_y[n];
1222                 x = floor_ptr->view_x[n];
1223                 g_ptr = &floor_ptr->grid_array[y][x];
1224
1225                 /* Clear the "CAVE_XTRA" flag */
1226                 g_ptr->info &= ~(CAVE_XTRA);
1227
1228                 /* Update only newly viewed grids */
1229                 if (g_ptr->info & (CAVE_TEMP)) continue;
1230
1231                 /* Add it to later visual update */
1232                 cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
1233         }
1234
1235         /* Wipe the old grids, update as needed */
1236         for (n = 0; n < tmp_pos.n; n++)
1237         {
1238                 y = tmp_pos.y[n];
1239                 x = tmp_pos.x[n];
1240                 g_ptr = &floor_ptr->grid_array[y][x];
1241
1242                 /* No longer in the array */
1243                 g_ptr->info &= ~(CAVE_TEMP);
1244
1245                 /* Update only non-viewable grids */
1246                 if (g_ptr->info & (CAVE_VIEW)) continue;
1247
1248                 /* Add it to later visual update */
1249                 cave_redraw_later(floor_ptr, g_ptr, y, x);
1250         }
1251
1252         tmp_pos.n = 0;
1253         subject_ptr->update |= (PU_DELAY_VIS);
1254 }
1255
1256
1257 /*!
1258  * @brief モンスターによる光量状態更新 / Add a square to the changes array
1259  * @param subject_ptr 主観となるクリーチャーの参照ポインタ
1260  * @param y Y座標
1261  * @param x X座標
1262  */
1263 static void mon_lite_hack(player_type *subject_ptr, POSITION y, POSITION x)
1264 {
1265         grid_type *g_ptr;
1266         int dpf, d;
1267         POSITION midpoint;
1268
1269         /* We trust this grid is in bounds */
1270         /* if (!in_bounds2(y, x)) return; */
1271
1272         g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
1273
1274         /* Want a unlit square in view of the player */
1275         if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW) return;
1276
1277         if (!cave_los_grid(g_ptr))
1278         {
1279                 /* Hack -- Prevent monster lite leakage in walls */
1280
1281                 /* Horizontal walls between player and a monster */
1282                 if (((y < subject_ptr->y) && (y > mon_fy)) || ((y > subject_ptr->y) && (y < mon_fy)))
1283                 {
1284                         dpf = subject_ptr->y - mon_fy;
1285                         d = y - mon_fy;
1286                         midpoint = mon_fx + ((subject_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
1287
1288                         /* Only first wall viewed from mid-x is lit */
1289                         if (x < midpoint)
1290                         {
1291                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1)) return;
1292                         }
1293                         else if (x > midpoint)
1294                         {
1295                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1)) return;
1296                         }
1297
1298                         /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1299                         else if (mon_invis) return;
1300                 }
1301
1302                 /* Vertical walls between player and a monster */
1303                 if (((x < subject_ptr->x) && (x > mon_fx)) || ((x > subject_ptr->x) && (x < mon_fx)))
1304                 {
1305                         dpf = subject_ptr->x - mon_fx;
1306                         d = x - mon_fx;
1307                         midpoint = mon_fy + ((subject_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
1308
1309                         /* Only first wall viewed from mid-y is lit */
1310                         if (y < midpoint)
1311                         {
1312                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x)) return;
1313                         }
1314                         else if (y > midpoint)
1315                         {
1316                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x)) return;
1317                         }
1318
1319                         /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1320                         else if (mon_invis) return;
1321                 }
1322         }
1323
1324         /* We trust tmp_pos.n does not exceed TEMP_MAX */
1325
1326         /* New grid */
1327         if (!(g_ptr->info & CAVE_MNDK))
1328         {
1329                 /* Save this square */
1330                 tmp_pos.x[tmp_pos.n] = x;
1331                 tmp_pos.y[tmp_pos.n] = y;
1332                 tmp_pos.n++;
1333         }
1334
1335         /* Darkened grid */
1336         else
1337         {
1338                 /* No longer dark */
1339                 g_ptr->info &= ~(CAVE_MNDK);
1340         }
1341
1342         /* Light it */
1343         g_ptr->info |= CAVE_MNLT;
1344 }
1345
1346
1347 /*
1348  * Add a square to the changes array
1349  */
1350 static void mon_dark_hack(player_type *subject_ptr, POSITION y, POSITION x)
1351 {
1352         grid_type *g_ptr;
1353         int midpoint, dpf, d;
1354
1355         /* We trust this grid is in bounds */
1356         /* if (!in_bounds2(y, x)) return; */
1357
1358         g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
1359
1360         /* Want a unlit and undarkened square in view of the player */
1361         if ((g_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW) return;
1362
1363         if (!cave_los_grid(g_ptr) && !cave_have_flag_grid(g_ptr, FF_PROJECT))
1364         {
1365                 /* Hack -- Prevent monster dark lite leakage in walls */
1366
1367                 /* Horizontal walls between player and a monster */
1368                 if (((y < subject_ptr->y) && (y > mon_fy)) || ((y > subject_ptr->y) && (y < mon_fy)))
1369                 {
1370                         dpf = subject_ptr->y - mon_fy;
1371                         d = y - mon_fy;
1372                         midpoint = mon_fx + ((subject_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
1373
1374                         /* Only first wall viewed from mid-x is lit */
1375                         if (x < midpoint)
1376                         {
1377                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1) && !cave_have_flag_bold(subject_ptr->current_floor_ptr, y, x + 1, FF_PROJECT)) return;
1378                         }
1379                         else if (x > midpoint)
1380                         {
1381                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1) && !cave_have_flag_bold(subject_ptr->current_floor_ptr, y, x - 1, FF_PROJECT)) return;
1382                         }
1383
1384                         /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1385                         else if (mon_invis) return;
1386                 }
1387
1388                 /* Vertical walls between player and a monster */
1389                 if (((x < subject_ptr->x) && (x > mon_fx)) || ((x > subject_ptr->x) && (x < mon_fx)))
1390                 {
1391                         dpf = subject_ptr->x - mon_fx;
1392                         d = x - mon_fx;
1393                         midpoint = mon_fy + ((subject_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
1394
1395                         /* Only first wall viewed from mid-y is lit */
1396                         if (y < midpoint)
1397                         {
1398                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x) && !cave_have_flag_bold(subject_ptr->current_floor_ptr, y + 1, x, FF_PROJECT)) return;
1399                         }
1400                         else if (y > midpoint)
1401                         {
1402                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x) && !cave_have_flag_bold(subject_ptr->current_floor_ptr, y - 1, x, FF_PROJECT)) return;
1403                         }
1404
1405                         /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1406                         else if (mon_invis) return;
1407                 }
1408         }
1409
1410         /* We trust tmp_pos.n does not exceed TEMP_MAX */
1411
1412         /* Save this square */
1413         tmp_pos.x[tmp_pos.n] = x;
1414         tmp_pos.y[tmp_pos.n] = y;
1415         tmp_pos.n++;
1416
1417         /* Darken it */
1418         g_ptr->info |= CAVE_MNDK;
1419 }
1420
1421
1422 /*
1423  * Update squares illuminated or darkened by monsters.
1424  *
1425  * Hack - use the CAVE_ROOM flag (renamed to be CAVE_MNLT) to
1426  * denote squares illuminated by monsters.
1427  *
1428  * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
1429  * updating.  Only squares in view of the player, whos state
1430  * changes are drawn via lite_spot().
1431  */
1432 void update_mon_lite(player_type *subject_ptr)
1433 {
1434         void(*add_mon_lite)(player_type *, POSITION, POSITION);
1435
1436         /* Non-Ninja player in the darkness */
1437         int dis_lim = ((d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !subject_ptr->see_nocto) ?
1438                 (MAX_SIGHT / 2 + 1) : (MAX_SIGHT + 3);
1439
1440         /* Clear all monster lit squares */
1441         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
1442         for (int i = 0; i < floor_ptr->mon_lite_n; i++)
1443         {
1444                 grid_type *g_ptr;
1445                 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
1446
1447                 /* Set temp or xtra flag */
1448                 g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
1449
1450                 /* Clear monster illumination flag */
1451                 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
1452         }
1453
1454         /* Empty temp list of new squares to lite up */
1455         tmp_pos.n = 0;
1456
1457         /* If a monster stops time, don't process */
1458         if (!current_world_ptr->timewalk_m_idx)
1459         {
1460                 monster_type *m_ptr;
1461                 monster_race *r_ptr;
1462
1463                 /* Loop through monsters, adding newly lit squares to changes list */
1464                 for (int i = 1; i < floor_ptr->m_max; i++)
1465                 {
1466                         m_ptr = &floor_ptr->m_list[i];
1467                         r_ptr = &r_info[m_ptr->r_idx];
1468                         if (!monster_is_valid(m_ptr)) continue;
1469
1470                         /* Is it too far away? */
1471                         if (m_ptr->cdis > dis_lim) continue;
1472
1473                         /* Get lite radius */
1474                         int rad = 0;
1475
1476                         /* Note the radii are cumulative */
1477                         if (r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_SELF_LITE_1)) rad++;
1478                         if (r_ptr->flags7 & (RF7_HAS_LITE_2 | RF7_SELF_LITE_2)) rad += 2;
1479                         if (r_ptr->flags7 & (RF7_HAS_DARK_1 | RF7_SELF_DARK_1)) rad--;
1480                         if (r_ptr->flags7 & (RF7_HAS_DARK_2 | RF7_SELF_DARK_2)) rad -= 2;
1481
1482                         /* Exit if has no light */
1483                         if (!rad) continue;
1484
1485                         int f_flag;
1486                         if (rad > 0)
1487                         {
1488                                 if (!(r_ptr->flags7 & (RF7_SELF_LITE_1 | RF7_SELF_LITE_2)) && (monster_csleep_remaining(m_ptr) || (!floor_ptr->dun_level && is_daytime()) || subject_ptr->phase_out)) continue;
1489                                 if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) rad = 1;
1490                                 add_mon_lite = mon_lite_hack;
1491                                 f_flag = FF_LOS;
1492                         }
1493                         else
1494                         {
1495                                 if (!(r_ptr->flags7 & (RF7_SELF_DARK_1 | RF7_SELF_DARK_2)) && (monster_csleep_remaining(m_ptr) || (!floor_ptr->dun_level && !is_daytime()))) continue;
1496                                 add_mon_lite = mon_dark_hack;
1497                                 f_flag = FF_PROJECT;
1498                                 rad = -rad; /* Use absolute value */
1499                         }
1500
1501                         mon_fx = m_ptr->fx;
1502                         mon_fy = m_ptr->fy;
1503
1504                         /* Is the monster visible? */
1505                         mon_invis = !(floor_ptr->grid_array[mon_fy][mon_fx].info & CAVE_VIEW);
1506
1507                         /* The square it is on */
1508                         add_mon_lite(subject_ptr, mon_fy, mon_fx);
1509
1510                         /* Adjacent squares */
1511                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx);
1512                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx);
1513                         add_mon_lite(subject_ptr, mon_fy, mon_fx + 1);
1514                         add_mon_lite(subject_ptr, mon_fy, mon_fx - 1);
1515                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 1);
1516                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 1);
1517                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 1);
1518                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 1);
1519
1520                         /* Radius 2 */
1521                         if (rad < 2) continue;
1522
1523                         /* South of the monster */
1524                         grid_type *g_ptr;
1525                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx, f_flag))
1526                         {
1527                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx + 1);
1528                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx);
1529                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx - 1);
1530
1531                                 g_ptr = &floor_ptr->grid_array[mon_fy + 2][mon_fx];
1532
1533                                 /* Radius 3 */
1534                                 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1535                                 {
1536                                         add_mon_lite(subject_ptr, mon_fy + 3, mon_fx + 1);
1537                                         add_mon_lite(subject_ptr, mon_fy + 3, mon_fx);
1538                                         add_mon_lite(subject_ptr, mon_fy + 3, mon_fx - 1);
1539                                 }
1540                         }
1541
1542                         /* North of the monster */
1543                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx, f_flag))
1544                         {
1545                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx + 1);
1546                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx);
1547                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx - 1);
1548
1549                                 g_ptr = &floor_ptr->grid_array[mon_fy - 2][mon_fx];
1550
1551                                 /* Radius 3 */
1552                                 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1553                                 {
1554                                         add_mon_lite(subject_ptr, mon_fy - 3, mon_fx + 1);
1555                                         add_mon_lite(subject_ptr, mon_fy - 3, mon_fx);
1556                                         add_mon_lite(subject_ptr, mon_fy - 3, mon_fx - 1);
1557                                 }
1558                         }
1559
1560                         /* East of the monster */
1561                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy, mon_fx + 1, f_flag))
1562                         {
1563                                 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 2);
1564                                 add_mon_lite(subject_ptr, mon_fy, mon_fx + 2);
1565                                 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 2);
1566
1567                                 g_ptr = &floor_ptr->grid_array[mon_fy][mon_fx + 2];
1568
1569                                 /* Radius 3 */
1570                                 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1571                                 {
1572                                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 3);
1573                                         add_mon_lite(subject_ptr, mon_fy, mon_fx + 3);
1574                                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 3);
1575                                 }
1576                         }
1577
1578                         /* West of the monster */
1579                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy, mon_fx - 1, f_flag))
1580                         {
1581                                 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 2);
1582                                 add_mon_lite(subject_ptr, mon_fy, mon_fx - 2);
1583                                 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 2);
1584
1585                                 g_ptr = &floor_ptr->grid_array[mon_fy][mon_fx - 2];
1586
1587                                 /* Radius 3 */
1588                                 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1589                                 {
1590                                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 3);
1591                                         add_mon_lite(subject_ptr, mon_fy, mon_fx - 3);
1592                                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 3);
1593                                 }
1594                         }
1595
1596                         /* Radius 3 */
1597                         if (rad != 3) continue;
1598
1599                         /* South-East of the monster */
1600                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx + 1, f_flag))
1601                         {
1602                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx + 2);
1603                         }
1604
1605                         /* South-West of the monster */
1606                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx - 1, f_flag))
1607                         {
1608                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx - 2);
1609                         }
1610
1611                         /* North-East of the monster */
1612                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx + 1, f_flag))
1613                         {
1614                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx + 2);
1615                         }
1616
1617                         /* North-West of the monster */
1618                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx - 1, f_flag))
1619                         {
1620                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx - 2);
1621                         }
1622                 }
1623         }
1624
1625         /* Save end of list of new squares */
1626         s16b end_temp = tmp_pos.n;
1627
1628         /*
1629          * Look at old set flags to see if there are any changes.
1630          */
1631         for (int i = 0; i < floor_ptr->mon_lite_n; i++)
1632         {
1633                 POSITION fx = floor_ptr->mon_lite_x[i];
1634                 POSITION fy = floor_ptr->mon_lite_y[i];
1635
1636                 grid_type *g_ptr;
1637                 g_ptr = &floor_ptr->grid_array[fy][fx];
1638
1639                 if (g_ptr->info & CAVE_TEMP) /* Pervious lit */
1640                 {
1641                         /* It it no longer lit? */
1642                         if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
1643                         {
1644                                 /* It is now unlit */
1645                                 /* Add it to later visual update */
1646                                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1647                         }
1648                 }
1649                 else /* Pervious darkened */
1650                 {
1651                         /* It it no longer darken? */
1652                         if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
1653                         {
1654                                 /* It is now undarken */
1655                                 /* Add it to later visual update */
1656                                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1657                         }
1658                 }
1659
1660                 /* Add to end of temp array */
1661                 tmp_pos.x[tmp_pos.n] = fx;
1662                 tmp_pos.y[tmp_pos.n] = fy;
1663                 tmp_pos.n++;
1664         }
1665
1666         /* Clear the lite array */
1667         floor_ptr->mon_lite_n = 0;
1668
1669         /* Copy the temp array into the lit array lighting the new squares. */
1670         for (int i = 0; i < end_temp; i++)
1671         {
1672                 POSITION fx = tmp_pos.x[i];
1673                 POSITION fy = tmp_pos.y[i];
1674
1675                 grid_type *g_ptr;
1676                 g_ptr = &floor_ptr->grid_array[fy][fx];
1677
1678                 if (g_ptr->info & CAVE_MNLT) /* Lit */
1679                 {
1680                         /* The is the square newly lit and visible? */
1681                         if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
1682                         {
1683                                 /* It is now lit */
1684                                 /* Add it to later visual update */
1685                                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1686                         }
1687                 }
1688                 else /* Darkened */
1689                 {
1690                         /* The is the square newly darkened and visible? */
1691                         if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
1692                         {
1693                                 /* It is now darkened */
1694                                 /* Add it to later visual update */
1695                                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1696                         }
1697                 }
1698
1699                 /* Save in the monster lit or darkened array */
1700                 floor_ptr->mon_lite_x[floor_ptr->mon_lite_n] = fx;
1701                 floor_ptr->mon_lite_y[floor_ptr->mon_lite_n] = fy;
1702                 floor_ptr->mon_lite_n++;
1703         }
1704
1705         /* Clear the temp flag for the old lit or darken grids */
1706         for (int i = end_temp; i < tmp_pos.n; i++)
1707         {
1708                 /* We trust this grid is in bounds */
1709
1710                 floor_ptr->grid_array[tmp_pos.y[i]][tmp_pos.x[i]].info &= ~(CAVE_TEMP | CAVE_XTRA);
1711         }
1712
1713         tmp_pos.n = 0;
1714
1715         /* Mega-Hack -- Visual update later */
1716         subject_ptr->update |= (PU_DELAY_VIS);
1717
1718         subject_ptr->monlite = (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_MNLT) ? TRUE : FALSE;
1719
1720         if (!(subject_ptr->special_defense & NINJA_S_STEALTH))
1721         {
1722                 subject_ptr->old_monlite = subject_ptr->monlite;
1723                 return;
1724         }
1725
1726         if (subject_ptr->old_monlite == subject_ptr->monlite)
1727         {
1728                 subject_ptr->old_monlite = subject_ptr->monlite;
1729                 return;
1730         }
1731
1732         if (subject_ptr->monlite)
1733         {
1734                 msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow becomes thin."));
1735         }
1736         else
1737         {
1738                 msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow is restored to its original darkness."));
1739         }
1740
1741         subject_ptr->old_monlite = subject_ptr->monlite;
1742 }
1743
1744
1745 void clear_mon_lite(floor_type *floor_ptr)
1746 {
1747         /* Clear all monster lit squares */
1748         for (int i = 0; i < floor_ptr->mon_lite_n; i++)
1749         {
1750                 /* Point to grid */
1751                 grid_type *g_ptr;
1752                 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
1753
1754                 /* Clear monster illumination flag */
1755                 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
1756         }
1757
1758         /* Empty the array */
1759         floor_ptr->mon_lite_n = 0;
1760 }