OSDN Git Service

4f26c5e748a83c80e3255918a6792b5e04df9992
[hengband/hengband.git] / src / floor / floor-events.c
1 #include "floor/floor-events.h"
2 #include "cmd-io/cmd-dump.h"
3 #include "core/disturbance.h"
4 #include "core/player-redraw-types.h"
5 #include "core/player-update-types.h"
6 #include "core/window-redrawer.h"
7 #include "dungeon/dungeon-flag-types.h"
8 #include "dungeon/dungeon.h"
9 #include "dungeon/quest.h"
10 #include "floor/cave.h"
11 #include "floor/floor.h"
12 #include "game-option/birth-options.h"
13 #include "game-option/cheat-options.h"
14 #include "game-option/disturbance-options.h"
15 #include "game-option/map-screen-options.h"
16 #include "grid/feature-flag-types.h"
17 #include "grid/grid.h"
18 #include "main/sound-of-music.h"
19 #include "mind/mind-ninja.h"
20 #include "monster-floor/monster-lite.h"
21 #include "monster-race/monster-race.h"
22 #include "monster-race/race-flags1.h"
23 #include "monster-race/race-flags7.h"
24 #include "monster/monster-info.h"
25 #include "monster/monster-list.h"
26 #include "monster/monster-status.h"
27 #include "object-enchant/object-ego.h"
28 #include "object-enchant/special-object-flags.h"
29 #include "object-hook/hook-checker.h"
30 #include "object-hook/hook-enchant.h"
31 #include "object/object-kind.h"
32 #include "object/object-mark-types.h"
33 #include "object/object-value.h"
34 #include "perception/object-perception.h"
35 #include "player/special-defense-types.h"
36 #include "sv-definition/sv-amulet-types.h"
37 #include "sv-definition/sv-protector-types.h"
38 #include "sv-definition/sv-ring-types.h"
39 #include "system/floor-type-definition.h"
40 #include "util/bit-flags-calculator.h"
41 #include "view/display-messages.h"
42 #include "world/world.h"
43
44 void day_break(player_type *subject_ptr)
45 {
46     msg_print(_("夜が明けた。", "The sun has risen."));
47     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
48     if (!subject_ptr->wild_mode) {
49         for (POSITION y = 0; y < floor_ptr->height; y++) {
50             for (POSITION x = 0; x < floor_ptr->width; x++) {
51                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
52                 g_ptr->info |= CAVE_GLOW;
53                 if (view_perma_grids)
54                     g_ptr->info |= CAVE_MARK;
55
56                 note_spot(subject_ptr, y, x);
57             }
58         }
59     }
60
61     subject_ptr->update |= PU_MONSTERS | PU_MON_LITE;
62     subject_ptr->redraw |= PR_MAP;
63     subject_ptr->window |= PW_OVERHEAD | PW_DUNGEON;
64     if (((subject_ptr->special_defense & NINJA_S_STEALTH) != 0) && ((floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_GLOW) != 0))
65         set_superstealth(subject_ptr, FALSE);
66 }
67
68 void night_falls(player_type *subject_ptr)
69 {
70     msg_print(_("日が沈んだ。", "The sun has fallen."));
71     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
72     if (!subject_ptr->wild_mode) {
73         for (POSITION y = 0; y < floor_ptr->height; y++) {
74             for (POSITION x = 0; x < floor_ptr->width; x++) {
75                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
76                 feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)];
77                 if (is_mirror_grid(g_ptr) || have_flag(f_ptr->flags, FF_QUEST_ENTER) || have_flag(f_ptr->flags, FF_ENTRANCE))
78                     continue;
79
80                 g_ptr->info &= ~(CAVE_GLOW);
81                 if (!have_flag(f_ptr->flags, FF_REMEMBER)) {
82                     g_ptr->info &= ~(CAVE_MARK);
83                     note_spot(subject_ptr, y, x);
84                 }
85             }
86
87             glow_deep_lava_and_bldg(subject_ptr);
88         }
89     }
90
91     subject_ptr->update |= PU_MONSTERS | PU_MON_LITE;
92     subject_ptr->redraw |= PR_MAP;
93     subject_ptr->window |= PW_OVERHEAD | PW_DUNGEON;
94
95     if (((subject_ptr->special_defense & NINJA_S_STEALTH) != 0) && ((floor_ptr->grid_array[subject_ptr->y][subject_ptr->x].info & CAVE_GLOW) != 0))
96         set_superstealth(subject_ptr, FALSE);
97 }
98
99 /*!
100  * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
101  */
102 static int rating_boost(int delta) { return delta * delta + 50 * delta; }
103
104 /*!
105  * @brief ダンジョンの雰囲気を算出する。
106  * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor
107  * @return 算出されたダンジョンの雰囲気ランク
108  */
109 static byte get_dungeon_feeling(player_type *subject_ptr)
110 {
111     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
112     if (!floor_ptr->dun_level)
113         return 0;
114
115     const int base = 10;
116     int rating = 0;
117     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
118         monster_type *m_ptr = &floor_ptr->m_list[i];
119         monster_race *r_ptr;
120         int delta = 0;
121         if (!monster_is_valid(m_ptr) || is_pet(m_ptr))
122             continue;
123
124         r_ptr = &r_info[m_ptr->r_idx];
125         if (r_ptr->flags1 & (RF1_UNIQUE)) {
126             if (r_ptr->level + 10 > floor_ptr->dun_level)
127                 delta += (r_ptr->level + 10 - floor_ptr->dun_level) * 2 * base;
128         } else if (r_ptr->level > floor_ptr->dun_level)
129             delta += (r_ptr->level - floor_ptr->dun_level) * base;
130
131         if (r_ptr->flags1 & RF1_FRIENDS) {
132             if (5 <= get_monster_crowd_number(floor_ptr, i))
133                 delta += 1;
134         } else if (2 <= get_monster_crowd_number(floor_ptr, i))
135             delta += 1;
136
137         rating += rating_boost(delta);
138     }
139
140     for (MONSTER_IDX i = 1; i < floor_ptr->o_max; i++) {
141         object_type *o_ptr = &floor_ptr->o_list[i];
142         object_kind *k_ptr = &k_info[o_ptr->k_idx];
143         int delta = 0;
144         if (!object_is_valid(o_ptr) || (object_is_known(o_ptr) && ((o_ptr->marked & OM_TOUCHED) != 0)) || ((o_ptr->ident & IDENT_SENSE) != 0))
145             continue;
146
147         if (object_is_ego(o_ptr)) {
148             ego_item_type *e_ptr = &e_info[o_ptr->name2];
149             delta += e_ptr->rating * base;
150         }
151
152         if (object_is_artifact(o_ptr)) {
153             PRICE cost = object_value_real(subject_ptr, o_ptr);
154             delta += 10 * base;
155             if (cost > 10000L)
156                 delta += 10 * base;
157
158             if (cost > 50000L)
159                 delta += 10 * base;
160
161             if (cost > 100000L)
162                 delta += 10 * base;
163
164             if (!preserve_mode)
165                 return 1;
166         }
167
168         if (o_ptr->tval == TV_DRAG_ARMOR)
169             delta += 30 * base;
170
171         if (o_ptr->tval == TV_SHIELD && o_ptr->sval == SV_DRAGON_SHIELD)
172             delta += 5 * base;
173
174         if (o_ptr->tval == TV_GLOVES && o_ptr->sval == SV_SET_OF_DRAGON_GLOVES)
175             delta += 5 * base;
176
177         if (o_ptr->tval == TV_BOOTS && o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE)
178             delta += 5 * base;
179
180         if (o_ptr->tval == TV_HELM && o_ptr->sval == SV_DRAGON_HELM)
181             delta += 5 * base;
182
183         if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_SPEED && !object_is_cursed(o_ptr))
184             delta += 25 * base;
185
186         if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_LORDLY && !object_is_cursed(o_ptr))
187             delta += 15 * base;
188
189         if (o_ptr->tval == TV_AMULET && o_ptr->sval == SV_AMULET_THE_MAGI && !object_is_cursed(o_ptr))
190             delta += 15 * base;
191
192         if (!object_is_cursed(o_ptr) && !object_is_broken(o_ptr) && k_ptr->level > floor_ptr->dun_level)
193             delta += (k_ptr->level - floor_ptr->dun_level) * base;
194
195         rating += rating_boost(delta);
196     }
197
198     if (rating > rating_boost(1000))
199         return 2;
200
201     if (rating > rating_boost(800))
202         return 3;
203
204     if (rating > rating_boost(600))
205         return 4;
206
207     if (rating > rating_boost(400))
208         return 5;
209
210     if (rating > rating_boost(300))
211         return 6;
212
213     if (rating > rating_boost(200))
214         return 7;
215
216     if (rating > rating_boost(100))
217         return 8;
218
219     if (rating > rating_boost(0))
220         return 9;
221
222     return 10;
223 }
224
225 /*!
226  * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する
227  * / Update dungeon feeling, and announce it if changed
228  * @return なし
229  */
230 void update_dungeon_feeling(player_type *subject_ptr)
231 {
232     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
233     if (!floor_ptr->dun_level)
234         return;
235
236     if (subject_ptr->phase_out)
237         return;
238
239     int delay = MAX(10, 150 - subject_ptr->skill_fos) * (150 - floor_ptr->dun_level) * TURNS_PER_TICK / 100;
240     if (current_world_ptr->game_turn < subject_ptr->feeling_turn + delay && !cheat_xtra)
241         return;
242
243     int quest_num = quest_number(subject_ptr, floor_ptr->dun_level);
244     if (quest_num
245         && (is_fixed_quest_idx(quest_num) && !((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT) || !(quest[quest_num].flags & QUEST_FLAG_PRESET))))
246         return;
247
248     byte new_feeling = get_dungeon_feeling(subject_ptr);
249     subject_ptr->feeling_turn = current_world_ptr->game_turn;
250     if (subject_ptr->feeling == new_feeling)
251         return;
252
253     subject_ptr->feeling = new_feeling;
254     do_cmd_feeling(subject_ptr);
255     select_floor_music(subject_ptr);
256     subject_ptr->redraw |= PR_DEPTH;
257     if (disturb_minor)
258         disturb(subject_ptr, FALSE, FALSE);
259 }
260
261 /*
262  * Glow deep lava and building entrances in the floor
263  */
264 void glow_deep_lava_and_bldg(player_type *subject_ptr)
265 {
266     if (d_info[subject_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
267         return;
268
269     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
270     for (POSITION y = 0; y < floor_ptr->height; y++) {
271         for (POSITION x = 0; x < floor_ptr->width; x++) {
272             grid_type *g_ptr;
273             g_ptr = &floor_ptr->grid_array[y][x];
274             if (!have_flag(f_info[get_feat_mimic(g_ptr)].flags, FF_GLOW))
275                 continue;
276
277             for (DIRECTION i = 0; i < 9; i++) {
278                 POSITION yy = y + ddy_ddd[i];
279                 POSITION xx = x + ddx_ddd[i];
280                 if (!in_bounds2(floor_ptr, yy, xx))
281                     continue;
282
283                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
284             }
285         }
286     }
287
288     subject_ptr->update |= PU_VIEW | PU_LITE | PU_MON_LITE;
289     subject_ptr->redraw |= PR_MAP;
290 }
291
292 /*
293  * Actually erase the entire "lite" array, redrawing every grid
294  */
295 void forget_lite(floor_type *floor_ptr)
296 {
297     if (!floor_ptr->lite_n)
298         return;
299
300     for (int i = 0; i < floor_ptr->lite_n; i++) {
301         POSITION y = floor_ptr->lite_y[i];
302         POSITION x = floor_ptr->lite_x[i];
303         floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
304     }
305
306     floor_ptr->lite_n = 0;
307 }
308
309 /*
310  * Update the set of grids "illuminated" by the player's lite.
311  *
312  * This routine needs to use the results of "update_view()"
313  *
314  * Note that "blindness" does NOT affect "torch lite".  Be careful!
315  *
316  * We optimize most lites (all non-artifact lites) by using "obvious"
317  * facts about the results of "small" lite radius, and we attempt to
318  * list the "nearby" grids before the more "distant" ones in the
319  * array of torch-lit grids.
320  *
321  * We assume that "radius zero" lite is in fact no lite at all.
322  *
323  *     Torch     Lantern     Artifacts
324  *     (etc)
325  *                              ***
326  *                 ***         *****
327  *      ***       *****       *******
328  *      *@*       **@**       ***@***
329  *      ***       *****       *******
330  *                 ***         *****
331  *                              ***
332  */
333 void update_lite(player_type *subject_ptr)
334 {
335     POSITION p = subject_ptr->cur_lite;
336     grid_type *g_ptr;
337     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
338     for (int i = 0; i < floor_ptr->lite_n; i++) {
339         POSITION y = floor_ptr->lite_y[i];
340         POSITION x = floor_ptr->lite_x[i];
341         floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
342         floor_ptr->grid_array[y][x].info |= CAVE_TEMP;
343         tmp_pos.y[tmp_pos.n] = y;
344         tmp_pos.x[tmp_pos.n] = x;
345         tmp_pos.n++;
346     }
347
348     floor_ptr->lite_n = 0;
349     if (p >= 1) {
350         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x);
351         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x);
352         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x);
353         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 1);
354         cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 1);
355         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1);
356         cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1);
357         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1);
358         cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1);
359     }
360
361     if (p >= 2) {
362         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x)) {
363             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x);
364             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 1);
365             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 1);
366         }
367
368         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x)) {
369             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x);
370             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 1);
371             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 1);
372         }
373
374         if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x + 1)) {
375             cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x + 2);
376             cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 2);
377             cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 2);
378         }
379
380         if (cave_los_bold(floor_ptr, subject_ptr->y, subject_ptr->x - 1)) {
381             cave_lite_hack(floor_ptr, subject_ptr->y, subject_ptr->x - 2);
382             cave_lite_hack(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 2);
383             cave_lite_hack(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 2);
384         }
385     }
386
387     if (p >= 3) {
388         int d;
389         if (p > 14)
390             p = 14;
391
392         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x + 1))
393             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x + 2);
394
395         if (cave_los_bold(floor_ptr, subject_ptr->y + 1, subject_ptr->x - 1))
396             cave_lite_hack(floor_ptr, subject_ptr->y + 2, subject_ptr->x - 2);
397
398         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x + 1))
399             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x + 2);
400
401         if (cave_los_bold(floor_ptr, subject_ptr->y - 1, subject_ptr->x - 1))
402             cave_lite_hack(floor_ptr, subject_ptr->y - 2, subject_ptr->x - 2);
403
404         POSITION min_y = subject_ptr->y - p;
405         if (min_y < 0)
406             min_y = 0;
407
408         POSITION max_y = subject_ptr->y + p;
409         if (max_y > floor_ptr->height - 1)
410             max_y = floor_ptr->height - 1;
411
412         POSITION min_x = subject_ptr->x - p;
413         if (min_x < 0)
414             min_x = 0;
415
416         POSITION max_x = subject_ptr->x + p;
417         if (max_x > floor_ptr->width - 1)
418             max_x = floor_ptr->width - 1;
419
420         for (POSITION y = min_y; y <= max_y; y++) {
421             for (POSITION x = min_x; x <= max_x; x++) {
422                 int dy = (subject_ptr->y > y) ? (subject_ptr->y - y) : (y - subject_ptr->y);
423                 int dx = (subject_ptr->x > x) ? (subject_ptr->x - x) : (x - subject_ptr->x);
424                 if ((dy <= 2) && (dx <= 2))
425                     continue;
426
427                 d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
428                 if (d > p)
429                     continue;
430
431                 if (floor_ptr->grid_array[y][x].info & CAVE_VIEW)
432                     cave_lite_hack(floor_ptr, y, x);
433             }
434         }
435     }
436
437     for (int i = 0; i < floor_ptr->lite_n; i++) {
438         POSITION y = floor_ptr->lite_y[i];
439         POSITION x = floor_ptr->lite_x[i];
440         g_ptr = &floor_ptr->grid_array[y][x];
441         if (g_ptr->info & CAVE_TEMP)
442             continue;
443
444         cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
445     }
446
447     for (int i = 0; i < tmp_pos.n; i++) {
448         POSITION y = tmp_pos.y[i];
449         POSITION x = tmp_pos.x[i];
450         g_ptr = &floor_ptr->grid_array[y][x];
451         g_ptr->info &= ~(CAVE_TEMP);
452         if (g_ptr->info & CAVE_LITE)
453             continue;
454
455         cave_redraw_later(floor_ptr, g_ptr, y, x);
456     }
457
458     tmp_pos.n = 0;
459     subject_ptr->update |= PU_DELAY_VIS;
460 }
461
462 /*
463  * Clear the viewable space
464  */
465 void forget_view(floor_type *floor_ptr)
466 {
467     if (!floor_ptr->view_n)
468         return;
469
470     for (int i = 0; i < floor_ptr->view_n; i++) {
471         POSITION y = floor_ptr->view_y[i];
472         POSITION x = floor_ptr->view_x[i];
473         grid_type *g_ptr;
474         g_ptr = &floor_ptr->grid_array[y][x];
475         g_ptr->info &= ~(CAVE_VIEW);
476     }
477
478     floor_ptr->view_n = 0;
479 }
480
481 /*
482  * Helper function for "update_view()" below
483  *
484  * We are checking the "viewability" of grid (y,x) by the player.
485  *
486  * This function assumes that (y,x) is legal (i.e. on the map).
487  *
488  * Grid (y1,x1) is on the "diagonal" between (subject_ptr->y,subject_ptr->x) and (y,x)
489  * Grid (y2,x2) is "adjacent", also between (subject_ptr->y,subject_ptr->x) and (y,x).
490  *
491  * Note that we are using the "CAVE_XTRA" field for marking grids as
492  * "easily viewable".  This bit is cleared at the end of "update_view()".
493  *
494  * This function adds (y,x) to the "viewable set" if necessary.
495  *
496  * This function now returns "TRUE" if vision is "blocked" by grid (y,x).
497  */
498 static bool update_view_aux(player_type *subject_ptr, POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
499 {
500     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
501     grid_type *g1_c_ptr;
502     grid_type *g2_c_ptr;
503     g1_c_ptr = &floor_ptr->grid_array[y1][x1];
504     g2_c_ptr = &floor_ptr->grid_array[y2][x2];
505     bool f1 = (cave_los_grid(g1_c_ptr));
506     bool f2 = (cave_los_grid(g2_c_ptr));
507     if (!f1 && !f2)
508         return TRUE;
509
510     bool v1 = (f1 && (g1_c_ptr->info & CAVE_VIEW));
511     bool v2 = (f2 && (g2_c_ptr->info & CAVE_VIEW));
512     if (!v1 && !v2)
513         return TRUE;
514
515     grid_type *g_ptr;
516     g_ptr = &floor_ptr->grid_array[y][x];
517     bool wall = (!cave_los_grid(g_ptr));
518     bool z1 = (v1 && (g1_c_ptr->info & CAVE_XTRA));
519     bool z2 = (v2 && (g2_c_ptr->info & CAVE_XTRA));
520     if (z1 && z2) {
521         g_ptr->info |= CAVE_XTRA;
522         cave_view_hack(floor_ptr, g_ptr, y, x);
523         return wall;
524     }
525
526     if (z1) {
527         cave_view_hack(floor_ptr, g_ptr, y, x);
528         return wall;
529     }
530
531     if (v1 && v2) {
532         cave_view_hack(floor_ptr, g_ptr, y, x);
533         return wall;
534     }
535
536     if (wall) {
537         cave_view_hack(floor_ptr, g_ptr, y, x);
538         return wall;
539     }
540
541     if (los(subject_ptr, subject_ptr->y, subject_ptr->x, y, x)) {
542         cave_view_hack(floor_ptr, g_ptr, y, x);
543         return wall;
544     }
545
546     return TRUE;
547 }
548
549 /*
550  * Calculate the viewable space
551  *
552  *  1: Process the player
553  *  1a: The player is always (easily) viewable
554  *  2: Process the diagonals
555  *  2a: The diagonals are (easily) viewable up to the first wall
556  *  2b: But never go more than 2/3 of the "full" distance
557  *  3: Process the main axes
558  *  3a: The main axes are (easily) viewable up to the first wall
559  *  3b: But never go more than the "full" distance
560  *  4: Process sequential "strips" in each of the eight octants
561  *  4a: Each strip runs along the previous strip
562  *  4b: The main axes are "previous" to the first strip
563  *  4c: Process both "sides" of each "direction" of each strip
564  *  4c1: Each side aborts as soon as possible
565  *  4c2: Each side tells the next strip how far it has to check
566  */
567 void update_view(player_type *subject_ptr)
568 {
569     int n, m, d, k, z;
570     POSITION y, x;
571
572     int se, sw, ne, nw, es, en, ws, wn;
573
574     int full, over;
575
576     floor_type *floor_ptr = subject_ptr->current_floor_ptr;
577     POSITION y_max = floor_ptr->height - 1;
578     POSITION x_max = floor_ptr->width - 1;
579
580     grid_type *g_ptr;
581     if (view_reduce_view && !floor_ptr->dun_level) {
582         full = MAX_SIGHT / 2;
583         over = MAX_SIGHT * 3 / 4;
584     } else {
585         full = MAX_SIGHT;
586         over = MAX_SIGHT * 3 / 2;
587     }
588
589     for (n = 0; n < floor_ptr->view_n; n++) {
590         y = floor_ptr->view_y[n];
591         x = floor_ptr->view_x[n];
592         g_ptr = &floor_ptr->grid_array[y][x];
593         g_ptr->info &= ~(CAVE_VIEW);
594         g_ptr->info |= CAVE_TEMP;
595         tmp_pos.y[tmp_pos.n] = y;
596         tmp_pos.x[tmp_pos.n] = x;
597         tmp_pos.n++;
598     }
599
600     floor_ptr->view_n = 0;
601     y = subject_ptr->y;
602     x = subject_ptr->x;
603     g_ptr = &floor_ptr->grid_array[y][x];
604     g_ptr->info |= CAVE_XTRA;
605     cave_view_hack(floor_ptr, g_ptr, y, x);
606
607     z = full * 2 / 3;
608     for (d = 1; d <= z; d++) {
609         g_ptr = &floor_ptr->grid_array[y + d][x + d];
610         g_ptr->info |= CAVE_XTRA;
611         cave_view_hack(floor_ptr, g_ptr, y + d, x + d);
612         if (!cave_los_grid(g_ptr))
613             break;
614     }
615
616     for (d = 1; d <= z; d++) {
617         g_ptr = &floor_ptr->grid_array[y + d][x - d];
618         g_ptr->info |= CAVE_XTRA;
619         cave_view_hack(floor_ptr, g_ptr, y + d, x - d);
620         if (!cave_los_grid(g_ptr))
621             break;
622     }
623
624     for (d = 1; d <= z; d++) {
625         g_ptr = &floor_ptr->grid_array[y - d][x + d];
626         g_ptr->info |= CAVE_XTRA;
627         cave_view_hack(floor_ptr, g_ptr, y - d, x + d);
628         if (!cave_los_grid(g_ptr))
629             break;
630     }
631
632     for (d = 1; d <= z; d++) {
633         g_ptr = &floor_ptr->grid_array[y - d][x - d];
634         g_ptr->info |= CAVE_XTRA;
635         cave_view_hack(floor_ptr, g_ptr, y - d, x - d);
636         if (!cave_los_grid(g_ptr))
637             break;
638     }
639
640     for (d = 1; d <= full; d++) {
641         g_ptr = &floor_ptr->grid_array[y + d][x];
642         g_ptr->info |= CAVE_XTRA;
643         cave_view_hack(floor_ptr, g_ptr, y + d, x);
644         if (!cave_los_grid(g_ptr))
645             break;
646     }
647
648     se = sw = d;
649     for (d = 1; d <= full; d++) {
650         g_ptr = &floor_ptr->grid_array[y - d][x];
651         g_ptr->info |= CAVE_XTRA;
652         cave_view_hack(floor_ptr, g_ptr, y - d, x);
653         if (!cave_los_grid(g_ptr))
654             break;
655     }
656
657     ne = nw = d;
658     for (d = 1; d <= full; d++) {
659         g_ptr = &floor_ptr->grid_array[y][x + d];
660         g_ptr->info |= CAVE_XTRA;
661         cave_view_hack(floor_ptr, g_ptr, y, x + d);
662         if (!cave_los_grid(g_ptr))
663             break;
664     }
665
666     es = en = d;
667     for (d = 1; d <= full; d++) {
668         g_ptr = &floor_ptr->grid_array[y][x - d];
669         g_ptr->info |= CAVE_XTRA;
670         cave_view_hack(floor_ptr, g_ptr, y, x - d);
671         if (!cave_los_grid(g_ptr))
672             break;
673     }
674
675     ws = wn = d;
676     for (n = 1; n <= over / 2; n++) {
677         POSITION ypn, ymn, xpn, xmn;
678         z = over - n - n;
679         if (z > full - n)
680             z = full - n;
681
682         while ((z + n + (n >> 1)) > full)
683             z--;
684
685         ypn = y + n;
686         ymn = y - n;
687         xpn = x + n;
688         xmn = x - n;
689         if (ypn < y_max) {
690             m = MIN(z, y_max - ypn);
691             if ((xpn <= x_max) && (n < se)) {
692                 for (k = n, d = 1; d <= m; d++) {
693                     if (update_view_aux(subject_ptr, ypn + d, xpn, ypn + d - 1, xpn - 1, ypn + d - 1, xpn)) {
694                         if (n + d >= se)
695                             break;
696                     } else
697                         k = n + d;
698                 }
699
700                 se = k + 1;
701             }
702
703             if ((xmn >= 0) && (n < sw)) {
704                 for (k = n, d = 1; d <= m; d++) {
705                     if (update_view_aux(subject_ptr, ypn + d, xmn, ypn + d - 1, xmn + 1, ypn + d - 1, xmn)) {
706                         if (n + d >= sw)
707                             break;
708                     } else
709                         k = n + d;
710                 }
711
712                 sw = k + 1;
713             }
714         }
715
716         if (ymn > 0) {
717             m = MIN(z, ymn);
718             if ((xpn <= x_max) && (n < ne)) {
719                 for (k = n, d = 1; d <= m; d++) {
720                     if (update_view_aux(subject_ptr, ymn - d, xpn, ymn - d + 1, xpn - 1, ymn - d + 1, xpn)) {
721                         if (n + d >= ne)
722                             break;
723                     } else
724                         k = n + d;
725                 }
726
727                 ne = k + 1;
728             }
729
730             if ((xmn >= 0) && (n < nw)) {
731                 for (k = n, d = 1; d <= m; d++) {
732                     if (update_view_aux(subject_ptr, ymn - d, xmn, ymn - d + 1, xmn + 1, ymn - d + 1, xmn)) {
733                         if (n + d >= nw)
734                             break;
735                     } else
736                         k = n + d;
737                 }
738
739                 nw = k + 1;
740             }
741         }
742
743         if (xpn < x_max) {
744             m = MIN(z, x_max - xpn);
745             if ((ypn <= x_max) && (n < es)) {
746                 for (k = n, d = 1; d <= m; d++) {
747                     if (update_view_aux(subject_ptr, ypn, xpn + d, ypn - 1, xpn + d - 1, ypn, xpn + d - 1)) {
748                         if (n + d >= es)
749                             break;
750                     } else
751                         k = n + d;
752                 }
753
754                 es = k + 1;
755             }
756
757             if ((ymn >= 0) && (n < en)) {
758                 for (k = n, d = 1; d <= m; d++) {
759                     if (update_view_aux(subject_ptr, ymn, xpn + d, ymn + 1, xpn + d - 1, ymn, xpn + d - 1)) {
760                         if (n + d >= en)
761                             break;
762                     } else
763                         k = n + d;
764                 }
765
766                 en = k + 1;
767             }
768         }
769
770         if (xmn > 0) {
771             m = MIN(z, xmn);
772             if ((ypn <= y_max) && (n < ws)) {
773                 for (k = n, d = 1; d <= m; d++) {
774                     if (update_view_aux(subject_ptr, ypn, xmn - d, ypn - 1, xmn - d + 1, ypn, xmn - d + 1)) {
775                         if (n + d >= ws)
776                             break;
777                     } else
778                         k = n + d;
779                 }
780
781                 ws = k + 1;
782             }
783
784             if ((ymn >= 0) && (n < wn)) {
785                 for (k = n, d = 1; d <= m; d++) {
786                     if (update_view_aux(subject_ptr, ymn, xmn - d, ymn + 1, xmn - d + 1, ymn, xmn - d + 1)) {
787                         if (n + d >= wn)
788                             break;
789                     } else
790                         k = n + d;
791                 }
792
793                 wn = k + 1;
794             }
795         }
796     }
797
798     for (n = 0; n < floor_ptr->view_n; n++) {
799         y = floor_ptr->view_y[n];
800         x = floor_ptr->view_x[n];
801         g_ptr = &floor_ptr->grid_array[y][x];
802         g_ptr->info &= ~(CAVE_XTRA);
803         if (g_ptr->info & CAVE_TEMP)
804             continue;
805
806         cave_note_and_redraw_later(floor_ptr, g_ptr, y, x);
807     }
808
809     for (n = 0; n < tmp_pos.n; n++) {
810         y = tmp_pos.y[n];
811         x = tmp_pos.x[n];
812         g_ptr = &floor_ptr->grid_array[y][x];
813         g_ptr->info &= ~(CAVE_TEMP);
814         if (g_ptr->info & CAVE_VIEW)
815             continue;
816
817         cave_redraw_later(floor_ptr, g_ptr, y, x);
818     }
819
820     tmp_pos.n = 0;
821     subject_ptr->update |= PU_DELAY_VIS;
822 }