OSDN Git Service

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