OSDN Git Service

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