6 #include "floor-events.h"
9 #include "monster-status.h"
11 #include "object-hook.h"
12 #include "player-move.h"
14 #include "player-effects.h"
15 #include "objectkind.h"
16 #include "object-ego.h"
18 #include "view-mainwindow.h"
20 static bool mon_invis;
21 static POSITION mon_fy, mon_fx;
23 void day_break(player_type *subject_ptr)
26 msg_print(_("夜が明けた。", "The sun has risen."));
28 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
29 if (!subject_ptr->wild_mode)
31 /* Hack -- Scan the town */
32 for (y = 0; y < floor_ptr->height; y++)
34 for (x = 0; x < floor_ptr->width; x++)
36 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
39 g_ptr->info |= (CAVE_GLOW);
41 /* Hack -- Memorize lit grids if allowed */
42 if (view_perma_grids) g_ptr->info |= (CAVE_MARK);
49 subject_ptr->update |= (PU_MONSTERS | PU_MON_LITE);
50 subject_ptr->redraw |= (PR_MAP);
51 subject_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
53 if (subject_ptr->special_defense & NINJA_S_STEALTH)
55 if (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_GLOW) set_superstealth(subject_ptr, FALSE);
60 void night_falls(player_type *subject_ptr)
63 msg_print(_("日が沈んだ。", "The sun has fallen."));
65 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
66 if (!subject_ptr->wild_mode)
68 /* Hack -- Scan the town */
69 for (y = 0; y < floor_ptr->height; y++)
71 for (x = 0; x < floor_ptr->width; x++)
73 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
75 /* Feature code (applying "mimic" field) */
76 feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)];
78 if (!is_mirror_grid(g_ptr) && !have_flag(f_ptr->flags, FF_QUEST_ENTER) &&
79 !have_flag(f_ptr->flags, FF_ENTRANCE))
82 g_ptr->info &= ~(CAVE_GLOW);
84 if (!have_flag(f_ptr->flags, FF_REMEMBER))
86 /* Forget the normal floor grid */
87 g_ptr->info &= ~(CAVE_MARK);
94 glow_deep_lava_and_bldg(subject_ptr);
98 subject_ptr->update |= (PU_MONSTERS | PU_MON_LITE);
99 subject_ptr->redraw |= (PR_MAP);
100 subject_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
102 if (subject_ptr->special_defense & NINJA_S_STEALTH)
104 if (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_GLOW) set_superstealth(subject_ptr, FALSE);
110 * @brief 現在フロアに残っている敵モンスターの数を返す /
111 * @return 現在の敵モンスターの数
113 MONSTER_NUMBER count_all_hostile_monsters(floor_type *floor_ptr)
116 MONSTER_NUMBER number_mon = 0;
118 for (x = 0; x < floor_ptr->width; ++x)
120 for (y = 0; y < floor_ptr->height; ++y)
122 MONSTER_IDX m_idx = floor_ptr->grid_array[y][x].m_idx;
124 if (m_idx > 0 && is_hostile(&floor_ptr->m_list[m_idx]))
137 * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
139 #define RATING_BOOST(delta) (delta * delta + 50 * delta)
142 * @brief ダンジョンの雰囲気を算出する。
143 * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor
144 * @return 算出されたダンジョンの雰囲気ランク
146 byte get_dungeon_feeling(floor_type *floor_ptr)
152 /* Hack -- no feeling in the town */
153 if (!floor_ptr->dun_level) return 0;
155 /* Examine each monster */
156 for (i = 1; i < floor_ptr->m_max; i++)
158 monster_type *m_ptr = &floor_ptr->m_list[i];
161 if (!monster_is_valid(m_ptr)) continue;
163 if (is_pet(m_ptr)) continue;
165 r_ptr = &r_info[m_ptr->r_idx];
167 if (r_ptr->flags1 & (RF1_UNIQUE))
169 /* Nearly out-of-depth unique monsters */
170 if (r_ptr->level + 10 > floor_ptr->dun_level)
172 /* Boost rating by twice delta-depth */
173 delta += (r_ptr->level + 10 - floor_ptr->dun_level) * 2 * base;
178 /* Out-of-depth monsters */
179 if (r_ptr->level > floor_ptr->dun_level)
181 /* Boost rating by delta-depth */
182 delta += (r_ptr->level - floor_ptr->dun_level) * base;
186 /* Unusually crowded monsters get a little bit of rating boost */
187 if (r_ptr->flags1 & RF1_FRIENDS)
189 if (5 <= get_monster_crowd_number(i)) delta += 1;
193 if (2 <= get_monster_crowd_number(i)) delta += 1;
197 rating += RATING_BOOST(delta);
200 /* Examine each unidentified object */
201 for (i = 1; i < floor_ptr->o_max; i++)
203 object_type *o_ptr = &floor_ptr->o_list[i];
204 object_kind *k_ptr = &k_info[o_ptr->k_idx];
207 if (!OBJECT_IS_VALID(o_ptr)) continue;
209 /* Skip known objects */
210 if (object_is_known(o_ptr))
213 if (o_ptr->marked & OM_TOUCHED) continue;
216 /* Skip pseudo-known objects */
217 if (o_ptr->ident & IDENT_SENSE) continue;
220 if (object_is_ego(o_ptr))
222 ego_item_type *e_ptr = &e_info[o_ptr->name2];
224 delta += e_ptr->rating * base;
228 if (object_is_artifact(o_ptr))
230 PRICE cost = object_value_real(o_ptr);
233 if (cost > 10000L) delta += 10 * base;
234 if (cost > 50000L) delta += 10 * base;
235 if (cost > 100000L) delta += 10 * base;
237 /* Special feeling */
238 if (!preserve_mode) return 1;
241 if (o_ptr->tval == TV_DRAG_ARMOR) delta += 30 * base;
242 if (o_ptr->tval == TV_SHIELD && o_ptr->sval == SV_DRAGON_SHIELD) delta += 5 * base;
243 if (o_ptr->tval == TV_GLOVES && o_ptr->sval == SV_SET_OF_DRAGON_GLOVES) delta += 5 * base;
244 if (o_ptr->tval == TV_BOOTS && o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE) delta += 5 * base;
245 if (o_ptr->tval == TV_HELM && o_ptr->sval == SV_DRAGON_HELM) delta += 5 * base;
246 if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_SPEED && !object_is_cursed(o_ptr)) delta += 25 * base;
247 if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_LORDLY && !object_is_cursed(o_ptr)) delta += 15 * base;
248 if (o_ptr->tval == TV_AMULET && o_ptr->sval == SV_AMULET_THE_MAGI && !object_is_cursed(o_ptr)) delta += 15 * base;
250 /* Out-of-depth objects */
251 if (!object_is_cursed(o_ptr) && !object_is_broken(o_ptr) && k_ptr->level > floor_ptr->dun_level)
253 /* Rating increase */
254 delta += (k_ptr->level - floor_ptr->dun_level) * base;
257 rating += RATING_BOOST(delta);
261 if (rating > RATING_BOOST(1000)) return 2;
262 if (rating > RATING_BOOST(800)) return 3;
263 if (rating > RATING_BOOST(600)) return 4;
264 if (rating > RATING_BOOST(400)) return 5;
265 if (rating > RATING_BOOST(300)) return 6;
266 if (rating > RATING_BOOST(200)) return 7;
267 if (rating > RATING_BOOST(100)) return 8;
268 if (rating > RATING_BOOST(0)) return 9;
274 * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する
275 * / Update dungeon feeling, and announce it if changed
278 void update_dungeon_feeling(player_type *subject_ptr)
284 /* No feeling on the surface */
285 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
286 if (!floor_ptr->dun_level) return;
288 /* No feeling in the arena */
289 if (subject_ptr->phase_out) return;
291 /* Extract delay time */
292 delay = MAX(10, 150 - subject_ptr->skill_fos) * (150 - floor_ptr->dun_level) * TURNS_PER_TICK / 100;
294 /* Not yet felt anything */
295 if (current_world_ptr->game_turn < subject_ptr->feeling_turn + delay && !cheat_xtra) return;
297 /* Extract quest number (if any) */
298 quest_num = quest_number(subject_ptr, floor_ptr->dun_level);
300 /* No feeling in a quest */
302 (is_fixed_quest_idx(quest_num) &&
303 !((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT) ||
304 !(quest[quest_num].flags & QUEST_FLAG_PRESET)))) return;
307 /* Get new dungeon feeling */
308 new_feeling = get_dungeon_feeling(floor_ptr);
310 /* Remember last time updated */
311 subject_ptr->feeling_turn = current_world_ptr->game_turn;
314 if (subject_ptr->feeling == new_feeling) return;
316 /* Dungeon feeling is changed */
317 subject_ptr->feeling = new_feeling;
319 /* Announce feeling */
320 do_cmd_feeling(subject_ptr);
322 select_floor_music(subject_ptr);
324 /* Update the level indicator */
325 subject_ptr->redraw |= (PR_DEPTH);
327 if (disturb_minor) disturb(subject_ptr, FALSE, FALSE);
332 * Glow deep lava and building entrances in the floor
334 void glow_deep_lava_and_bldg(player_type *subject_ptr)
336 POSITION y, x, yy, xx;
340 /* Not in the darkness dungeon */
341 if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) return;
343 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
344 for (y = 0; y < floor_ptr->height; y++)
346 for (x = 0; x < floor_ptr->width; x++)
348 g_ptr = &floor_ptr->grid_array[y][x];
350 /* Feature code (applying "mimic" field) */
352 if (have_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_GLOW))
354 for (i = 0; i < 9; i++)
358 if (!in_bounds2(floor_ptr, yy, xx)) continue;
359 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);
370 * Actually erase the entire "lite" array, redrawing every grid
372 void forget_lite(floor_type *floor_ptr)
378 if (!floor_ptr->lite_n) return;
381 for (i = 0; i < floor_ptr->lite_n; i++)
383 y = floor_ptr->lite_y[i];
384 x = floor_ptr->lite_x[i];
386 /* Forget "LITE" flag */
387 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
389 /* lite_spot(y, x); Perhaps don't need? */
393 floor_ptr->lite_n = 0;
399 * Update the set of grids "illuminated" by the player's lite.
401 * This routine needs to use the results of "update_view()"
403 * Note that "blindness" does NOT affect "torch lite". Be careful!
405 * We optimize most lites (all non-artifact lites) by using "obvious"
406 * facts about the results of "small" lite radius, and we attempt to
407 * list the "nearby" grids before the more "distant" ones in the
408 * array of torch-lit grids.
410 * We assume that "radius zero" lite is in fact no lite at all.
412 * Torch Lantern Artifacts
422 void update_lite(player_type *subject_ptr)
425 POSITION x, y, min_x, max_x, min_y, max_y;
426 POSITION p = subject_ptr->cur_lite;
429 /*** Special case ***/
432 /* Hack -- Player has no lite */
435 /* Forget the old lite */
436 /* forget_lite(); Perhaps don't need? */
438 /* Add it to later visual update */
439 cave_redraw_later(floor_ptr, &floor_ptr->grid_array[subject_ptr->y][subject_ptr->x], subject_ptr->y, subject_ptr->x);
443 /*** Save the old "lite" grids for later ***/
446 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
447 for (i = 0; i < floor_ptr->lite_n; i++)
449 y = floor_ptr->lite_y[i];
450 x = floor_ptr->lite_x[i];
452 /* Mark the grid as not "lite" */
453 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
455 /* Mark the grid as "seen" */
456 floor_ptr->grid_array[y][x].info |= (CAVE_TEMP);
458 /* Add it to the "seen" set */
459 tmp_pos.y[tmp_pos.n] = y;
460 tmp_pos.x[tmp_pos.n] = x;
465 floor_ptr->lite_n = 0;
468 /*** Collect the new "lite" grids ***/
470 /* Radius 1 -- torch radius */
474 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x);
477 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x);
478 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x);
479 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 1);
480 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 1);
483 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1);
484 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1);
485 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1);
486 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1);
489 /* Radius 2 -- lantern radius */
492 /* South of the player */
493 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x))
495 cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x);
496 cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 1);
497 cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 1);
500 /* North of the player */
501 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x))
503 cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x);
504 cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 1);
505 cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 1);
508 /* East of the player */
509 if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x + 1))
511 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 2);
512 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 2);
513 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 2);
516 /* West of the player */
517 if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x - 1))
519 cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 2);
520 cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 2);
521 cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 2);
525 /* Radius 3+ -- artifact radius */
530 /* Paranoia -- see "LITE_MAX" */
533 /* South-East of the player */
534 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1))
536 cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 2);
539 /* South-West of the player */
540 if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1))
542 cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 2);
545 /* North-East of the player */
546 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1))
548 cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 2);
551 /* North-West of the player */
552 if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1))
554 cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 2);
558 min_y = subject_ptr->y - p;
559 if (min_y < 0) min_y = 0;
562 max_y = subject_ptr->y + p;
563 if (max_y > floor_ptr->height - 1) max_y = floor_ptr->height - 1;
566 min_x = subject_ptr->x - p;
567 if (min_x < 0) min_x = 0;
570 max_x = subject_ptr->x + p;
571 if (max_x > floor_ptr->width - 1) max_x = floor_ptr->width - 1;
573 /* Scan the maximal box */
574 for (y = min_y; y <= max_y; y++)
576 for (x = min_x; x <= max_x; x++)
578 int dy = (subject_ptr->y > y) ? (subject_ptr->y - y) : (y - subject_ptr->y);
579 int dx = (subject_ptr->x > x) ? (subject_ptr->x - x) : (x - subject_ptr->x);
581 /* Skip the "central" grids (above) */
582 if ((dy <= 2) && (dx <= 2)) continue;
584 /* Hack -- approximate the distance */
585 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
587 /* Skip distant grids */
590 /* Viewable, nearby, grids get "torch lit" */
591 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW)
593 /* This grid is "torch lit" */
594 cave_lite_hack(floor_ptr, y, x);
601 /*** Complete the algorithm ***/
603 /* Draw the new grids */
604 for (i = 0; i < floor_ptr->lite_n; i++)
606 y = floor_ptr->lite_y[i];
607 x = floor_ptr->lite_x[i];
609 g_ptr = &floor_ptr->grid_array[y][x];
611 /* Update fresh grids */
612 if (g_ptr->info & (CAVE_TEMP)) continue;
614 /* Add it to later visual update */
615 cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
619 for (i = 0; i < tmp_pos.n; i++)
624 g_ptr = &floor_ptr->grid_array[y][x];
626 /* No longer in the array */
627 g_ptr->info &= ~(CAVE_TEMP);
629 /* Update stale grids */
630 if (g_ptr->info & (CAVE_LITE)) continue;
632 /* Add it to later visual update */
633 cave_redraw_later(floor_ptr, g_ptr, y, x);
639 /* Mega-Hack -- Visual update later */
640 subject_ptr->update |= (PU_DELAY_VIS);
645 * Clear the viewable space
647 void forget_view(floor_type *floor_ptr)
654 if (!floor_ptr->view_n) return;
657 for (i = 0; i < floor_ptr->view_n; i++)
659 POSITION y = floor_ptr->view_y[i];
660 POSITION x = floor_ptr->view_x[i];
661 g_ptr = &floor_ptr->grid_array[y][x];
663 /* Forget that the grid is viewable */
664 g_ptr->info &= ~(CAVE_VIEW);
666 /* if (!panel_contains(y, x)) continue; */
668 /* Update the screen */
669 /* lite_spot(y, x); Perhaps don't need? */
673 floor_ptr->view_n = 0;
678 * Helper function for "update_view()" below
680 * We are checking the "viewability" of grid (y,x) by the player.
682 * This function assumes that (y,x) is legal (i.e. on the map).
684 * Grid (y1,x1) is on the "diagonal" between (subject_ptr->y,subject_ptr->x) and (y,x)
685 * Grid (y2,x2) is "adjacent", also between (subject_ptr->y,subject_ptr->x) and (y,x).
687 * Note that we are using the "CAVE_XTRA" field for marking grids as
688 * "easily viewable". This bit is cleared at the end of "update_view()".
690 * This function adds (y,x) to the "viewable set" if necessary.
692 * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
694 static bool update_view_aux(player_type *subject_ptr, POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
696 bool f1, f2, v1, v2, z1, z2, wall;
703 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
704 g1_c_ptr = &floor_ptr->grid_array[y1][x1];
705 g2_c_ptr = &floor_ptr->grid_array[y2][x2];
708 /* Check for walls */
709 f1 = (cave_los_grid(g1_c_ptr));
710 f2 = (cave_los_grid(g2_c_ptr));
712 /* Totally blocked by physical walls */
713 if (!f1 && !f2) return TRUE;
716 /* Check for visibility */
717 v1 = (f1 && (g1_c_ptr->info & (CAVE_VIEW)));
718 v2 = (f2 && (g2_c_ptr->info & (CAVE_VIEW)));
720 /* Totally blocked by "unviewable neighbors" */
721 if (!v1 && !v2) return TRUE;
723 g_ptr = &floor_ptr->grid_array[y][x];
726 /* Check for walls */
727 wall = (!cave_los_grid(g_ptr));
730 /* Check the "ease" of visibility */
731 z1 = (v1 && (g1_c_ptr->info & (CAVE_XTRA)));
732 z2 = (v2 && (g2_c_ptr->info & (CAVE_XTRA)));
734 /* Hack -- "easy" plus "easy" yields "easy" */
737 g_ptr->info |= (CAVE_XTRA);
739 cave_view_hack(floor_ptr, g_ptr, y, x);
744 /* Hack -- primary "easy" yields "viewed" */
747 cave_view_hack(floor_ptr, g_ptr, y, x);
752 /* Hack -- "view" plus "view" yields "view" */
755 /* g_ptr->info |= (CAVE_XTRA); */
757 cave_view_hack(floor_ptr, g_ptr, y, x);
763 /* Mega-Hack -- the "los()" function works poorly on walls */
766 cave_view_hack(floor_ptr, g_ptr, y, x);
772 /* Hack -- check line of sight */
773 if (los(floor_ptr, subject_ptr->y, subject_ptr->x, y, x))
775 cave_view_hack(floor_ptr, g_ptr, y, x);
781 /* Assume no line of sight. */
787 * Calculate the viewable space
789 * 1: Process the player
790 * 1a: The player is always (easily) viewable
791 * 2: Process the diagonals
792 * 2a: The diagonals are (easily) viewable up to the first wall
793 * 2b: But never go more than 2/3 of the "full" distance
794 * 3: Process the main axes
795 * 3a: The main axes are (easily) viewable up to the first wall
796 * 3b: But never go more than the "full" distance
797 * 4: Process sequential "strips" in each of the eight octants
798 * 4a: Each strip runs along the previous strip
799 * 4b: The main axes are "previous" to the first strip
800 * 4c: Process both "sides" of each "direction" of each strip
801 * 4c1: Each side aborts as soon as possible
802 * 4c2: Each side tells the next strip how far it has to check
804 * Note that the octant processing involves some pretty interesting
805 * observations involving when a grid might possibly be viewable from
806 * a given grid, and on the order in which the strips are processed.
808 * Note the use of the mathematical facts shown below, which derive
809 * from the fact that (1 < sqrt(2) < 1.5), and that the length of the
810 * hypotenuse of a right triangle is primarily determined by the length
811 * of the longest side, when one side is small, and is strictly less
812 * than one-and-a-half times as long as the longest side when both of
813 * the sides are large.
815 * if (manhatten(dy,dx) < R) then (hypot(dy,dx) < R)
816 * if (manhatten(dy,dx) > R*3/2) then (hypot(dy,dx) > R)
818 * hypot(dy,dx) is approximated by (dx+dy+MAX(dx,dy)) / 2
820 * These observations are important because the calculation of the actual
821 * value of "hypot(dx,dy)" is extremely expensive, involving square roots,
822 * while for small values (up to about 20 or so), the approximations above
823 * are correct to within an error of at most one grid or so.
825 * Observe the use of "full" and "over" in the code below, and the use of
826 * the specialized calculation involving "limit", all of which derive from
827 * the observations given above. Basically, we note that the "circle" of
828 * view is completely contained in an "octagon" whose bounds are easy to
829 * determine, and that only a few steps are needed to derive the actual
830 * bounds of the circle given the bounds of the octagon.
832 * Note that by skipping all the grids in the corners of the octagon, we
833 * place an upper limit on the number of grids in the field of view, given
834 * that "full" is never more than 20. Of the 1681 grids in the "square" of
835 * view, only about 1475 of these are in the "octagon" of view, and even
836 * fewer are in the "circle" of view, so 1500 or 1536 is more than enough
837 * entries to completely contain the actual field of view.
839 * Note also the care taken to prevent "running off the map". The use of
840 * explicit checks on the "validity" of the "diagonal", and the fact that
841 * the loops are never allowed to "leave" the map, lets "update_view_aux()"
842 * use the optimized "cave_los_bold()" macro, and to avoid the overhead
843 * of multiple checks on the validity of grids.
845 * Note the "optimizations" involving the "se","sw","ne","nw","es","en",
846 * "ws","wn" variables. They work like this: While travelling down the
847 * south-bound strip just to the east of the main south axis, as soon as
848 * we get to a grid which does not "transmit" viewing, if all of the strips
849 * preceding us (in this case, just the main axis) had terminated at or before
850 * the same point, then we can stop, and reset the "max distance" to ourself.
851 * So, each strip (named by major axis plus offset, thus "se" in this case)
852 * maintains a "blockage" variable, initialized during the main axis step,
853 * and checks it whenever a blockage is observed. After processing each
854 * strip as far as the previous strip told us to process, the next strip is
855 * told not to go farther than the current strip's farthest viewable grid,
856 * unless open space is still available. This uses the "k" variable.
858 * Note the use of "inline" macros for efficiency. The "cave_los_grid()"
859 * macro is a replacement for "cave_los_bold()" which takes a pointer to
860 * a grid instead of its location. The "cave_view_hack()" macro is a
861 * chunk of code which adds the given location to the "view" array if it
862 * is not already there, using both the actual location and a pointer to
863 * the grid. See above.
865 * By the way, the purpose of this code is to reduce the dependancy on the
866 * "los()" function which is slow, and, in some cases, not very accurate.
868 * It is very possible that I am the only person who fully understands this
869 * function, and for that I am truly sorry, but efficiency was very important
870 * and the "simple" version of this function was just not fast enough. I am
871 * more than willing to replace this function with a simpler one, if it is
872 * equally efficient, and especially willing if the new function happens to
873 * derive "reverse-line-of-sight" at the same time, since currently monsters
874 * just use an optimized hack of "you see me, so I see you", and then use the
875 * actual "projectable()" function to check spell attacks.
877 void update_view(player_type *subject_ptr, floor_type *floor_ptr)
882 int se, sw, ne, nw, es, en, ws, wn;
886 POSITION y_max = floor_ptr->height - 1;
887 POSITION x_max = floor_ptr->width - 1;
894 if (view_reduce_view && !floor_ptr->dun_level)
896 /* Full radius (10) */
897 full = MAX_SIGHT / 2;
899 /* Octagon factor (15) */
900 over = MAX_SIGHT * 3 / 4;
906 /* Full radius (20) */
909 /* Octagon factor (30) */
910 over = MAX_SIGHT * 3 / 2;
914 /*** Step 0 -- Begin ***/
916 /* Save the old "view" grids for later */
917 for (n = 0; n < floor_ptr->view_n; n++)
919 y = floor_ptr->view_y[n];
920 x = floor_ptr->view_x[n];
921 g_ptr = &floor_ptr->grid_array[y][x];
923 /* Mark the grid as not in "view" */
924 g_ptr->info &= ~(CAVE_VIEW);
926 /* Mark the grid as "seen" */
927 g_ptr->info |= (CAVE_TEMP);
929 /* Add it to the "seen" set */
930 tmp_pos.y[tmp_pos.n] = y;
931 tmp_pos.x[tmp_pos.n] = x;
935 /* Start over with the "view" array */
936 floor_ptr->view_n = 0;
938 /*** Step 1 -- adjacent grids ***/
940 /* Now start on the player */
943 g_ptr = &floor_ptr->grid_array[y][x];
945 /* Assume the player grid is easily viewable */
946 g_ptr->info |= (CAVE_XTRA);
948 /* Assume the player grid is viewable */
949 cave_view_hack(floor_ptr, g_ptr, y, x);
952 /*** Step 2 -- Major Diagonals ***/
957 /* Scan south-east */
958 for (d = 1; d <= z; d++)
960 g_ptr = &floor_ptr->grid_array[y + d][x + d];
961 g_ptr->info |= (CAVE_XTRA);
962 cave_view_hack(floor_ptr, g_ptr, y + d, x + d);
963 if (!cave_los_grid(g_ptr)) break;
966 /* Scan south-west */
967 for (d = 1; d <= z; d++)
969 g_ptr = &floor_ptr->grid_array[y + d][x - d];
970 g_ptr->info |= (CAVE_XTRA);
971 cave_view_hack(floor_ptr, g_ptr, y + d, x - d);
972 if (!cave_los_grid(g_ptr)) break;
975 /* Scan north-east */
976 for (d = 1; d <= z; d++)
978 g_ptr = &floor_ptr->grid_array[y - d][x + d];
979 g_ptr->info |= (CAVE_XTRA);
980 cave_view_hack(floor_ptr, g_ptr, y - d, x + d);
981 if (!cave_los_grid(g_ptr)) break;
984 /* Scan north-west */
985 for (d = 1; d <= z; d++)
987 g_ptr = &floor_ptr->grid_array[y - d][x - d];
988 g_ptr->info |= (CAVE_XTRA);
989 cave_view_hack(floor_ptr, g_ptr, y - d, x - d);
990 if (!cave_los_grid(g_ptr)) break;
993 /*** Step 3 -- major axes ***/
996 for (d = 1; d <= full; d++)
998 g_ptr = &floor_ptr->grid_array[y + d][x];
999 g_ptr->info |= (CAVE_XTRA);
1000 cave_view_hack(floor_ptr, g_ptr, y + d, x);
1001 if (!cave_los_grid(g_ptr)) break;
1004 /* Initialize the "south strips" */
1008 for (d = 1; d <= full; d++)
1010 g_ptr = &floor_ptr->grid_array[y - d][x];
1011 g_ptr->info |= (CAVE_XTRA);
1012 cave_view_hack(floor_ptr, g_ptr, y - d, x);
1013 if (!cave_los_grid(g_ptr)) break;
1016 /* Initialize the "north strips" */
1020 for (d = 1; d <= full; d++)
1022 g_ptr = &floor_ptr->grid_array[y][x + d];
1023 g_ptr->info |= (CAVE_XTRA);
1024 cave_view_hack(floor_ptr, g_ptr, y, x + d);
1025 if (!cave_los_grid(g_ptr)) break;
1028 /* Initialize the "east strips" */
1032 for (d = 1; d <= full; d++)
1034 g_ptr = &floor_ptr->grid_array[y][x - d];
1035 g_ptr->info |= (CAVE_XTRA);
1036 cave_view_hack(floor_ptr, g_ptr, y, x - d);
1037 if (!cave_los_grid(g_ptr)) break;
1040 /* Initialize the "west strips" */
1044 /*** Step 4 -- Divide each "octant" into "strips" ***/
1046 /* Now check each "diagonal" (in parallel) */
1047 for (n = 1; n <= over / 2; n++)
1049 POSITION ypn, ymn, xpn, xmn;
1051 /* Acquire the "bounds" of the maximal circle */
1053 if (z > full - n) z = full - n;
1054 while ((z + n + (n >> 1)) > full) z--;
1057 /* Access the four diagonal grids */
1067 /* Maximum distance */
1068 m = MIN(z, y_max - ypn);
1071 if ((xpn <= x_max) && (n < se))
1074 for (k = n, d = 1; d <= m; d++)
1076 /* Check grid "d" in strip "n", notice "blockage" */
1077 if (update_view_aux(subject_ptr, ypn + d, xpn, ypn + d - 1, xpn - 1, ypn + d - 1, xpn))
1079 if (n + d >= se) break;
1082 /* Track most distant "non-blockage" */
1089 /* Limit the next strip */
1094 if ((xmn >= 0) && (n < sw))
1097 for (k = n, d = 1; d <= m; d++)
1099 /* Check grid "d" in strip "n", notice "blockage" */
1100 if (update_view_aux(subject_ptr, ypn + d, xmn, ypn + d - 1, xmn + 1, ypn + d - 1, xmn))
1102 if (n + d >= sw) break;
1105 /* Track most distant "non-blockage" */
1112 /* Limit the next strip */
1121 /* Maximum distance */
1125 if ((xpn <= x_max) && (n < ne))
1128 for (k = n, d = 1; d <= m; d++)
1130 /* Check grid "d" in strip "n", notice "blockage" */
1131 if (update_view_aux(subject_ptr, ymn - d, xpn, ymn - d + 1, xpn - 1, ymn - d + 1, xpn))
1133 if (n + d >= ne) break;
1136 /* Track most distant "non-blockage" */
1143 /* Limit the next strip */
1148 if ((xmn >= 0) && (n < nw))
1151 for (k = n, d = 1; d <= m; d++)
1153 /* Check grid "d" in strip "n", notice "blockage" */
1154 if (update_view_aux(subject_ptr, ymn - d, xmn, ymn - d + 1, xmn + 1, ymn - d + 1, xmn))
1156 if (n + d >= nw) break;
1159 /* Track most distant "non-blockage" */
1166 /* Limit the next strip */
1175 /* Maximum distance */
1176 m = MIN(z, x_max - xpn);
1179 if ((ypn <= x_max) && (n < es))
1182 for (k = n, d = 1; d <= m; d++)
1184 /* Check grid "d" in strip "n", notice "blockage" */
1185 if (update_view_aux(subject_ptr, ypn, xpn + d, ypn - 1, xpn + d - 1, ypn, xpn + d - 1))
1187 if (n + d >= es) break;
1190 /* Track most distant "non-blockage" */
1197 /* Limit the next strip */
1202 if ((ymn >= 0) && (n < en))
1205 for (k = n, d = 1; d <= m; d++)
1207 /* Check grid "d" in strip "n", notice "blockage" */
1208 if (update_view_aux(subject_ptr, ymn, xpn + d, ymn + 1, xpn + d - 1, ymn, xpn + d - 1))
1210 if (n + d >= en) break;
1213 /* Track most distant "non-blockage" */
1220 /* Limit the next strip */
1229 /* Maximum distance */
1233 if ((ypn <= y_max) && (n < ws))
1236 for (k = n, d = 1; d <= m; d++)
1238 /* Check grid "d" in strip "n", notice "blockage" */
1239 if (update_view_aux(subject_ptr, ypn, xmn - d, ypn - 1, xmn - d + 1, ypn, xmn - d + 1))
1241 if (n + d >= ws) break;
1244 /* Track most distant "non-blockage" */
1251 /* Limit the next strip */
1256 if ((ymn >= 0) && (n < wn))
1259 for (k = n, d = 1; d <= m; d++)
1261 /* Check grid "d" in strip "n", notice "blockage" */
1262 if (update_view_aux(subject_ptr, ymn, xmn - d, ymn + 1, xmn - d + 1, ymn, xmn - d + 1))
1264 if (n + d >= wn) break;
1267 /* Track most distant "non-blockage" */
1274 /* Limit the next strip */
1281 /*** Step 5 -- Complete the algorithm ***/
1283 /* Update all the new grids */
1284 for (n = 0; n < floor_ptr->view_n; n++)
1286 y = floor_ptr->view_y[n];
1287 x = floor_ptr->view_x[n];
1288 g_ptr = &floor_ptr->grid_array[y][x];
1290 /* Clear the "CAVE_XTRA" flag */
1291 g_ptr->info &= ~(CAVE_XTRA);
1293 /* Update only newly viewed grids */
1294 if (g_ptr->info & (CAVE_TEMP)) continue;
1296 /* Add it to later visual update */
1297 cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
1300 /* Wipe the old grids, update as needed */
1301 for (n = 0; n < tmp_pos.n; n++)
1305 g_ptr = &floor_ptr->grid_array[y][x];
1307 /* No longer in the array */
1308 g_ptr->info &= ~(CAVE_TEMP);
1310 /* Update only non-viewable grids */
1311 if (g_ptr->info & (CAVE_VIEW)) continue;
1313 /* Add it to later visual update */
1314 cave_redraw_later(floor_ptr, g_ptr, y, x);
1320 /* Mega-Hack -- Visual update later */
1321 subject_ptr->update |= (PU_DELAY_VIS);
1326 * @brief モンスターによる光量状態更新 / Add a square to the changes array
1327 * @param subject_ptr 主観となるクリーチャーの参照ポインタ
1331 static void mon_lite_hack(player_type *subject_ptr, POSITION y, POSITION x)
1337 /* We trust this grid is in bounds */
1338 /* if (!in_bounds2(y, x)) return; */
1340 g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
1342 /* Want a unlit square in view of the player */
1343 if ((g_ptr->info & (CAVE_MNLT | CAVE_VIEW)) != CAVE_VIEW) return;
1345 if (!cave_los_grid(g_ptr))
1347 /* Hack -- Prevent monster lite leakage in walls */
1349 /* Horizontal walls between player and a monster */
1350 if (((y < subject_ptr->y) && (y > mon_fy)) || ((y > subject_ptr->y) && (y < mon_fy)))
1352 dpf = subject_ptr->y - mon_fy;
1354 midpoint = mon_fx + ((subject_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
1356 /* Only first wall viewed from mid-x is lit */
1359 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x + 1)) return;
1361 else if (x > midpoint)
1363 if (!cave_los_bold(subject_ptr->current_floor_ptr, y, x - 1)) return;
1366 /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1367 else if (mon_invis) return;
1370 /* Vertical walls between player and a monster */
1371 if (((x < subject_ptr->x) && (x > mon_fx)) || ((x > subject_ptr->x) && (x < mon_fx)))
1373 dpf = subject_ptr->x - mon_fx;
1375 midpoint = mon_fy + ((subject_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
1377 /* Only first wall viewed from mid-y is lit */
1380 if (!cave_los_bold(subject_ptr->current_floor_ptr, y + 1, x)) return;
1382 else if (y > midpoint)
1384 if (!cave_los_bold(subject_ptr->current_floor_ptr, y - 1, x)) return;
1387 /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1388 else if (mon_invis) return;
1392 /* We trust tmp_pos.n does not exceed TEMP_MAX */
1395 if (!(g_ptr->info & CAVE_MNDK))
1397 /* Save this square */
1398 tmp_pos.x[tmp_pos.n] = x;
1399 tmp_pos.y[tmp_pos.n] = y;
1406 /* No longer dark */
1407 g_ptr->info &= ~(CAVE_MNDK);
1411 g_ptr->info |= CAVE_MNLT;
1416 * Add a square to the changes array
1418 static void mon_dark_hack(player_type *subject_ptr, POSITION y, POSITION x)
1421 int midpoint, dpf, d;
1423 /* We trust this grid is in bounds */
1424 /* if (!in_bounds2(y, x)) return; */
1426 g_ptr = &subject_ptr->current_floor_ptr->grid_array[y][x];
1428 /* Want a unlit and undarkened square in view of the player */
1429 if ((g_ptr->info & (CAVE_LITE | CAVE_MNLT | CAVE_MNDK | CAVE_VIEW)) != CAVE_VIEW) return;
1431 if (!cave_los_grid(g_ptr) && !cave_have_flag_grid(g_ptr, FF_PROJECT))
1433 /* Hack -- Prevent monster dark lite leakage in walls */
1435 /* Horizontal walls between player and a monster */
1436 if (((y < subject_ptr->y) && (y > mon_fy)) || ((y > subject_ptr->y) && (y < mon_fy)))
1438 dpf = subject_ptr->y - mon_fy;
1440 midpoint = mon_fx + ((subject_ptr->x - mon_fx) * ABS(d)) / ABS(dpf);
1442 /* Only first wall viewed from mid-x is lit */
1445 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;
1447 else if (x > midpoint)
1449 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;
1452 /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1453 else if (mon_invis) return;
1456 /* Vertical walls between player and a monster */
1457 if (((x < subject_ptr->x) && (x > mon_fx)) || ((x > subject_ptr->x) && (x < mon_fx)))
1459 dpf = subject_ptr->x - mon_fx;
1461 midpoint = mon_fy + ((subject_ptr->y - mon_fy) * ABS(d)) / ABS(dpf);
1463 /* Only first wall viewed from mid-y is lit */
1466 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;
1468 else if (y > midpoint)
1470 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;
1473 /* Hack XXX XXX - Is it a wall and monster not in LOS? */
1474 else if (mon_invis) return;
1478 /* We trust tmp_pos.n does not exceed TEMP_MAX */
1480 /* Save this square */
1481 tmp_pos.x[tmp_pos.n] = x;
1482 tmp_pos.y[tmp_pos.n] = y;
1486 g_ptr->info |= CAVE_MNDK;
1490 * Update squares illuminated or darkened by monsters.
1492 * Hack - use the CAVE_ROOM flag (renamed to be CAVE_MNLT) to
1493 * denote squares illuminated by monsters.
1495 * The CAVE_TEMP and CAVE_XTRA flag are used to store the state during the
1496 * updating. Only squares in view of the player, whos state
1497 * changes are drawn via lite_spot().
1499 void update_mon_lite(player_type *subject_ptr)
1505 void(*add_mon_lite)(player_type *, POSITION, POSITION);
1510 /* Non-Ninja player in the darkness */
1511 int dis_lim = ((d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) && !subject_ptr->see_nocto) ?
1512 (MAX_SIGHT / 2 + 1) : (MAX_SIGHT + 3);
1514 /* Clear all monster lit squares */
1515 floor_type *floor_ptr = subject_ptr->current_floor_ptr;
1516 for (i = 0; i < floor_ptr->mon_lite_n; i++)
1519 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
1521 /* Set temp or xtra flag */
1522 g_ptr->info |= (g_ptr->info & CAVE_MNLT) ? CAVE_TEMP : CAVE_XTRA;
1524 /* Clear monster illumination flag */
1525 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
1528 /* Empty temp list of new squares to lite up */
1531 /* If a monster stops time, don't process */
1532 if (!current_world_ptr->timewalk_m_idx)
1534 monster_type *m_ptr;
1535 monster_race *r_ptr;
1537 /* Loop through monsters, adding newly lit squares to changes list */
1538 for (i = 1; i < floor_ptr->m_max; i++)
1540 m_ptr = &floor_ptr->m_list[i];
1541 r_ptr = &r_info[m_ptr->r_idx];
1542 if (!monster_is_valid(m_ptr)) continue;
1544 /* Is it too far away? */
1545 if (m_ptr->cdis > dis_lim) continue;
1547 /* Get lite radius */
1550 /* Note the radii are cumulative */
1551 if (r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_SELF_LITE_1)) rad++;
1552 if (r_ptr->flags7 & (RF7_HAS_LITE_2 | RF7_SELF_LITE_2)) rad += 2;
1553 if (r_ptr->flags7 & (RF7_HAS_DARK_1 | RF7_SELF_DARK_1)) rad--;
1554 if (r_ptr->flags7 & (RF7_HAS_DARK_2 | RF7_SELF_DARK_2)) rad -= 2;
1556 /* Exit if has no light */
1560 if (!(r_ptr->flags7 & (RF7_SELF_LITE_1 | RF7_SELF_LITE_2)) && (MON_CSLEEP(m_ptr) || (!floor_ptr->dun_level && is_daytime()) || subject_ptr->phase_out)) continue;
1561 if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS) rad = 1;
1562 add_mon_lite = mon_lite_hack;
1567 if (!(r_ptr->flags7 & (RF7_SELF_DARK_1 | RF7_SELF_DARK_2)) && (MON_CSLEEP(m_ptr) || (!floor_ptr->dun_level && !is_daytime()))) continue;
1568 add_mon_lite = mon_dark_hack;
1569 f_flag = FF_PROJECT;
1570 rad = -rad; /* Use absolute value */
1576 /* Is the monster visible? */
1577 mon_invis = !(floor_ptr->grid_array[mon_fy][mon_fx].info & CAVE_VIEW);
1579 /* The square it is on */
1580 add_mon_lite(subject_ptr, mon_fy, mon_fx);
1582 /* Adjacent squares */
1583 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx);
1584 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx);
1585 add_mon_lite(subject_ptr, mon_fy, mon_fx + 1);
1586 add_mon_lite(subject_ptr, mon_fy, mon_fx - 1);
1587 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 1);
1588 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 1);
1589 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 1);
1590 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 1);
1595 /* South of the monster */
1596 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx, f_flag))
1598 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx + 1);
1599 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx);
1600 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx - 1);
1602 g_ptr = &floor_ptr->grid_array[mon_fy + 2][mon_fx];
1605 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1607 add_mon_lite(subject_ptr, mon_fy + 3, mon_fx + 1);
1608 add_mon_lite(subject_ptr, mon_fy + 3, mon_fx);
1609 add_mon_lite(subject_ptr, mon_fy + 3, mon_fx - 1);
1613 /* North of the monster */
1614 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx, f_flag))
1616 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx + 1);
1617 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx);
1618 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx - 1);
1620 g_ptr = &floor_ptr->grid_array[mon_fy - 2][mon_fx];
1623 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1625 add_mon_lite(subject_ptr, mon_fy - 3, mon_fx + 1);
1626 add_mon_lite(subject_ptr, mon_fy - 3, mon_fx);
1627 add_mon_lite(subject_ptr, mon_fy - 3, mon_fx - 1);
1631 /* East of the monster */
1632 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy, mon_fx + 1, f_flag))
1634 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 2);
1635 add_mon_lite(subject_ptr, mon_fy, mon_fx + 2);
1636 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 2);
1638 g_ptr = &floor_ptr->grid_array[mon_fy][mon_fx + 2];
1641 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1643 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx + 3);
1644 add_mon_lite(subject_ptr, mon_fy, mon_fx + 3);
1645 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx + 3);
1649 /* West of the monster */
1650 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy, mon_fx - 1, f_flag))
1652 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 2);
1653 add_mon_lite(subject_ptr, mon_fy, mon_fx - 2);
1654 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 2);
1656 g_ptr = &floor_ptr->grid_array[mon_fy][mon_fx - 2];
1659 if ((rad == 3) && cave_have_flag_grid(g_ptr, f_flag))
1661 add_mon_lite(subject_ptr, mon_fy + 1, mon_fx - 3);
1662 add_mon_lite(subject_ptr, mon_fy, mon_fx - 3);
1663 add_mon_lite(subject_ptr, mon_fy - 1, mon_fx - 3);
1671 /* South-East of the monster */
1672 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx + 1, f_flag))
1674 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx + 2);
1677 /* South-West of the monster */
1678 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy + 1, mon_fx - 1, f_flag))
1680 add_mon_lite(subject_ptr, mon_fy + 2, mon_fx - 2);
1683 /* North-East of the monster */
1684 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx + 1, f_flag))
1686 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx + 2);
1689 /* North-West of the monster */
1690 if (cave_have_flag_bold(subject_ptr->current_floor_ptr, mon_fy - 1, mon_fx - 1, f_flag))
1692 add_mon_lite(subject_ptr, mon_fy - 2, mon_fx - 2);
1698 /* Save end of list of new squares */
1699 end_temp = tmp_pos.n;
1702 * Look at old set flags to see if there are any changes.
1704 for (i = 0; i < floor_ptr->mon_lite_n; i++)
1706 fx = floor_ptr->mon_lite_x[i];
1707 fy = floor_ptr->mon_lite_y[i];
1709 /* We trust this grid is in bounds */
1712 g_ptr = &floor_ptr->grid_array[fy][fx];
1714 if (g_ptr->info & CAVE_TEMP) /* Pervious lit */
1716 /* It it no longer lit? */
1717 if ((g_ptr->info & (CAVE_VIEW | CAVE_MNLT)) == CAVE_VIEW)
1719 /* It is now unlit */
1720 /* Add it to later visual update */
1721 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1724 else /* Pervious darkened */
1726 /* It it no longer darken? */
1727 if ((g_ptr->info & (CAVE_VIEW | CAVE_MNDK)) == CAVE_VIEW)
1729 /* It is now undarken */
1730 /* Add it to later visual update */
1731 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1735 /* Add to end of temp array */
1736 tmp_pos.x[tmp_pos.n] = fx;
1737 tmp_pos.y[tmp_pos.n] = fy;
1741 /* Clear the lite array */
1742 floor_ptr->mon_lite_n = 0;
1744 /* Copy the temp array into the lit array lighting the new squares. */
1745 for (i = 0; i < end_temp; i++)
1750 /* We trust this grid is in bounds */
1753 g_ptr = &floor_ptr->grid_array[fy][fx];
1755 if (g_ptr->info & CAVE_MNLT) /* Lit */
1757 /* The is the square newly lit and visible? */
1758 if ((g_ptr->info & (CAVE_VIEW | CAVE_TEMP)) == CAVE_VIEW)
1761 /* Add it to later visual update */
1762 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1767 /* The is the square newly darkened and visible? */
1768 if ((g_ptr->info & (CAVE_VIEW | CAVE_XTRA)) == CAVE_VIEW)
1770 /* It is now darkened */
1771 /* Add it to later visual update */
1772 cave_note_and_redraw_later(floor_ptr, g_ptr, fy, fx);
1776 /* Save in the monster lit or darkened array */
1777 floor_ptr->mon_lite_x[floor_ptr->mon_lite_n] = fx;
1778 floor_ptr->mon_lite_y[floor_ptr->mon_lite_n] = fy;
1779 floor_ptr->mon_lite_n++;
1782 /* Clear the temp flag for the old lit or darken grids */
1783 for (i = end_temp; i < tmp_pos.n; i++)
1785 /* We trust this grid is in bounds */
1787 floor_ptr->grid_array[tmp_pos.y[i]][tmp_pos.x[i]].info &= ~(CAVE_TEMP | CAVE_XTRA);
1790 /* Finished with tmp_pos.n */
1793 /* Mega-Hack -- Visual update later */
1794 subject_ptr->update |= (PU_DELAY_VIS);
1796 subject_ptr->monlite = (floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_MNLT) ? TRUE : FALSE;
1798 if (subject_ptr->special_defense & NINJA_S_STEALTH)
1800 if (subject_ptr->old_monlite != subject_ptr->monlite)
1802 if (subject_ptr->monlite)
1804 msg_print(_("影の覆いが薄れた気がする。", "Your mantle of shadow become thin."));
1808 msg_print(_("影の覆いが濃くなった!", "Your mantle of shadow restored its original darkness."));
1812 subject_ptr->old_monlite = subject_ptr->monlite;
1815 void clear_mon_lite(floor_type *floor_ptr)
1820 /* Clear all monster lit squares */
1821 for (i = 0; i < floor_ptr->mon_lite_n; i++)
1824 g_ptr = &floor_ptr->grid_array[floor_ptr->mon_lite_y[i]][floor_ptr->mon_lite_x[i]];
1826 /* Clear monster illumination flag */
1827 g_ptr->info &= ~(CAVE_MNLT | CAVE_MNDK);
1830 /* Empty the array */
1831 floor_ptr->mon_lite_n = 0;