OSDN Git Service

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