OSDN Git Service

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