OSDN Git Service

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