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"
35 static bool mon_invis;
36 static POSITION mon_fy, mon_fx;
38 void day_break(player_type *subject_ptr)
41 msg_print(_("夜が明けた。", "The sun has risen."));
43 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
44 if (!subject_ptr->wild_mode)
46 /* Hack -- Scan the town */
47 for (y = 0; y < floor_ptr->height; y++)
49 for (x = 0; x < floor_ptr->width; x++)
51 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
54 g_ptr->info |= (CAVE_GLOW);
56 /* Hack -- Memorize lit grids if allowed */
57 if (view_perma_grids) g_ptr->info |= (CAVE_MARK);
59 note_spot(subject_ptr, y, x);
64 subject_ptr->update |= (PU_MONSTERS | PU_MON_LITE);
65 subject_ptr->redraw |= (PR_MAP);
66 subject_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
68 if (subject_ptr->special_defense & NINJA_S_STEALTH)
70 if (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_GLOW) set_superstealth(subject_ptr, FALSE);
75 void night_falls(player_type *subject_ptr)
78 msg_print(_("日が沈んだ。", "The sun has fallen."));
80 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
81 if (!subject_ptr->wild_mode)
83 /* Hack -- Scan the town */
84 for (y = 0; y < floor_ptr->height; y++)
86 for (x = 0; x < floor_ptr->width; x++)
88 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
90 /* Feature code (applying "mimic" field) */
91 feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)];
93 if (!is_mirror_grid(g_ptr) && !have_flag(f_ptr->flags, FF_QUEST_ENTER) &&
94 !have_flag(f_ptr->flags, FF_ENTRANCE))
97 g_ptr->info &= ~(CAVE_GLOW);
99 if (!have_flag(f_ptr->flags, FF_REMEMBER))
101 /* Forget the normal floor grid */
102 g_ptr->info &= ~(CAVE_MARK);
104 note_spot(subject_ptr, y, x);
109 glow_deep_lava_and_bldg(subject_ptr);
113 subject_ptr->update |= (PU_MONSTERS | PU_MON_LITE);
114 subject_ptr->redraw |= (PR_MAP);
115 subject_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
117 if (subject_ptr->special_defense & NINJA_S_STEALTH)
119 if (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_GLOW) set_superstealth(subject_ptr, FALSE);
125 * @brief 現在フロアに残っている敵モンスターの数を返す /
126 * @return 現在の敵モンスターの数
128 MONSTER_NUMBER count_all_hostile_monsters(floor_type *floor_ptr)
130 MONSTER_NUMBER number_mon = 0;
132 for (POSITION x = 0; x < floor_ptr->width; ++x)
134 for (POSITION y = 0; y < floor_ptr->height; ++y)
136 MONSTER_IDX m_idx = floor_ptr->grid_array[y][x].m_idx;
138 if (m_idx > 0 && is_hostile(&floor_ptr->m_list[m_idx]))
149 * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
151 #define RATING_BOOST(delta) (delta * delta + 50 * delta)
154 * @brief ダンジョンの雰囲気を算出する。
155 * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor
156 * @return 算出されたダンジョンの雰囲気ランク
158 byte get_dungeon_feeling(floor_type *floor_ptr)
160 /* Hack -- no feeling in the town */
161 if (!floor_ptr->dun_level) return 0;
163 /* Examine each monster */
166 for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++)
168 monster_type *m_ptr = &floor_ptr->m_list[i];
171 if (!monster_is_valid(m_ptr)) continue;
173 if (is_pet(m_ptr)) continue;
175 r_ptr = &r_info[m_ptr->r_idx];
177 if (r_ptr->flags1 & (RF1_UNIQUE))
179 /* Nearly out-of-depth unique monsters */
180 if (r_ptr->level + 10 > floor_ptr->dun_level)
182 /* Boost rating by twice delta-depth */
183 delta += (r_ptr->level + 10 - floor_ptr->dun_level) * 2 * base;
188 /* Out-of-depth monsters */
189 if (r_ptr->level > floor_ptr->dun_level)
191 /* Boost rating by delta-depth */
192 delta += (r_ptr->level - floor_ptr->dun_level) * base;
196 /* Unusually crowded monsters get a little bit of rating boost */
197 if (r_ptr->flags1 & RF1_FRIENDS)
199 if (5 <= get_monster_crowd_number(floor_ptr, i)) delta += 1;
203 if (2 <= get_monster_crowd_number(floor_ptr, i)) delta += 1;
207 rating += RATING_BOOST(delta);
210 /* Examine each unidentified object */
211 for (MONSTER_IDX i = 1; i < floor_ptr->o_max; i++)
213 object_type *o_ptr = &floor_ptr->o_list[i];
214 object_kind *k_ptr = &k_info[o_ptr->k_idx];
217 if (!OBJECT_IS_VALID(o_ptr)) continue;
219 /* Skip known objects */
220 if (object_is_known(o_ptr))
223 if (o_ptr->marked & OM_TOUCHED) continue;
226 /* Skip pseudo-known objects */
227 if (o_ptr->ident & IDENT_SENSE) continue;
230 if (object_is_ego(o_ptr))
232 ego_item_type *e_ptr = &e_info[o_ptr->name2];
234 delta += e_ptr->rating * base;
238 if (object_is_artifact(o_ptr))
240 PRICE cost = object_value_real(o_ptr);
243 if (cost > 10000L) delta += 10 * base;
244 if (cost > 50000L) delta += 10 * base;
245 if (cost > 100000L) delta += 10 * base;
247 /* Special feeling */
248 if (!preserve_mode) return 1;
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;
260 /* Out-of-depth objects */
261 if (!object_is_cursed(o_ptr) && !object_is_broken(o_ptr) && k_ptr->level > floor_ptr->dun_level)
263 /* Rating increase */
264 delta += (k_ptr->level - floor_ptr->dun_level) * base;
267 rating += RATING_BOOST(delta);
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;
283 * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する
284 * / Update dungeon feeling, and announce it if changed
287 void update_dungeon_feeling(player_type *subject_ptr)
289 /* No feeling on the surface */
290 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
291 if (!floor_ptr->dun_level) return;
293 /* No feeling in the arena */
294 if (subject_ptr->phase_out) return;
296 /* Extract delay time */
297 int delay = MAX(10, 150 - subject_ptr->skill_fos) * (150 - floor_ptr->dun_level) * TURNS_PER_TICK / 100;
299 /* Not yet felt anything */
300 if (current_world_ptr->game_turn < subject_ptr->feeling_turn + delay && !cheat_xtra) return;
302 /* Extract quest number (if any) */
303 int quest_num = quest_number(subject_ptr, floor_ptr->dun_level);
305 /* No feeling in a quest */
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;
312 /* Get new dungeon feeling */
313 byte new_feeling = get_dungeon_feeling(floor_ptr);
315 /* Remember last time updated */
316 subject_ptr->feeling_turn = current_world_ptr->game_turn;
319 if (subject_ptr->feeling == new_feeling) return;
321 /* Dungeon feeling is changed */
322 subject_ptr->feeling = new_feeling;
324 /* Announce feeling */
325 do_cmd_feeling(subject_ptr);
327 select_floor_music(subject_ptr);
329 /* Update the level indicator */
330 subject_ptr->redraw |= (PR_DEPTH);
332 if (disturb_minor) disturb(subject_ptr, FALSE, FALSE);
337 * Glow deep lava and building entrances in the floor
339 void glow_deep_lava_and_bldg(player_type *subject_ptr)
341 /* Not in the darkness dungeon */
342 if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) return;
344 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
345 for (POSITION y = 0; y < floor_ptr->height; y++)
347 for (POSITION x = 0; x < floor_ptr->width; x++)
350 g_ptr = &floor_ptr->grid_array[y][x];
352 if (!have_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_GLOW))
355 for (DIRECTION i = 0; i < 9; i++)
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;
365 subject_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
366 subject_ptr->redraw |= (PR_MAP);
371 * Actually erase the entire "lite" array, redrawing every grid
373 void forget_lite(floor_type *floor_ptr)
376 if (!floor_ptr->lite_n) return;
379 for (int i = 0; i < floor_ptr->lite_n; i++)
381 POSITION y = floor_ptr->lite_y[i];
382 POSITION x = floor_ptr->lite_x[i];
384 /* Forget "LITE" flag */
385 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
388 floor_ptr->lite_n = 0;
393 * Update the set of grids "illuminated" by the player's lite.
395 * This routine needs to use the results of "update_view()"
397 * Note that "blindness" does NOT affect "torch lite". Be careful!
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.
404 * We assume that "radius zero" lite is in fact no lite at all.
406 * Torch Lantern Artifacts
416 void update_lite(player_type *subject_ptr)
418 POSITION p = subject_ptr->cur_lite;
421 /*** Save the old "lite" grids for later ***/
424 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
425 for (int i = 0; i < floor_ptr->lite_n; i++)
427 POSITION y = floor_ptr->lite_y[i];
428 POSITION x = floor_ptr->lite_x[i];
430 /* Mark the grid as not "lite" */
431 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
433 /* Mark the grid as "seen" */
434 floor_ptr->grid_array[y][x].info |= (CAVE_TEMP);
436 /* Add it to the "seen" set */
437 tmp_pos.y[tmp_pos.n] = y;
438 tmp_pos.x[tmp_pos.n] = x;
443 floor_ptr->lite_n = 0;
446 /*** Collect the new "lite" grids ***/
448 /* Radius 1 -- torch radius */
452 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x);
455 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x);
456 cave_lite_hack(floor_ptr, subject_ptr->y - 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);
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);
467 /* Radius 2 -- lantern radius */
470 /* South of the player */
471 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x))
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);
478 /* North of the player */
479 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x))
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);
486 /* East of the player */
487 if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x + 1))
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);
494 /* West of the player */
495 if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x - 1))
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);
503 /* Radius 3+ -- artifact radius */
508 /* Paranoia -- see "LITE_MAX" */
511 /* South-East of the player */
512 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1))
514 cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 2);
517 /* South-West of the player */
518 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1))
520 cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 2);
523 /* North-East of the player */
524 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1))
526 cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 2);
529 /* North-West of the player */
530 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1))
532 cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 2);
536 POSITION min_y = subject_ptr->y - p;
537 if (min_y < 0) min_y = 0;
540 POSITION max_y = subject_ptr->y + p;
541 if (max_y > floor_ptr->height - 1) max_y = floor_ptr->height - 1;
544 POSITION min_x = subject_ptr->x - p;
545 if (min_x < 0) min_x = 0;
548 POSITION max_x = subject_ptr->x + p;
549 if (max_x > floor_ptr->width - 1) max_x = floor_ptr->width - 1;
551 /* Scan the maximal box */
552 for (POSITION y = min_y; y <= max_y; y++)
554 for (POSITION x = min_x; x <= max_x; x++)
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);
559 /* Skip the "central" grids (above) */
560 if ((dy <= 2) && (dx <= 2)) continue;
562 /* Hack -- approximate the distance */
563 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
565 /* Skip distant grids */
568 /* Viewable, nearby, grids get "torch lit" */
569 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW)
571 /* This grid is "torch lit" */
572 cave_lite_hack(floor_ptr, y, x);
579 /*** Complete the algorithm ***/
581 /* Draw the new grids */
582 for (int i = 0; i < floor_ptr->lite_n; i++)
584 POSITION y = floor_ptr->lite_y[i];
585 POSITION x = floor_ptr->lite_x[i];
587 g_ptr = &floor_ptr->grid_array[y][x];
589 /* Update fresh grids */
590 if (g_ptr->info & (CAVE_TEMP)) continue;
592 /* Add it to later visual update */
593 cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
597 for (int i = 0; i < tmp_pos.n; i++)
599 POSITION y = tmp_pos.y[i];
600 POSITION x = tmp_pos.x[i];
602 g_ptr = &floor_ptr->grid_array[y][x];
604 /* No longer in the array */
605 g_ptr->info &= ~(CAVE_TEMP);
607 /* Update stale grids */
608 if (g_ptr->info & (CAVE_LITE)) continue;
610 /* Add it to later visual update */
611 cave_redraw_later(floor_ptr, g_ptr, y, x);
615 subject_ptr->update |= (PU_DELAY_VIS);
620 * Clear the viewable space
622 void forget_view(floor_type *floor_ptr)
625 if (!floor_ptr->view_n) return;
628 for (int i = 0; i < floor_ptr->view_n; i++)
630 POSITION y = floor_ptr->view_y[i];
631 POSITION x = floor_ptr->view_x[i];
633 g_ptr = &floor_ptr->grid_array[y][x];
635 /* Forget that the grid is viewable */
636 g_ptr->info &= ~(CAVE_VIEW);
639 floor_ptr->view_n = 0;
644 * Helper function for "update_view()" below
646 * We are checking the "viewability" of grid (y,x) by the player.
648 * This function assumes that (y,x) is legal (i.e. on the map).
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).
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()".
656 * This function adds (y,x) to the "viewable set" if necessary.
658 * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
660 static bool update_view_aux(player_type *subject_ptr, POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
662 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
665 g1_c_ptr = &floor_ptr->grid_array[y1][x1];
666 g2_c_ptr = &floor_ptr->grid_array[y2][x2];
668 /* Check for walls */
669 bool f1 = (cave_los_grid(g1_c_ptr));
670 bool f2 = (cave_los_grid(g2_c_ptr));
672 /* Totally blocked by physical walls */
673 if (!f1 && !f2) return TRUE;
675 /* Check for visibility */
676 bool v1 = (f1 && (g1_c_ptr->info & (CAVE_VIEW)));
677 bool v2 = (f2 && (g2_c_ptr->info & (CAVE_VIEW)));
679 /* Totally blocked by "unviewable neighbors" */
680 if (!v1 && !v2) return TRUE;
683 g_ptr = &floor_ptr->grid_array[y][x];
685 /* Check for walls */
686 bool wall = (!cave_los_grid(g_ptr));
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)));
692 /* Hack -- "easy" plus "easy" yields "easy" */
695 g_ptr->info |= (CAVE_XTRA);
696 cave_view_hack(floor_ptr, g_ptr, y, x);
700 /* Hack -- primary "easy" yields "viewed" */
703 cave_view_hack(floor_ptr, g_ptr, y, x);
707 /* Hack -- "view" plus "view" yields "view" */
710 cave_view_hack(floor_ptr, g_ptr, y, x);
714 /* Mega-Hack -- the "los()" function works poorly on walls */
717 cave_view_hack(floor_ptr, g_ptr, y, x);
721 /* Hack -- check line of sight */
722 if (los(subject_ptr, subject_ptr->y, subject_ptr->x, y, x))
724 cave_view_hack(floor_ptr, g_ptr, y, x);
733 * Calculate the viewable space
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
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.
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.
761 * if (manhatten(dy,dx) < R) then (hypot(dy,dx) < R)
762 * if (manhatten(dy,dx) > R*3/2) then (hypot(dy,dx) > R)
764 * hypot(dy,dx) is approximated by (dx+dy+MAX(dx,dy)) / 2
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.
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.
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.
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.
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.
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.
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.
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.
823 void update_view(player_type *subject_ptr)
828 int se, sw, ne, nw, es, en, ws, wn;
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;
841 if (view_reduce_view && !floor_ptr->dun_level)
843 /* Full radius (10) */
844 full = MAX_SIGHT / 2;
846 /* Octagon factor (15) */
847 over = MAX_SIGHT * 3 / 4;
853 /* Full radius (20) */
856 /* Octagon factor (30) */
857 over = MAX_SIGHT * 3 / 2;
861 /*** Step 0 -- Begin ***/
863 /* Save the old "view" grids for later */
864 for (n = 0; n < floor_ptr->view_n; n++)
866 y = floor_ptr->view_y[n];
867 x = floor_ptr->view_x[n];
868 g_ptr = &floor_ptr->grid_array[y][x];
870 /* Mark the grid as not in "view" */
871 g_ptr->info &= ~(CAVE_VIEW);
873 /* Mark the grid as "seen" */
874 g_ptr->info |= (CAVE_TEMP);
876 /* Add it to the "seen" set */
877 tmp_pos.y[tmp_pos.n] = y;
878 tmp_pos.x[tmp_pos.n] = x;
882 /* Start over with the "view" array */
883 floor_ptr->view_n = 0;
885 /*** Step 1 -- adjacent grids ***/
887 /* Now start on the player */
890 g_ptr = &floor_ptr->grid_array[y][x];
892 /* Assume the player grid is easily viewable */
893 g_ptr->info |= (CAVE_XTRA);
895 /* Assume the player grid is viewable */
896 cave_view_hack(floor_ptr, g_ptr, y, x);
899 /*** Step 2 -- Major Diagonals ***/
904 /* Scan south-east */
905 for (d = 1; d <= z; d++)
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;
913 /* Scan south-west */
914 for (d = 1; d <= z; d++)
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;
922 /* Scan north-east */
923 for (d = 1; d <= z; d++)
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;
931 /* Scan north-west */
932 for (d = 1; d <= z; d++)
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;
940 /*** Step 3 -- major axes ***/
943 for (d = 1; d <= full; d++)
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;
951 /* Initialize the "south strips" */
955 for (d = 1; d <= full; d++)
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;
963 /* Initialize the "north strips" */
967 for (d = 1; d <= full; d++)
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;
975 /* Initialize the "east strips" */
979 for (d = 1; d <= full; d++)
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;
987 /* Initialize the "west strips" */
991 /*** Step 4 -- Divide each "octant" into "strips" ***/
993 /* Now check each "diagonal" (in parallel) */
994 for (n = 1; n <= over / 2; n++)
996 POSITION ypn, ymn, xpn, xmn;
998 /* Acquire the "bounds" of the maximal circle */
1000 if (z > full - n) z = full - n;
1001 while ((z + n + (n >> 1)) > full) z--;
1003 /* Access the four diagonal grids */
1012 /* Maximum distance */
1013 m = MIN(z, y_max - ypn);
1016 if ((xpn <= x_max) && (n < se))
1019 for (k = n, d = 1; d <= m; d++)
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))
1024 if (n + d >= se) break;
1027 /* Track most distant "non-blockage" */
1034 /* Limit the next strip */
1039 if ((xmn >= 0) && (n < sw))
1042 for (k = n, d = 1; d <= m; d++)
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))
1047 if (n + d >= sw) break;
1050 /* Track most distant "non-blockage" */
1057 /* Limit the next strip */
1065 /* Maximum distance */
1069 if ((xpn <= x_max) && (n < ne))
1072 for (k = n, d = 1; d <= m; d++)
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))
1077 if (n + d >= ne) break;
1080 /* Track most distant "non-blockage" */
1087 /* Limit the next strip */
1092 if ((xmn >= 0) && (n < nw))
1095 for (k = n, d = 1; d <= m; d++)
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))
1100 if (n + d >= nw) break;
1103 /* Track most distant "non-blockage" */
1110 /* Limit the next strip */
1118 /* Maximum distance */
1119 m = MIN(z, x_max - xpn);
1122 if ((ypn <= x_max) && (n < es))
1125 for (k = n, d = 1; d <= m; d++)
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))
1130 if (n + d >= es) break;
1133 /* Track most distant "non-blockage" */
1140 /* Limit the next strip */
1145 if ((ymn >= 0) && (n < en))
1148 for (k = n, d = 1; d <= m; d++)
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))
1153 if (n + d >= en) break;
1156 /* Track most distant "non-blockage" */
1163 /* Limit the next strip */
1171 /* Maximum distance */
1175 if ((ypn <= y_max) && (n < ws))
1178 for (k = n, d = 1; d <= m; d++)
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))
1183 if (n + d >= ws) break;
1186 /* Track most distant "non-blockage" */
1193 /* Limit the next strip */
1198 if ((ymn >= 0) && (n < wn))
1201 for (k = n, d = 1; d <= m; d++)
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))
1206 if (n + d >= wn) break;
1209 /* Track most distant "non-blockage" */
1216 /* Limit the next strip */
1222 /*** Step 5 -- Complete the algorithm ***/
1224 /* Update all the new grids */
1225 for (n = 0; n < floor_ptr->view_n; n++)
1227 y = floor_ptr->view_y[n];
1228 x = floor_ptr->view_x[n];
1229 g_ptr = &floor_ptr->grid_array[y][x];
1231 /* Clear the "CAVE_XTRA" flag */
1232 g_ptr->info &= ~(CAVE_XTRA);
1234 /* Update only newly viewed grids */
1235 if (g_ptr->info & (CAVE_TEMP)) continue;
1237 /* Add it to later visual update */
1238 cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
1241 /* Wipe the old grids, update as needed */
1242 for (n = 0; n < tmp_pos.n; n++)
1246 g_ptr = &floor_ptr->grid_array[y][x];
1248 /* No longer in the array */
1249 g_ptr->info &= ~(CAVE_TEMP);
1251 /* Update only non-viewable grids */
1252 if (g_ptr->info & (CAVE_VIEW)) continue;
1254 /* Add it to later visual update */
1255 cave_redraw_later(floor_ptr, g_ptr, y, x);
1259 subject_ptr->update |= (PU_DELAY_VIS);
1264 * @brief モンスターによる光量状態更新 / Add a square to the changes array
1265 * @param subject_ptr 主観となるクリーチャーの参照ポインタ
1269 static void mon_lite_hack(player_type *subject_ptr, POSITION y, POSITION x)
1275 /* We trust this grid is in bounds */
1276 /* if (!in_bounds2(y, x)) return; */
1278 g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
1280 /* Want a unlit square in view of the player */
1281 if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW) return;
1283 if (!cave_los_grid(g_ptr))
1285 /* Hack -- Prevent monster lite leakage in walls */
1287 /* Horizontal walls between player and a monster */
1288 if (((y < subject_ptr->y) && (y > mon_fy)) || ((y > subject_ptr->y) && (y < mon_fy)))
1290 dpf = subject_ptr->y - mon_fy;
1292 midpoint = mon_fx + ((subject_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
1294 /* Only first wall viewed from mid-x is lit */
1297 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1)) return;
1299 else if (x > midpoint)
1301 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1)) return;
1304 /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1305 else if (mon_invis) return;
1308 /* Vertical walls between player and a monster */
1309 if (((x < subject_ptr->x) && (x > mon_fx)) || ((x > subject_ptr->x) && (x < mon_fx)))
1311 dpf = subject_ptr->x - mon_fx;
1313 midpoint = mon_fy + ((subject_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
1315 /* Only first wall viewed from mid-y is lit */
1318 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x)) return;
1320 else if (y > midpoint)
1322 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x)) return;
1325 /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1326 else if (mon_invis) return;
1330 /* We trust tmp_pos.n does not exceed TEMP_MAX */
1333 if (!(g_ptr->info & CAVE_MNDK))
1335 /* Save this square */
1336 tmp_pos.x[tmp_pos.n] = x;
1337 tmp_pos.y[tmp_pos.n] = y;
1344 /* No longer dark */
1345 g_ptr->info &= ~(CAVE_MNDK);
1349 g_ptr->info |= CAVE_MNLT;
1354 * Add a square to the changes array
1356 static void mon_dark_hack(player_type *subject_ptr, POSITION y, POSITION x)
1359 int midpoint, dpf, d;
1361 /* We trust this grid is in bounds */
1362 /* if (!in_bounds2(y, x)) return; */
1364 g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
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;
1369 if (!cave_los_grid(g_ptr) && !cave_have_flag_grid(g_ptr, FF_PROJECT))
1371 /* Hack -- Prevent monster dark lite leakage in walls */
1373 /* Horizontal walls between player and a monster */
1374 if (((y < subject_ptr->y) && (y > mon_fy)) || ((y > subject_ptr->y) && (y < mon_fy)))
1376 dpf = subject_ptr->y - mon_fy;
1378 midpoint = mon_fx + ((subject_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
1380 /* Only first wall viewed from mid-x is lit */
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;
1385 else if (x > midpoint)
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;
1390 /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1391 else if (mon_invis) return;
1394 /* Vertical walls between player and a monster */
1395 if (((x < subject_ptr->x) && (x > mon_fx)) || ((x > subject_ptr->x) && (x < mon_fx)))
1397 dpf = subject_ptr->x - mon_fx;
1399 midpoint = mon_fy + ((subject_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
1401 /* Only first wall viewed from mid-y is lit */
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;
1406 else if (y > midpoint)
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;
1411 /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1412 else if (mon_invis) return;
1416 /* We trust tmp_pos.n does not exceed TEMP_MAX */
1418 /* Save this square */
1419 tmp_pos.x[tmp_pos.n] = x;
1420 tmp_pos.y[tmp_pos.n] = y;
1424 g_ptr->info |= CAVE_MNDK;
1429 * Update squares illuminated or darkened by monsters.
1431 * Hack - use the CAVE_ROOM flag (renamed to be CAVE_MNLT) to
1432 * denote squares illuminated by monsters.
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().
1438 void update_mon_lite(player_type *subject_ptr)
1440 void(*add_mon_lite)(player_type *, POSITION, POSITION);
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);
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++)
1451 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
1453 /* Set temp or xtra flag */
1454 g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
1456 /* Clear monster illumination flag */
1457 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
1460 /* Empty temp list of new squares to lite up */
1463 /* If a monster stops time, don't process */
1464 if (!current_world_ptr->timewalk_m_idx)
1466 monster_type *m_ptr;
1467 monster_race *r_ptr;
1469 /* Loop through monsters, adding newly lit squares to changes list */
1470 for (int i = 1; i < floor_ptr->m_max; i++)
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;
1476 /* Is it too far away? */
1477 if (m_ptr->cdis > dis_lim) continue;
1479 /* Get lite radius */
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;
1488 /* Exit if has no light */
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;
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 */
1510 /* Is the monster visible? */
1511 mon_invis = !(floor_ptr->grid_array[mon_fy][mon_fx].info & CAVE_VIEW);
1513 /* The square it is on */
1514 add_mon_lite(subject_ptr, mon_fy, mon_fx);
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);
1527 if (rad < 2) continue;
1529 /* South of the monster */
1531 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx, f_flag))
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);
1537 g_ptr = &floor_ptr->grid_array[mon_fy + 2][mon_fx];
1540 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
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);
1548 /* North of the monster */
1549 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx, f_flag))
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);
1555 g_ptr = &floor_ptr->grid_array[mon_fy - 2][mon_fx];
1558 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
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);
1566 /* East of the monster */
1567 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy, mon_fx + 1, f_flag))
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);
1573 g_ptr = &floor_ptr->grid_array[mon_fy][mon_fx + 2];
1576 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
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);
1584 /* West of the monster */
1585 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy, mon_fx - 1, f_flag))
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);
1591 g_ptr = &floor_ptr->grid_array[mon_fy][mon_fx - 2];
1594 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
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);
1603 if (rad != 3) continue;
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))
1608 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx + 2);
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))
1614 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx - 2);
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))
1620 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx + 2);
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))
1626 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx - 2);
1631 /* Save end of list of new squares */
1632 s16b end_temp = tmp_pos.n;
1635 * Look at old set flags to see if there are any changes.
1637 for (int i = 0; i < floor_ptr->mon_lite_n; i++)
1639 POSITION fx = floor_ptr->mon_lite_x[i];
1640 POSITION fy = floor_ptr->mon_lite_y[i];
1643 g_ptr = &floor_ptr->grid_array[fy][fx];
1645 if (g_ptr->info & CAVE_TEMP) /* Pervious lit */
1647 /* It it no longer lit? */
1648 if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
1650 /* It is now unlit */
1651 /* Add it to later visual update */
1652 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1655 else /* Pervious darkened */
1657 /* It it no longer darken? */
1658 if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
1660 /* It is now undarken */
1661 /* Add it to later visual update */
1662 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1666 /* Add to end of temp array */
1667 tmp_pos.x[tmp_pos.n] = fx;
1668 tmp_pos.y[tmp_pos.n] = fy;
1672 /* Clear the lite array */
1673 floor_ptr->mon_lite_n = 0;
1675 /* Copy the temp array into the lit array lighting the new squares. */
1676 for (int i = 0; i < end_temp; i++)
1678 POSITION fx = tmp_pos.x[i];
1679 POSITION fy = tmp_pos.y[i];
1682 g_ptr = &floor_ptr->grid_array[fy][fx];
1684 if (g_ptr->info & CAVE_MNLT) /* Lit */
1686 /* The is the square newly lit and visible? */
1687 if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
1690 /* Add it to later visual update */
1691 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1696 /* The is the square newly darkened and visible? */
1697 if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
1699 /* It is now darkened */
1700 /* Add it to later visual update */
1701 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
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++;
1711 /* Clear the temp flag for the old lit or darken grids */
1712 for (int i = end_temp; i < tmp_pos.n; i++)
1714 /* We trust this grid is in bounds */
1716 floor_ptr->grid_array[tmp_pos.y[i]][tmp_pos.x[i]].info &= ~(CAVE_TEMP | CAVE_XTRA);
1721 /* Mega-Hack -- Visual update later */
1722 subject_ptr->update |= (PU_DELAY_VIS);
1724 subject_ptr->monlite = (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_MNLT) ? TRUE : FALSE;
1726 if (!(subject_ptr->special_defense & NINJA_S_STEALTH))
1728 subject_ptr->old_monlite = subject_ptr->monlite;
1732 if (subject_ptr->old_monlite == subject_ptr->monlite)
1734 subject_ptr->old_monlite = subject_ptr->monlite;
1738 if (subject_ptr->monlite)
1740 msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow becomes thin."));
1744 msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow is restored to its original darkness."));
1747 subject_ptr->old_monlite = subject_ptr->monlite;
1751 void clear_mon_lite(floor_type *floor_ptr)
1753 /* Clear all monster lit squares */
1754 for (int i = 0; i < floor_ptr->mon_lite_n; i++)
1758 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
1760 /* Clear monster illumination flag */
1761 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
1764 /* Empty the array */
1765 floor_ptr->mon_lite_n = 0;