OSDN Git Service

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