OSDN Git Service

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