OSDN Git Service

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