OSDN Git Service

[Refactor] #40569 Separated cave.c/h from floor.c/h; Can't go back to that place...
[hengband/hengband.git] / src / floor / floor.c
1 #include "floor/floor.h"
2 #include "core/player-redraw-types.h"
3 #include "core/player-update-types.h"
4 #include "core/window-redrawer.h"
5 #include "dungeon/dungeon-flag-types.h"
6 #include "dungeon/dungeon.h"
7 #include "dungeon/quest.h"
8 #include "effect/effect-characteristics.h"
9 #include "effect/spells-effect-util.h"
10 #include "floor/cave.h"
11 #include "floor/floor-generate.h"
12 #include "floor/floor-object.h"
13 #include "game-option/birth-options.h"
14 #include "game-option/cheat-options.h"
15 #include "game-option/map-screen-options.h"
16 #include "grid/grid.h"
17 #include "grid/trap.h"
18 #include "io/targeting.h"
19 #include "mind/mind-ninja.h"
20 #include "monster-floor/monster-generator.h"
21 #include "monster-floor/monster-remover.h"
22 #include "monster/monster-update.h"
23 #include "monster-floor/place-monster-types.h"
24 #include "object-enchant/special-object-flags.h"
25 #include "object-hook/hook-checker.h"
26 #include "object-hook/hook-enchant.h"
27 #include "object/object-generator.h"
28 #include "object/object-kind.h"
29 #include "perception/object-perception.h"
30 #include "player/special-defense-types.h"
31 #include "room/rooms.h"
32 #include "system/artifact-type-definition.h"
33 #include "system/floor-type-definition.h"
34 #include "util/bit-flags-calculator.h"
35 #include "view/display-messages.h"
36 #include "world/world-object.h"
37 #include "world/world.h"
38
39 /*
40  * The array of floor [MAX_WID][MAX_HGT].
41  * Not completely allocated, that would be inefficient
42  * Not completely hardcoded, that would overflow memory
43  */
44 floor_type floor_info;
45
46 /*
47  * Grid based version of "cave_empty_bold()"
48  */
49 bool is_cave_empty_grid(player_type *player_ptr, grid_type *g_ptr)
50 {
51         bool is_empty_grid = cave_have_flag_grid(g_ptr, FF_PLACE);
52         is_empty_grid &= g_ptr->m_idx == 0;
53         is_empty_grid &= !player_grid(player_ptr, g_ptr);
54         return is_empty_grid;
55 }
56
57
58 bool pattern_tile(floor_type *floor_ptr, POSITION y, POSITION x)
59 {
60         return cave_have_flag_bold(floor_ptr, y, x, FF_PATTERN);
61 }
62
63
64 /*
65  * Determine if a "legal" grid is an "empty" floor grid
66  * Determine if monsters are allowed to move into a grid
67  *
68  * Line 1 -- forbid non-placement grids
69  * Line 2 -- forbid normal monsters
70  * Line 3 -- forbid the player
71  */
72 bool is_cave_empty_bold(player_type *player_ptr, POSITION y, POSITION x)
73 {
74         floor_type *floor_ptr = player_ptr->current_floor_ptr;
75         bool is_empty_grid = cave_have_flag_bold(floor_ptr, y, x, FF_PLACE);
76         is_empty_grid &= !(floor_ptr->grid_array[y][x].m_idx);
77         is_empty_grid &= !player_bold(player_ptr, y, x);
78         return is_empty_grid;
79 }
80
81
82 /*
83   * Determine if a "legal" grid is an "empty" floor grid
84   * Determine if monster generation is allowed in a grid
85   *
86   * Line 1 -- forbid non-empty grids
87   * Line 2 -- forbid trees while dungeon generation
88   */
89 bool is_cave_empty_bold2(player_type *player_ptr, POSITION y, POSITION x)
90 {
91         bool is_empty_grid = is_cave_empty_bold(player_ptr, y, x);
92         is_empty_grid &= current_world_ptr->character_dungeon || !cave_have_flag_bold(player_ptr->current_floor_ptr, y, x, FF_TREE);
93         return is_empty_grid;
94 }
95
96
97 /*!
98 * @brief 鍵のかかったドアを配置する
99 * @param player_ptr プレーヤーへの参照ポインタ
100 * @param y 配置したいフロアのY座標
101 * @param x 配置したいフロアのX座標
102 * @return なし
103 */
104 void place_locked_door(player_type *player_ptr, POSITION y, POSITION x)
105 {
106         floor_type *floor_ptr = player_ptr->current_floor_ptr;
107         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
108         {
109                 place_bold(player_ptr, y, x, GB_FLOOR);
110                 return;
111         }
112
113         set_cave_feat(floor_ptr, y, x, feat_locked_door_random((d_info[player_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
114         floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
115         delete_monster(player_ptr, y, x);
116 }
117
118
119 /*!
120 * @brief 隠しドアを配置する
121 * @param player_ptr プレーヤーへの参照ポインタ
122 * @param y 配置したいフロアのY座標
123 * @param x 配置したいフロアのX座標
124 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
125 * @return なし
126 */
127 void place_secret_door(player_type *player_ptr, POSITION y, POSITION x, int type)
128 {
129         floor_type *floor_ptr = player_ptr->current_floor_ptr;
130         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
131         {
132                 place_bold(player_ptr, y, x, GB_FLOOR);
133                 return;
134         }
135
136         if (type == DOOR_DEFAULT)
137         {
138                 type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
139                         one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
140                         ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
141         }
142
143         place_closed_door(player_ptr, y, x, type);
144         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
145         if (type != DOOR_CURTAIN)
146         {
147                 g_ptr->mimic = feat_wall_inner;
148                 if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
149                 {
150                         if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
151                         {
152                                 g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
153                         }
154
155                         g_ptr->mimic = 0;
156                 }
157         }
158
159         g_ptr->info &= ~(CAVE_FLOOR);
160         delete_monster(player_ptr, y, x);
161 }
162
163 static int scent_when = 0;
164
165 /*
166  * Characters leave scent trails for perceptive monsters to track.
167  *
168  * Smell is rather more limited than sound.  Many creatures cannot use
169  * it at all, it doesn't extend very far outwards from the character's
170  * current position, and monsters can use it to home in the character,
171  * but not to run away from him.
172  *
173  * Smell is valued according to age.  When a character takes his turn,
174  * scent is aged by one, and new scent of the current age is laid down.
175  * Speedy characters leave more scent, true, but it also ages faster,
176  * which makes it harder to hunt them down.
177  *
178  * Whenever the age count loops, most of the scent trail is erased and
179  * the age of the remainder is recalculated.
180  */
181 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
182 {
183         /* Create a table that controls the spread of scent */
184         const int scent_adjust[5][5] =
185         {
186                 { -1, 0, 0, 0,-1 },
187                 {  0, 1, 1, 1, 0 },
188                 {  0, 1, 2, 1, 0 },
189                 {  0, 1, 1, 1, 0 },
190                 { -1, 0, 0, 0,-1 },
191         };
192
193         if (++scent_when == 254)
194         {
195                 for (POSITION y = 0; y < floor_ptr->height; y++)
196                 {
197                         for (POSITION x = 0; x < floor_ptr->width; x++)
198                         {
199                                 int w = floor_ptr->grid_array[y][x].when;
200                                 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
201                         }
202                 }
203
204                 scent_when = 126;
205         }
206
207         for (POSITION i = 0; i < 5; i++)
208         {
209                 for (POSITION j = 0; j < 5; j++)
210                 {
211                         grid_type *g_ptr;
212                         POSITION y = i + subject_ptr->y - 2;
213                         POSITION x = j + subject_ptr->x - 2;
214                         if (!in_bounds(floor_ptr, y, x)) continue;
215
216                         g_ptr = &floor_ptr->grid_array[y][x];
217                         if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(subject_ptr, g_ptr->feat)) continue;
218                         if (!player_has_los_bold(subject_ptr, y, x)) continue;
219                         if (scent_adjust[i][j] == -1) continue;
220
221                         g_ptr->when = scent_when + scent_adjust[i][j];
222                 }
223         }
224 }
225
226
227 /*
228  * Hack -- forget the "flow" information
229  */
230 void forget_flow(floor_type *floor_ptr)
231 {
232         for (POSITION y = 0; y < floor_ptr->height; y++)
233         {
234                 for (POSITION x = 0; x < floor_ptr->width; x++)
235                 {
236                         floor_ptr->grid_array[y][x].dist = 0;
237                         floor_ptr->grid_array[y][x].cost = 0;
238                         floor_ptr->grid_array[y][x].when = 0;
239                 }
240         }
241 }
242
243
244 /*
245  * Routine used by the random vault creators to add a door to a location
246  * Note that range checking has to be done in the calling routine.
247  *
248  * The doors must be INSIDE the allocated region.
249  */
250 void add_door(player_type *player_ptr, POSITION x, POSITION y)
251 {
252         floor_type *floor_ptr = player_ptr->current_floor_ptr;
253         if (!is_outer_bold(floor_ptr, y, x)) return;
254
255         /* look at:
256         *  x#x
257         *  .#.
258         *  x#x
259         *
260         *  where x=don't care
261         *  .=floor, #=wall
262         */
263
264         if (is_floor_bold(floor_ptr, y - 1, x) && is_floor_bold(floor_ptr, y + 1, x) &&
265                 (is_outer_bold(floor_ptr, y, x - 1) && is_outer_bold(floor_ptr, y, x + 1)))
266         {
267                 place_secret_door(player_ptr, y, x, DOOR_DEFAULT);
268                 place_bold(player_ptr, y, x - 1, GB_SOLID);
269                 place_bold(player_ptr, y, x + 1, GB_SOLID);
270         }
271
272         /* look at:
273         *  x#x
274         *  .#.
275         *  x#x
276         *
277         *  where x = don't care
278         *  .=floor, #=wall
279         */
280         if (is_outer_bold(floor_ptr, y - 1, x) && is_outer_bold(floor_ptr, y + 1, x) &&
281                 is_floor_bold(floor_ptr, y, x - 1) && is_floor_bold(floor_ptr, y, x + 1))
282         {
283                 place_secret_door(player_ptr, y, x, DOOR_DEFAULT);
284                 place_bold(player_ptr, y - 1, x, GB_SOLID);
285                 place_bold(player_ptr, y + 1, x, GB_SOLID);
286         }
287 }
288
289
290 /*!
291  * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
292  * @param player_ptr プレーヤーへの参照ポインタ
293  * @param y 配置を試みたいマスのY座標
294  * @param x 配置を試みたいマスのX座標
295  * @return なし
296  */
297 void place_random_stairs(player_type *player_ptr, POSITION y, POSITION x)
298 {
299         bool up_stairs = TRUE;
300         bool down_stairs = TRUE;
301         grid_type *g_ptr;
302         floor_type *floor_ptr = player_ptr->current_floor_ptr;
303         g_ptr = &floor_ptr->grid_array[y][x];
304         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
305
306         if (!floor_ptr->dun_level) up_stairs = FALSE;
307         if (ironman_downward) up_stairs = FALSE;
308         if (floor_ptr->dun_level >= d_info[player_ptr->dungeon_idx].maxdepth) down_stairs = FALSE;
309         if (quest_number(player_ptr, floor_ptr->dun_level) && (floor_ptr->dun_level > 1)) down_stairs = FALSE;
310
311         if (down_stairs && up_stairs)
312         {
313                 if (randint0(100) < 50) up_stairs = FALSE;
314                 else down_stairs = FALSE;
315         }
316
317         if (up_stairs) set_cave_feat(floor_ptr, y, x, feat_up_stair);
318         else if (down_stairs) set_cave_feat(floor_ptr, y, x, feat_down_stair);
319 }
320
321
322 /*!
323  * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
324  * @param player_ptr プレーヤーへの参照ポインタ
325  * @param y1 始点のy座標
326  * @param x1 始点のx座標
327  * @param y2 終点のy座標
328  * @param x2 終点のx座標
329  * @return LOSが通っているならTRUEを返す。
330  * @details
331  * A simple, fast, integer-based line-of-sight algorithm.  By Joseph Hall,\n
332  * 4116 Brewster Drive, Raleigh NC 27606.  Email to jnh@ecemwl.ncsu.edu.\n
333  *\n
334  * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
335  *\n
336  * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
337  * the tile (x2,y2).  If los() is to return TRUE, all of the tiles this line\n
338  * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
339  *\n
340  * We assume that the "mathematical corner" of a non-floor tile does not\n
341  * block line of sight.\n
342  *\n
343  * Because this function uses (short) ints for all calculations, overflow may\n
344  * occur if dx and dy exceed 90.\n
345  *\n
346  * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
347  * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
348  * we can use integer arithmetic.\n
349  *\n
350  * We travel from start to finish along the longer axis, starting at the border\n
351  * between the first and second tiles, where the y offset = .5 * slope, taking\n
352  * into account the scale factor.  See below.\n
353  *\n
354  * Also note that this function and the "move towards target" code do NOT\n
355  * share the same properties.  Thus, you can see someone, target them, and\n
356  * then fire a bolt at them, but the bolt may hit a wall, not them.  However\n,
357  * by clever choice of target locations, you can sometimes throw a "curve".\n
358  *\n
359  * Note that "line of sight" is not "reflexive" in all cases.\n
360  *\n
361  * Use the "projectable()" routine to test "spell/missile line of sight".\n
362  *\n
363  * Use the "update_view()" function to determine player line-of-sight.\n
364  */
365 bool los(player_type *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
366 {
367         POSITION dy = y2 - y1;
368         POSITION dx = x2 - x1;
369         POSITION ay = ABS(dy);
370         POSITION ax = ABS(dx);
371         if ((ax < 2) && (ay < 2)) return TRUE;
372
373         /* Directly South/North */
374         floor_type *floor_ptr = player_ptr->current_floor_ptr;
375         POSITION tx, ty;
376         if (!dx)
377         {
378                 /* South -- check for walls */
379                 if (dy > 0)
380                 {
381                         for (ty = y1 + 1; ty < y2; ty++)
382                         {
383                                 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
384                         }
385                 }
386
387                 /* North -- check for walls */
388                 else
389                 {
390                         for (ty = y1 - 1; ty > y2; ty--)
391                         {
392                                 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
393                         }
394                 }
395
396                 /* Assume los */
397                 return TRUE;
398         }
399
400         /* Directly East/West */
401         if (!dy)
402         {
403                 /* East -- check for walls */
404                 if (dx > 0)
405                 {
406                         for (tx = x1 + 1; tx < x2; tx++)
407                         {
408                                 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
409                         }
410                 }
411
412                 /* West -- check for walls */
413                 else
414                 {
415                         for (tx = x1 - 1; tx > x2; tx--)
416                         {
417                                 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
418                         }
419                 }
420
421                 return TRUE;
422         }
423
424         POSITION sx = (dx < 0) ? -1 : 1;
425         POSITION sy = (dy < 0) ? -1 : 1;
426
427         if (ax == 1)
428         {
429                 if (ay == 2)
430                 {
431                         if (cave_los_bold(floor_ptr, y1 + sy, x1)) return TRUE;
432                 }
433         }
434         else if (ay == 1)
435         {
436                 if (ax == 2)
437                 {
438                         if (cave_los_bold(floor_ptr, y1, x1 + sx)) return TRUE;
439                 }
440         }
441
442         POSITION f2 = (ax * ay);
443         POSITION f1 = f2 << 1;
444         POSITION qy;
445         POSITION m;
446         if (ax >= ay)
447         {
448                 qy = ay * ay;
449                 m = qy << 1;
450                 tx = x1 + sx;
451                 if (qy == f2)
452                 {
453                         ty = y1 + sy;
454                         qy -= f1;
455                 }
456                 else
457                 {
458                         ty = y1;
459                 }
460
461                 /* Note (below) the case (qy == f2), where */
462                 /* the LOS exactly meets the corner of a tile. */
463                 while (x2 - tx)
464                 {
465                         if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
466
467                         qy += m;
468
469                         if (qy < f2)
470                         {
471                                 tx += sx;
472                                 continue;
473                         }
474                         
475                         if (qy > f2)
476                         {
477                                 ty += sy;
478                                 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
479                                 qy -= f1;
480                                 tx += sx;
481                                 continue;
482                         }
483
484                         ty += sy;
485                         qy -= f1;
486                         tx += sx;
487                 }
488
489                 return TRUE;
490         }
491
492         /* Travel vertically */
493         POSITION qx = ax * ax;
494         m = qx << 1;
495         ty = y1 + sy;
496         if (qx == f2)
497         {
498                 tx = x1 + sx;
499                 qx -= f1;
500         }
501         else
502         {
503                 tx = x1;
504         }
505
506         /* Note (below) the case (qx == f2), where */
507         /* the LOS exactly meets the corner of a tile. */
508         while (y2 - ty)
509         {
510                 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
511
512                 qx += m;
513
514                 if (qx < f2)
515                 {
516                         ty += sy;
517                         continue;
518                 }
519
520                 if (qx > f2)
521                 {
522                         tx += sx;
523                         if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
524                         qx -= f1;
525                         ty += sy;
526                         continue;
527                 }
528
529                 tx += sx;
530                 qx -= f1;
531                 ty += sy;
532         }
533
534         return TRUE;
535 }
536
537
538 /*
539  * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
540  * at the final destination, assuming no monster gets in the way.
541  *
542  * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
543  */
544 bool projectable(player_type *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
545 {
546         u16b grid_g[512];
547     int grid_n = project_path(player_ptr, grid_g, (project_length ? project_length : get_max_range(player_ptr)), y1, x1, y2, x2, 0);
548         if (!grid_n) return TRUE;
549
550         POSITION y = GRID_Y(grid_g[grid_n - 1]);
551         POSITION x = GRID_X(grid_g[grid_n - 1]);
552         if ((y != y2) || (x != x2)) return FALSE;
553
554         return TRUE;
555 }
556
557
558 /*!
559  * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
560  * @param player_ptr プレーヤーへの参照ポインタ
561  * @param y1 モンスターを配置したいマスの中心Y座標
562  * @param x1 モンスターを配置したいマスの中心X座標
563  * @param num 配置したいモンスターの数
564  * @return なし
565  * @details
566  * Only really called by some of the "vault" routines.
567  */
568 void vault_monsters(player_type *player_ptr, POSITION y1, POSITION x1, int num)
569 {
570         floor_type *floor_ptr = player_ptr->current_floor_ptr;
571         for (int k = 0; k < num; k++)
572         {
573                 for (int i = 0; i < 9; i++)
574                 {
575                         int d = 1;
576                         POSITION y, x;
577                         scatter(player_ptr, &y, &x, y1, x1, d, 0);
578                         grid_type *g_ptr;
579                         g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
580                         if (!is_cave_empty_grid(player_ptr, g_ptr)) continue;
581
582                         floor_ptr->monster_level = floor_ptr->base_level + 2;
583                         (void)place_monster(player_ptr, y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
584                         floor_ptr->monster_level = floor_ptr->base_level;
585                 }
586         }
587 }
588
589
590 /*!
591  * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
592  * @param player_ptr プレーヤーへの参照ポインタ
593  * @param y y座標
594  * @param x x座標
595  * @return 各種の変更が可能ならTRUEを返す。
596  * @details
597  * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
598  */
599 bool cave_valid_bold(floor_type *floor_ptr, POSITION y, POSITION x)
600 {
601         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
602         if (cave_perma_grid(g_ptr)) return FALSE;
603
604         OBJECT_IDX next_o_idx = 0;
605         for (OBJECT_IDX this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
606         {
607                 object_type *o_ptr;
608                 o_ptr = &floor_ptr->o_list[this_o_idx];
609                 next_o_idx = o_ptr->next_o_idx;
610                 if (object_is_artifact(o_ptr)) return FALSE;
611         }
612
613         return TRUE;
614 }
615
616
617 /*
618  * Change the "feat" flag for a grid, and notice/redraw the grid
619  */
620 void cave_set_feat(player_type *player_ptr, POSITION y, POSITION x, FEAT_IDX feat)
621 {
622         floor_type *floor_ptr = player_ptr->current_floor_ptr;
623         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
624         feature_type *f_ptr = &f_info[feat];
625         if (!current_world_ptr->character_dungeon)
626         {
627                 g_ptr->mimic = 0;
628                 g_ptr->feat = feat;
629                 if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
630                 {
631                         for (DIRECTION i = 0; i < 9; i++)
632                         {
633                                 POSITION yy = y + ddy_ddd[i];
634                                 POSITION xx = x + ddx_ddd[i];
635                                 if (!in_bounds2(floor_ptr, yy, xx)) continue;
636                                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
637                         }
638                 }
639
640                 return;
641         }
642
643         bool old_los = cave_have_flag_bold(floor_ptr, y, x, FF_LOS);
644         bool old_mirror = is_mirror_grid(g_ptr);
645
646         g_ptr->mimic = 0;
647         g_ptr->feat = feat;
648         g_ptr->info &= ~(CAVE_OBJECT);
649         if (old_mirror && (d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
650         {
651                 g_ptr->info &= ~(CAVE_GLOW);
652                 if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
653
654                 update_local_illumination(player_ptr, y, x);
655         }
656
657         if (!have_flag(f_ptr->flags, FF_REMEMBER)) g_ptr->info &= ~(CAVE_MARK);
658         if (g_ptr->m_idx) update_monster(player_ptr, g_ptr->m_idx, FALSE);
659
660         note_spot(player_ptr, y, x);
661         lite_spot(player_ptr, y, x);
662         if (old_los ^ have_flag(f_ptr->flags, FF_LOS))
663         {
664
665 #ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
666
667                 update_local_illumination(player_ptr, y, x);
668
669 #endif /* COMPLEX_WALL_ILLUMINATION */
670
671                 player_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS);
672         }
673
674         if (!have_flag(f_ptr->flags, FF_GLOW) || (d_info[player_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
675                 return;
676
677         for (DIRECTION i = 0; i < 9; i++)
678         {
679                 POSITION yy = y + ddy_ddd[i];
680                 POSITION xx = x + ddx_ddd[i];
681                 if (!in_bounds2(floor_ptr, yy, xx)) continue;
682
683                 grid_type *cc_ptr;
684                 cc_ptr = &floor_ptr->grid_array[yy][xx];
685                 cc_ptr->info |= CAVE_GLOW;
686
687                 if (player_has_los_grid(cc_ptr))
688                 {
689                         if (cc_ptr->m_idx) update_monster(player_ptr, cc_ptr->m_idx, FALSE);
690                         note_spot(player_ptr, yy, xx);
691                         lite_spot(player_ptr, yy, xx);
692                 }
693
694                 update_local_illumination(player_ptr, yy, xx);
695         }
696
697         if (player_ptr->special_defense & NINJA_S_STEALTH)
698         {
699                 if (floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) set_superstealth(player_ptr, FALSE);
700         }
701 }
702
703
704 /*!
705  * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
706  * @param player_ptr プレーヤーへの参照ポインタ
707  * @param y ドアの配置を試みたいマスのY座標
708  * @param x ドアの配置を試みたいマスのX座標
709  * @param room 部屋に接している場合向けのドア生成か否か
710  * @return なし
711  */
712 void place_random_door(player_type *player_ptr, POSITION y, POSITION x, bool room)
713 {
714         floor_type *floor_ptr = player_ptr->current_floor_ptr;
715         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
716         g_ptr->mimic = 0;
717
718         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
719         {
720                 place_bold(player_ptr, y, x, GB_FLOOR);
721                 return;
722         }
723
724         int type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
725                 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
726                 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
727
728         int tmp = randint0(1000);
729         FEAT_IDX feat = feat_none;
730         if (tmp < 300)
731         {
732                 feat = feat_door[type].open;
733         }
734         else if (tmp < 400)
735         {
736                 feat = feat_door[type].broken;
737         }
738         else if (tmp < 600)
739         {
740                 place_closed_door(player_ptr, y, x, type);
741
742                 if (type != DOOR_CURTAIN)
743                 {
744                         g_ptr->mimic = room ? feat_wall_outer : feat_wall_type[randint0(100)];
745                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
746                         {
747                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
748                                 {
749                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
750                                 }
751                                 g_ptr->mimic = 0;
752                         }
753                 }
754         }
755         else
756         {
757                 place_closed_door(player_ptr, y, x, type);
758         }
759
760         if (tmp >= 400)
761         {
762                 delete_monster(player_ptr, y, x);
763                 return;
764         }
765
766         if (feat != feat_none)
767         {
768                 set_cave_feat(floor_ptr, y, x, feat);
769         }
770         else
771         {
772                 place_bold(player_ptr, y, x, GB_FLOOR);
773         }
774
775         delete_monster(player_ptr, y, x);
776 }
777
778
779 /*!
780  * @brief グローバルオブジェクト配列を初期化する /
781  * Delete all the items when player leaves the level
782  * @note we do NOT visually reflect these (irrelevant) changes
783  * @details
784  * Hack -- we clear the "g_ptr->o_idx" field for every grid,
785  * and the "m_ptr->next_o_idx" field for every monster, since
786  * we know we are clearing every object.  Technically, we only
787  * clear those fields for grids/monsters containing objects,
788  * and we clear it once for every such object.
789  * @return なし
790  */
791 void wipe_o_list(floor_type *floor_ptr)
792 {
793         for (int i = 1; i < floor_ptr->o_max; i++)
794         {
795                 object_type *o_ptr = &floor_ptr->o_list[i];
796                 if (!object_is_valid(o_ptr)) continue;
797
798                 if (!current_world_ptr->character_dungeon || preserve_mode)
799                 {
800                         if (object_is_fixed_artifact(o_ptr) && !object_is_known(o_ptr))
801                         {
802                                 a_info[o_ptr->name1].cur_num = 0;
803                         }
804                 }
805
806                 if (object_is_held_monster(o_ptr))
807                 {
808                         monster_type *m_ptr;
809                         m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
810                         m_ptr->hold_o_idx = 0;
811                         object_wipe(o_ptr);
812                         continue;
813                 }
814
815                 grid_type *g_ptr;
816                 POSITION y = o_ptr->iy;
817                 POSITION x = o_ptr->ix;
818
819                 g_ptr = &floor_ptr->grid_array[y][x];
820                 g_ptr->o_idx = 0;
821                 object_wipe(o_ptr);
822         }
823
824         floor_ptr->o_max = 1;
825         floor_ptr->o_cnt = 0;
826 }
827
828
829 /*!
830  * @brief 所定の位置に各種の閉じたドアを配置する / Place a random type of normal door at the given location.
831  * @param player_ptr プレーヤーへの参照ポインタ
832  * @param y ドアの配置を試みたいマスのY座標
833  * @param x ドアの配置を試みたいマスのX座標
834  * @param type ドアの地形ID
835  * @return なし
836  */
837 void place_closed_door(player_type *player_ptr, POSITION y, POSITION x, int type)
838 {
839         floor_type *floor_ptr = player_ptr->current_floor_ptr;
840         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
841         {
842                 place_bold(player_ptr, y, x, GB_FLOOR);
843                 return;
844         }
845
846         int tmp = randint0(400);
847         FEAT_IDX feat = feat_none;
848         if (tmp < 300)
849         {
850                 /* Create closed door */
851                 feat = feat_door[type].closed;
852         }
853         else if (tmp < 399)
854         {
855                 feat = feat_locked_door_random(type);
856         }
857         else
858         {
859                 feat = feat_jammed_door_random(type);
860         }
861
862         if (feat == feat_none)
863         {
864                 place_bold(player_ptr, y, x, GB_FLOOR);
865                 return;
866         }
867
868         cave_set_feat(player_ptr, y, x, feat);
869         floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
870 }
871
872
873 /*!
874  * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
875  * @param y トラップを配置したいマスの中心Y座標
876  * @param x トラップを配置したいマスの中心X座標
877  * @param yd Y方向の配置分散マス数
878  * @param xd X方向の配置分散マス数
879  * @return なし
880  * @details
881  * Only really called by some of the "vault" routines.
882  */
883 void vault_trap_aux(player_type *player_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd)
884 {
885         grid_type *g_ptr;
886         floor_type *floor_ptr = player_ptr->current_floor_ptr;
887         int y1 = y, x1 = x;
888         int dummy = 0;
889         for (int count = 0; count <= 5; count++)
890         {
891                 while (dummy < SAFE_MAX_ATTEMPTS)
892                 {
893                         y1 = rand_spread(y, yd);
894                         x1 = rand_spread(x, xd);
895                         dummy++;
896                         if (!in_bounds(floor_ptr, y1, x1)) continue;
897                         break;
898                 }
899
900                 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
901                 {
902                         msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
903                 }
904
905                 g_ptr = &floor_ptr->grid_array[y1][x1];
906                 if (!is_floor_grid(g_ptr) || g_ptr->o_idx || g_ptr->m_idx) continue;
907
908                 place_trap(player_ptr, y1, x1);
909                 break;
910         }
911 }
912
913
914 /*!
915  * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor.  (Includes range checking.)
916  * @param x チェックするマスのX座標
917  * @param y チェックするマスのY座標
918  * @return 床系地形ならばTRUE
919  */
920 bool get_is_floor(floor_type *floor_ptr, POSITION x, POSITION y)
921 {
922         if (!in_bounds(floor_ptr, y, x))
923         {
924                 return FALSE;
925         }
926
927         if (is_floor_bold(floor_ptr, y, x)) return TRUE;
928
929         return FALSE;
930 }
931
932
933 /*!
934 * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
935 * @param y1 基準となるマスのY座標
936 * @param x1 基準となるマスのX座標
937 * @return 通路の数
938 * @note Assumes "in_bounds(y1, x1)"
939 * @details
940 * XXX XXX This routine currently only counts actual "empty floor"\n
941 * grids which are not in rooms.  We might want to also count stairs,\n
942 * open doors, closed doors, etc.
943 */
944 static int next_to_corr(floor_type *floor_ptr, POSITION y1, POSITION x1)
945 {
946         int k = 0;
947         for (int i = 0; i < 4; i++)
948         {
949                 POSITION y = y1 + ddy_ddd[i];
950                 POSITION x = x1 + ddx_ddd[i];
951                 grid_type *g_ptr;
952                 g_ptr = &floor_ptr->grid_array[y][x];
953
954                 if (cave_have_flag_grid(g_ptr, FF_WALL)) continue;
955                 if (!is_floor_grid(g_ptr)) continue;
956                 if (g_ptr->info & (CAVE_ROOM)) continue;
957
958                 k++;
959         }
960
961         return k;
962 }
963
964 /*!
965 * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
966 * @param y 判定を行いたいマスのY座標
967 * @param x 判定を行いたいマスのX座標
968 * @return ドアを設置可能ならばTRUEを返す
969 * @note Assumes "in_bounds()"
970 * @details
971 * \n
972 * Assumes "in_bounds()"\n
973 */
974 static bool possible_doorway(floor_type *floor_ptr, POSITION y, POSITION x)
975 {
976         if (next_to_corr(floor_ptr, y, x) < 2) return FALSE;
977
978         /* Check Vertical */
979         if (cave_have_flag_bold(floor_ptr, y - 1, x, FF_WALL) &&
980                 cave_have_flag_bold(floor_ptr, y + 1, x, FF_WALL))
981         {
982                 return TRUE;
983         }
984
985         /* Check Horizontal */
986         if (cave_have_flag_bold(floor_ptr, y, x - 1, FF_WALL) &&
987                 cave_have_flag_bold(floor_ptr, y, x + 1, FF_WALL))
988         {
989                 return TRUE;
990         }
991
992         return FALSE;
993 }
994
995
996 /*!
997 * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
998 * @param player_ptr プレーヤーへの参照ポインタ
999 * @param y 設置を行いたいマスのY座標
1000 * @param x 設置を行いたいマスのX座標
1001 * @return なし
1002 */
1003 void try_door(player_type *player_ptr, POSITION y, POSITION x)
1004 {
1005         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1006         if (!in_bounds(floor_ptr, y, x)) return;
1007
1008         if (cave_have_flag_bold(floor_ptr, y, x, FF_WALL)) return;
1009         if (floor_ptr->grid_array[y][x].info & (CAVE_ROOM)) return;
1010
1011         bool can_place_door = randint0(100) < dun_tun_jct;
1012         can_place_door &= possible_doorway(floor_ptr, y, x);
1013         can_place_door &= (d_info[player_ptr->dungeon_idx].flags1 & DF1_NO_DOORS) == 0;
1014         if (can_place_door)
1015         {
1016                 place_random_door(player_ptr, y, x, FALSE);
1017         }
1018 }
1019
1020
1021 FEAT_IDX conv_dungeon_feat(floor_type *floor_ptr, FEAT_IDX newfeat)
1022 {
1023         feature_type *f_ptr = &f_info[newfeat];
1024         if (have_flag(f_ptr->flags, FF_CONVERT))
1025         {
1026                 switch (f_ptr->subtype)
1027                 {
1028                 case CONVERT_TYPE_FLOOR:
1029                         return feat_ground_type[randint0(100)];
1030                 case CONVERT_TYPE_WALL:
1031                         return feat_wall_type[randint0(100)];
1032                 case CONVERT_TYPE_INNER:
1033                         return feat_wall_inner;
1034                 case CONVERT_TYPE_OUTER:
1035                         return feat_wall_outer;
1036                 case CONVERT_TYPE_SOLID:
1037                         return feat_wall_solid;
1038                 case CONVERT_TYPE_STREAM1:
1039                         return d_info[floor_ptr->dungeon_idx].stream1;
1040                 case CONVERT_TYPE_STREAM2:
1041                         return d_info[floor_ptr->dungeon_idx].stream2;
1042                 default:
1043                         return newfeat;
1044                 }
1045         }
1046         else return newfeat;
1047 }
1048
1049
1050 /*!
1051  * @brief 特殊な部屋向けに各種アイテムを配置する / Create up to "num" objects near the given coordinates
1052  * @param player_ptr プレーヤーへの参照ポインタ
1053  * @param y 配置したい中心マスのY座標
1054  * @param x 配置したい中心マスのX座標
1055  * @param num 配置したい数
1056  * @return なし
1057  * @details
1058  * Only really called by some of the "vault" routines.
1059  */
1060 void vault_objects(player_type *player_ptr, POSITION y, POSITION x, int num)
1061 {
1062         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1063         for (; num > 0; --num)
1064         {
1065                 int j = y, k = x;
1066                 int dummy = 0;
1067                 for (int i = 0; i < 11; ++i)
1068                 {
1069                         while (dummy < SAFE_MAX_ATTEMPTS)
1070                         {
1071                                 j = rand_spread(y, 2);
1072                                 k = rand_spread(x, 3);
1073                                 dummy++;
1074                                 if (!in_bounds(floor_ptr, j, k)) continue;
1075                                 break;
1076                         }
1077
1078                         if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
1079                         {
1080                                 msg_print(_("警告!地下室のアイテムを配置できません!", "Warning! Could not place vault object!"));
1081                         }
1082
1083                         grid_type *g_ptr;
1084                         g_ptr = &floor_ptr->grid_array[j][k];
1085                         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) continue;
1086
1087                         if (randint0(100) < 75)
1088                         {
1089                                 place_object(player_ptr, j, k, 0L);
1090                         }
1091                         else
1092                         {
1093                                 place_gold(player_ptr, j, k);
1094                         }
1095
1096                         break;
1097                 }
1098         }
1099 }
1100
1101
1102 /*!
1103  * @brief 始点から終点への直線経路を返す /
1104  * Determine the path taken by a projection.
1105  * @param player_ptr プレーヤーへの参照ポインタ
1106  * @param gp 経路座標リストを返す参照ポインタ
1107  * @param range 距離
1108  * @param y1 始点Y座標
1109  * @param x1 始点X座標
1110  * @param y2 終点Y座標
1111  * @param x2 終点X座標
1112  * @param flg フラグID
1113  * @return リストの長さ
1114  * @details
1115  * <pre>
1116  * The projection will always start from the grid (y1,x1), and will travel
1117  * towards the grid (y2,x2), touching one grid per unit of distance along
1118  * the major axis, and stopping when it enters the destination grid or a
1119  * wall grid, or has travelled the maximum legal distance of "range".
1120  *
1121  * Note that "distance" in this function (as in the "update_view()" code)
1122  * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
1123  * actually has an "octagon of projection" not a "circle of projection".
1124  *
1125  * The path grids are saved into the grid array pointed to by "gp", and
1126  * there should be room for at least "range" grids in "gp".  Note that
1127  * due to the way in which distance is calculated, this function normally
1128  * uses fewer than "range" grids for the projection path, so the result
1129  * of this function should never be compared directly to "range".  Note
1130  * that the initial grid (y1,x1) is never saved into the grid array, not
1131  * even if the initial grid is also the final grid.
1132  *
1133  * The "flg" flags can be used to modify the behavior of this function.
1134  *
1135  * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
1136  * semantics as they do for the "project" function, namely, that the path
1137  * will stop as soon as it hits a monster, or that the path will continue
1138  * through the destination grid, respectively.
1139  *
1140  * The "PROJECT_JUMP" flag, which for the "project()" function means to
1141  * start at a special grid (which makes no sense in this function), means
1142  * that the path should be "angled" slightly if needed to avoid any wall
1143  * grids, allowing the player to "target" any grid which is in "view".
1144  * This flag is non-trivial and has not yet been implemented, but could
1145  * perhaps make use of the "vinfo" array (above).
1146  *
1147  * This function returns the number of grids (if any) in the path.  This
1148  * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
1149  *
1150  * This algorithm is similar to, but slightly different from, the one used
1151  * by "update_view_los()", and very different from the one used by "los()".
1152  * </pre>
1153  */
1154 int project_path(player_type *player_ptr, u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg)
1155 {
1156         if ((x1 == x2) && (y1 == y2)) return 0;
1157
1158         POSITION y, x;
1159         POSITION ay, ax;
1160         POSITION sy, sx;
1161         int frac;
1162         int m;
1163
1164         if (y2 < y1)
1165         {
1166                 ay = (y1 - y2);
1167                 sy = -1;
1168         }
1169         else
1170         {
1171                 ay = (y2 - y1);
1172                 sy = 1;
1173         }
1174
1175         if (x2 < x1)
1176         {
1177                 ax = (x1 - x2);
1178                 sx = -1;
1179         }
1180         else
1181         {
1182                 ax = (x2 - x1);
1183                 sx = 1;
1184         }
1185
1186         int half = (ay * ax);
1187         int full = half << 1;
1188
1189         /* Vertical */
1190         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1191         int n = 0;
1192         int k = 0;
1193         if (ay > ax)
1194         {
1195                 m = ax * ax * 2;
1196                 y = y1 + sy;
1197                 x = x1;
1198                 frac = m;
1199                 if (frac > half)
1200                 {
1201                         x += sx;
1202                         frac -= full;
1203                         k++;
1204                 }
1205
1206                 while (TRUE)
1207                 {
1208                         gp[n++] = GRID(y, x);
1209                         if ((n + (k >> 1)) >= range) break;
1210
1211                         if (!(flg & (PROJECT_THRU)))
1212                         {
1213                                 if ((x == x2) && (y == y2)) break;
1214                         }
1215
1216                         if (flg & (PROJECT_DISI))
1217                         {
1218                                 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1219                         }
1220                         else if (flg & (PROJECT_LOS))
1221                         {
1222                                 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1223                         }
1224                         else if (!(flg & (PROJECT_PATH)))
1225                         {
1226                                 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1227                         }
1228
1229                         if (flg & (PROJECT_STOP))
1230                         {
1231                                 if ((n > 0) &&
1232                                         (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1233                                         break;
1234                         }
1235
1236                         if (!in_bounds(floor_ptr, y, x)) break;
1237
1238                         if (m)
1239                         {
1240                                 frac += m;
1241                                 if (frac > half)
1242                                 {
1243                                         x += sx;
1244                                         frac -= full;
1245                                         k++;
1246                                 }
1247                         }
1248
1249                         y += sy;
1250                 }
1251
1252                 return n;
1253         }
1254
1255         /* Horizontal */
1256         if (ax > ay)
1257         {
1258                 m = ay * ay * 2;
1259                 y = y1;
1260                 x = x1 + sx;
1261                 frac = m;
1262                 if (frac > half)
1263                 {
1264                         y += sy;
1265                         frac -= full;
1266                         k++;
1267                 }
1268
1269                 while (TRUE)
1270                 {
1271                         gp[n++] = GRID(y, x);
1272                         if ((n + (k >> 1)) >= range) break;
1273
1274                         if (!(flg & (PROJECT_THRU)))
1275                         {
1276                                 if ((x == x2) && (y == y2)) break;
1277                         }
1278
1279                         if (flg & (PROJECT_DISI))
1280                         {
1281                                 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1282                         }
1283                         else if (flg & (PROJECT_LOS))
1284                         {
1285                                 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1286                         }
1287                         else if (!(flg & (PROJECT_PATH)))
1288                         {
1289                                 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1290                         }
1291
1292                         if (flg & (PROJECT_STOP))
1293                         {
1294                                 if ((n > 0) &&
1295                                         (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1296                                         break;
1297                         }
1298
1299                         if (!in_bounds(floor_ptr, y, x)) break;
1300
1301                         if (m)
1302                         {
1303                                 frac += m;
1304                                 if (frac > half)
1305                                 {
1306                                         y += sy;
1307                                         frac -= full;
1308                                         k++;
1309                                 }
1310                         }
1311
1312                         x += sx;
1313                 }
1314
1315                 return n;
1316         }
1317
1318         y = y1 + sy;
1319         x = x1 + sx;
1320
1321         while (TRUE)
1322         {
1323                 gp[n++] = GRID(y, x);
1324                 if ((n + (n >> 1)) >= range) break;
1325
1326                 if (!(flg & (PROJECT_THRU)))
1327                 {
1328                         if ((x == x2) && (y == y2)) break;
1329                 }
1330
1331                 if (flg & (PROJECT_DISI))
1332                 {
1333                         if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1334                 }
1335                 else if (flg & (PROJECT_LOS))
1336                 {
1337                         if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1338                 }
1339                 else if (!(flg & (PROJECT_PATH)))
1340                 {
1341                         if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1342                 }
1343
1344                 if (flg & (PROJECT_STOP))
1345                 {
1346                         if ((n > 0) &&
1347                                 (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1348                                 break;
1349                 }
1350
1351                 if (!in_bounds(floor_ptr, y, x)) break;
1352
1353                 y += sy;
1354                 x += sx;
1355         }
1356
1357         return n;
1358 }
1359
1360
1361 /*!
1362  * @brief 指定のマスを床地形に変える / Set a square to be floor.  (Includes range checking.)
1363  * @param player_ptr プレーヤーへの参照ポインタ
1364  * @param x 地形を変えたいマスのX座標
1365  * @param y 地形を変えたいマスのY座標
1366  * @return なし
1367  */
1368 void set_floor(player_type *player_ptr, POSITION x, POSITION y)
1369 {
1370         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1371         if (!in_bounds(floor_ptr, y, x))
1372         {
1373                 return;
1374         }
1375
1376         if (floor_ptr->grid_array[y][x].info & CAVE_ROOM)
1377         {
1378                 return;
1379         }
1380
1381         if (is_extra_bold(floor_ptr, y, x))
1382                 place_bold(player_ptr, y, x, GB_FLOOR);
1383 }
1384
1385
1386 /*!
1387  * @brief フロアの指定位置に生成階に応じたベースアイテムの生成を行う。
1388  * Attempt to place an object (normal or good/great) at the given location.
1389  * @param owner_ptr プレーヤーへの参照ポインタ
1390  * @param y 配置したいフロアのY座標
1391  * @param x 配置したいフロアのX座標
1392  * @param mode オプションフラグ
1393  * @return 生成に成功したらTRUEを返す。
1394  * @details
1395  * This routine plays nasty games to generate the "special artifacts".\n
1396  * This routine uses "object_level" for the "generation level".\n
1397  * This routine requires a clean floor grid destination.\n
1398  */
1399 void place_object(player_type *owner_ptr, POSITION y, POSITION x, BIT_FLAGS mode)
1400 {
1401         floor_type *floor_ptr = owner_ptr->current_floor_ptr;
1402         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1403         object_type forge;
1404         object_type *q_ptr;
1405         if (!in_bounds(floor_ptr, y, x)) return;
1406         if (!cave_drop_bold(floor_ptr, y, x)) return;
1407         if (g_ptr->o_idx) return;
1408
1409         q_ptr = &forge;
1410         object_wipe(q_ptr);
1411         if (!make_object(owner_ptr, q_ptr, mode)) return;
1412
1413         OBJECT_IDX o_idx = o_pop(floor_ptr);
1414         if (o_idx == 0)
1415         {
1416                 if (object_is_fixed_artifact(q_ptr))
1417                 {
1418                         a_info[q_ptr->name1].cur_num = 0;
1419                 }
1420
1421                 return;
1422         }
1423
1424         object_type *o_ptr;
1425         o_ptr = &floor_ptr->o_list[o_idx];
1426         object_copy(o_ptr, q_ptr);
1427
1428         o_ptr->iy = y;
1429         o_ptr->ix = x;
1430         o_ptr->next_o_idx = g_ptr->o_idx;
1431
1432         g_ptr->o_idx = o_idx;
1433         note_spot(owner_ptr, y, x);
1434         lite_spot(owner_ptr, y, x);
1435 }
1436
1437
1438 /*!
1439  * @brief フロアの指定位置に生成階に応じた財宝オブジェクトの生成を行う。
1440  * Places a treasure (Gold or Gems) at given location
1441  * @param player_ptr プレーヤーへの参照ポインタ
1442  * @param y 配置したいフロアのY座標
1443  * @param x 配置したいフロアのX座標
1444  * @return 生成に成功したらTRUEを返す。
1445  * @details
1446  * The location must be a legal, clean, floor grid.
1447  */
1448 void place_gold(player_type *player_ptr, POSITION y, POSITION x)
1449 {
1450         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1451         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1452         if (!in_bounds(floor_ptr, y, x)) return;
1453         if (!cave_drop_bold(floor_ptr, y, x)) return;
1454         if (g_ptr->o_idx) return;
1455
1456         object_type forge;
1457         object_type *q_ptr;
1458         q_ptr = &forge;
1459         object_wipe(q_ptr);
1460         if (!make_gold(player_ptr, q_ptr)) return;
1461
1462         OBJECT_IDX o_idx = o_pop(floor_ptr);
1463         if (o_idx == 0) return;
1464
1465         object_type *o_ptr;
1466         o_ptr = &floor_ptr->o_list[o_idx];
1467         object_copy(o_ptr, q_ptr);
1468
1469         o_ptr->iy = y;
1470         o_ptr->ix = x;
1471         o_ptr->next_o_idx = g_ptr->o_idx;
1472
1473         g_ptr->o_idx = o_idx;
1474         note_spot(player_ptr, y, x);
1475         lite_spot(player_ptr, y, x);
1476 }
1477
1478
1479 /*!
1480  * @brief 指定位置に存在するモンスターを削除する / Delete the monster, if any, at a given location
1481  * @param player_ptr プレーヤーへの参照ポインタ
1482  * @param x 削除位置x座標
1483  * @param y 削除位置y座標
1484  * @return なし
1485  */
1486 void delete_monster(player_type *player_ptr, POSITION y, POSITION x)
1487 {
1488         grid_type *g_ptr;
1489         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1490         if (!in_bounds(floor_ptr, y, x)) return;
1491
1492         g_ptr = &floor_ptr->grid_array[y][x];
1493         if (g_ptr->m_idx) delete_monster_idx(player_ptr, g_ptr->m_idx);
1494 }
1495
1496
1497 /*!
1498  * @brief グローバルオブジェクト配列に対し指定範囲のオブジェクトを整理してIDの若い順に寄せる /
1499  * Move an object from index i1 to index i2 in the object list
1500  * @param i1 整理したい配列の始点
1501  * @param i2 整理したい配列の終点
1502  * @return なし
1503  */
1504 static void compact_objects_aux(floor_type *floor_ptr, OBJECT_IDX i1, OBJECT_IDX i2)
1505 {
1506         if (i1 == i2) return;
1507
1508         object_type *o_ptr;
1509         for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++)
1510         {
1511                 o_ptr = &floor_ptr->o_list[i];
1512                 if (!o_ptr->k_idx) continue;
1513
1514                 if (o_ptr->next_o_idx == i1)
1515                 {
1516                         o_ptr->next_o_idx = i2;
1517                 }
1518         }
1519
1520         o_ptr = &floor_ptr->o_list[i1];
1521
1522         if (object_is_held_monster(o_ptr))
1523         {
1524                 monster_type *m_ptr;
1525                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
1526                 if (m_ptr->hold_o_idx == i1)
1527                 {
1528                         m_ptr->hold_o_idx = i2;
1529                 }
1530         }
1531         else
1532         {
1533                 POSITION y = o_ptr->iy;
1534                 POSITION x = o_ptr->ix;
1535                 grid_type *g_ptr;
1536                 g_ptr = &floor_ptr->grid_array[y][x];
1537
1538                 if (g_ptr->o_idx == i1)
1539                 {
1540                         g_ptr->o_idx = i2;
1541                 }
1542         }
1543
1544         floor_ptr->o_list[i2] = floor_ptr->o_list[i1];
1545         object_wipe(o_ptr);
1546 }
1547
1548
1549 /*!
1550  * @brief グローバルオブジェクト配列から優先度の低いものを削除し、データを圧縮する。 /
1551  * Compact and Reorder the object list.
1552  * @param player_ptr プレーヤーへの参照ポインタ
1553  * @param size 最低でも減らしたいオブジェクト数の水準
1554  * @return なし
1555  * @details
1556  * (危険なので使用には注意すること)
1557  * This function can be very dangerous, use with caution!\n
1558  *\n
1559  * When actually "compacting" objects, we base the saving throw on a\n
1560  * combination of object level, distance from player, and current\n
1561  * "desperation".\n
1562  *\n
1563  * After "compacting" (if needed), we "reorder" the objects into a more\n
1564  * compact order, and we reset the allocation info, and the "live" array.\n
1565  */
1566 void compact_objects(player_type *player_ptr, int size)
1567 {
1568         object_type *o_ptr;
1569         if (size)
1570         {
1571                 msg_print(_("アイテム情報を圧縮しています...", "Compacting objects..."));
1572                 player_ptr->redraw |= (PR_MAP);
1573                 player_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1574         }
1575
1576         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1577         for (int num = 0, cnt = 1; num < size; cnt++)
1578         {
1579                 int cur_lev = 5 * cnt;
1580                 int cur_dis = 5 * (20 - cnt);
1581                 for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++)
1582                 {
1583                         o_ptr = &floor_ptr->o_list[i];
1584
1585                         if (!object_is_valid(o_ptr)) continue;
1586                         if (k_info[o_ptr->k_idx].level > cur_lev) continue;
1587
1588                         POSITION y, x;
1589                         if (object_is_held_monster(o_ptr))
1590                         {
1591                                 monster_type *m_ptr;
1592                                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
1593                                 y = m_ptr->fy;
1594                                 x = m_ptr->fx;
1595
1596                                 if (randint0(100) < 90) continue;
1597                         }
1598                         else
1599                         {
1600                                 y = o_ptr->iy;
1601                                 x = o_ptr->ix;
1602                         }
1603
1604                         if ((cur_dis > 0) && (distance(player_ptr->y, player_ptr->x, y, x) < cur_dis)) continue;
1605
1606                         int chance = 90;
1607                         if ((object_is_fixed_artifact(o_ptr) || o_ptr->art_name) &&
1608                                 (cnt < 1000)) chance = 100;
1609
1610                         if (randint0(100) < chance) continue;
1611
1612                         delete_object_idx(player_ptr, i);
1613                         num++;
1614                 }
1615         }
1616
1617         for (OBJECT_IDX i = floor_ptr->o_max - 1; i >= 1; i--)
1618         {
1619                 o_ptr = &floor_ptr->o_list[i];
1620                 if (o_ptr->k_idx) continue;
1621
1622                 compact_objects_aux(floor_ptr, floor_ptr->o_max - 1, i);
1623                 floor_ptr->o_max--;
1624         }
1625 }
1626
1627
1628 /*!
1629  * @brief 特殊な部屋向けに各種アイテムを配置する(メインルーチン) / Place some traps with a given displacement of given location
1630  * @param player_ptr プレーヤーへの参照ポインタ
1631  * @param y トラップを配置したいマスの中心Y座標
1632  * @param x トラップを配置したいマスの中心X座標
1633  * @param yd Y方向の配置分散マス数
1634  * @param xd X方向の配置分散マス数
1635  * @param num 配置したいトラップの数
1636  * @return なし
1637  * @details
1638  * Only really called by some of the "vault" routines.
1639  */
1640 void vault_traps(player_type *player_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd, int num)
1641 {
1642         for (int i = 0; i < num; i++)
1643         {
1644                 vault_trap_aux(player_ptr, y, x, yd, xd);
1645         }
1646 }
1647
1648
1649 /*
1650  * Standard "find me a location" function
1651  *
1652  * Obtains a legal location within the given distance of the initial
1653  * location, and with "los()" from the source to destination location.
1654  *
1655  * This function is often called from inside a loop which searches for
1656  * locations while increasing the "d" distance.
1657  *
1658  * Currently the "m" parameter is unused.
1659  */
1660 void scatter(player_type *player_ptr, POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION d, BIT_FLAGS mode)
1661 {
1662         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1663         POSITION nx, ny;
1664         while (TRUE)
1665         {
1666                 ny = rand_spread(y, d);
1667                 nx = rand_spread(x, d);
1668
1669                 if (!in_bounds(floor_ptr, ny, nx)) continue;
1670                 if ((d > 1) && (distance(y, x, ny, nx) > d)) continue;
1671                 if (mode & PROJECT_LOS)
1672                 {
1673                         if (los(player_ptr, y, x, ny, nx)) break;
1674                         continue;
1675                 }
1676
1677                 if (projectable(player_ptr, y, x, ny, nx)) break;
1678         }
1679
1680         *yp = ny;
1681         *xp = nx;
1682 }
1683
1684
1685 /*
1686  * @brief 指定のマスが光を通すか(LOSフラグを持つか)を返す。 / Aux function -- see below
1687  * @param floor_ptr 配置するフロアの参照ポインタ
1688  * @param y 指定Y座標
1689  * @param x 指定X座標
1690  * @return 光を通すならばtrueを返す。
1691  */
1692 bool cave_los_bold(floor_type *floor_ptr, POSITION y, POSITION x)
1693 {
1694         return feat_supports_los(floor_ptr->grid_array[y][x].feat);
1695 }