OSDN Git Service

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