OSDN Git Service

[Refactor] #38997 anger_monster() にplayer_type * 引数を追加 / Added player_type * argument...
[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         /*** Save the old "lite" grids for later ***/
407
408         /* Clear them all */
409         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
410         for (int i = 0; i < floor_ptr->lite_n; i++)
411         {
412                 POSITION y = floor_ptr->lite_y[i];
413                 POSITION x = floor_ptr->lite_x[i];
414
415                 /* Mark the grid as not "lite" */
416                 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
417
418                 /* Mark the grid as "seen" */
419                 floor_ptr->grid_array[y][x].info |= (CAVE_TEMP);
420
421                 /* Add it to the "seen" set */
422                 tmp_pos.y[tmp_pos.n] = y;
423                 tmp_pos.x[tmp_pos.n] = x;
424                 tmp_pos.n++;
425         }
426
427         /* None left */
428         floor_ptr->lite_n = 0;
429
430
431         /*** Collect the new "lite" grids ***/
432
433         /* Radius 1 -- torch radius */
434         if (p >= 1)
435         {
436                 /* Player grid */
437                 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x);
438
439                 /* Adjacent grid */
440                 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x);
441                 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x);
442                 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 1);
443                 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 1);
444
445                 /* Diagonal grids */
446                 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1);
447                 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1);
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         }
451
452         /* Radius 2 -- lantern radius */
453         if (p >= 2)
454         {
455                 /* South of the player */
456                 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x))
457                 {
458                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x);
459                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 1);
460                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 1);
461                 }
462
463                 /* North of the player */
464                 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x))
465                 {
466                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x);
467                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 1);
468                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 1);
469                 }
470
471                 /* East of the player */
472                 if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x + 1))
473                 {
474                         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 2);
475                         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 2);
476                         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 2);
477                 }
478
479                 /* West of the player */
480                 if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x - 1))
481                 {
482                         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 2);
483                         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 2);
484                         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 2);
485                 }
486         }
487
488         /* Radius 3+ -- artifact radius */
489         if (p >= 3)
490         {
491                 int d;
492
493                 /* Paranoia -- see "LITE_MAX" */
494                 if (p > 14) p = 14;
495
496                 /* South-East of the player */
497                 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1))
498                 {
499                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 2);
500                 }
501
502                 /* South-West of the player */
503                 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1))
504                 {
505                         cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 2);
506                 }
507
508                 /* North-East of the player */
509                 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1))
510                 {
511                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 2);
512                 }
513
514                 /* North-West of the player */
515                 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1))
516                 {
517                         cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 2);
518                 }
519
520                 /* Maximal north */
521                 POSITION min_y = subject_ptr->y - p;
522                 if (min_y < 0) min_y = 0;
523
524                 /* Maximal south */
525                 POSITION max_y = subject_ptr->y + p;
526                 if (max_y > floor_ptr->height - 1) max_y = floor_ptr->height - 1;
527
528                 /* Maximal west */
529                 POSITION min_x = subject_ptr->x - p;
530                 if (min_x < 0) min_x = 0;
531
532                 /* Maximal east */
533                 POSITION max_x = subject_ptr->x + p;
534                 if (max_x > floor_ptr->width - 1) max_x = floor_ptr->width - 1;
535
536                 /* Scan the maximal box */
537                 for (POSITION y = min_y; y <= max_y; y++)
538                 {
539                         for (POSITION x = min_x; x <= max_x; x++)
540                         {
541                                 int dy = (subject_ptr->y > y) ? (subject_ptr->y - y) : (y - subject_ptr->y);
542                                 int dx = (subject_ptr->x > x) ? (subject_ptr->x - x) : (x - subject_ptr->x);
543
544                                 /* Skip the "central" grids (above) */
545                                 if ((dy <= 2) && (dx <= 2)) continue;
546
547                                 /* Hack -- approximate the distance */
548                                 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
549
550                                 /* Skip distant grids */
551                                 if (d > p) continue;
552
553                                 /* Viewable, nearby, grids get "torch lit" */
554                                 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW)
555                                 {
556                                         /* This grid is "torch lit" */
557                                         cave_lite_hack(floor_ptr, y, x);
558                                 }
559                         }
560                 }
561         }
562
563
564         /*** Complete the algorithm ***/
565
566         /* Draw the new grids */
567         for (int i = 0; i < floor_ptr->lite_n; i++)
568         {
569                 POSITION y = floor_ptr->lite_y[i];
570                 POSITION x = floor_ptr->lite_x[i];
571
572                 g_ptr = &floor_ptr->grid_array[y][x];
573
574                 /* Update fresh grids */
575                 if (g_ptr->info & (CAVE_TEMP)) continue;
576
577                 /* Add it to later visual update */
578                 cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
579         }
580
581         /* Clear them all */
582         for (int i = 0; i < tmp_pos.n; i++)
583         {
584                 POSITION y = tmp_pos.y[i];
585                 POSITION x = tmp_pos.x[i];
586
587                 g_ptr = &floor_ptr->grid_array[y][x];
588
589                 /* No longer in the array */
590                 g_ptr->info &= ~(CAVE_TEMP);
591
592                 /* Update stale grids */
593                 if (g_ptr->info & (CAVE_LITE)) continue;
594
595                 /* Add it to later visual update */
596                 cave_redraw_later(floor_ptr, g_ptr, y, x);
597         }
598
599         tmp_pos.n = 0;
600         subject_ptr->update |= (PU_DELAY_VIS);
601 }
602
603
604 /*
605  * Clear the viewable space
606  */
607 void forget_view(floor_type *floor_ptr)
608 {
609         /* None to forget */
610         if (!floor_ptr->view_n) return;
611
612         /* Clear them all */
613         for (int i = 0; i < floor_ptr->view_n; i++)
614         {
615                 POSITION y = floor_ptr->view_y[i];
616                 POSITION x = floor_ptr->view_x[i];
617                 grid_type *g_ptr;
618                 g_ptr = &floor_ptr->grid_array[y][x];
619
620                 /* Forget that the grid is viewable */
621                 g_ptr->info &= ~(CAVE_VIEW);
622         }
623
624         floor_ptr->view_n = 0;
625 }
626
627
628 /*
629  * Helper function for "update_view()" below
630  *
631  * We are checking the "viewability" of grid (y,x) by the player.
632  *
633  * This function assumes that (y,x) is legal (i.e. on the map).
634  *
635  * Grid (y1,x1) is on the "diagonal" between (subject_ptr->y,subject_ptr->x) and (y,x)
636  * Grid (y2,x2) is "adjacent", also between (subject_ptr->y,subject_ptr->x) and (y,x).
637  *
638  * Note that we are using the "CAVE_XTRA" field for marking grids as
639  * "easily viewable".  This bit is cleared at the end of "update_view()".
640  *
641  * This function adds (y,x) to the "viewable set" if necessary.
642  *
643  * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
644  */
645 static bool update_view_aux(player_type *subject_ptr, POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
646 {
647         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
648         grid_type *g1_c_ptr;
649         grid_type *g2_c_ptr;
650         g1_c_ptr = &floor_ptr->grid_array[y1][x1];
651         g2_c_ptr = &floor_ptr->grid_array[y2][x2];
652
653         /* Check for walls */
654         bool f1 = (cave_los_grid(g1_c_ptr));
655         bool f2 = (cave_los_grid(g2_c_ptr));
656
657         /* Totally blocked by physical walls */
658         if (!f1 && !f2) return TRUE;
659
660         /* Check for visibility */
661         bool v1 = (f1 && (g1_c_ptr->info & (CAVE_VIEW)));
662         bool v2 = (f2 && (g2_c_ptr->info & (CAVE_VIEW)));
663
664         /* Totally blocked by "unviewable neighbors" */
665         if (!v1 && !v2) return TRUE;
666
667         grid_type *g_ptr;
668         g_ptr = &floor_ptr->grid_array[y][x];
669
670         /* Check for walls */
671         bool wall = (!cave_los_grid(g_ptr));
672
673         /* Check the "ease" of visibility */
674         bool z1 = (v1 && (g1_c_ptr->info & (CAVE_XTRA)));
675         bool z2 = (v2 && (g2_c_ptr->info & (CAVE_XTRA)));
676
677         /* Hack -- "easy" plus "easy" yields "easy" */
678         if (z1 && z2)
679         {
680                 g_ptr->info |= (CAVE_XTRA);
681                 cave_view_hack(floor_ptr, g_ptr, y, x);
682                 return wall;
683         }
684
685         /* Hack -- primary "easy" yields "viewed" */
686         if (z1)
687         {
688                 cave_view_hack(floor_ptr, g_ptr, y, x);
689                 return wall;
690         }
691
692         /* Hack -- "view" plus "view" yields "view" */
693         if (v1 && v2)
694         {
695                 cave_view_hack(floor_ptr, g_ptr, y, x);
696                 return wall;
697         }
698
699         /* Mega-Hack -- the "los()" function works poorly on walls */
700         if (wall)
701         {
702                 cave_view_hack(floor_ptr, g_ptr, y, x);
703                 return wall;
704         }
705
706         /* Hack -- check line of sight */
707         if (los(subject_ptr, subject_ptr->y, subject_ptr->x, y, x))
708         {
709                 cave_view_hack(floor_ptr, g_ptr, y, x);
710                 return wall;
711         }
712
713         return TRUE;
714 }
715
716
717 /*
718  * Calculate the viewable space
719  *
720  *  1: Process the player
721  *  1a: The player is always (easily) viewable
722  *  2: Process the diagonals
723  *  2a: The diagonals are (easily) viewable up to the first wall
724  *  2b: But never go more than 2/3 of the "full" distance
725  *  3: Process the main axes
726  *  3a: The main axes are (easily) viewable up to the first wall
727  *  3b: But never go more than the "full" distance
728  *  4: Process sequential "strips" in each of the eight octants
729  *  4a: Each strip runs along the previous strip
730  *  4b: The main axes are "previous" to the first strip
731  *  4c: Process both "sides" of each "direction" of each strip
732  *  4c1: Each side aborts as soon as possible
733  *  4c2: Each side tells the next strip how far it has to check
734  *
735  * Note that the octant processing involves some pretty interesting
736  * observations involving when a grid might possibly be viewable from
737  * a given grid, and on the order in which the strips are processed.
738  *
739  * Note the use of the mathematical facts shown below, which derive
740  * from the fact that (1 < sqrt(2) < 1.5), and that the length of the
741  * hypotenuse of a right triangle is primarily determined by the length
742  * of the longest side, when one side is small, and is strictly less
743  * than one-and-a-half times as long as the longest side when both of
744  * the sides are large.
745  *
746  *   if (manhatten(dy,dx) < R) then (hypot(dy,dx) < R)
747  *   if (manhatten(dy,dx) > R*3/2) then (hypot(dy,dx) > R)
748  *
749  *   hypot(dy,dx) is approximated by (dx+dy+MAX(dx,dy)) / 2
750  *
751  * These observations are important because the calculation of the actual
752  * value of "hypot(dx,dy)" is extremely expensive, involving square roots,
753  * while for small values (up to about 20 or so), the approximations above
754  * are correct to within an error of at most one grid or so.
755  *
756  * Observe the use of "full" and "over" in the code below, and the use of
757  * the specialized calculation involving "limit", all of which derive from
758  * the observations given above.  Basically, we note that the "circle" of
759  * view is completely contained in an "octagon" whose bounds are easy to
760  * determine, and that only a few steps are needed to derive the actual
761  * bounds of the circle given the bounds of the octagon.
762  *
763  * Note that by skipping all the grids in the corners of the octagon, we
764  * place an upper limit on the number of grids in the field of view, given
765  * that "full" is never more than 20.  Of the 1681 grids in the "square" of
766  * view, only about 1475 of these are in the "octagon" of view, and even
767  * fewer are in the "circle" of view, so 1500 or 1536 is more than enough
768  * entries to completely contain the actual field of view.
769  *
770  * Note also the care taken to prevent "running off the map".  The use of
771  * explicit checks on the "validity" of the "diagonal", and the fact that
772  * the loops are never allowed to "leave" the map, lets "update_view_aux()"
773  * use the optimized "cave_los_bold()" macro, and to avoid the overhead
774  * of multiple checks on the validity of grids.
775  *
776  * Note the "optimizations" involving the "se","sw","ne","nw","es","en",
777  * "ws","wn" variables.  They work like this: While travelling down the
778  * south-bound strip just to the east of the main south axis, as soon as
779  * we get to a grid which does not "transmit" viewing, if all of the strips
780  * preceding us (in this case, just the main axis) had terminated at or before
781  * the same point, then we can stop, and reset the "max distance" to ourself.
782  * So, each strip (named by major axis plus offset, thus "se" in this case)
783  * maintains a "blockage" variable, initialized during the main axis step,
784  * and checks it whenever a blockage is observed.  After processing each
785  * strip as far as the previous strip told us to process, the next strip is
786  * told not to go farther than the current strip's farthest viewable grid,
787  * unless open space is still available.  This uses the "k" variable.
788  *
789  * Note the use of "inline" macros for efficiency.  The "cave_los_grid()"
790  * macro is a replacement for "cave_los_bold()" which takes a pointer to
791  * a grid instead of its location.  The "cave_view_hack()" macro is a
792  * chunk of code which adds the given location to the "view" array if it
793  * is not already there, using both the actual location and a pointer to
794  * the grid.  See above.
795  *
796  * By the way, the purpose of this code is to reduce the dependancy on the
797  * "los()" function which is slow, and, in some cases, not very accurate.
798  *
799  * It is very possible that I am the only person who fully understands this
800  * function, and for that I am truly sorry, but efficiency was very important
801  * and the "simple" version of this function was just not fast enough.  I am
802  * more than willing to replace this function with a simpler one, if it is
803  * equally efficient, and especially willing if the new function happens to
804  * derive "reverse-line-of-sight" at the same time, since currently monsters
805  * just use an optimized hack of "you see me, so I see you", and then use the
806  * actual "projectable()" function to check spell attacks.
807  */
808 void update_view(player_type *subject_ptr, floor_type *floor_ptr)
809 {
810         int n, m, d, k, z;
811         POSITION y, x;
812
813         int se, sw, ne, nw, es, en, ws, wn;
814
815         int full, over;
816
817         POSITION y_max = floor_ptr->height - 1;
818         POSITION x_max = floor_ptr->width - 1;
819
820         grid_type *g_ptr;
821
822         /*** Initialize ***/
823
824         /* Optimize */
825         if (view_reduce_view && !floor_ptr->dun_level)
826         {
827                 /* Full radius (10) */
828                 full = MAX_SIGHT / 2;
829
830                 /* Octagon factor (15) */
831                 over = MAX_SIGHT * 3 / 4;
832         }
833
834         /* Normal */
835         else
836         {
837                 /* Full radius (20) */
838                 full = MAX_SIGHT;
839
840                 /* Octagon factor (30) */
841                 over = MAX_SIGHT * 3 / 2;
842         }
843
844
845         /*** Step 0 -- Begin ***/
846
847         /* Save the old "view" grids for later */
848         for (n = 0; n < floor_ptr->view_n; n++)
849         {
850                 y = floor_ptr->view_y[n];
851                 x = floor_ptr->view_x[n];
852                 g_ptr = &floor_ptr->grid_array[y][x];
853
854                 /* Mark the grid as not in "view" */
855                 g_ptr->info &= ~(CAVE_VIEW);
856
857                 /* Mark the grid as "seen" */
858                 g_ptr->info |= (CAVE_TEMP);
859
860                 /* Add it to the "seen" set */
861                 tmp_pos.y[tmp_pos.n] = y;
862                 tmp_pos.x[tmp_pos.n] = x;
863                 tmp_pos.n++;
864         }
865
866         /* Start over with the "view" array */
867         floor_ptr->view_n = 0;
868
869         /*** Step 1 -- adjacent grids ***/
870
871         /* Now start on the player */
872         y = subject_ptr->y;
873         x = subject_ptr->x;
874         g_ptr = &floor_ptr->grid_array[y][x];
875
876         /* Assume the player grid is easily viewable */
877         g_ptr->info |= (CAVE_XTRA);
878
879         /* Assume the player grid is viewable */
880         cave_view_hack(floor_ptr, g_ptr, y, x);
881
882
883         /*** Step 2 -- Major Diagonals ***/
884
885         /* Hack -- Limit */
886         z = full * 2 / 3;
887
888         /* Scan south-east */
889         for (d = 1; d <= z; d++)
890         {
891                 g_ptr = &floor_ptr->grid_array[y + d][x + d];
892                 g_ptr->info |= (CAVE_XTRA);
893                 cave_view_hack(floor_ptr, g_ptr, y + d, x + d);
894                 if (!cave_los_grid(g_ptr)) break;
895         }
896
897         /* Scan south-west */
898         for (d = 1; d <= z; d++)
899         {
900                 g_ptr = &floor_ptr->grid_array[y + d][x - d];
901                 g_ptr->info |= (CAVE_XTRA);
902                 cave_view_hack(floor_ptr, g_ptr, y + d, x - d);
903                 if (!cave_los_grid(g_ptr)) break;
904         }
905
906         /* Scan north-east */
907         for (d = 1; d <= z; d++)
908         {
909                 g_ptr = &floor_ptr->grid_array[y - d][x + d];
910                 g_ptr->info |= (CAVE_XTRA);
911                 cave_view_hack(floor_ptr, g_ptr, y - d, x + d);
912                 if (!cave_los_grid(g_ptr)) break;
913         }
914
915         /* Scan north-west */
916         for (d = 1; d <= z; d++)
917         {
918                 g_ptr = &floor_ptr->grid_array[y - d][x - d];
919                 g_ptr->info |= (CAVE_XTRA);
920                 cave_view_hack(floor_ptr, g_ptr, y - d, x - d);
921                 if (!cave_los_grid(g_ptr)) break;
922         }
923
924         /*** Step 3 -- major axes ***/
925
926         /* Scan south */
927         for (d = 1; d <= full; d++)
928         {
929                 g_ptr = &floor_ptr->grid_array[y + d][x];
930                 g_ptr->info |= (CAVE_XTRA);
931                 cave_view_hack(floor_ptr, g_ptr, y + d, x);
932                 if (!cave_los_grid(g_ptr)) break;
933         }
934
935         /* Initialize the "south strips" */
936         se = sw = d;
937
938         /* Scan north */
939         for (d = 1; d <= full; d++)
940         {
941                 g_ptr = &floor_ptr->grid_array[y - d][x];
942                 g_ptr->info |= (CAVE_XTRA);
943                 cave_view_hack(floor_ptr, g_ptr, y - d, x);
944                 if (!cave_los_grid(g_ptr)) break;
945         }
946
947         /* Initialize the "north strips" */
948         ne = nw = d;
949
950         /* Scan east */
951         for (d = 1; d <= full; d++)
952         {
953                 g_ptr = &floor_ptr->grid_array[y][x + d];
954                 g_ptr->info |= (CAVE_XTRA);
955                 cave_view_hack(floor_ptr, g_ptr, y, x + d);
956                 if (!cave_los_grid(g_ptr)) break;
957         }
958
959         /* Initialize the "east strips" */
960         es = en = d;
961
962         /* Scan west */
963         for (d = 1; d <= full; d++)
964         {
965                 g_ptr = &floor_ptr->grid_array[y][x - d];
966                 g_ptr->info |= (CAVE_XTRA);
967                 cave_view_hack(floor_ptr, g_ptr, y, x - d);
968                 if (!cave_los_grid(g_ptr)) break;
969         }
970
971         /* Initialize the "west strips" */
972         ws = wn = d;
973
974
975         /*** Step 4 -- Divide each "octant" into "strips" ***/
976
977         /* Now check each "diagonal" (in parallel) */
978         for (n = 1; n <= over / 2; n++)
979         {
980                 POSITION ypn, ymn, xpn, xmn;
981
982                 /* Acquire the "bounds" of the maximal circle */
983                 z = over - n - n;
984                 if (z > full - n) z = full - n;
985                 while ((z + n + (n >> 1)) > full) z--;
986
987                 /* Access the four diagonal grids */
988                 ypn = y + n;
989                 ymn = y - n;
990                 xpn = x + n;
991                 xmn = x - n;
992
993                 /* South strip */
994                 if (ypn < y_max)
995                 {
996                         /* Maximum distance */
997                         m = MIN(z, y_max - ypn);
998
999                         /* East side */
1000                         if ((xpn <= x_max) && (n < se))
1001                         {
1002                                 /* Scan */
1003                                 for (k = n, d = 1; d <= m; d++)
1004                                 {
1005                                         /* Check grid "d" in strip "n", notice "blockage" */
1006                                         if (update_view_aux(subject_ptr, ypn + d, xpn, ypn + d - 1, xpn - 1, ypn + d - 1, xpn))
1007                                         {
1008                                                 if (n + d >= se) break;
1009                                         }
1010
1011                                         /* Track most distant "non-blockage" */
1012                                         else
1013                                         {
1014                                                 k = n + d;
1015                                         }
1016                                 }
1017
1018                                 /* Limit the next strip */
1019                                 se = k + 1;
1020                         }
1021
1022                         /* West side */
1023                         if ((xmn >= 0) && (n < sw))
1024                         {
1025                                 /* Scan */
1026                                 for (k = n, d = 1; d <= m; d++)
1027                                 {
1028                                         /* Check grid "d" in strip "n", notice "blockage" */
1029                                         if (update_view_aux(subject_ptr, ypn + d, xmn, ypn + d - 1, xmn + 1, ypn + d - 1, xmn))
1030                                         {
1031                                                 if (n + d >= sw) break;
1032                                         }
1033
1034                                         /* Track most distant "non-blockage" */
1035                                         else
1036                                         {
1037                                                 k = n + d;
1038                                         }
1039                                 }
1040
1041                                 /* Limit the next strip */
1042                                 sw = k + 1;
1043                         }
1044                 }
1045
1046                 /* North strip */
1047                 if (ymn > 0)
1048                 {
1049                         /* Maximum distance */
1050                         m = MIN(z, ymn);
1051
1052                         /* East side */
1053                         if ((xpn <= x_max) && (n < ne))
1054                         {
1055                                 /* Scan */
1056                                 for (k = n, d = 1; d <= m; d++)
1057                                 {
1058                                         /* Check grid "d" in strip "n", notice "blockage" */
1059                                         if (update_view_aux(subject_ptr, ymn - d, xpn, ymn - d + 1, xpn - 1, ymn - d + 1, xpn))
1060                                         {
1061                                                 if (n + d >= ne) break;
1062                                         }
1063
1064                                         /* Track most distant "non-blockage" */
1065                                         else
1066                                         {
1067                                                 k = n + d;
1068                                         }
1069                                 }
1070
1071                                 /* Limit the next strip */
1072                                 ne = k + 1;
1073                         }
1074
1075                         /* West side */
1076                         if ((xmn >= 0) && (n < nw))
1077                         {
1078                                 /* Scan */
1079                                 for (k = n, d = 1; d <= m; d++)
1080                                 {
1081                                         /* Check grid "d" in strip "n", notice "blockage" */
1082                                         if (update_view_aux(subject_ptr, ymn - d, xmn, ymn - d + 1, xmn + 1, ymn - d + 1, xmn))
1083                                         {
1084                                                 if (n + d >= nw) break;
1085                                         }
1086
1087                                         /* Track most distant "non-blockage" */
1088                                         else
1089                                         {
1090                                                 k = n + d;
1091                                         }
1092                                 }
1093
1094                                 /* Limit the next strip */
1095                                 nw = k + 1;
1096                         }
1097                 }
1098
1099                 /* East strip */
1100                 if (xpn < x_max)
1101                 {
1102                         /* Maximum distance */
1103                         m = MIN(z, x_max - xpn);
1104
1105                         /* South side */
1106                         if ((ypn <= x_max) && (n < es))
1107                         {
1108                                 /* Scan */
1109                                 for (k = n, d = 1; d <= m; d++)
1110                                 {
1111                                         /* Check grid "d" in strip "n", notice "blockage" */
1112                                         if (update_view_aux(subject_ptr, ypn, xpn + d, ypn - 1, xpn + d - 1, ypn, xpn + d - 1))
1113                                         {
1114                                                 if (n + d >= es) break;
1115                                         }
1116
1117                                         /* Track most distant "non-blockage" */
1118                                         else
1119                                         {
1120                                                 k = n + d;
1121                                         }
1122                                 }
1123
1124                                 /* Limit the next strip */
1125                                 es = k + 1;
1126                         }
1127
1128                         /* North side */
1129                         if ((ymn >= 0) && (n < en))
1130                         {
1131                                 /* Scan */
1132                                 for (k = n, d = 1; d <= m; d++)
1133                                 {
1134                                         /* Check grid "d" in strip "n", notice "blockage" */
1135                                         if (update_view_aux(subject_ptr, ymn, xpn + d, ymn + 1, xpn + d - 1, ymn, xpn + d - 1))
1136                                         {
1137                                                 if (n + d >= en) break;
1138                                         }
1139
1140                                         /* Track most distant "non-blockage" */
1141                                         else
1142                                         {
1143                                                 k = n + d;
1144                                         }
1145                                 }
1146
1147                                 /* Limit the next strip */
1148                                 en = k + 1;
1149                         }
1150                 }
1151
1152                 /* West strip */
1153                 if (xmn > 0)
1154                 {
1155                         /* Maximum distance */
1156                         m = MIN(z, xmn);
1157
1158                         /* South side */
1159                         if ((ypn <= y_max) && (n < ws))
1160                         {
1161                                 /* Scan */
1162                                 for (k = n, d = 1; d <= m; d++)
1163                                 {
1164                                         /* Check grid "d" in strip "n", notice "blockage" */
1165                                         if (update_view_aux(subject_ptr, ypn, xmn - d, ypn - 1, xmn - d + 1, ypn, xmn - d + 1))
1166                                         {
1167                                                 if (n + d >= ws) break;
1168                                         }
1169
1170                                         /* Track most distant "non-blockage" */
1171                                         else
1172                                         {
1173                                                 k = n + d;
1174                                         }
1175                                 }
1176
1177                                 /* Limit the next strip */
1178                                 ws = k + 1;
1179                         }
1180
1181                         /* North side */
1182                         if ((ymn >= 0) && (n < wn))
1183                         {
1184                                 /* Scan */
1185                                 for (k = n, d = 1; d <= m; d++)
1186                                 {
1187                                         /* Check grid "d" in strip "n", notice "blockage" */
1188                                         if (update_view_aux(subject_ptr, ymn, xmn - d, ymn + 1, xmn - d + 1, ymn, xmn - d + 1))
1189                                         {
1190                                                 if (n + d >= wn) break;
1191                                         }
1192
1193                                         /* Track most distant "non-blockage" */
1194                                         else
1195                                         {
1196                                                 k = n + d;
1197                                         }
1198                                 }
1199
1200                                 /* Limit the next strip */
1201                                 wn = k + 1;
1202                         }
1203                 }
1204         }
1205
1206         /*** Step 5 -- Complete the algorithm ***/
1207
1208         /* Update all the new grids */
1209         for (n = 0; n < floor_ptr->view_n; n++)
1210         {
1211                 y = floor_ptr->view_y[n];
1212                 x = floor_ptr->view_x[n];
1213                 g_ptr = &floor_ptr->grid_array[y][x];
1214
1215                 /* Clear the "CAVE_XTRA" flag */
1216                 g_ptr->info &= ~(CAVE_XTRA);
1217
1218                 /* Update only newly viewed grids */
1219                 if (g_ptr->info & (CAVE_TEMP)) continue;
1220
1221                 /* Add it to later visual update */
1222                 cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
1223         }
1224
1225         /* Wipe the old grids, update as needed */
1226         for (n = 0; n < tmp_pos.n; n++)
1227         {
1228                 y = tmp_pos.y[n];
1229                 x = tmp_pos.x[n];
1230                 g_ptr = &floor_ptr->grid_array[y][x];
1231
1232                 /* No longer in the array */
1233                 g_ptr->info &= ~(CAVE_TEMP);
1234
1235                 /* Update only non-viewable grids */
1236                 if (g_ptr->info & (CAVE_VIEW)) continue;
1237
1238                 /* Add it to later visual update */
1239                 cave_redraw_later(floor_ptr, g_ptr, y, x);
1240         }
1241
1242         tmp_pos.n = 0;
1243         subject_ptr->update |= (PU_DELAY_VIS);
1244 }
1245
1246
1247 /*!
1248  * @brief モンスターによる光量状態更新 / Add a square to the changes array
1249  * @param subject_ptr 主観となるクリーチャーの参照ポインタ
1250  * @param y Y座標
1251  * @param x X座標
1252  */
1253 static void mon_lite_hack(player_type *subject_ptr, POSITION y, POSITION x)
1254 {
1255         grid_type *g_ptr;
1256         int dpf, d;
1257         POSITION midpoint;
1258
1259         /* We trust this grid is in bounds */
1260         /* if (!in_bounds2(y, x)) return; */
1261
1262         g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
1263
1264         /* Want a unlit square in view of the player */
1265         if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW) return;
1266
1267         if (!cave_los_grid(g_ptr))
1268         {
1269                 /* Hack -- Prevent monster lite leakage in walls */
1270
1271                 /* Horizontal walls between player and a monster */
1272                 if (((y < subject_ptr->y) && (y > mon_fy)) || ((y > subject_ptr->y) && (y < mon_fy)))
1273                 {
1274                         dpf = subject_ptr->y - mon_fy;
1275                         d = y - mon_fy;
1276                         midpoint = mon_fx + ((subject_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
1277
1278                         /* Only first wall viewed from mid-x is lit */
1279                         if (x < midpoint)
1280                         {
1281                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1)) return;
1282                         }
1283                         else if (x > midpoint)
1284                         {
1285                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1)) return;
1286                         }
1287
1288                         /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1289                         else if (mon_invis) return;
1290                 }
1291
1292                 /* Vertical walls between player and a monster */
1293                 if (((x < subject_ptr->x) && (x > mon_fx)) || ((x > subject_ptr->x) && (x < mon_fx)))
1294                 {
1295                         dpf = subject_ptr->x - mon_fx;
1296                         d = x - mon_fx;
1297                         midpoint = mon_fy + ((subject_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
1298
1299                         /* Only first wall viewed from mid-y is lit */
1300                         if (y < midpoint)
1301                         {
1302                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x)) return;
1303                         }
1304                         else if (y > midpoint)
1305                         {
1306                                 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x)) return;
1307                         }
1308
1309                         /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1310                         else if (mon_invis) return;
1311                 }
1312         }
1313
1314         /* We trust tmp_pos.n does not exceed TEMP_MAX */
1315
1316         /* New grid */
1317         if (!(g_ptr->info & CAVE_MNDK))
1318         {
1319                 /* Save this square */
1320                 tmp_pos.x[tmp_pos.n] = x;
1321                 tmp_pos.y[tmp_pos.n] = y;
1322                 tmp_pos.n++;
1323         }
1324
1325         /* Darkened grid */
1326         else
1327         {
1328                 /* No longer dark */
1329                 g_ptr->info &= ~(CAVE_MNDK);
1330         }
1331
1332         /* Light it */
1333         g_ptr->info |= CAVE_MNLT;
1334 }
1335
1336
1337 /*
1338  * Add a square to the changes array
1339  */
1340 static void mon_dark_hack(player_type *subject_ptr, POSITION y, POSITION x)
1341 {
1342         grid_type *g_ptr;
1343         int midpoint, dpf, d;
1344
1345         /* We trust this grid is in bounds */
1346         /* if (!in_bounds2(y, x)) return; */
1347
1348         g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
1349
1350         /* Want a unlit and undarkened square in view of the player */
1351         if ((g_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW) return;
1352
1353         if (!cave_los_grid(g_ptr) && !cave_have_flag_grid(g_ptr, FF_PROJECT))
1354         {
1355                 /* Hack -- Prevent monster dark lite leakage in walls */
1356
1357                 /* Horizontal walls between player and a monster */
1358                 if (((y < subject_ptr->y) && (y > mon_fy)) || ((y > subject_ptr->y) && (y < mon_fy)))
1359                 {
1360                         dpf = subject_ptr->y - mon_fy;
1361                         d = y - mon_fy;
1362                         midpoint = mon_fx + ((subject_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
1363
1364                         /* Only first wall viewed from mid-x is lit */
1365                         if (x < midpoint)
1366                         {
1367                                 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;
1368                         }
1369                         else if (x > midpoint)
1370                         {
1371                                 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;
1372                         }
1373
1374                         /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1375                         else if (mon_invis) return;
1376                 }
1377
1378                 /* Vertical walls between player and a monster */
1379                 if (((x < subject_ptr->x) && (x > mon_fx)) || ((x > subject_ptr->x) && (x < mon_fx)))
1380                 {
1381                         dpf = subject_ptr->x - mon_fx;
1382                         d = x - mon_fx;
1383                         midpoint = mon_fy + ((subject_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
1384
1385                         /* Only first wall viewed from mid-y is lit */
1386                         if (y < midpoint)
1387                         {
1388                                 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;
1389                         }
1390                         else if (y > midpoint)
1391                         {
1392                                 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;
1393                         }
1394
1395                         /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1396                         else if (mon_invis) return;
1397                 }
1398         }
1399
1400         /* We trust tmp_pos.n does not exceed TEMP_MAX */
1401
1402         /* Save this square */
1403         tmp_pos.x[tmp_pos.n] = x;
1404         tmp_pos.y[tmp_pos.n] = y;
1405         tmp_pos.n++;
1406
1407         /* Darken it */
1408         g_ptr->info |= CAVE_MNDK;
1409 }
1410
1411
1412 /*
1413  * Update squares illuminated or darkened by monsters.
1414  *
1415  * Hack - use the CAVE_ROOM flag (renamed to be CAVE_MNLT) to
1416  * denote squares illuminated by monsters.
1417  *
1418  * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
1419  * updating.  Only squares in view of the player, whos state
1420  * changes are drawn via lite_spot().
1421  */
1422 void update_mon_lite(player_type *subject_ptr)
1423 {
1424         void(*add_mon_lite)(player_type *, POSITION, POSITION);
1425
1426         /* Non-Ninja player in the darkness */
1427         int dis_lim = ((d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !subject_ptr->see_nocto) ?
1428                 (MAX_SIGHT / 2 + 1) : (MAX_SIGHT + 3);
1429
1430         /* Clear all monster lit squares */
1431         floor_type *floor_ptr = subject_ptr->current_floor_ptr;
1432         for (int i = 0; i < floor_ptr->mon_lite_n; i++)
1433         {
1434                 grid_type *g_ptr;
1435                 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
1436
1437                 /* Set temp or xtra flag */
1438                 g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
1439
1440                 /* Clear monster illumination flag */
1441                 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
1442         }
1443
1444         /* Empty temp list of new squares to lite up */
1445         tmp_pos.n = 0;
1446
1447         /* If a monster stops time, don't process */
1448         if (!current_world_ptr->timewalk_m_idx)
1449         {
1450                 monster_type *m_ptr;
1451                 monster_race *r_ptr;
1452
1453                 /* Loop through monsters, adding newly lit squares to changes list */
1454                 for (int i = 1; i < floor_ptr->m_max; i++)
1455                 {
1456                         m_ptr = &floor_ptr->m_list[i];
1457                         r_ptr = &r_info[m_ptr->r_idx];
1458                         if (!monster_is_valid(m_ptr)) continue;
1459
1460                         /* Is it too far away? */
1461                         if (m_ptr->cdis > dis_lim) continue;
1462
1463                         /* Get lite radius */
1464                         int rad = 0;
1465
1466                         /* Note the radii are cumulative */
1467                         if (r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_SELF_LITE_1)) rad++;
1468                         if (r_ptr->flags7 & (RF7_HAS_LITE_2 | RF7_SELF_LITE_2)) rad += 2;
1469                         if (r_ptr->flags7 & (RF7_HAS_DARK_1 | RF7_SELF_DARK_1)) rad--;
1470                         if (r_ptr->flags7 & (RF7_HAS_DARK_2 | RF7_SELF_DARK_2)) rad -= 2;
1471
1472                         /* Exit if has no light */
1473                         if (!rad) continue;
1474
1475                         int f_flag;
1476                         if (rad > 0)
1477                         {
1478                                 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;
1479                                 if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) rad = 1;
1480                                 add_mon_lite = mon_lite_hack;
1481                                 f_flag = FF_LOS;
1482                         }
1483                         else
1484                         {
1485                                 if (!(r_ptr->flags7 & (RF7_SELF_DARK_1 | RF7_SELF_DARK_2)) && (MON_CSLEEP(m_ptr) || (!floor_ptr->dun_level && !is_daytime()))) continue;
1486                                 add_mon_lite = mon_dark_hack;
1487                                 f_flag = FF_PROJECT;
1488                                 rad = -rad; /* Use absolute value */
1489                         }
1490
1491                         mon_fx = m_ptr->fx;
1492                         mon_fy = m_ptr->fy;
1493
1494                         /* Is the monster visible? */
1495                         mon_invis = !(floor_ptr->grid_array[mon_fy][mon_fx].info & CAVE_VIEW);
1496
1497                         /* The square it is on */
1498                         add_mon_lite(subject_ptr, mon_fy, mon_fx);
1499
1500                         /* Adjacent squares */
1501                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx);
1502                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx);
1503                         add_mon_lite(subject_ptr, mon_fy, mon_fx + 1);
1504                         add_mon_lite(subject_ptr, mon_fy, mon_fx - 1);
1505                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 1);
1506                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 1);
1507                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 1);
1508                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 1);
1509
1510                         /* Radius 2 */
1511                         if (rad < 2) continue;
1512
1513                         /* South of the monster */
1514                         grid_type *g_ptr;
1515                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx, f_flag))
1516                         {
1517                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx + 1);
1518                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx);
1519                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx - 1);
1520
1521                                 g_ptr = &floor_ptr->grid_array[mon_fy + 2][mon_fx];
1522
1523                                 /* Radius 3 */
1524                                 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1525                                 {
1526                                         add_mon_lite(subject_ptr, mon_fy + 3, mon_fx + 1);
1527                                         add_mon_lite(subject_ptr, mon_fy + 3, mon_fx);
1528                                         add_mon_lite(subject_ptr, mon_fy + 3, mon_fx - 1);
1529                                 }
1530                         }
1531
1532                         /* North of the monster */
1533                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx, f_flag))
1534                         {
1535                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx + 1);
1536                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx);
1537                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx - 1);
1538
1539                                 g_ptr = &floor_ptr->grid_array[mon_fy - 2][mon_fx];
1540
1541                                 /* Radius 3 */
1542                                 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1543                                 {
1544                                         add_mon_lite(subject_ptr, mon_fy - 3, mon_fx + 1);
1545                                         add_mon_lite(subject_ptr, mon_fy - 3, mon_fx);
1546                                         add_mon_lite(subject_ptr, mon_fy - 3, mon_fx - 1);
1547                                 }
1548                         }
1549
1550                         /* East of the monster */
1551                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy, mon_fx + 1, f_flag))
1552                         {
1553                                 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 2);
1554                                 add_mon_lite(subject_ptr, mon_fy, mon_fx + 2);
1555                                 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 2);
1556
1557                                 g_ptr = &floor_ptr->grid_array[mon_fy][mon_fx + 2];
1558
1559                                 /* Radius 3 */
1560                                 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1561                                 {
1562                                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 3);
1563                                         add_mon_lite(subject_ptr, mon_fy, mon_fx + 3);
1564                                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 3);
1565                                 }
1566                         }
1567
1568                         /* West of the monster */
1569                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy, mon_fx - 1, f_flag))
1570                         {
1571                                 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 2);
1572                                 add_mon_lite(subject_ptr, mon_fy, mon_fx - 2);
1573                                 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 2);
1574
1575                                 g_ptr = &floor_ptr->grid_array[mon_fy][mon_fx - 2];
1576
1577                                 /* Radius 3 */
1578                                 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1579                                 {
1580                                         add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 3);
1581                                         add_mon_lite(subject_ptr, mon_fy, mon_fx - 3);
1582                                         add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 3);
1583                                 }
1584                         }
1585
1586                         /* Radius 3 */
1587                         if (rad != 3) continue;
1588
1589                         /* South-East of the monster */
1590                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx + 1, f_flag))
1591                         {
1592                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx + 2);
1593                         }
1594
1595                         /* South-West of the monster */
1596                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx - 1, f_flag))
1597                         {
1598                                 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx - 2);
1599                         }
1600
1601                         /* North-East of the monster */
1602                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx + 1, f_flag))
1603                         {
1604                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx + 2);
1605                         }
1606
1607                         /* North-West of the monster */
1608                         if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx - 1, f_flag))
1609                         {
1610                                 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx - 2);
1611                         }
1612                 }
1613         }
1614
1615         /* Save end of list of new squares */
1616         s16b end_temp = tmp_pos.n;
1617
1618         /*
1619          * Look at old set flags to see if there are any changes.
1620          */
1621         for (int i = 0; i < floor_ptr->mon_lite_n; i++)
1622         {
1623                 POSITION fx = floor_ptr->mon_lite_x[i];
1624                 POSITION fy = floor_ptr->mon_lite_y[i];
1625
1626                 grid_type *g_ptr;
1627                 g_ptr = &floor_ptr->grid_array[fy][fx];
1628
1629                 if (g_ptr->info & CAVE_TEMP) /* Pervious lit */
1630                 {
1631                         /* It it no longer lit? */
1632                         if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
1633                         {
1634                                 /* It is now unlit */
1635                                 /* Add it to later visual update */
1636                                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1637                         }
1638                 }
1639                 else /* Pervious darkened */
1640                 {
1641                         /* It it no longer darken? */
1642                         if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
1643                         {
1644                                 /* It is now undarken */
1645                                 /* Add it to later visual update */
1646                                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1647                         }
1648                 }
1649
1650                 /* Add to end of temp array */
1651                 tmp_pos.x[tmp_pos.n] = fx;
1652                 tmp_pos.y[tmp_pos.n] = fy;
1653                 tmp_pos.n++;
1654         }
1655
1656         /* Clear the lite array */
1657         floor_ptr->mon_lite_n = 0;
1658
1659         /* Copy the temp array into the lit array lighting the new squares. */
1660         for (int i = 0; i < end_temp; i++)
1661         {
1662                 POSITION fx = tmp_pos.x[i];
1663                 POSITION fy = tmp_pos.y[i];
1664
1665                 grid_type *g_ptr;
1666                 g_ptr = &floor_ptr->grid_array[fy][fx];
1667
1668                 if (g_ptr->info & CAVE_MNLT) /* Lit */
1669                 {
1670                         /* The is the square newly lit and visible? */
1671                         if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
1672                         {
1673                                 /* It is now lit */
1674                                 /* Add it to later visual update */
1675                                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1676                         }
1677                 }
1678                 else /* Darkened */
1679                 {
1680                         /* The is the square newly darkened and visible? */
1681                         if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
1682                         {
1683                                 /* It is now darkened */
1684                                 /* Add it to later visual update */
1685                                 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1686                         }
1687                 }
1688
1689                 /* Save in the monster lit or darkened array */
1690                 floor_ptr->mon_lite_x[floor_ptr->mon_lite_n] = fx;
1691                 floor_ptr->mon_lite_y[floor_ptr->mon_lite_n] = fy;
1692                 floor_ptr->mon_lite_n++;
1693         }
1694
1695         /* Clear the temp flag for the old lit or darken grids */
1696         for (int i = end_temp; i < tmp_pos.n; i++)
1697         {
1698                 /* We trust this grid is in bounds */
1699
1700                 floor_ptr->grid_array[tmp_pos.y[i]][tmp_pos.x[i]].info &= ~(CAVE_TEMP | CAVE_XTRA);
1701         }
1702
1703         tmp_pos.n = 0;
1704
1705         /* Mega-Hack -- Visual update later */
1706         subject_ptr->update |= (PU_DELAY_VIS);
1707
1708         subject_ptr->monlite = (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_MNLT) ? TRUE : FALSE;
1709
1710         if (!(subject_ptr->special_defense & NINJA_S_STEALTH))
1711         {
1712                 subject_ptr->old_monlite = subject_ptr->monlite;
1713                 return;
1714         }
1715
1716         if (subject_ptr->old_monlite == subject_ptr->monlite)
1717         {
1718                 subject_ptr->old_monlite = subject_ptr->monlite;
1719                 return;
1720         }
1721
1722         if (subject_ptr->monlite)
1723         {
1724                 msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow become thin."));
1725         }
1726         else
1727         {
1728                 msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow restored its original darkness."));
1729         }
1730
1731         subject_ptr->old_monlite = subject_ptr->monlite;
1732 }
1733
1734
1735 void clear_mon_lite(floor_type *floor_ptr)
1736 {
1737         /* Clear all monster lit squares */
1738         for (int i = 0; i < floor_ptr->mon_lite_n; i++)
1739         {
1740                 /* Point to grid */
1741                 grid_type *g_ptr;
1742                 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
1743
1744                 /* Clear monster illumination flag */
1745                 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
1746         }
1747
1748         /* Empty the array */
1749         floor_ptr->mon_lite_n = 0;
1750 }