OSDN Git Service

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