OSDN Git Service

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