OSDN Git Service

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