OSDN Git Service

[Refactor] #38997 is_extra_bold() に floor_type * 引数を追加. / Add floor_type * argument...
[hengband/hengband.git] / src / grid.c
1 
2  /*!
3   * @file grid.c
4   * @brief グリッドの実装 / low level dungeon routines -BEN-
5   * @date 2013/12/30
6   * @author
7   * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
8   *\n
9   * This software may be copied and distributed for educational, research,\n
10   * and not for profit purposes provided that this copyright and statement\n
11   * are included in all such copies.  Other copyrights may also apply.\n
12   * \n
13   * Support for Adam Bolt's tileset, lighting and transparency effects\n
14   * by Robert Ruehlmann (rr9@angband.org)\n
15   * \n
16   * 2013 Deskull Doxygen向けのコメント整理\n
17   */
18
19
20 #include "angband.h"
21 #include "util.h"
22 #include "term.h"
23
24 #include "floor.h"
25 #include "world.h"
26 #include "object-flavor.h"
27 #include "object-hook.h"
28 #include "dungeon.h"
29 #include "floor-generate.h"
30 #include "grid.h"
31 #include "trap.h"
32 #include "rooms.h"
33 #include "monster.h"
34 #include "quest.h"
35 #include "feature.h"
36 #include "monster-status.h"
37 #include "player-status.h"
38 #include "player-effects.h"
39 #include "player-class.h"
40 #include "spells.h"
41 #include "view-mainwindow.h"
42 #include "realm-song.h"
43
44 #define MONSTER_FLOW_DEPTH 32 /*!< 敵のプレイヤーに対する移動道のりの最大値(この値以上は処理を打ち切る) / OPTION: Maximum flow depth when using "MONSTER_FLOW" */
45
46 /*
47  * Feature action flags
48  */
49 #define FAF_DESTROY     0x01
50 #define FAF_NO_DROP     0x02
51 #define FAF_CRASH_GLASS 0x04
52
53 #define feat_locked_door_random(DOOR_TYPE) \
54         (feat_door[(DOOR_TYPE)].num_locked ? \
55          feat_door[(DOOR_TYPE)].locked[randint0(feat_door[(DOOR_TYPE)].num_locked)] : feat_none)
56
57 #define feat_jammed_door_random(DOOR_TYPE) \
58         (feat_door[(DOOR_TYPE)].num_jammed ? \
59          feat_door[(DOOR_TYPE)].jammed[randint0(feat_door[(DOOR_TYPE)].num_jammed)] : feat_none)
60
61 /*!
62  * @brief 地形状態フラグテーブル /
63  * The table of features' actions
64  */
65 static const byte feature_action_flags[FF_FLAG_MAX] =
66 {
67         0, /* LOS */
68         0, /* PROJECT */
69         0, /* MOVE */
70         0, /* PLACE */
71         0, /* DROP */
72         0, /* SECRET */
73         0, /* NOTICE */
74         0, /* REMEMBER */
75         0, /* OPEN */
76         0, /* CLOSE */
77         FAF_CRASH_GLASS, /* BASH */
78         0, /* SPIKE */
79         FAF_DESTROY, /* DISARM */
80         0, /* STORE */
81         FAF_DESTROY | FAF_CRASH_GLASS, /* TUNNEL */
82         0, /* MAY_HAVE_GOLD */
83         0, /* HAS_GOLD */
84         0, /* HAS_ITEM */
85         0, /* DOOR */
86         0, /* TRAP */
87         0, /* STAIRS */
88         0, /* GLYPH */
89         0, /* LESS */
90         0, /* MORE */
91         0, /* RUN */
92         0, /* FLOOR */
93         0, /* WALL */
94         0, /* PERMANENT */
95         0, /* INNER */
96         0, /* OUTER */
97         0, /* SOLID */
98         0, /* HIT_TRAP */
99
100         0, /* BRIDGE */
101         0, /* RIVER */
102         0, /* LAKE */
103         0, /* BRIDGED */
104         0, /* COVERED */
105         0, /* GLOW */
106         0, /* ENSECRET */
107         0, /* WATER */
108         0, /* LAVA */
109         0, /* SHALLOW */
110         0, /* DEEP */
111         0, /* FILLED */
112         FAF_DESTROY | FAF_CRASH_GLASS, /* HURT_ROCK */
113         0, /* HURT_FIRE */
114         0, /* HURT_COLD */
115         0, /* HURT_ACID */
116         0, /* ICE */
117         0, /* ACID */
118         0, /* OIL */
119         0, /* XXX04 */
120         0, /* CAN_CLIMB */
121         0, /* CAN_FLY */
122         0, /* CAN_SWIM */
123         0, /* CAN_PASS */
124         0, /* CAN_OOZE */
125         0, /* CAN_DIG */
126         0, /* HIDE_ITEM */
127         0, /* HIDE_SNEAK */
128         0, /* HIDE_SWIM */
129         0, /* HIDE_DIG */
130         0, /* KILL_HUGE */
131         0, /* KILL_MOVE */
132
133         0, /* PICK_TRAP */
134         0, /* PICK_DOOR */
135         0, /* ALLOC */
136         0, /* CHEST */
137         0, /* DROP_1D2 */
138         0, /* DROP_2D2 */
139         0, /* DROP_GOOD */
140         0, /* DROP_GREAT */
141         0, /* HURT_POIS */
142         0, /* HURT_ELEC */
143         0, /* HURT_WATER */
144         0, /* HURT_BWATER */
145         0, /* USE_FEAT */
146         0, /* GET_FEAT */
147         0, /* GROUND */
148         0, /* OUTSIDE */
149         0, /* EASY_HIDE */
150         0, /* EASY_CLIMB */
151         0, /* MUST_CLIMB */
152         0, /* TREE */
153         0, /* NEED_TREE */
154         0, /* BLOOD */
155         0, /* DUST */
156         0, /* SLIME */
157         0, /* PLANT */
158         0, /* XXX2 */
159         0, /* INSTANT */
160         0, /* EXPLODE */
161         0, /* TIMED */
162         0, /* ERUPT */
163         0, /* STRIKE */
164         0, /* SPREAD */
165
166         0, /* SPECIAL */
167         FAF_DESTROY | FAF_NO_DROP | FAF_CRASH_GLASS, /* HURT_DISI */
168         0, /* QUEST_ENTER */
169         0, /* QUEST_EXIT */
170         0, /* QUEST */
171         0, /* SHAFT */
172         0, /* MOUNTAIN */
173         0, /* BLDG */
174         0, /* MINOR_GLYPH */
175         0, /* PATTERN */
176         0, /* TOWN */
177         0, /* ENTRANCE */
178         0, /* MIRROR */
179         0, /* UNPERM */
180         0, /* TELEPORTABLE */
181         0, /* CONVERT */
182         0, /* GLASS */
183 };
184
185 /*!
186  * @brief 新規フロアに入りたてのプレイヤーをランダムな場所に配置する / Returns random co-ordinates for player/monster/object
187  * @return 配置に成功したらTRUEを返す
188  */
189 bool new_player_spot(void)
190 {
191         POSITION y = 0, x = 0;
192         int max_attempts = 10000;
193
194         grid_type *g_ptr;
195         feature_type *f_ptr;
196
197         while (max_attempts--)
198         {
199                 /* Pick a legal spot */
200                 y = (POSITION)rand_range(1, p_ptr->current_floor_ptr->height - 2);
201                 x = (POSITION)rand_range(1, p_ptr->current_floor_ptr->width - 2);
202
203                 g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
204
205                 /* Must be a "naked" floor grid */
206                 if (g_ptr->m_idx) continue;
207                 if (p_ptr->current_floor_ptr->dun_level)
208                 {
209                         f_ptr = &f_info[g_ptr->feat];
210
211                         if (max_attempts > 5000) /* Rule 1 */
212                         {
213                                 if (!have_flag(f_ptr->flags, FF_FLOOR)) continue;
214                         }
215                         else /* Rule 2 */
216                         {
217                                 if (!have_flag(f_ptr->flags, FF_MOVE)) continue;
218                                 if (have_flag(f_ptr->flags, FF_HIT_TRAP)) continue;
219                         }
220
221                         /* Refuse to start on anti-teleport grids in dungeon */
222                         if (!have_flag(f_ptr->flags, FF_TELEPORTABLE)) continue;
223                 }
224                 if (!player_can_enter(g_ptr->feat, 0)) continue;
225                 if (!in_bounds(p_ptr->current_floor_ptr, y, x)) continue;
226
227                 /* Refuse to start on anti-teleport grids */
228                 if (g_ptr->info & (CAVE_ICKY)) continue;
229
230                 break;
231         }
232
233         if (max_attempts < 1) /* Should be -1, actually if we failed... */
234                 return FALSE;
235
236         /* Save the new player grid */
237         p_ptr->y = y;
238         p_ptr->x = x;
239
240         return TRUE;
241 }
242
243
244
245 /*!
246  * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
247  * @param y 配置を試みたいマスのY座標
248  * @param x 配置を試みたいマスのX座標
249  * @return なし
250  */
251 void place_random_stairs(POSITION y, POSITION x)
252 {
253         bool up_stairs = TRUE;
254         bool down_stairs = TRUE;
255         grid_type *g_ptr;
256         g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
257         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
258
259         if (!p_ptr->current_floor_ptr->dun_level) up_stairs = FALSE;
260         if (ironman_downward) up_stairs = FALSE;
261         if (p_ptr->current_floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) down_stairs = FALSE;
262         if (quest_number(p_ptr->current_floor_ptr->dun_level) && (p_ptr->current_floor_ptr->dun_level > 1)) down_stairs = FALSE;
263
264         /* We can't place both */
265         if (down_stairs && up_stairs)
266         {
267                 /* Choose a staircase randomly */
268                 if (randint0(100) < 50) up_stairs = FALSE;
269                 else down_stairs = FALSE;
270         }
271
272         /* Place the stairs */
273         if (up_stairs) set_cave_feat(p_ptr->current_floor_ptr, y, x, feat_up_stair);
274         else if (down_stairs) set_cave_feat(p_ptr->current_floor_ptr, y, x, feat_down_stair);
275 }
276
277 /*!
278  * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
279  * @param y ドアの配置を試みたいマスのY座標
280  * @param x ドアの配置を試みたいマスのX座標
281  * @param room 部屋に接している場合向けのドア生成か否か
282  * @return なし
283  */
284 void place_random_door(POSITION y, POSITION x, bool room)
285 {
286         int tmp, type;
287         FEAT_IDX feat = feat_none;
288         grid_type *g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
289
290         /* Initialize mimic info */
291         g_ptr->mimic = 0;
292
293         if (d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
294         {
295                 place_floor_bold(y, x);
296                 return;
297         }
298
299         type = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
300                 one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
301                 ((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
302
303         /* Choose an object */
304         tmp = randint0(1000);
305
306         /* Open doors (300/1000) */
307         if (tmp < 300)
308         {
309                 /* Create open door */
310                 feat = feat_door[type].open;
311         }
312
313         /* Broken doors (100/1000) */
314         else if (tmp < 400)
315         {
316                 /* Create broken door */
317                 feat = feat_door[type].broken;
318         }
319
320         /* Secret doors (200/1000) */
321         else if (tmp < 600)
322         {
323                 /* Create secret door */
324                 place_closed_door(y, x, type);
325
326                 if (type != DOOR_CURTAIN)
327                 {
328                         /* Hide. If on the edge of room, use outer wall. */
329                         g_ptr->mimic = room ? feat_wall_outer : feat_wall_type[randint0(100)];
330
331                         /* Floor type terrain cannot hide a door */
332                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
333                         {
334                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
335                                 {
336                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
337                                 }
338                                 g_ptr->mimic = 0;
339                         }
340                 }
341         }
342
343         /* Closed, locked, or stuck doors (400/1000) */
344         else place_closed_door(y, x, type);
345
346         if (tmp < 400)
347         {
348                 if (feat != feat_none)
349                 {
350                         set_cave_feat(p_ptr->current_floor_ptr, y, x, feat);
351                 }
352                 else
353                 {
354                         place_floor_bold(y, x);
355                 }
356         }
357
358         delete_monster(y, x);
359 }
360
361 /*!
362  * @brief 所定の位置に各種の閉じたドアを配置する / Place a random type of normal door at the given location.
363  * @param y ドアの配置を試みたいマスのY座標
364  * @param x ドアの配置を試みたいマスのX座標
365  * @param type ドアの地形ID
366  * @return なし
367  */
368 void place_closed_door(POSITION y, POSITION x, int type)
369 {
370         int tmp;
371         FEAT_IDX feat = feat_none;
372
373         if (d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
374         {
375                 place_floor_bold(y, x);
376                 return;
377         }
378
379         /* Choose an object */
380         tmp = randint0(400);
381
382         /* Closed doors (300/400) */
383         if (tmp < 300)
384         {
385                 /* Create closed door */
386                 feat = feat_door[type].closed;
387         }
388
389         /* Locked doors (99/400) */
390         else if (tmp < 399)
391         {
392                 /* Create locked door */
393                 feat = feat_locked_door_random(type);
394         }
395
396         /* Stuck doors (1/400) */
397         else
398         {
399                 /* Create jammed door */
400                 feat = feat_jammed_door_random(type);
401         }
402
403         if (feat != feat_none)
404         {
405                 cave_set_feat(y, x, feat);
406
407                 /* Now it is not floor */
408                 p_ptr->current_floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
409         }
410         else
411         {
412                 place_floor_bold(y, x);
413         }
414 }
415
416 /*!
417 * @brief 鍵のかかったドアを配置する
418 * @param y 配置したいフロアのY座標
419 * @param x 配置したいフロアのX座標
420 * @return なし
421 */
422 void place_locked_door(POSITION y, POSITION x)
423 {
424         if (d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
425         {
426                 place_floor_bold(y, x);
427         }
428         else
429         {
430                 set_cave_feat(p_ptr->current_floor_ptr, y, x, feat_locked_door_random((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
431                 p_ptr->current_floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
432                 delete_monster(y, x);
433         }
434 }
435
436
437 /*!
438 * @brief 隠しドアを配置する
439 * @param y 配置したいフロアのY座標
440 * @param x 配置したいフロアのX座標
441 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
442 * @return なし
443 */
444 void place_secret_door(POSITION y, POSITION x, int type)
445 {
446         if (d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
447         {
448                 place_floor_bold(y, x);
449         }
450         else
451         {
452                 grid_type *g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
453
454                 if (type == DOOR_DEFAULT)
455                 {
456                         type = ((d_info[p_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
457                                 one_in_((d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
458                                 ((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
459                 }
460
461                 /* Create secret door */
462                 place_closed_door(y, x, type);
463
464                 if (type != DOOR_CURTAIN)
465                 {
466                         /* Hide by inner wall because this is used in rooms only */
467                         g_ptr->mimic = feat_wall_inner;
468
469                         /* Floor type terrain cannot hide a door */
470                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
471                         {
472                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
473                                 {
474                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
475                                 }
476                                 g_ptr->mimic = 0;
477                         }
478                 }
479
480                 g_ptr->info &= ~(CAVE_FLOOR);
481                 delete_monster(y, x);
482         }
483 }
484
485 /*
486  * Routine used by the random vault creators to add a door to a location
487  * Note that range checking has to be done in the calling routine.
488  *
489  * The doors must be INSIDE the allocated region.
490  */
491 void add_door(POSITION x, POSITION y)
492 {
493         /* Need to have a wall in the center square */
494         if (!is_outer_bold(y, x)) return;
495
496         /* look at:
497         *  x#x
498         *  .#.
499         *  x#x
500         *
501         *  where x=don't care
502         *  .=floor, #=wall
503         */
504
505         if (is_floor_bold(p_ptr->current_floor_ptr, y - 1, x) && is_floor_bold(p_ptr->current_floor_ptr, y + 1, x) &&
506                 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
507         {
508                 /* secret door */
509                 place_secret_door(y, x, DOOR_DEFAULT);
510
511                 /* set boundarys so don't get wide doors */
512                 place_solid_bold(y, x - 1);
513                 place_solid_bold(y, x + 1);
514         }
515
516
517         /* look at:
518         *  x#x
519         *  .#.
520         *  x#x
521         *
522         *  where x = don't care
523         *  .=floor, #=wall
524         */
525         if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
526                 is_floor_bold(p_ptr->current_floor_ptr, y, x - 1) && is_floor_bold(p_ptr->current_floor_ptr, y, x + 1))
527         {
528                 /* secret door */
529                 place_secret_door(y, x, DOOR_DEFAULT);
530
531                 /* set boundarys so don't get wide doors */
532                 place_solid_bold(y - 1, x);
533                 place_solid_bold(y + 1, x);
534         }
535 }
536
537 /*!
538 * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
539 * @param y1 基準となるマスのY座標
540 * @param x1 基準となるマスのX座標
541 * @return 通路の数
542 * @note Assumes "in_bounds(p_ptr->current_floor_ptr, y1, x1)"
543 * @details
544 * XXX XXX This routine currently only counts actual "empty floor"\n
545 * grids which are not in rooms.  We might want to also count stairs,\n
546 * open doors, closed doors, etc.
547 */
548 static int next_to_corr(POSITION y1, POSITION x1)
549 {
550         int i, k = 0;
551         POSITION y, x;
552
553         grid_type *g_ptr;
554
555         /* Scan adjacent grids */
556         for (i = 0; i < 4; i++)
557         {
558                 y = y1 + ddy_ddd[i];
559                 x = x1 + ddx_ddd[i];
560                 g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
561
562                 /* Skip non floors */
563                 if (cave_have_flag_grid(g_ptr, FF_WALL)) continue;
564
565                 /* Skip non "empty floor" grids */
566                 if (!is_floor_grid(g_ptr))
567                         continue;
568
569                 /* Skip grids inside rooms */
570                 if (g_ptr->info & (CAVE_ROOM)) continue;
571
572                 /* Count these grids */
573                 k++;
574         }
575
576         /* Return the number of corridors */
577         return (k);
578 }
579
580 /*!
581 * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
582 * @param y 判定を行いたいマスのY座標
583 * @param x 判定を行いたいマスのX座標
584 * @return ドアを設置可能ならばTRUEを返す
585 * @note Assumes "in_bounds(p_ptr->current_floor_ptr, y1, x1)"
586 * @details
587 * \n
588 * Assumes "in_bounds(p_ptr->current_floor_ptr, y, x)"\n
589 */
590 static bool possible_doorway(POSITION y, POSITION x)
591 {
592         /* Count the adjacent corridors */
593         if (next_to_corr(y, x) >= 2)
594         {
595                 /* Check Vertical */
596                 if (cave_have_flag_bold(y - 1, x, FF_WALL) &&
597                         cave_have_flag_bold(y + 1, x, FF_WALL))
598                 {
599                         return (TRUE);
600                 }
601
602                 /* Check Horizontal */
603                 if (cave_have_flag_bold(y, x - 1, FF_WALL) &&
604                         cave_have_flag_bold(y, x + 1, FF_WALL))
605                 {
606                         return (TRUE);
607                 }
608         }
609
610         /* No doorway */
611         return (FALSE);
612 }
613
614 /*!
615 * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
616 * @param y 設置を行いたいマスのY座標
617 * @param x 設置を行いたいマスのX座標
618 * @return なし
619 */
620 void try_door(POSITION y, POSITION x)
621 {       if (!in_bounds(p_ptr->current_floor_ptr, y, x)) return;
622
623         /* Ignore walls */
624         if (cave_have_flag_bold(y, x, FF_WALL)) return;
625
626         /* Ignore room grids */
627         if (p_ptr->current_floor_ptr->grid_array[y][x].info & (CAVE_ROOM)) return;
628
629         /* Occasional door (if allowed) */
630         if ((randint0(100) < dun_tun_jct) && possible_doorway(y, x) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_DOORS))
631         {
632                 /* Place a door */
633                 place_random_door(y, x, FALSE);
634         }
635 }
636
637
638 /*!
639  * @brief 長方形の空洞を生成する / Make an empty square floor, for the middle of rooms
640  * @param x1 長方形の左端X座標(-1)
641  * @param x2 長方形の右端X座標(+1)
642  * @param y1 長方形の上端Y座標(-1)
643  * @param y2 長方形の下端Y座標(+1)
644  * @param light 照明の有無
645  * @return なし
646  */
647 void place_floor(POSITION x1, POSITION x2, POSITION y1, POSITION y2, bool light)
648 {
649         POSITION x, y;
650
651         /* Place a full floor under the room */
652         for (y = y1 - 1; y <= y2 + 1; y++)
653         {
654                 for (x = x1 - 1; x <= x2 + 1; x++)
655                 {
656                         place_floor_bold(y, x);
657                         add_cave_info(y, x, CAVE_ROOM);
658                         if (light) add_cave_info(y, x, CAVE_GLOW);
659                 }
660         }
661 }
662
663
664 /*!
665  * @brief 長方形の部屋を生成する / Make an empty square room, only floor and wall grids
666  * @param x1 長方形の左端X座標(-1)
667  * @param x2 長方形の右端X座標(+1)
668  * @param y1 長方形の上端Y座標(-1)
669  * @param y2 長方形の下端Y座標(+1)
670  * @param light 照明の有無
671  * @return なし
672  */
673 void place_room(POSITION x1, POSITION x2, POSITION y1, POSITION y2, bool light)
674 {
675         POSITION y, x;
676
677         place_floor(x1, x2, y1, y2, light);
678
679         /* Walls around the room */
680         for (y = y1 - 1; y <= y2 + 1; y++)
681         {
682                 place_outer_bold(y, x1 - 1);
683                 place_outer_bold(y, x2 + 1);
684         }
685         for (x = x1 - 1; x <= x2 + 1; x++)
686         {
687                 place_outer_bold(y1 - 1, x);
688                 place_outer_bold(y2 + 1, x);
689         }
690 }
691
692
693 /*!
694  * @brief 特殊な部屋向けに各種アイテムを配置する / Create up to "num" objects near the given coordinates
695  * @param y 配置したい中心マスのY座標
696  * @param x 配置したい中心マスのX座標
697  * @param num 配置したい数
698  * @return なし
699  * @details
700  * Only really called by some of the "vault" routines.
701  */
702 void vault_objects(POSITION y, POSITION x, int num)
703 {
704         int dummy = 0;
705         int i = 0, j = y, k = x;
706
707         grid_type *g_ptr;
708
709
710         /* Attempt to place 'num' objects */
711         for (; num > 0; --num)
712         {
713                 /* Try up to 11 spots looking for empty space */
714                 for (i = 0; i < 11; ++i)
715                 {
716                         /* Pick a random location */
717                         while (dummy < SAFE_MAX_ATTEMPTS)
718                         {
719                                 j = rand_spread(y, 2);
720                                 k = rand_spread(x, 3);
721                                 dummy++;
722                                 if (!in_bounds(p_ptr->current_floor_ptr, j, k)) continue;
723                                 break;
724                         }
725
726                         if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
727                         {
728                                 msg_print(_("警告!地下室のアイテムを配置できません!", "Warning! Could not place vault object!"));
729                         }
730
731                         /* Require "clean" floor space */
732                         g_ptr = &p_ptr->current_floor_ptr->grid_array[j][k];
733                         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) continue;
734
735                         if (randint0(100) < 75)
736                         {
737                                 place_object(j, k, 0L);
738                         }
739                         else
740                         {
741                                 place_gold(j, k);
742                         }
743
744                         /* Placement accomplished */
745                         break;
746                 }
747         }
748 }
749
750 /*!
751  * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
752  * @param y トラップを配置したいマスの中心Y座標
753  * @param x トラップを配置したいマスの中心X座標
754  * @param yd Y方向の配置分散マス数
755  * @param xd X方向の配置分散マス数
756  * @return なし
757  * @details
758  * Only really called by some of the "vault" routines.
759  */
760 void vault_trap_aux(POSITION y, POSITION x, POSITION yd, POSITION xd)
761 {
762         int count = 0, y1 = y, x1 = x;
763         int dummy = 0;
764
765         grid_type *g_ptr;
766
767         /* Place traps */
768         for (count = 0; count <= 5; count++)
769         {
770                 /* Get a location */
771                 while (dummy < SAFE_MAX_ATTEMPTS)
772                 {
773                         y1 = rand_spread(y, yd);
774                         x1 = rand_spread(x, xd);
775                         dummy++;
776                         if (!in_bounds(p_ptr->current_floor_ptr, y1, x1)) continue;
777                         break;
778                 }
779
780                 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
781                 {
782                         msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
783                 }
784
785                 /* Require "naked" floor grids */
786                 g_ptr = &p_ptr->current_floor_ptr->grid_array[y1][x1];
787                 if (!is_floor_grid(g_ptr) || g_ptr->o_idx || g_ptr->m_idx) continue;
788
789                 /* Place the trap */
790                 place_trap(y1, x1);
791
792                 break;
793         }
794 }
795
796 /*!
797  * @brief 特殊な部屋向けに各種アイテムを配置する(メインルーチン) / Place some traps with a given displacement of given location
798  * @param y トラップを配置したいマスの中心Y座標
799  * @param x トラップを配置したいマスの中心X座標
800  * @param yd Y方向の配置分散マス数
801  * @param xd X方向の配置分散マス数
802  * @param num 配置したいトラップの数
803  * @return なし
804  * @details
805  * Only really called by some of the "vault" routines.
806  */
807 void vault_traps(POSITION y, POSITION x, POSITION yd, POSITION xd, int num)
808 {
809         int i;
810
811         for (i = 0; i < num; i++)
812         {
813                 vault_trap_aux(y, x, yd, xd);
814         }
815 }
816
817 /*!
818  * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
819  * @param y1 モンスターを配置したいマスの中心Y座標
820  * @param x1 モンスターを配置したいマスの中心X座標
821  * @param num 配置したいモンスターの数
822  * @return なし
823  * @details
824  * Only really called by some of the "vault" routines.
825  */
826 void vault_monsters(POSITION y1, POSITION x1, int num)
827 {
828         int k, i;
829         POSITION y, x;
830         grid_type *g_ptr;
831
832         /* Try to summon "num" monsters "near" the given location */
833         for (k = 0; k < num; k++)
834         {
835                 /* Try nine locations */
836                 for (i = 0; i < 9; i++)
837                 {
838                         int d = 1;
839
840                         /* Pick a nearby location */
841                         scatter(&y, &x, y1, x1, d, 0);
842
843                         /* Require "empty" floor grids */
844                         g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
845                         if (!cave_empty_grid(g_ptr)) continue;
846
847                         /* Place the monster (allow groups) */
848                         p_ptr->current_floor_ptr->monster_level = p_ptr->current_floor_ptr->base_level + 2;
849                         (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
850                         p_ptr->current_floor_ptr->monster_level = p_ptr->current_floor_ptr->base_level;
851                 }
852         }
853 }
854
855 /*!
856  * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor.  (Includes range checking.)
857  * @param x チェックするマスのX座標
858  * @param y チェックするマスのY座標
859  * @return 床系地形ならばTRUE
860  */
861 bool get_is_floor(POSITION x, POSITION y)
862 {
863         if (!in_bounds(p_ptr->current_floor_ptr, y, x))
864         {
865                 /* Out of bounds */
866                 return (FALSE);
867         }
868
869         /* Do the real check */
870         if (is_floor_bold(p_ptr->current_floor_ptr, y, x)) return (TRUE);
871
872         return (FALSE);
873 }
874
875 /*!
876  * @brief 指定のマスを床地形に変える / Set a square to be floor.  (Includes range checking.)
877  * @param x 地形を変えたいマスのX座標
878  * @param y 地形を変えたいマスのY座標
879  * @return なし
880  */
881 void set_floor(POSITION x, POSITION y)
882 {
883         if (!in_bounds(p_ptr->current_floor_ptr, y, x))
884         {
885                 /* Out of bounds */
886                 return;
887         }
888
889         if (p_ptr->current_floor_ptr->grid_array[y][x].info & CAVE_ROOM)
890         {
891                 /* A room border don't touch. */
892                 return;
893         }
894
895         /* Set to be floor if is a wall (don't touch lakes). */
896         if (is_extra_bold(p_ptr->current_floor_ptr, y, x))
897                 place_floor_bold(y, x);
898 }
899
900 /*!
901  * @brief マスにフロア端用の永久壁を配置する / Set boundary mimic and add "solid" perma-wall
902  * @param g_ptr 永久壁を配置したいマス構造体の参照ポインタ
903  * @return なし
904  */
905 void place_bound_perm_wall(grid_type *g_ptr)
906 {
907         if (bound_walls_perm)
908         {
909                 /* Clear boundary mimic */
910                 g_ptr->mimic = 0;
911         }
912         else
913         {
914                 feature_type *f_ptr = &f_info[g_ptr->feat];
915
916                 /* Hack -- Decline boundary walls with known treasure  */
917                 if ((have_flag(f_ptr->flags, FF_HAS_GOLD) || have_flag(f_ptr->flags, FF_HAS_ITEM)) &&
918                         !have_flag(f_ptr->flags, FF_SECRET))
919                         g_ptr->feat = feat_state(g_ptr->feat, FF_ENSECRET);
920
921                 /* Set boundary mimic */
922                 g_ptr->mimic = g_ptr->feat;
923         }
924
925         /* Add "solid" perma-wall */
926         place_solid_perm_grid(g_ptr);
927 }
928
929 /*!
930  * @brief マスに看破済みの罠があるかの判定を行う。 / Return TRUE if the given grid is a known trap
931  * @param g_ptr マス構造体の参照ポインタ
932  * @return 看破済みの罠があるならTRUEを返す。
933  */
934 bool is_known_trap(grid_type *g_ptr)
935 {
936         if (!g_ptr->mimic && !cave_have_flag_grid(g_ptr, FF_SECRET) &&
937                 is_trap(g_ptr->feat)) return TRUE;
938         else
939                 return FALSE;
940 }
941
942
943
944 /*!
945  * @brief マスに隠されたドアがあるかの判定を行う。 / Return TRUE if the given grid is a hidden closed door
946  * @param g_ptr マス構造体の参照ポインタ
947  * @return 隠されたドアがあるならTRUEを返す。
948  */
949 bool is_hidden_door(grid_type *g_ptr)
950 {
951         if ((g_ptr->mimic || cave_have_flag_grid(g_ptr, FF_SECRET)) &&
952                 is_closed_door(g_ptr->feat))
953                 return TRUE;
954         else
955                 return FALSE;
956 }
957
958 #define COMPLEX_WALL_ILLUMINATION /*!< 照明状態を壁により影響を受ける、より複雑な判定に切り替えるマクロ */
959
960
961 /*!
962  * @brief 指定された座標のマスが現在照らされているかを返す。 / Check for "local" illumination
963  * @param y y座標
964  * @param x x座標
965  * @return 指定された座標に照明がかかっているならTRUEを返す。。
966  */
967 bool check_local_illumination(POSITION y, POSITION x)
968 {
969         /* Hack -- move towards player */
970         POSITION yy = (y < p_ptr->y) ? (y + 1) : (y > p_ptr->y) ? (y - 1) : y;
971         POSITION xx = (x < p_ptr->x) ? (x + 1) : (x > p_ptr->x) ? (x - 1) : x;
972
973         /* Check for "local" illumination */
974
975 #ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
976
977         /* Check for "complex" illumination */
978         if ((feat_supports_los(get_feat_mimic(&p_ptr->current_floor_ptr->grid_array[yy][xx])) &&
979                 (p_ptr->current_floor_ptr->grid_array[yy][xx].info & CAVE_GLOW)) ||
980                 (feat_supports_los(get_feat_mimic(&p_ptr->current_floor_ptr->grid_array[y][xx])) &&
981                 (p_ptr->current_floor_ptr->grid_array[y][xx].info & CAVE_GLOW)) ||
982                         (feat_supports_los(get_feat_mimic(&p_ptr->current_floor_ptr->grid_array[yy][x])) &&
983                 (p_ptr->current_floor_ptr->grid_array[yy][x].info & CAVE_GLOW)))
984         {
985                 return TRUE;
986         }
987         else return FALSE;
988
989 #else /* COMPLEX_WALL_ILLUMINATION */
990
991         /* Check for "simple" illumination */
992         return (p_ptr->current_floor_ptr->grid_array[yy][xx].info & CAVE_GLOW) ? TRUE : FALSE;
993
994 #endif /* COMPLEX_WALL_ILLUMINATION */
995 }
996
997
998 /*! 対象座標のマスの照明状態を更新する際の補助処理マクロ */
999 #define update_local_illumination_aux(Y, X) \
1000 { \
1001         if (player_has_los_bold((Y), (X))) \
1002         { \
1003                 /* Update the monster */ \
1004                 if (p_ptr->current_floor_ptr->grid_array[(Y)][(X)].m_idx) update_monster(p_ptr->current_floor_ptr->grid_array[(Y)][(X)].m_idx, FALSE); \
1005 \
1006                 /* Notice and redraw */ \
1007                 note_spot((Y), (X)); \
1008                 lite_spot((Y), (X)); \
1009         } \
1010 }
1011
1012 /*!
1013  * @brief 指定された座標の照明状態を更新する / Update "local" illumination
1014  * @param creature_ptr 視界元のクリーチャー
1015  * @param y 視界先y座標
1016  * @param x 視界先x座標
1017  * @return なし
1018  */
1019 void update_local_illumination(player_type * creature_ptr, POSITION y, POSITION x)
1020 {
1021         int i;
1022         POSITION yy, xx;
1023
1024         if (!in_bounds(p_ptr->current_floor_ptr, y, x)) return;
1025
1026 #ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
1027
1028         if ((y != creature_ptr->y) && (x != creature_ptr->x))
1029         {
1030                 yy = (y < creature_ptr->y) ? (y - 1) : (y + 1);
1031                 xx = (x < creature_ptr->x) ? (x - 1) : (x + 1);
1032                 update_local_illumination_aux(yy, xx);
1033                 update_local_illumination_aux(y, xx);
1034                 update_local_illumination_aux(yy, x);
1035         }
1036         else if (x != creature_ptr->x) /* y == creature_ptr->y */
1037         {
1038                 xx = (x < creature_ptr->x) ? (x - 1) : (x + 1);
1039                 for (i = -1; i <= 1; i++)
1040                 {
1041                         yy = y + i;
1042                         update_local_illumination_aux(yy, xx);
1043                 }
1044                 yy = y - 1;
1045                 update_local_illumination_aux(yy, x);
1046                 yy = y + 1;
1047                 update_local_illumination_aux(yy, x);
1048         }
1049         else if (y != creature_ptr->y) /* x == creature_ptr->x */
1050         {
1051                 yy = (y < creature_ptr->y) ? (y - 1) : (y + 1);
1052                 for (i = -1; i <= 1; i++)
1053                 {
1054                         xx = x + i;
1055                         update_local_illumination_aux(yy, xx);
1056                 }
1057                 xx = x - 1;
1058                 update_local_illumination_aux(y, xx);
1059                 xx = x + 1;
1060                 update_local_illumination_aux(y, xx);
1061         }
1062         else /* Player's grid */
1063         {
1064                 for (i = 0; i < 8; i++)
1065                 {
1066                         yy = y + ddy_cdd[i];
1067                         xx = x + ddx_cdd[i];
1068                         update_local_illumination_aux(yy, xx);
1069                 }
1070         }
1071
1072 #else /* COMPLEX_WALL_ILLUMINATION */
1073
1074         if ((y != creature_ptr->y) && (x != creature_ptr->x))
1075         {
1076                 yy = (y < creature_ptr->y) ? (y - 1) : (y + 1);
1077                 xx = (x < creature_ptr->x) ? (x - 1) : (x + 1);
1078                 update_local_illumination_aux(yy, xx);
1079         }
1080         else if (x != creature_ptr->x) /* y == creature_ptr->y */
1081         {
1082                 xx = (x < creature_ptr->x) ? (x - 1) : (x + 1);
1083                 for (i = -1; i <= 1; i++)
1084                 {
1085                         yy = y + i;
1086                         update_local_illumination_aux(yy, xx);
1087                 }
1088         }
1089         else if (y != creature_ptr->y) /* x == creature_ptr->x */
1090         {
1091                 yy = (y < creature_ptr->y) ? (y - 1) : (y + 1);
1092                 for (i = -1; i <= 1; i++)
1093                 {
1094                         xx = x + i;
1095                         update_local_illumination_aux(yy, xx);
1096                 }
1097         }
1098         else /* Player's grid */
1099         {
1100                 for (i = 0; i < 8; i++)
1101                 {
1102                         yy = y + ddy_cdd[i];
1103                         xx = x + ddx_cdd[i];
1104                         update_local_illumination_aux(yy, xx);
1105                 }
1106         }
1107
1108 #endif /* COMPLEX_WALL_ILLUMINATION */
1109 }
1110
1111
1112 /*!
1113  * @brief 指定された座標をプレイヤー収められていない状態かどうか / Returns true if the player's grid is dark
1114  * @return 視覚に収められていないならTRUEを返す
1115  * @details player_can_see_bold()関数の返り値の否定を返している。
1116  */
1117 bool no_lite(void)
1118 {
1119         return (!player_can_see_bold(p_ptr->y, p_ptr->x));
1120 }
1121
1122
1123 /*!
1124  * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
1125  * @param y y座標
1126  * @param x x座標
1127  * @return 各種の変更が可能ならTRUEを返す。
1128  * @details
1129  * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
1130  */
1131 bool cave_valid_bold(POSITION y, POSITION x)
1132 {
1133         grid_type *g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
1134         OBJECT_IDX this_o_idx, next_o_idx = 0;
1135
1136         /* Forbid perma-grids */
1137         if (cave_perma_grid(g_ptr)) return (FALSE);
1138
1139         /* Check objects */
1140         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1141         {
1142                 object_type *o_ptr;
1143                 o_ptr = &p_ptr->current_floor_ptr->o_list[this_o_idx];
1144                 next_o_idx = o_ptr->next_o_idx;
1145
1146                 /* Forbid artifact grids */
1147                 if (object_is_artifact(o_ptr)) return (FALSE);
1148         }
1149
1150         /* Accept */
1151         return (TRUE);
1152 }
1153
1154
1155
1156 /*
1157  * Place an attr/char pair at the given map coordinate, if legal.
1158  */
1159 void print_rel(SYMBOL_CODE c, TERM_COLOR a, TERM_LEN y, TERM_LEN x)
1160 {
1161         /* Only do "legal" locations */
1162         if (panel_contains(y, x))
1163         {
1164                 /* Hack -- fake monochrome */
1165                 if (!use_graphics)
1166                 {
1167                         if (current_world_ptr->timewalk_m_idx) a = TERM_DARK;
1168                         else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
1169                         else if (p_ptr->wraith_form) a = TERM_L_DARK;
1170                 }
1171
1172                 /* Draw the char using the attr */
1173                 Term_queue_bigchar(panel_col_of(x), y - panel_row_prt, a, c, 0, 0);
1174         }
1175 }
1176
1177
1178
1179
1180
1181 /*
1182  * Memorize interesting viewable object/features in the given grid
1183  *
1184  * This function should only be called on "legal" grids.
1185  *
1186  * This function will memorize the object and/or feature in the given
1187  * grid, if they are (1) viewable and (2) interesting.  Note that all
1188  * objects are interesting, all terrain features except floors (and
1189  * invisible traps) are interesting, and floors (and invisible traps)
1190  * are interesting sometimes (depending on various options involving
1191  * the illumination of floor grids).
1192  *
1193  * The automatic memorization of all objects and non-floor terrain
1194  * features as soon as they are displayed allows incredible amounts
1195  * of optimization in various places, especially "map_info()".
1196  *
1197  * Note that the memorization of objects is completely separate from
1198  * the memorization of terrain features, preventing annoying floor
1199  * memorization when a detected object is picked up from a dark floor,
1200  * and object memorization when an object is dropped into a floor grid
1201  * which is memorized but out-of-sight.
1202  *
1203  * This function should be called every time the "memorization" of
1204  * a grid (or the object in a grid) is called into question, such
1205  * as when an object is created in a grid, when a terrain feature
1206  * "changes" from "floor" to "non-floor", when any grid becomes
1207  * "illuminated" or "viewable", and when a "floor" grid becomes
1208  * "torch-lit".
1209  *
1210  * Note the relatively efficient use of this function by the various
1211  * "update_view()" and "update_lite()" calls, to allow objects and
1212  * terrain features to be memorized (and drawn) whenever they become
1213  * viewable or illuminated in any way, but not when they "maintain"
1214  * or "lose" their previous viewability or illumination.
1215  *
1216  * Note the butchered "internal" version of "player_can_see_bold()",
1217  * optimized primarily for the most common cases, that is, for the
1218  * non-marked floor grids.
1219  */
1220 void note_spot(POSITION y, POSITION x)
1221 {
1222         grid_type *g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
1223         OBJECT_IDX this_o_idx, next_o_idx = 0;
1224
1225         /* Blind players see nothing */
1226         if (p_ptr->blind) return;
1227
1228         /* Analyze non-torch-lit grids */
1229         if (!(g_ptr->info & (CAVE_LITE | CAVE_MNLT)))
1230         {
1231                 /* Require line of sight to the grid */
1232                 if (!(g_ptr->info & (CAVE_VIEW))) return;
1233
1234                 /* Require "perma-lite" of the grid */
1235                 if ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) != CAVE_GLOW)
1236                 {
1237                         /* Not Ninja */
1238                         if (!p_ptr->see_nocto) return;
1239                 }
1240         }
1241
1242
1243         /* Hack -- memorize objects */
1244         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
1245         {
1246                 object_type *o_ptr = &p_ptr->current_floor_ptr->o_list[this_o_idx];
1247                 next_o_idx = o_ptr->next_o_idx;
1248
1249                 /* Memorize objects */
1250                 o_ptr->marked |= OM_FOUND;
1251         }
1252
1253
1254         /* Hack -- memorize grids */
1255         if (!(g_ptr->info & (CAVE_MARK)))
1256         {
1257                 /* Feature code (applying "mimic" field) */
1258                 feature_type *f_ptr = &f_info[get_feat_mimic(g_ptr)];
1259
1260                 /* Memorize some "boring" grids */
1261                 if (!have_flag(f_ptr->flags, FF_REMEMBER))
1262                 {
1263                         /* Option -- memorize all torch-lit floors */
1264                         if (view_torch_grids &&
1265                                 ((g_ptr->info & (CAVE_LITE | CAVE_MNLT)) || p_ptr->see_nocto))
1266                         {
1267                                 g_ptr->info |= (CAVE_MARK);
1268                         }
1269
1270                         /* Option -- memorize all perma-lit floors */
1271                         else if (view_perma_grids && ((g_ptr->info & (CAVE_GLOW | CAVE_MNDK)) == CAVE_GLOW))
1272                         {
1273                                 g_ptr->info |= (CAVE_MARK);
1274                         }
1275                 }
1276
1277                 /* Memorize normal grids */
1278                 else if (have_flag(f_ptr->flags, FF_LOS))
1279                 {
1280                         g_ptr->info |= (CAVE_MARK);
1281                 }
1282
1283                 /* Memorize torch-lit walls */
1284                 else if (g_ptr->info & (CAVE_LITE | CAVE_MNLT))
1285                 {
1286                         g_ptr->info |= (CAVE_MARK);
1287                 }
1288
1289                 /* Memorize walls seen by noctovision of Ninja */
1290                 else if (p_ptr->see_nocto)
1291                 {
1292                         g_ptr->info |= (CAVE_MARK);
1293                 }
1294
1295                 /* Memorize certain non-torch-lit wall grids */
1296                 else if (check_local_illumination(y, x))
1297                 {
1298                         g_ptr->info |= (CAVE_MARK);
1299                 }
1300         }
1301
1302         /* Memorize terrain of the grid */
1303         g_ptr->info |= (CAVE_KNOWN);
1304 }
1305
1306 /*
1307  * Redraw (on the screen) a given MAP location
1308  *
1309  * This function should only be called on "legal" grids
1310  */
1311 void lite_spot(POSITION y, POSITION x)
1312 {
1313         /* Redraw if on screen */
1314         if (panel_contains(y, x) && in_bounds2(y, x))
1315         {
1316                 TERM_COLOR a;
1317                 SYMBOL_CODE c;
1318                 TERM_COLOR ta;
1319                 SYMBOL_CODE tc;
1320
1321                 map_info(y, x, &a, &c, &ta, &tc);
1322
1323                 /* Hack -- fake monochrome */
1324                 if (!use_graphics)
1325                 {
1326                         if (current_world_ptr->timewalk_m_idx) a = TERM_DARK;
1327                         else if (IS_INVULN() || p_ptr->timewalk) a = TERM_WHITE;
1328                         else if (p_ptr->wraith_form) a = TERM_L_DARK;
1329                 }
1330
1331                 /* Hack -- Queue it */
1332                 Term_queue_bigchar(panel_col_of(x), y - panel_row_prt, a, c, ta, tc);
1333
1334                 /* Update sub-windows */
1335                 p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1336         }
1337 }
1338
1339 /*
1340  * Some comments on the grid flags.  -BEN-
1341  *
1342  *
1343  * One of the major bottlenecks in previous versions of Angband was in
1344  * the calculation of "line of sight" from the player to various grids,
1345  * such as monsters.  This was such a nasty bottleneck that a lot of
1346  * silly things were done to reduce the dependancy on "line of sight",
1347  * for example, you could not "see" any grids in a lit room until you
1348  * actually entered the room, and there were all kinds of bizarre grid
1349  * flags to enable this behavior.  This is also why the "call light"
1350  * spells always lit an entire room.
1351  *
1352  * The code below provides functions to calculate the "field of view"
1353  * for the player, which, once calculated, provides extremely fast
1354  * calculation of "line of sight from the player", and to calculate
1355  * the "field of torch lite", which, again, once calculated, provides
1356  * extremely fast calculation of "which grids are lit by the player's
1357  * lite source".  In addition to marking grids as "GRID_VIEW" and/or
1358  * "GRID_LITE", as appropriate, these functions maintain an array for
1359  * each of these two flags, each array containing the locations of all
1360  * of the grids marked with the appropriate flag, which can be used to
1361  * very quickly scan through all of the grids in a given set.
1362  *
1363  * To allow more "semantically valid" field of view semantics, whenever
1364  * the field of view (or the set of torch lit grids) changes, all of the
1365  * grids in the field of view (or the set of torch lit grids) are "drawn"
1366  * so that changes in the world will become apparent as soon as possible.
1367  * This has been optimized so that only grids which actually "change" are
1368  * redrawn, using the "temp" array and the "GRID_TEMP" flag to keep track
1369  * of the grids which are entering or leaving the relevent set of grids.
1370  *
1371  * These new methods are so efficient that the old nasty code was removed.
1372  *
1373  * Note that there is no reason to "update" the "viewable space" unless
1374  * the player "moves", or walls/doors are created/destroyed, and there
1375  * is no reason to "update" the "torch lit grids" unless the field of
1376  * view changes, or the "light radius" changes.  This means that when
1377  * the player is resting, or digging, or doing anything that does not
1378  * involve movement or changing the state of the dungeon, there is no
1379  * need to update the "view" or the "lite" regions, which is nice.
1380  *
1381  * Note that the calls to the nasty "los()" function have been reduced
1382  * to a bare minimum by the use of the new "field of view" calculations.
1383  *
1384  * I wouldn't be surprised if slight modifications to the "update_view()"
1385  * function would allow us to determine "reverse line-of-sight" as well
1386  * as "normal line-of-sight", which would allow monsters to use a more
1387  * "correct" calculation to determine if they can "see" the player.  For
1388  * now, monsters simply "cheat" somewhat and assume that if the player
1389  * has "line of sight" to the monster, then the monster can "pretend"
1390  * that it has "line of sight" to the player.
1391  *
1392  *
1393  * The "update_lite()" function maintains the "CAVE_LITE" flag for each
1394  * grid and maintains an array of all "CAVE_LITE" grids.
1395  *
1396  * This set of grids is the complete set of all grids which are lit by
1397  * the players light source, which allows the "player_can_see_bold()"
1398  * function to work very quickly.
1399  *
1400  * Note that every "CAVE_LITE" grid is also a "CAVE_VIEW" grid, and in
1401  * fact, the player (unless blind) can always "see" all grids which are
1402  * marked as "CAVE_LITE", unless they are "off screen".
1403  *
1404  *
1405  * The "update_view()" function maintains the "CAVE_VIEW" flag for each
1406  * grid and maintains an array of all "CAVE_VIEW" grids.
1407  *
1408  * This set of grids is the complete set of all grids within line of sight
1409  * of the player, allowing the "player_has_los_bold()" macro to work very
1410  * quickly.
1411  *
1412  *
1413  * The current "update_view()" algorithm uses the "CAVE_XTRA" flag as a
1414  * temporary internal flag to mark those grids which are not only in view,
1415  * but which are also "easily" in line of sight of the player.  This flag
1416  * is always cleared when we are done.
1417  *
1418  *
1419  * The current "update_lite()" and "update_view()" algorithms use the
1420  * "CAVE_TEMP" flag, and the array of grids which are marked as "CAVE_TEMP",
1421  * to keep track of which grids were previously marked as "CAVE_LITE" or
1422  * "CAVE_VIEW", which allows us to optimize the "screen updates".
1423  *
1424  * The "CAVE_TEMP" flag, and the array of "CAVE_TEMP" grids, is also used
1425  * for various other purposes, such as spreading lite or darkness during
1426  * "lite_room()" / "unlite_room()", and for calculating monster flow.
1427  *
1428  *
1429  * Any grid can be marked as "CAVE_GLOW" which means that the grid itself is
1430  * in some way permanently lit.  However, for the player to "see" anything
1431  * in the grid, as determined by "player_can_see()", the player must not be
1432  * blind, the grid must be marked as "CAVE_VIEW", and, in addition, "wall"
1433  * grids, even if marked as "perma lit", are only illuminated if they touch
1434  * a grid which is not a wall and is marked both "CAVE_GLOW" and "CAVE_VIEW".
1435  *
1436  *
1437  * To simplify various things, a grid may be marked as "CAVE_MARK", meaning
1438  * that even if the player cannot "see" the grid, he "knows" the terrain in
1439  * that grid.  This is used to "remember" walls/doors/stairs/floors when they
1440  * are "seen" or "detected", and also to "memorize" floors, after "wiz_lite(p_ptr, )",
1441  * or when one of the "memorize floor grids" options induces memorization.
1442  *
1443  * Objects are "memorized" in a different way, using a special "marked" flag
1444  * on the object itself, which is set when an object is observed or detected.
1445  *
1446  *
1447  * A grid may be marked as "CAVE_ROOM" which means that it is part of a "room",
1448  * and should be illuminated by "lite room" and "darkness" spells.
1449  *
1450  *
1451  * A grid may be marked as "CAVE_ICKY" which means it is part of a "vault",
1452  * and should be unavailable for "teleportation" destinations.
1453  *
1454  *
1455  * The "view_perma_grids" allows the player to "memorize" every perma-lit grid
1456  * which is observed, and the "view_torch_grids" allows the player to memorize
1457  * every torch-lit grid.  The player will always memorize important walls,
1458  * doors, stairs, and other terrain features, as well as any "detected" grids.
1459  *
1460  * Note that the new "update_view()" method allows, among other things, a room
1461  * to be "partially" seen as the player approaches it, with a growing cone of
1462  * floor appearing as the player gets closer to the door.  Also, by not turning
1463  * on the "memorize perma-lit grids" option, the player will only "see" those
1464  * floor grids which are actually in line of sight.
1465  *
1466  * And my favorite "plus" is that you can now use a special option to draw the
1467  * "floors" in the "viewable region" brightly (actually, to draw the *other*
1468  * grids dimly), providing a "pretty" effect as the player runs around, and
1469  * to efficiently display the "torch lite" in a special color.
1470  *
1471  *
1472  * Some comments on the "update_view()" algorithm...
1473  *
1474  * The algorithm is very fast, since it spreads "obvious" grids very quickly,
1475  * and only has to call "los()" on the borderline cases.  The major axes/diags
1476  * even terminate early when they hit walls.  I need to find a quick way
1477  * to "terminate" the other scans.
1478  *
1479  * Note that in the worst case (a big empty area with say 5% scattered walls),
1480  * each of the 1500 or so nearby grids is checked once, most of them getting
1481  * an "instant" rating, and only a small portion requiring a call to "los()".
1482  *
1483  * The only time that the algorithm appears to be "noticeably" too slow is
1484  * when running, and this is usually only important in town, since the town
1485  * provides about the worst scenario possible, with large open regions and
1486  * a few scattered obstructions.  There is a special "efficiency" option to
1487  * allow the player to reduce his field of view in town, if needed.
1488  *
1489  * In the "best" case (say, a normal stretch of corridor), the algorithm
1490  * makes one check for each viewable grid, and makes no calls to "los()".
1491  * So running in corridors is very fast, and if a lot of monsters are
1492  * nearby, it is much faster than the old methods.
1493  *
1494  * Note that resting, most normal commands, and several forms of running,
1495  * plus all commands executed near large groups of monsters, are strictly
1496  * more efficient with "update_view()" that with the old "compute los() on
1497  * demand" method, primarily because once the "field of view" has been
1498  * calculated, it does not have to be recalculated until the player moves
1499  * (or a wall or door is created or destroyed).
1500  *
1501  * Note that we no longer have to do as many "los()" checks, since once the
1502  * "view" region has been built, very few things cause it to be "changed"
1503  * (player movement, and the opening/closing of doors, changes in wall status).
1504  * Note that door/wall changes are only relevant when the door/wall itself is
1505  * in the "view" region.
1506  *
1507  * The algorithm seems to only call "los()" from zero to ten times, usually
1508  * only when coming down a corridor into a room, or standing in a room, just
1509  * misaligned with a corridor.  So if, say, there are five "nearby" monsters,
1510  * we will be reducing the calls to "los()".
1511  *
1512  * I am thinking in terms of an algorithm that "walks" from the central point
1513  * out to the maximal "distance", at each point, determining the "view" code
1514  * (above).  For each grid not on a major axis or diagonal, the "view" code
1515  * depends on the "cave_los_bold()" and "view" of exactly two other grids
1516  * (the one along the nearest diagonal, and the one next to that one, see
1517  * "update_view_aux()"...).
1518  *
1519  * We "memorize" the viewable space array, so that at the cost of under 3000
1520  * bytes, we reduce the time taken by "forget_view()" to one assignment for
1521  * each grid actually in the "viewable space".  And for another 3000 bytes,
1522  * we prevent "erase + redraw" ineffiencies via the "seen" set.  These bytes
1523  * are also used by other routines, thus reducing the cost to almost nothing.
1524  *
1525  * A similar thing is done for "forget_lite()" in which case the savings are
1526  * much less, but save us from doing bizarre maintenance checking.
1527  *
1528  * In the worst "normal" case (in the middle of the town), the reachable space
1529  * actually reaches to more than half of the largest possible "circle" of view,
1530  * or about 800 grids, and in the worse case (in the middle of a dungeon level
1531  * where all the walls have been removed), the reachable space actually reaches
1532  * the theoretical maximum size of just under 1500 grids.
1533  *
1534  * Each grid G examines the "state" of two (?) other (adjacent) grids, G1 & G2.
1535  * If G1 is lite, G is lite.  Else if G2 is lite, G is half.  Else if G1 and G2
1536  * are both half, G is half.  Else G is dark.  It only takes 2 (or 4) bits to
1537  * "name" a grid, so (for MAX_RAD of 20) we could use 1600 bytes, and scan the
1538  * entire possible space (including initialization) in one step per grid.  If
1539  * we do the "clearing" as a separate step (and use an array of "view" grids),
1540  * then the clearing will take as many steps as grids that were viewed, and the
1541  * algorithm will be able to "stop" scanning at various points.
1542  * Oh, and outside of the "torch radius", only "lite" grids need to be scanned.
1543  */
1544
1545 /*
1546  * Mega-Hack -- Delayed visual update
1547  * Only used if update_view(), update_lite() or update_mon_lite() was called
1548  */
1549 void delayed_visual_update(void)
1550 {
1551         int i;
1552         POSITION y, x;
1553         grid_type *g_ptr;
1554
1555         /* Update needed grids */
1556         for (i = 0; i < p_ptr->current_floor_ptr->redraw_n; i++)
1557         {
1558                 y = p_ptr->current_floor_ptr->redraw_y[i];
1559                 x = p_ptr->current_floor_ptr->redraw_x[i];
1560                 g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
1561
1562                 /* Update only needed grids (prevent multiple updating) */
1563                 if (!(g_ptr->info & CAVE_REDRAW)) continue;
1564
1565                 /* If required, note */
1566                 if (g_ptr->info & CAVE_NOTE) note_spot(y, x);
1567
1568                 lite_spot(y, x);
1569
1570                 /* Hack -- Visual update of monster on this grid */
1571                 if (g_ptr->m_idx) update_monster(g_ptr->m_idx, FALSE);
1572
1573                 /* No longer in the array */
1574                 g_ptr->info &= ~(CAVE_NOTE | CAVE_REDRAW);
1575         }
1576
1577         /* None left */
1578         p_ptr->current_floor_ptr->redraw_n = 0;
1579 }
1580
1581
1582 /*
1583  * Hack -- forget the "flow" information
1584  */
1585 void forget_flow(void)
1586 {
1587         POSITION x, y;
1588
1589         /* Check the entire dungeon */
1590         for (y = 0; y < p_ptr->current_floor_ptr->height; y++)
1591         {
1592                 for (x = 0; x < p_ptr->current_floor_ptr->width; x++)
1593                 {
1594                         /* Forget the old data */
1595                         p_ptr->current_floor_ptr->grid_array[y][x].dist = 0;
1596                         p_ptr->current_floor_ptr->grid_array[y][x].cost = 0;
1597                         p_ptr->current_floor_ptr->grid_array[y][x].when = 0;
1598                 }
1599         }
1600 }
1601
1602
1603 /*
1604  * Hack - speed up the update_flow algorithm by only doing
1605  * it everytime the player moves out of LOS of the last
1606  * "way-point".
1607  */
1608 static POSITION flow_x = 0;
1609 static POSITION flow_y = 0;
1610
1611
1612
1613 /*
1614  * Hack -- fill in the "cost" field of every grid that the player
1615  * can "reach" with the number of steps needed to reach that grid.
1616  * This also yields the "distance" of the player from every grid.
1617  *
1618  * In addition, mark the "when" of the grids that can reach
1619  * the player with the incremented value of "flow_n".
1620  *
1621  * Hack -- use the "seen" array as a "circular queue".
1622  *
1623  * We do not need a priority queue because the cost from grid
1624  * to grid is always "one" and we process them in order.
1625  */
1626 void update_flow(void)
1627 {
1628         POSITION x, y;
1629         DIRECTION d;
1630         int flow_head = 1;
1631         int flow_tail = 0;
1632
1633         /* Paranoia -- make sure the array is empty */
1634         if (tmp_pos.n) return;
1635
1636         /* The last way-point is on the map */
1637         if (p_ptr->running && in_bounds(p_ptr->current_floor_ptr, flow_y, flow_x))
1638         {
1639                 /* The way point is in sight - do not update.  (Speedup) */
1640                 if (p_ptr->current_floor_ptr->grid_array[flow_y][flow_x].info & CAVE_VIEW) return;
1641         }
1642
1643         /* Erase all of the current flow information */
1644         for (y = 0; y < p_ptr->current_floor_ptr->height; y++)
1645         {
1646                 for (x = 0; x < p_ptr->current_floor_ptr->width; x++)
1647                 {
1648                         p_ptr->current_floor_ptr->grid_array[y][x].cost = 0;
1649                         p_ptr->current_floor_ptr->grid_array[y][x].dist = 0;
1650                 }
1651         }
1652
1653         /* Save player position */
1654         flow_y = p_ptr->y;
1655         flow_x = p_ptr->x;
1656
1657         /* Add the player's grid to the queue */
1658         tmp_pos.y[0] = p_ptr->y;
1659         tmp_pos.x[0] = p_ptr->x;
1660
1661         /* Now process the queue */
1662         while (flow_head != flow_tail)
1663         {
1664                 int ty, tx;
1665
1666                 /* Extract the next entry */
1667                 ty = tmp_pos.y[flow_tail];
1668                 tx = tmp_pos.x[flow_tail];
1669
1670                 /* Forget that entry */
1671                 if (++flow_tail == TEMP_MAX) flow_tail = 0;
1672
1673                 /* Add the "children" */
1674                 for (d = 0; d < 8; d++)
1675                 {
1676                         int old_head = flow_head;
1677                         byte_hack m = p_ptr->current_floor_ptr->grid_array[ty][tx].cost + 1;
1678                         byte_hack n = p_ptr->current_floor_ptr->grid_array[ty][tx].dist + 1;
1679                         grid_type *g_ptr;
1680
1681                         /* Child location */
1682                         y = ty + ddy_ddd[d];
1683                         x = tx + ddx_ddd[d];
1684
1685                         /* Ignore player's grid */
1686                         if (player_bold(y, x)) continue;
1687
1688                         g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
1689
1690                         if (is_closed_door(g_ptr->feat)) m += 3;
1691
1692                         /* Ignore "pre-stamped" entries */
1693                         if (g_ptr->dist != 0 && g_ptr->dist <= n && g_ptr->cost <= m) continue;
1694
1695                         /* Ignore "walls" and "rubble" */
1696                         if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
1697
1698                         /* Save the flow cost */
1699                         if (g_ptr->cost == 0 || g_ptr->cost > m) g_ptr->cost = m;
1700                         if (g_ptr->dist == 0 || g_ptr->dist > n) g_ptr->dist = n;
1701
1702                         /* Hack -- limit flow depth */
1703                         if (n == MONSTER_FLOW_DEPTH) continue;
1704
1705                         /* Enqueue that entry */
1706                         tmp_pos.y[flow_head] = y;
1707                         tmp_pos.x[flow_head] = x;
1708
1709                         /* Advance the queue */
1710                         if (++flow_head == TEMP_MAX) flow_head = 0;
1711
1712                         /* Hack -- notice overflow by forgetting new entry */
1713                         if (flow_head == flow_tail) flow_head = old_head;
1714                 }
1715         }
1716 }
1717
1718
1719 static int scent_when = 0;
1720
1721 /*
1722  * Characters leave scent trails for perceptive monsters to track.
1723  *
1724  * Smell is rather more limited than sound.  Many creatures cannot use
1725  * it at all, it doesn't extend very far outwards from the character's
1726  * current position, and monsters can use it to home in the character,
1727  * but not to run away from him.
1728  *
1729  * Smell is valued according to age.  When a character takes his current_world_ptr->game_turn,
1730  * scent is aged by one, and new scent of the current age is laid down.
1731  * Speedy characters leave more scent, true, but it also ages faster,
1732  * which makes it harder to hunt them down.
1733  *
1734  * Whenever the age count loops, most of the scent trail is erased and
1735  * the age of the remainder is recalculated.
1736  */
1737 void update_smell(void)
1738 {
1739         POSITION i, j;
1740         POSITION y, x;
1741
1742         /* Create a table that controls the spread of scent */
1743         const int scent_adjust[5][5] =
1744         {
1745                 { -1, 0, 0, 0,-1 },
1746                 {  0, 1, 1, 1, 0 },
1747                 {  0, 1, 2, 1, 0 },
1748                 {  0, 1, 1, 1, 0 },
1749                 { -1, 0, 0, 0,-1 },
1750         };
1751
1752         /* Loop the age and adjust scent values when necessary */
1753         if (++scent_when == 254)
1754         {
1755                 /* Scan the entire dungeon */
1756                 for (y = 0; y < p_ptr->current_floor_ptr->height; y++)
1757                 {
1758                         for (x = 0; x < p_ptr->current_floor_ptr->width; x++)
1759                         {
1760                                 int w = p_ptr->current_floor_ptr->grid_array[y][x].when;
1761                                 p_ptr->current_floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
1762                         }
1763                 }
1764
1765                 /* Restart */
1766                 scent_when = 126;
1767         }
1768
1769
1770         /* Lay down new scent */
1771         for (i = 0; i < 5; i++)
1772         {
1773                 for (j = 0; j < 5; j++)
1774                 {
1775                         grid_type *g_ptr;
1776
1777                         /* Translate table to map grids */
1778                         y = i + p_ptr->y - 2;
1779                         x = j + p_ptr->x - 2;
1780
1781                         /* Check Bounds */
1782                         if (!in_bounds(p_ptr->current_floor_ptr, y, x)) continue;
1783
1784                         g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
1785
1786                         /* Walls, water, and lava cannot hold scent. */
1787                         if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
1788
1789                         /* Grid must not be blocked by walls from the character */
1790                         if (!player_has_los_bold(y, x)) continue;
1791
1792                         /* Note grids that are too far away */
1793                         if (scent_adjust[i][j] == -1) continue;
1794
1795                         /* Mark the grid with new scent */
1796                         g_ptr->when = scent_when + scent_adjust[i][j];
1797                 }
1798         }
1799 }
1800
1801
1802
1803 /*
1804  * Change the "feat" flag for a grid, and notice/redraw the grid
1805  */
1806 void cave_set_feat(POSITION y, POSITION x, FEAT_IDX feat)
1807 {
1808         grid_type *g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
1809         feature_type *f_ptr = &f_info[feat];
1810         bool old_los, old_mirror;
1811
1812         if (!current_world_ptr->character_dungeon)
1813         {
1814                 /* Clear mimic type */
1815                 g_ptr->mimic = 0;
1816
1817                 /* Change the feature */
1818                 g_ptr->feat = feat;
1819
1820                 /* Hack -- glow the GLOW terrain */
1821                 if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
1822                 {
1823                         DIRECTION i;
1824                         POSITION yy, xx;
1825
1826                         for (i = 0; i < 9; i++)
1827                         {
1828                                 yy = y + ddy_ddd[i];
1829                                 xx = x + ddx_ddd[i];
1830                                 if (!in_bounds2(yy, xx)) continue;
1831                                 p_ptr->current_floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
1832                         }
1833                 }
1834
1835                 return;
1836         }
1837
1838         old_los = cave_have_flag_bold(y, x, FF_LOS);
1839         old_mirror = is_mirror_grid(g_ptr);
1840
1841         /* Clear mimic type */
1842         g_ptr->mimic = 0;
1843
1844         /* Change the feature */
1845         g_ptr->feat = feat;
1846
1847         /* Remove flag for mirror/glyph */
1848         g_ptr->info &= ~(CAVE_OBJECT);
1849
1850         if (old_mirror && (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
1851         {
1852                 g_ptr->info &= ~(CAVE_GLOW);
1853                 if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
1854
1855                 update_local_illumination(p_ptr, y, x);
1856         }
1857
1858         /* Check for change to boring grid */
1859         if (!have_flag(f_ptr->flags, FF_REMEMBER)) g_ptr->info &= ~(CAVE_MARK);
1860         if (g_ptr->m_idx) update_monster(g_ptr->m_idx, FALSE);
1861
1862         note_spot(y, x);
1863         lite_spot(y, x);
1864
1865         /* Check if los has changed */
1866         if (old_los ^ have_flag(f_ptr->flags, FF_LOS))
1867         {
1868
1869 #ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
1870
1871                 update_local_illumination(p_ptr, y, x);
1872
1873 #endif /* COMPLEX_WALL_ILLUMINATION */
1874
1875                 /* Update the visuals */
1876                 p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS);
1877         }
1878
1879         /* Hack -- glow the GLOW terrain */
1880         if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
1881         {
1882                 DIRECTION i;
1883                 POSITION yy, xx;
1884                 grid_type *cc_ptr;
1885
1886                 for (i = 0; i < 9; i++)
1887                 {
1888                         yy = y + ddy_ddd[i];
1889                         xx = x + ddx_ddd[i];
1890                         if (!in_bounds2(yy, xx)) continue;
1891                         cc_ptr = &p_ptr->current_floor_ptr->grid_array[yy][xx];
1892                         cc_ptr->info |= CAVE_GLOW;
1893
1894                         if (player_has_los_grid(cc_ptr))
1895                         {
1896                                 if (cc_ptr->m_idx) update_monster(cc_ptr->m_idx, FALSE);
1897
1898                                 note_spot(yy, xx);
1899
1900                                 lite_spot(yy, xx);
1901                         }
1902
1903                         update_local_illumination(p_ptr, yy, xx);
1904                 }
1905
1906                 if (p_ptr->special_defense & NINJA_S_STEALTH)
1907                 {
1908                         if (p_ptr->current_floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(p_ptr, FALSE);
1909                 }
1910         }
1911 }
1912
1913 FEAT_IDX conv_dungeon_feat(FEAT_IDX newfeat)
1914 {
1915         feature_type *f_ptr = &f_info[newfeat];
1916
1917         if (have_flag(f_ptr->flags, FF_CONVERT))
1918         {
1919                 switch (f_ptr->subtype)
1920                 {
1921                 case CONVERT_TYPE_FLOOR:
1922                         return feat_ground_type[randint0(100)];
1923                 case CONVERT_TYPE_WALL:
1924                         return feat_wall_type[randint0(100)];
1925                 case CONVERT_TYPE_INNER:
1926                         return feat_wall_inner;
1927                 case CONVERT_TYPE_OUTER:
1928                         return feat_wall_outer;
1929                 case CONVERT_TYPE_SOLID:
1930                         return feat_wall_solid;
1931                 case CONVERT_TYPE_STREAM1:
1932                         return d_info[p_ptr->dungeon_idx].stream1;
1933                 case CONVERT_TYPE_STREAM2:
1934                         return d_info[p_ptr->dungeon_idx].stream2;
1935                 default:
1936                         return newfeat;
1937                 }
1938         }
1939         else return newfeat;
1940 }
1941
1942
1943 /*
1944  * Take a feature, determine what that feature becomes
1945  * through applying the given action.
1946  */
1947 FEAT_IDX feat_state(FEAT_IDX feat, int action)
1948 {
1949         feature_type *f_ptr = &f_info[feat];
1950         int i;
1951
1952         /* Get the new feature */
1953         for (i = 0; i < MAX_FEAT_STATES; i++)
1954         {
1955                 if (f_ptr->state[i].action == action) return conv_dungeon_feat(f_ptr->state[i].result);
1956         }
1957
1958         if (have_flag(f_ptr->flags, FF_PERMANENT)) return feat;
1959
1960         return (feature_action_flags[action] & FAF_DESTROY) ? conv_dungeon_feat(f_ptr->destroyed) : feat;
1961 }
1962
1963 /*
1964  * Takes a location and action and changes the feature at that
1965  * location through applying the given action.
1966  */
1967 void cave_alter_feat(POSITION y, POSITION x, int action)
1968 {
1969         /* Set old feature */
1970         FEAT_IDX oldfeat = p_ptr->current_floor_ptr->grid_array[y][x].feat;
1971
1972         /* Get the new feat */
1973         FEAT_IDX newfeat = feat_state(oldfeat, action);
1974
1975         /* No change */
1976         if (newfeat == oldfeat) return;
1977
1978         /* Set the new feature */
1979         cave_set_feat(y, x, newfeat);
1980
1981         if (!(feature_action_flags[action] & FAF_NO_DROP))
1982         {
1983                 feature_type *old_f_ptr = &f_info[oldfeat];
1984                 feature_type *f_ptr = &f_info[newfeat];
1985                 bool found = FALSE;
1986
1987                 /* Handle gold */
1988                 if (have_flag(old_f_ptr->flags, FF_HAS_GOLD) && !have_flag(f_ptr->flags, FF_HAS_GOLD))
1989                 {
1990                         /* Place some gold */
1991                         place_gold(y, x);
1992                         found = TRUE;
1993                 }
1994
1995                 /* Handle item */
1996                 if (have_flag(old_f_ptr->flags, FF_HAS_ITEM) && !have_flag(f_ptr->flags, FF_HAS_ITEM) && (randint0(100) < (15 - p_ptr->current_floor_ptr->dun_level / 2)))
1997                 {
1998                         /* Place object */
1999                         place_object(y, x, 0L);
2000                         found = TRUE;
2001                 }
2002
2003                 if (found && current_world_ptr->character_dungeon && player_can_see_bold(y, x))
2004                 {
2005                         msg_print(_("何かを発見した!", "You have found something!"));
2006                 }
2007         }
2008
2009         if (feature_action_flags[action] & FAF_CRASH_GLASS)
2010         {
2011                 feature_type *old_f_ptr = &f_info[oldfeat];
2012
2013                 if (have_flag(old_f_ptr->flags, FF_GLASS) && current_world_ptr->character_dungeon)
2014                 {
2015                         project(PROJECT_WHO_GLASS_SHARDS, 1, y, x, MIN(p_ptr->current_floor_ptr->dun_level, 100) / 4, GF_SHARDS,
2016                                 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_HIDE | PROJECT_JUMP | PROJECT_NO_HANGEKI), -1);
2017                 }
2018         }
2019 }
2020
2021
2022 /* Remove a mirror */
2023 void remove_mirror(POSITION y, POSITION x)
2024 {
2025         grid_type *g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
2026
2027         /* Remove the mirror */
2028         g_ptr->info &= ~(CAVE_OBJECT);
2029         g_ptr->mimic = 0;
2030
2031         if (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS)
2032         {
2033                 g_ptr->info &= ~(CAVE_GLOW);
2034                 if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
2035                 if (g_ptr->m_idx) update_monster(g_ptr->m_idx, FALSE);
2036
2037                 update_local_illumination(p_ptr, y, x);
2038         }
2039
2040         note_spot(y, x);
2041
2042         lite_spot(y, x);
2043 }
2044
2045
2046 /*
2047  *  Return TRUE if there is a mirror on the grid.
2048  */
2049 bool is_mirror_grid(grid_type *g_ptr)
2050 {
2051         if ((g_ptr->info & CAVE_OBJECT) && have_flag(f_info[g_ptr->mimic].flags, FF_MIRROR))
2052                 return TRUE;
2053         else
2054                 return FALSE;
2055 }
2056
2057
2058 /*
2059  *  Return TRUE if there is a mirror on the grid.
2060  */
2061 bool is_glyph_grid(grid_type *g_ptr)
2062 {
2063         if ((g_ptr->info & CAVE_OBJECT) && have_flag(f_info[g_ptr->mimic].flags, FF_GLYPH))
2064                 return TRUE;
2065         else
2066                 return FALSE;
2067 }
2068
2069
2070 /*
2071  *  Return TRUE if there is a mirror on the grid.
2072  */
2073 bool is_explosive_rune_grid(grid_type *g_ptr)
2074 {
2075         if ((g_ptr->info & CAVE_OBJECT) && have_flag(f_info[g_ptr->mimic].flags, FF_MINOR_GLYPH))
2076                 return TRUE;
2077         else
2078                 return FALSE;
2079 }
2080
2081 /*!
2082 * @brief 指定されたマスがモンスターのテレポート可能先かどうかを判定する。
2083 * @param m_idx モンスターID
2084 * @param y 移動先Y座標
2085 * @param x 移動先X座標
2086 * @param mode オプション
2087 * @return テレポート先として妥当ならばtrue
2088 */
2089 bool cave_monster_teleportable_bold(MONSTER_IDX m_idx, POSITION y, POSITION x, BIT_FLAGS mode)
2090 {
2091         monster_type *m_ptr = &p_ptr->current_floor_ptr->m_list[m_idx];
2092         grid_type    *g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
2093         feature_type *f_ptr = &f_info[g_ptr->feat];
2094
2095         /* Require "teleportable" space */
2096         if (!have_flag(f_ptr->flags, FF_TELEPORTABLE)) return FALSE;
2097
2098         if (g_ptr->m_idx && (g_ptr->m_idx != m_idx)) return FALSE;
2099         if (player_bold(y, x)) return FALSE;
2100
2101         /* Hack -- no teleport onto glyph of warding */
2102         if (is_glyph_grid(g_ptr)) return FALSE;
2103         if (is_explosive_rune_grid(g_ptr)) return FALSE;
2104
2105         if (!(mode & TELEPORT_PASSIVE))
2106         {
2107                 if (!monster_can_cross_terrain(g_ptr->feat, &r_info[m_ptr->r_idx], 0)) return FALSE;
2108         }
2109
2110         return TRUE;
2111 }
2112
2113 /*!
2114 * @brief 指定されたマスにプレイヤーがテレポート可能かどうかを判定する。
2115 * @param y 移動先Y座標
2116 * @param x 移動先X座標
2117 * @param mode オプション
2118 * @return テレポート先として妥当ならばtrue
2119 */
2120 bool cave_player_teleportable_bold(POSITION y, POSITION x, BIT_FLAGS mode)
2121 {
2122         grid_type    *g_ptr = &p_ptr->current_floor_ptr->grid_array[y][x];
2123         feature_type *f_ptr = &f_info[g_ptr->feat];
2124
2125         /* Require "teleportable" space */
2126         if (!have_flag(f_ptr->flags, FF_TELEPORTABLE)) return FALSE;
2127
2128         /* No magical teleporting into vaults and such */
2129         if (!(mode & TELEPORT_NONMAGICAL) && (g_ptr->info & CAVE_ICKY)) return FALSE;
2130
2131         if (g_ptr->m_idx && (g_ptr->m_idx != p_ptr->riding)) return FALSE;
2132
2133         /* don't teleport on a trap. */
2134         if (have_flag(f_ptr->flags, FF_HIT_TRAP)) return FALSE;
2135
2136         if (!(mode & TELEPORT_PASSIVE))
2137         {
2138                 if (!player_can_enter(g_ptr->feat, 0)) return FALSE;
2139
2140                 if (have_flag(f_ptr->flags, FF_WATER) && have_flag(f_ptr->flags, FF_DEEP))
2141                 {
2142                         if (!p_ptr->levitation && !p_ptr->can_swim) return FALSE;
2143                 }
2144
2145                 if (have_flag(f_ptr->flags, FF_LAVA) && !p_ptr->immune_fire && !IS_INVULN())
2146                 {
2147                         /* Always forbid deep lava */
2148                         if (have_flag(f_ptr->flags, FF_DEEP)) return FALSE;
2149
2150                         /* Forbid shallow lava when the player don't have levitation */
2151                         if (!p_ptr->levitation) return FALSE;
2152                 }
2153
2154         }
2155
2156         return TRUE;
2157 }
2158
2159 /*!
2160  * @brief 地形は開くものであって、かつ開かれているかを返す /
2161  * Attempt to open the given chest at the given location
2162  * @param feat 地形ID
2163  * @return 開いた地形である場合TRUEを返す /  Return TRUE if the given feature is an open door
2164  */
2165 bool is_open(FEAT_IDX feat)
2166 {
2167         return have_flag(f_info[feat].flags, FF_CLOSE) && (feat != feat_state(feat, FF_CLOSE));
2168 }
2169
2170 /*!
2171  * @brief プレイヤーが地形踏破可能かを返す
2172  * @param feature 判定したい地形ID
2173  * @param mode 移動に関するオプションフラグ
2174  * @return 移動可能ならばTRUEを返す
2175  */
2176 bool player_can_enter(FEAT_IDX feature, BIT_FLAGS16 mode)
2177 {
2178         feature_type *f_ptr = &f_info[feature];
2179
2180         if (p_ptr->riding) return monster_can_cross_terrain(feature, &r_info[p_ptr->current_floor_ptr->m_list[p_ptr->riding].r_idx], mode | CEM_RIDING);
2181
2182         if (have_flag(f_ptr->flags, FF_PATTERN))
2183         {
2184                 if (!(mode & CEM_P_CAN_ENTER_PATTERN)) return FALSE;
2185         }
2186
2187         if (have_flag(f_ptr->flags, FF_CAN_FLY) && p_ptr->levitation) return TRUE;
2188         if (have_flag(f_ptr->flags, FF_CAN_SWIM) && p_ptr->can_swim) return TRUE;
2189         if (have_flag(f_ptr->flags, FF_CAN_PASS) && p_ptr->pass_wall) return TRUE;
2190
2191         if (!have_flag(f_ptr->flags, FF_MOVE)) return FALSE;
2192
2193         return TRUE;
2194 }
2195