OSDN Git Service

[Refactor] #38997 place_locked_door() のfloor_type * 引数をplayer_type * 引数に変更 / Changed...
[hengband/hengband.git] / src / floor.c
1 #include "angband.h"
2 #include "floor.h"
3 #include "floor-save.h"
4 #include "floor-generate.h"
5 #include "grid.h"
6 #include "dungeon.h"
7 #include "rooms.h"
8 #include "quest.h"
9 #include "object-hook.h"
10 #include "world.h"
11 #include "player-effects.h"
12 #include "object.h"
13 #include "object-hook.h"
14 #include "artifact.h"
15 #include "objectkind.h"
16 #include "trap.h"
17
18 /*
19  * The array of floor [MAX_WID][MAX_HGT].
20  * Not completely allocated, that would be inefficient
21  * Not completely hardcoded, that would overflow memory
22  */
23 floor_type floor_info;
24
25 /*
26  * The array of saved floors
27  */
28 saved_floor_type saved_floors[MAX_SAVED_FLOORS];
29
30 /*!
31 * @brief 鍵のかかったドアを配置する
32 * @param player_ptr プレーヤーへの参照ポインタ
33 * @param y 配置したいフロアのY座標
34 * @param x 配置したいフロアのX座標
35 * @return なし
36 */
37 void place_locked_door(player_type *player_ptr, POSITION y, POSITION x)
38 {
39         floor_type *floor_ptr = player_ptr->current_floor_ptr;
40         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
41         {
42                 place_floor_bold(floor_ptr, y, x);
43         }
44         else
45         {
46                 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));
47                 floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
48                 delete_monster(floor_ptr, y, x);
49         }
50 }
51
52
53 /*!
54 * @brief 隠しドアを配置する
55 * @param y 配置したいフロアのY座標
56 * @param x 配置したいフロアのX座標
57 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
58 * @return なし
59 */
60 void place_secret_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
61 {
62         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
63         {
64                 place_floor_bold(floor_ptr, y, x);
65         }
66         else
67         {
68                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
69
70                 if (type == DOOR_DEFAULT)
71                 {
72                         type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
73                                 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
74                                 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
75                 }
76
77                 /* Create secret door */
78                 place_closed_door(floor_ptr, y, x, type);
79
80                 if (type != DOOR_CURTAIN)
81                 {
82                         /* Hide by inner wall because this is used in rooms only */
83                         g_ptr->mimic = feat_wall_inner;
84
85                         /* Floor type terrain cannot hide a door */
86                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
87                         {
88                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
89                                 {
90                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
91                                 }
92                                 g_ptr->mimic = 0;
93                         }
94                 }
95
96                 g_ptr->info &= ~(CAVE_FLOOR);
97                 delete_monster(floor_ptr, y, x);
98         }
99 }
100
101 static int scent_when = 0;
102
103 /*
104  * Characters leave scent trails for perceptive monsters to track.
105  *
106  * Smell is rather more limited than sound.  Many creatures cannot use
107  * it at all, it doesn't extend very far outwards from the character's
108  * current position, and monsters can use it to home in the character,
109  * but not to run away from him.
110  *
111  * Smell is valued according to age.  When a character takes his turn,
112  * scent is aged by one, and new scent of the current age is laid down.
113  * Speedy characters leave more scent, true, but it also ages faster,
114  * which makes it harder to hunt them down.
115  *
116  * Whenever the age count loops, most of the scent trail is erased and
117  * the age of the remainder is recalculated.
118  */
119 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
120 {
121         POSITION i, j;
122         POSITION y, x;
123
124         /* Create a table that controls the spread of scent */
125         const int scent_adjust[5][5] =
126         {
127                 { -1, 0, 0, 0,-1 },
128                 {  0, 1, 1, 1, 0 },
129                 {  0, 1, 2, 1, 0 },
130                 {  0, 1, 1, 1, 0 },
131                 { -1, 0, 0, 0,-1 },
132         };
133
134         /* Loop the age and adjust scent values when necessary */
135         if (++scent_when == 254)
136         {
137                 /* Scan the entire dungeon */
138                 for (y = 0; y < floor_ptr->height; y++)
139                 {
140                         for (x = 0; x < floor_ptr->width; x++)
141                         {
142                                 int w = floor_ptr->grid_array[y][x].when;
143                                 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
144                         }
145                 }
146
147                 /* Restart */
148                 scent_when = 126;
149         }
150
151
152         /* Lay down new scent */
153         for (i = 0; i < 5; i++)
154         {
155                 for (j = 0; j < 5; j++)
156                 {
157                         grid_type *g_ptr;
158
159                         /* Translate table to map grids */
160                         y = i + subject_ptr->y - 2;
161                         x = j + subject_ptr->x - 2;
162
163                         /* Check Bounds */
164                         if (!in_bounds(floor_ptr, y, x)) continue;
165
166                         g_ptr = &floor_ptr->grid_array[y][x];
167
168                         /* Walls, water, and lava cannot hold scent. */
169                         if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
170
171                         /* Grid must not be blocked by walls from the character */
172                         if (!player_has_los_bold(subject_ptr, y, x)) continue;
173
174                         /* Note grids that are too far away */
175                         if (scent_adjust[i][j] == -1) continue;
176
177                         /* Mark the grid with new scent */
178                         g_ptr->when = scent_when + scent_adjust[i][j];
179                 }
180         }
181 }
182
183
184 /*
185  * Hack -- forget the "flow" information
186  */
187 void forget_flow(floor_type *floor_ptr)
188 {
189         POSITION x, y;
190
191         /* Check the entire dungeon */
192         for (y = 0; y < floor_ptr->height; y++)
193         {
194                 for (x = 0; x < floor_ptr->width; x++)
195                 {
196                         /* Forget the old data */
197                         floor_ptr->grid_array[y][x].dist = 0;
198                         floor_ptr->grid_array[y][x].cost = 0;
199                         floor_ptr->grid_array[y][x].when = 0;
200                 }
201         }
202 }
203
204 /*
205  * Routine used by the random vault creators to add a door to a location
206  * Note that range checking has to be done in the calling routine.
207  *
208  * The doors must be INSIDE the allocated region.
209  */
210 void add_door(floor_type* floor_ptr, POSITION x, POSITION y)
211 {
212         /* Need to have a wall in the center square */
213         if (!is_outer_bold(floor_ptr, y, x)) return;
214
215         /* look at:
216         *  x#x
217         *  .#.
218         *  x#x
219         *
220         *  where x=don't care
221         *  .=floor, #=wall
222         */
223
224         if (is_floor_bold(floor_ptr, y - 1, x) && is_floor_bold(floor_ptr, y + 1, x) &&
225                 (is_outer_bold(floor_ptr, y, x - 1) && is_outer_bold(floor_ptr, y, x + 1)))
226         {
227                 /* secret door */
228                 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
229
230                 /* set boundarys so don't get wide doors */
231                 place_solid_bold(floor_ptr, y, x - 1);
232                 place_solid_bold(floor_ptr, y, x + 1);
233         }
234
235
236         /* look at:
237         *  x#x
238         *  .#.
239         *  x#x
240         *
241         *  where x = don't care
242         *  .=floor, #=wall
243         */
244         if (is_outer_bold(floor_ptr, y - 1, x) && is_outer_bold(floor_ptr, y + 1, x) &&
245                 is_floor_bold(floor_ptr, y, x - 1) && is_floor_bold(floor_ptr, y, x + 1))
246         {
247                 /* secret door */
248                 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
249
250                 /* set boundarys so don't get wide doors */
251                 place_solid_bold(floor_ptr, y - 1, x);
252                 place_solid_bold(floor_ptr, y + 1, x);
253         }
254 }
255
256 /*!
257  * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
258 * @param player_ptr プレーヤーへの参照ポインタ
259  * @param y 配置を試みたいマスのY座標
260  * @param x 配置を試みたいマスのX座標
261  * @return なし
262  */
263 void place_random_stairs(player_type *player_ptr, POSITION y, POSITION x)
264 {
265         bool up_stairs = TRUE;
266         bool down_stairs = TRUE;
267         grid_type *g_ptr;
268         floor_type *floor_ptr = player_ptr->current_floor_ptr;
269         g_ptr = &floor_ptr->grid_array[y][x];
270         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
271
272         if (!floor_ptr->dun_level) up_stairs = FALSE;
273         if (ironman_downward) up_stairs = FALSE;
274         if (floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) down_stairs = FALSE;
275         if (quest_number(player_ptr, floor_ptr->dun_level) && (floor_ptr->dun_level > 1)) down_stairs = FALSE;
276
277         /* We can't place both */
278         if (down_stairs && up_stairs)
279         {
280                 /* Choose a staircase randomly */
281                 if (randint0(100) < 50) up_stairs = FALSE;
282                 else down_stairs = FALSE;
283         }
284
285         /* Place the stairs */
286         if (up_stairs) set_cave_feat(floor_ptr, y, x, feat_up_stair);
287         else if (down_stairs) set_cave_feat(floor_ptr, y, x, feat_down_stair);
288 }
289
290 /*!
291  * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
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(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
333 {
334         /* Delta */
335         POSITION dx, dy;
336
337         /* Absolute */
338         POSITION ax, ay;
339
340         /* Signs */
341         POSITION sx, sy;
342
343         /* Fractions */
344         POSITION qx, qy;
345
346         /* Scanners */
347         POSITION tx, ty;
348
349         /* Scale factors */
350         POSITION f1, f2;
351
352         /* Slope, or 1/Slope, of LOS */
353         POSITION m;
354
355
356         /* Extract the offset */
357         dy = y2 - y1;
358         dx = x2 - x1;
359
360         /* Extract the absolute offset */
361         ay = ABS(dy);
362         ax = ABS(dx);
363
364
365         /* Handle adjacent (or identical) grids */
366         if ((ax < 2) && (ay < 2)) return TRUE;
367
368
369         /* Paranoia -- require "safe" origin */
370         /* if (!in_bounds(floor_ptr, y1, x1)) return FALSE; */
371         /* if (!in_bounds(floor_ptr, y2, x2)) return FALSE; */
372
373
374         /* Directly South/North */
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                 /* Assume los */
421                 return TRUE;
422         }
423
424
425         /* Extract some signs */
426         sx = (dx < 0) ? -1 : 1;
427         sy = (dy < 0) ? -1 : 1;
428
429
430         /* Vertical "knights" */
431         if (ax == 1)
432         {
433                 if (ay == 2)
434                 {
435                         if (cave_los_bold(floor_ptr, y1 + sy, x1)) return TRUE;
436                 }
437         }
438
439         /* Horizontal "knights" */
440         else if (ay == 1)
441         {
442                 if (ax == 2)
443                 {
444                         if (cave_los_bold(floor_ptr, y1, x1 + sx)) return TRUE;
445                 }
446         }
447
448
449         /* Calculate scale factor div 2 */
450         f2 = (ax * ay);
451
452         /* Calculate scale factor */
453         f1 = f2 << 1;
454
455
456         /* Travel horizontally */
457         if (ax >= ay)
458         {
459                 /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
460                 qy = ay * ay;
461                 m = qy << 1;
462
463                 tx = x1 + sx;
464
465                 /* Consider the special case where slope == 1. */
466                 if (qy == f2)
467                 {
468                         ty = y1 + sy;
469                         qy -= f1;
470                 }
471                 else
472                 {
473                         ty = y1;
474                 }
475
476                 /* Note (below) the case (qy == f2), where */
477                 /* the LOS exactly meets the corner of a tile. */
478                 while (x2 - tx)
479                 {
480                         if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
481
482                         qy += m;
483
484                         if (qy < f2)
485                         {
486                                 tx += sx;
487                         }
488                         else if (qy > f2)
489                         {
490                                 ty += sy;
491                                 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
492                                 qy -= f1;
493                                 tx += sx;
494                         }
495                         else
496                         {
497                                 ty += sy;
498                                 qy -= f1;
499                                 tx += sx;
500                         }
501                 }
502         }
503
504         /* Travel vertically */
505         else
506         {
507                 /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
508                 qx = ax * ax;
509                 m = qx << 1;
510
511                 ty = y1 + sy;
512
513                 if (qx == f2)
514                 {
515                         tx = x1 + sx;
516                         qx -= f1;
517                 }
518                 else
519                 {
520                         tx = x1;
521                 }
522
523                 /* Note (below) the case (qx == f2), where */
524                 /* the LOS exactly meets the corner of a tile. */
525                 while (y2 - ty)
526                 {
527                         if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
528
529                         qx += m;
530
531                         if (qx < f2)
532                         {
533                                 ty += sy;
534                         }
535                         else if (qx > f2)
536                         {
537                                 tx += sx;
538                                 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
539                                 qx -= f1;
540                                 ty += sy;
541                         }
542                         else
543                         {
544                                 tx += sx;
545                                 qx -= f1;
546                                 ty += sy;
547                         }
548                 }
549         }
550
551         /* Assume los */
552         return TRUE;
553 }
554
555
556 /*
557  * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
558  * at the final destination, assuming no monster gets in the way.
559  *
560  * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
561  */
562 bool projectable(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
563 {
564         POSITION y, x;
565
566         int grid_n = 0;
567         u16b grid_g[512];
568
569         /* Check the projection path */
570         grid_n = project_path(floor_ptr, grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
571
572         /* Identical grid */
573         if (!grid_n) return TRUE;
574
575         /* Final grid */
576         y = GRID_Y(grid_g[grid_n - 1]);
577         x = GRID_X(grid_g[grid_n - 1]);
578
579         /* May not end in an unrequested grid */
580         if ((y != y2) || (x != x2)) return FALSE;
581
582         /* Assume okay */
583         return TRUE;
584 }
585
586
587 /*!
588  * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
589  * @param y1 モンスターを配置したいマスの中心Y座標
590  * @param x1 モンスターを配置したいマスの中心X座標
591  * @param num 配置したいモンスターの数
592  * @return なし
593  * @details
594  * Only really called by some of the "vault" routines.
595  */
596 void vault_monsters(floor_type *floor_ptr, POSITION y1, POSITION x1, int num)
597 {
598         int k, i;
599         POSITION y, x;
600         grid_type *g_ptr;
601
602         /* Try to summon "num" monsters "near" the given location */
603         for (k = 0; k < num; k++)
604         {
605                 /* Try nine locations */
606                 for (i = 0; i < 9; i++)
607                 {
608                         int d = 1;
609
610                         /* Pick a nearby location */
611                         scatter(floor_ptr, &y, &x, y1, x1, d, 0);
612
613                         /* Require "empty" floor grids */
614                         g_ptr = &floor_ptr->grid_array[y][x];
615                         if (!cave_empty_grid(g_ptr)) continue;
616
617                         /* Place the monster (allow groups) */
618                         floor_ptr->monster_level = floor_ptr->base_level + 2;
619                         (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
620                         floor_ptr->monster_level = floor_ptr->base_level;
621                 }
622         }
623 }
624
625
626 /*!
627  * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
628  * @param player_ptr プレーヤーへの参照ポインタ
629  * @param y y座標
630  * @param x x座標
631  * @return 各種の変更が可能ならTRUEを返す。
632  * @details
633  * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
634  */
635 bool cave_valid_bold(floor_type *floor_ptr, POSITION y, POSITION x)
636 {
637         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
638         OBJECT_IDX this_o_idx, next_o_idx = 0;
639
640         /* Forbid perma-grids */
641         if (cave_perma_grid(g_ptr)) return FALSE;
642
643         /* Check objects */
644         for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
645         {
646                 object_type *o_ptr;
647                 o_ptr = &floor_ptr->o_list[this_o_idx];
648                 next_o_idx = o_ptr->next_o_idx;
649
650                 /* Forbid artifact grids */
651                 if (object_is_artifact(o_ptr)) return FALSE;
652         }
653
654         /* Accept */
655         return TRUE;
656 }
657
658 /*
659  * Change the "feat" flag for a grid, and notice/redraw the grid
660  */
661 void cave_set_feat(floor_type *floor_ptr, POSITION y, POSITION x, FEAT_IDX feat)
662 {
663         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
664         feature_type *f_ptr = &f_info[feat];
665         bool old_los, old_mirror;
666
667         if (!current_world_ptr->character_dungeon)
668         {
669                 /* Clear mimic type */
670                 g_ptr->mimic = 0;
671
672                 /* Change the feature */
673                 g_ptr->feat = feat;
674
675                 /* Hack -- glow the GLOW terrain */
676                 if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
677                 {
678                         DIRECTION i;
679                         POSITION yy, xx;
680
681                         for (i = 0; i < 9; i++)
682                         {
683                                 yy = y + ddy_ddd[i];
684                                 xx = x + ddx_ddd[i];
685                                 if (!in_bounds2(floor_ptr, yy, xx)) continue;
686                                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
687                         }
688                 }
689
690                 return;
691         }
692
693         old_los = cave_have_flag_bold(floor_ptr, y, x, FF_LOS);
694         old_mirror = is_mirror_grid(g_ptr);
695
696         /* Clear mimic type */
697         g_ptr->mimic = 0;
698
699         /* Change the feature */
700         g_ptr->feat = feat;
701
702         /* Remove flag for mirror/glyph */
703         g_ptr->info &= ~(CAVE_OBJECT);
704
705         if (old_mirror && (d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
706         {
707                 g_ptr->info &= ~(CAVE_GLOW);
708                 if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
709
710                 update_local_illumination(p_ptr, y, x);
711         }
712
713         /* Check for change to boring grid */
714         if (!have_flag(f_ptr->flags, FF_REMEMBER)) g_ptr->info &= ~(CAVE_MARK);
715         if (g_ptr->m_idx) update_monster(p_ptr, g_ptr->m_idx, FALSE);
716
717         note_spot(y, x);
718         lite_spot(y, x);
719
720         /* Check if los has changed */
721         if (old_los ^ have_flag(f_ptr->flags, FF_LOS))
722         {
723
724 #ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
725
726                 update_local_illumination(p_ptr, y, x);
727
728 #endif /* COMPLEX_WALL_ILLUMINATION */
729
730                 /* Update the visuals */
731                 p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS);
732         }
733
734         /* Hack -- glow the GLOW terrain */
735         if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
736         {
737                 DIRECTION i;
738                 POSITION yy, xx;
739                 grid_type *cc_ptr;
740
741                 for (i = 0; i < 9; i++)
742                 {
743                         yy = y + ddy_ddd[i];
744                         xx = x + ddx_ddd[i];
745                         if (!in_bounds2(floor_ptr, yy, xx)) continue;
746                         cc_ptr = &floor_ptr->grid_array[yy][xx];
747                         cc_ptr->info |= CAVE_GLOW;
748
749                         if (player_has_los_grid(cc_ptr))
750                         {
751                                 if (cc_ptr->m_idx) update_monster(p_ptr, cc_ptr->m_idx, FALSE);
752                                 note_spot(yy, xx);
753                                 lite_spot(yy, xx);
754                         }
755
756                         update_local_illumination(p_ptr, yy, xx);
757                 }
758
759                 if (p_ptr->special_defense & NINJA_S_STEALTH)
760                 {
761                         if (floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(p_ptr, FALSE);
762                 }
763         }
764 }
765
766
767 /*!
768  * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
769  * @param y ドアの配置を試みたいマスのY座標
770  * @param x ドアの配置を試みたいマスのX座標
771  * @param room 部屋に接している場合向けのドア生成か否か
772  * @return なし
773  */
774 void place_random_door(floor_type *floor_ptr, POSITION y, POSITION x, bool room)
775 {
776         int tmp, type;
777         FEAT_IDX feat = feat_none;
778         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
779
780         /* Initialize mimic info */
781         g_ptr->mimic = 0;
782
783         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
784         {
785                 place_floor_bold(floor_ptr, y, x);
786                 return;
787         }
788
789         type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
790                 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
791                 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
792
793         /* Choose an object */
794         tmp = randint0(1000);
795
796         /* Open doors (300/1000) */
797         if (tmp < 300)
798         {
799                 /* Create open door */
800                 feat = feat_door[type].open;
801         }
802
803         /* Broken doors (100/1000) */
804         else if (tmp < 400)
805         {
806                 /* Create broken door */
807                 feat = feat_door[type].broken;
808         }
809
810         /* Secret doors (200/1000) */
811         else if (tmp < 600)
812         {
813                 /* Create secret door */
814                 place_closed_door(floor_ptr, y, x, type);
815
816                 if (type != DOOR_CURTAIN)
817                 {
818                         /* Hide. If on the edge of room, use outer wall. */
819                         g_ptr->mimic = room ? feat_wall_outer : feat_wall_type[randint0(100)];
820
821                         /* Floor type terrain cannot hide a door */
822                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
823                         {
824                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
825                                 {
826                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
827                                 }
828                                 g_ptr->mimic = 0;
829                         }
830                 }
831         }
832
833         /* Closed, locked, or stuck doors (400/1000) */
834         else place_closed_door(floor_ptr, y, x, type);
835
836         if (tmp < 400)
837         {
838                 if (feat != feat_none)
839                 {
840                         set_cave_feat(floor_ptr, y, x, feat);
841                 }
842                 else
843                 {
844                         place_floor_bold(floor_ptr, y, x);
845                 }
846         }
847
848         delete_monster(floor_ptr, y, x);
849 }
850
851
852
853 /*!
854  * @brief グローバルオブジェクト配列を初期化する /
855  * Delete all the items when player leaves the level
856  * @note we do NOT visually reflect these (irrelevant) changes
857  * @details
858  * Hack -- we clear the "g_ptr->o_idx" field for every grid,
859  * and the "m_ptr->next_o_idx" field for every monster, since
860  * we know we are clearing every object.  Technically, we only
861  * clear those fields for grids/monsters containing objects,
862  * and we clear it once for every such object.
863  * @return なし
864  */
865 void wipe_o_list(floor_type *floor_ptr)
866 {
867         int i;
868
869         /* Delete the existing objects */
870         for (i = 1; i < floor_ptr->o_max; i++)
871         {
872                 object_type *o_ptr = &floor_ptr->o_list[i];
873
874                 if (!OBJECT_IS_VALID(o_ptr)) continue;
875
876                 /* Mega-Hack -- preserve artifacts */
877                 if (!current_world_ptr->character_dungeon || preserve_mode)
878                 {
879                         /* Hack -- Preserve unknown artifacts */
880                         if (object_is_fixed_artifact(o_ptr) && !object_is_known(o_ptr))
881                         {
882                                 /* Mega-Hack -- Preserve the artifact */
883                                 a_info[o_ptr->name1].cur_num = 0;
884                         }
885                 }
886
887                 if (OBJECT_IS_HELD_MONSTER(o_ptr))
888                 {
889                         monster_type *m_ptr;
890                         m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
891
892                         /* Hack -- see above */
893                         m_ptr->hold_o_idx = 0;
894                 }
895
896                 /* Dungeon */
897                 else
898                 {
899                         grid_type *g_ptr;
900
901                         /* Access location */
902                         POSITION y = o_ptr->iy;
903                         POSITION x = o_ptr->ix;
904
905                         /* Access grid */
906                         g_ptr = &floor_ptr->grid_array[y][x];
907
908                         /* Hack -- see above */
909                         g_ptr->o_idx = 0;
910                 }
911                 object_wipe(o_ptr);
912         }
913
914         /* Reset "floor_ptr->o_max" */
915         floor_ptr->o_max = 1;
916
917         /* Reset "floor_ptr->o_cnt" */
918         floor_ptr->o_cnt = 0;
919 }
920
921
922 /*!
923  * @brief 所定の位置に各種の閉じたドアを配置する / Place a random type of normal door at the given location.
924  * @param y ドアの配置を試みたいマスのY座標
925  * @param x ドアの配置を試みたいマスのX座標
926  * @param type ドアの地形ID
927  * @return なし
928  */
929 void place_closed_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
930 {
931         int tmp;
932         FEAT_IDX feat = feat_none;
933
934         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
935         {
936                 place_floor_bold(floor_ptr, y, x);
937                 return;
938         }
939
940         /* Choose an object */
941         tmp = randint0(400);
942
943         /* Closed doors (300/400) */
944         if (tmp < 300)
945         {
946                 /* Create closed door */
947                 feat = feat_door[type].closed;
948         }
949
950         /* Locked doors (99/400) */
951         else if (tmp < 399)
952         {
953                 /* Create locked door */
954                 feat = feat_locked_door_random(type);
955         }
956
957         /* Stuck doors (1/400) */
958         else
959         {
960                 /* Create jammed door */
961                 feat = feat_jammed_door_random(type);
962         }
963
964         if (feat != feat_none)
965         {
966                 cave_set_feat(floor_ptr, y, x, feat);
967
968                 /* Now it is not floor */
969                 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
970         }
971         else
972         {
973                 place_floor_bold(floor_ptr, y, x);
974         }
975 }
976
977 /*!
978  * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
979  * @param y トラップを配置したいマスの中心Y座標
980  * @param x トラップを配置したいマスの中心X座標
981  * @param yd Y方向の配置分散マス数
982  * @param xd X方向の配置分散マス数
983  * @return なし
984  * @details
985  * Only really called by some of the "vault" routines.
986  */
987 void vault_trap_aux(player_type *player_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd)
988 {
989         int count = 0, y1 = y, x1 = x;
990         int dummy = 0;
991
992         grid_type *g_ptr;
993
994         /* Place traps */
995         floor_type *floor_ptr = player_ptr->current_floor_ptr;
996         for (count = 0; count <= 5; count++)
997         {
998                 /* Get a location */
999                 while (dummy < SAFE_MAX_ATTEMPTS)
1000                 {
1001                         y1 = rand_spread(y, yd);
1002                         x1 = rand_spread(x, xd);
1003                         dummy++;
1004                         if (!in_bounds(floor_ptr, y1, x1)) continue;
1005                         break;
1006                 }
1007
1008                 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
1009                 {
1010                         msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
1011                 }
1012
1013                 /* Require "naked" floor grids */
1014                 g_ptr = &floor_ptr->grid_array[y1][x1];
1015                 if (!is_floor_grid(g_ptr) || g_ptr->o_idx || g_ptr->m_idx) continue;
1016
1017                 /* Place the trap */
1018                 place_trap(player_ptr, y1, x1);
1019
1020                 break;
1021         }
1022 }
1023
1024 /*!
1025  * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor.  (Includes range checking.)
1026  * @param x チェックするマスのX座標
1027  * @param y チェックするマスのY座標
1028  * @return 床系地形ならばTRUE
1029  */
1030 bool get_is_floor(floor_type *floor_ptr, POSITION x, POSITION y)
1031 {
1032         if (!in_bounds(floor_ptr, y, x))
1033         {
1034                 /* Out of bounds */
1035                 return FALSE;
1036         }
1037
1038         /* Do the real check */
1039         if (is_floor_bold(floor_ptr, y, x)) return TRUE;
1040
1041         return FALSE;
1042 }
1043
1044 /*!
1045 * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
1046 * @param y1 基準となるマスのY座標
1047 * @param x1 基準となるマスのX座標
1048 * @return 通路の数
1049 * @note Assumes "in_bounds(y1, x1)"
1050 * @details
1051 * XXX XXX This routine currently only counts actual "empty floor"\n
1052 * grids which are not in rooms.  We might want to also count stairs,\n
1053 * open doors, closed doors, etc.
1054 */
1055 static int next_to_corr(floor_type *floor_ptr, POSITION y1, POSITION x1)
1056 {
1057         int i, k = 0;
1058         POSITION y, x;
1059
1060         grid_type *g_ptr;
1061
1062         /* Scan adjacent grids */
1063         for (i = 0; i < 4; i++)
1064         {
1065                 y = y1 + ddy_ddd[i];
1066                 x = x1 + ddx_ddd[i];
1067                 g_ptr = &floor_ptr->grid_array[y][x];
1068
1069                 /* Skip non floors */
1070                 if (cave_have_flag_grid(g_ptr, FF_WALL)) continue;
1071
1072                 /* Skip non "empty floor" grids */
1073                 if (!is_floor_grid(g_ptr))
1074                         continue;
1075
1076                 /* Skip grids inside rooms */
1077                 if (g_ptr->info & (CAVE_ROOM)) continue;
1078
1079                 /* Count these grids */
1080                 k++;
1081         }
1082
1083         /* Return the number of corridors */
1084         return (k);
1085 }
1086
1087 /*!
1088 * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
1089 * @param y 判定を行いたいマスのY座標
1090 * @param x 判定を行いたいマスのX座標
1091 * @return ドアを設置可能ならばTRUEを返す
1092 * @note Assumes "in_bounds()"
1093 * @details
1094 * \n
1095 * Assumes "in_bounds()"\n
1096 */
1097 static bool possible_doorway(floor_type *floor_ptr, POSITION y, POSITION x)
1098 {
1099         /* Count the adjacent corridors */
1100         if (next_to_corr(floor_ptr, y, x) >= 2)
1101         {
1102                 /* Check Vertical */
1103                 if (cave_have_flag_bold(floor_ptr, y - 1, x, FF_WALL) &&
1104                         cave_have_flag_bold(floor_ptr, y + 1, x, FF_WALL))
1105                 {
1106                         return TRUE;
1107                 }
1108
1109                 /* Check Horizontal */
1110                 if (cave_have_flag_bold(floor_ptr, y, x - 1, FF_WALL) &&
1111                         cave_have_flag_bold(floor_ptr, y, x + 1, FF_WALL))
1112                 {
1113                         return TRUE;
1114                 }
1115         }
1116
1117         /* No doorway */
1118         return FALSE;
1119 }
1120
1121 /*!
1122 * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
1123 * @param player_ptr プレーヤーへの参照ポインタ
1124 * @param y 設置を行いたいマスのY座標
1125 * @param x 設置を行いたいマスのX座標
1126 * @return なし
1127 */
1128 void try_door(floor_type *floor_ptr, POSITION y, POSITION x)
1129 {
1130         if (!in_bounds(floor_ptr, y, x)) return;
1131
1132         /* Ignore walls */
1133         if (cave_have_flag_bold(floor_ptr, y, x, FF_WALL)) return;
1134
1135         /* Ignore room grids */
1136         if (floor_ptr->grid_array[y][x].info & (CAVE_ROOM)) return;
1137
1138         /* Occasional door (if allowed) */
1139         if ((randint0(100) < dun_tun_jct) && possible_doorway(floor_ptr, y, x) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_NO_DOORS))
1140         {
1141                 /* Place a door */
1142                 place_random_door(floor_ptr, y, x, FALSE);
1143         }
1144 }
1145
1146
1147 FEAT_IDX conv_dungeon_feat(floor_type *floor_ptr, FEAT_IDX newfeat)
1148 {
1149         feature_type *f_ptr = &f_info[newfeat];
1150
1151         if (have_flag(f_ptr->flags, FF_CONVERT))
1152         {
1153                 switch (f_ptr->subtype)
1154                 {
1155                 case CONVERT_TYPE_FLOOR:
1156                         return feat_ground_type[randint0(100)];
1157                 case CONVERT_TYPE_WALL:
1158                         return feat_wall_type[randint0(100)];
1159                 case CONVERT_TYPE_INNER:
1160                         return feat_wall_inner;
1161                 case CONVERT_TYPE_OUTER:
1162                         return feat_wall_outer;
1163                 case CONVERT_TYPE_SOLID:
1164                         return feat_wall_solid;
1165                 case CONVERT_TYPE_STREAM1:
1166                         return d_info[floor_ptr->dungeon_idx].stream1;
1167                 case CONVERT_TYPE_STREAM2:
1168                         return d_info[floor_ptr->dungeon_idx].stream2;
1169                 default:
1170                         return newfeat;
1171                 }
1172         }
1173         else return newfeat;
1174 }
1175
1176
1177 /*!
1178  * @brief 特殊な部屋向けに各種アイテムを配置する / Create up to "num" objects near the given coordinates
1179  * @param player_ptr プレーヤーへの参照ポインタ
1180  * @param y 配置したい中心マスのY座標
1181  * @param x 配置したい中心マスのX座標
1182  * @param num 配置したい数
1183  * @return なし
1184  * @details
1185  * Only really called by some of the "vault" routines.
1186  */
1187 void vault_objects(player_type *player_ptr, POSITION y, POSITION x, int num)
1188 {
1189         int dummy = 0;
1190         int i = 0, j = y, k = x;
1191
1192         grid_type *g_ptr;
1193         floor_type *floor_ptr = player_ptr->current_floor_ptr;
1194
1195         /* Attempt to place 'num' objects */
1196         for (; num > 0; --num)
1197         {
1198                 /* Try up to 11 spots looking for empty space */
1199                 for (i = 0; i < 11; ++i)
1200                 {
1201                         /* Pick a random location */
1202                         while (dummy < SAFE_MAX_ATTEMPTS)
1203                         {
1204                                 j = rand_spread(y, 2);
1205                                 k = rand_spread(x, 3);
1206                                 dummy++;
1207                                 if (!in_bounds(floor_ptr, j, k)) continue;
1208                                 break;
1209                         }
1210
1211                         if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
1212                         {
1213                                 msg_print(_("警告!地下室のアイテムを配置できません!", "Warning! Could not place vault object!"));
1214                         }
1215
1216                         /* Require "clean" floor space */
1217                         g_ptr = &floor_ptr->grid_array[j][k];
1218                         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) continue;
1219
1220                         if (randint0(100) < 75)
1221                         {
1222                                 place_object(player_ptr, j, k, 0L);
1223                         }
1224                         else
1225                         {
1226                                 place_gold(floor_ptr, j, k);
1227                         }
1228
1229                         /* Placement accomplished */
1230                         break;
1231                 }
1232         }
1233 }
1234
1235 /*!
1236  * @brief 始点から終点への直線経路を返す /
1237  * Determine the path taken by a projection.
1238  * @param player_ptr プレーヤーへの参照ポインタ
1239  * @param gp 経路座標リストを返す参照ポインタ
1240  * @param range 距離
1241  * @param y1 始点Y座標
1242  * @param x1 始点X座標
1243  * @param y2 終点Y座標
1244  * @param x2 終点X座標
1245  * @param flg フラグID
1246  * @return リストの長さ
1247  * @details
1248  * <pre>
1249  * The projection will always start from the grid (y1,x1), and will travel
1250  * towards the grid (y2,x2), touching one grid per unit of distance along
1251  * the major axis, and stopping when it enters the destination grid or a
1252  * wall grid, or has travelled the maximum legal distance of "range".
1253  *
1254  * Note that "distance" in this function (as in the "update_view()" code)
1255  * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
1256  * actually has an "octagon of projection" not a "circle of projection".
1257  *
1258  * The path grids are saved into the grid array pointed to by "gp", and
1259  * there should be room for at least "range" grids in "gp".  Note that
1260  * due to the way in which distance is calculated, this function normally
1261  * uses fewer than "range" grids for the projection path, so the result
1262  * of this function should never be compared directly to "range".  Note
1263  * that the initial grid (y1,x1) is never saved into the grid array, not
1264  * even if the initial grid is also the final grid.
1265  *
1266  * The "flg" flags can be used to modify the behavior of this function.
1267  *
1268  * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
1269  * semantics as they do for the "project" function, namely, that the path
1270  * will stop as soon as it hits a monster, or that the path will continue
1271  * through the destination grid, respectively.
1272  *
1273  * The "PROJECT_JUMP" flag, which for the "project()" function means to
1274  * start at a special grid (which makes no sense in this function), means
1275  * that the path should be "angled" slightly if needed to avoid any wall
1276  * grids, allowing the player to "target" any grid which is in "view".
1277  * This flag is non-trivial and has not yet been implemented, but could
1278  * perhaps make use of the "vinfo" array (above).
1279  *
1280  * This function returns the number of grids (if any) in the path.  This
1281  * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
1282  *
1283  * This algorithm is similar to, but slightly different from, the one used
1284  * by "update_view_los()", and very different from the one used by "los()".
1285  * </pre>
1286  */
1287 sint project_path(floor_type *floor_ptr, u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg)
1288 {
1289         POSITION y, x;
1290
1291         int n = 0;
1292         int k = 0;
1293
1294         /* Absolute */
1295         POSITION ay, ax;
1296
1297         /* Offsets */
1298         POSITION sy, sx;
1299
1300         /* Fractions */
1301         int frac;
1302
1303         /* Scale factors */
1304         int full, half;
1305
1306         /* Slope */
1307         int m;
1308
1309         /* No path necessary (or allowed) */
1310         if ((x1 == x2) && (y1 == y2)) return (0);
1311
1312
1313         /* Analyze "dy" */
1314         if (y2 < y1)
1315         {
1316                 ay = (y1 - y2);
1317                 sy = -1;
1318         }
1319         else
1320         {
1321                 ay = (y2 - y1);
1322                 sy = 1;
1323         }
1324
1325         /* Analyze "dx" */
1326         if (x2 < x1)
1327         {
1328                 ax = (x1 - x2);
1329                 sx = -1;
1330         }
1331         else
1332         {
1333                 ax = (x2 - x1);
1334                 sx = 1;
1335         }
1336
1337
1338         /* Number of "units" in one "half" grid */
1339         half = (ay * ax);
1340
1341         /* Number of "units" in one "full" grid */
1342         full = half << 1;
1343
1344         /* Vertical */
1345         if (ay > ax)
1346         {
1347                 /* Let m = ((dx/dy) * full) = (dx * dx * 2) */
1348                 m = ax * ax * 2;
1349
1350                 /* Start */
1351                 y = y1 + sy;
1352                 x = x1;
1353
1354                 frac = m;
1355
1356                 if (frac > half)
1357                 {
1358                         /* Advance (X) part 2 */
1359                         x += sx;
1360
1361                         /* Advance (X) part 3 */
1362                         frac -= full;
1363
1364                         /* Track distance */
1365                         k++;
1366                 }
1367
1368                 /* Create the projection path */
1369                 while (TRUE)
1370                 {
1371                         /* Save grid */
1372                         gp[n++] = GRID(y, x);
1373
1374                         /* Hack -- Check maximum range */
1375                         if ((n + (k >> 1)) >= range) break;
1376
1377                         /* Sometimes stop at destination grid */
1378                         if (!(flg & (PROJECT_THRU)))
1379                         {
1380                                 if ((x == x2) && (y == y2)) break;
1381                         }
1382
1383                         if (flg & (PROJECT_DISI))
1384                         {
1385                                 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1386                         }
1387                         else if (flg & (PROJECT_LOS))
1388                         {
1389                                 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1390                         }
1391                         else if (!(flg & (PROJECT_PATH)))
1392                         {
1393                                 /* Always stop at non-initial wall grids */
1394                                 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1395                         }
1396
1397                         /* Sometimes stop at non-initial monsters/players */
1398                         if (flg & (PROJECT_STOP))
1399                         {
1400                                 if ((n > 0) &&
1401                                         (player_bold(p_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1402                                         break;
1403                         }
1404
1405                         if (!in_bounds(floor_ptr, y, x)) break;
1406
1407                         /* Slant */
1408                         if (m)
1409                         {
1410                                 /* Advance (X) part 1 */
1411                                 frac += m;
1412
1413                                 /* Horizontal change */
1414                                 if (frac > half)
1415                                 {
1416                                         /* Advance (X) part 2 */
1417                                         x += sx;
1418
1419                                         /* Advance (X) part 3 */
1420                                         frac -= full;
1421
1422                                         /* Track distance */
1423                                         k++;
1424                                 }
1425                         }
1426
1427                         /* Advance (Y) */
1428                         y += sy;
1429                 }
1430         }
1431
1432         /* Horizontal */
1433         else if (ax > ay)
1434         {
1435                 /* Let m = ((dy/dx) * full) = (dy * dy * 2) */
1436                 m = ay * ay * 2;
1437
1438                 /* Start */
1439                 y = y1;
1440                 x = x1 + sx;
1441
1442                 frac = m;
1443
1444                 /* Vertical change */
1445                 if (frac > half)
1446                 {
1447                         /* Advance (Y) part 2 */
1448                         y += sy;
1449
1450                         /* Advance (Y) part 3 */
1451                         frac -= full;
1452
1453                         /* Track distance */
1454                         k++;
1455                 }
1456
1457                 /* Create the projection path */
1458                 while (TRUE)
1459                 {
1460                         /* Save grid */
1461                         gp[n++] = GRID(y, x);
1462
1463                         /* Hack -- Check maximum range */
1464                         if ((n + (k >> 1)) >= range) break;
1465
1466                         /* Sometimes stop at destination grid */
1467                         if (!(flg & (PROJECT_THRU)))
1468                         {
1469                                 if ((x == x2) && (y == y2)) break;
1470                         }
1471
1472                         if (flg & (PROJECT_DISI))
1473                         {
1474                                 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1475                         }
1476                         else if (flg & (PROJECT_LOS))
1477                         {
1478                                 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1479                         }
1480                         else if (!(flg & (PROJECT_PATH)))
1481                         {
1482                                 /* Always stop at non-initial wall grids */
1483                                 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1484                         }
1485
1486                         /* Sometimes stop at non-initial monsters/players */
1487                         if (flg & (PROJECT_STOP))
1488                         {
1489                                 if ((n > 0) &&
1490                                         (player_bold(p_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1491                                         break;
1492                         }
1493
1494                         if (!in_bounds(floor_ptr, y, x)) break;
1495
1496                         /* Slant */
1497                         if (m)
1498                         {
1499                                 /* Advance (Y) part 1 */
1500                                 frac += m;
1501
1502                                 /* Vertical change */
1503                                 if (frac > half)
1504                                 {
1505                                         /* Advance (Y) part 2 */
1506                                         y += sy;
1507
1508                                         /* Advance (Y) part 3 */
1509                                         frac -= full;
1510
1511                                         /* Track distance */
1512                                         k++;
1513                                 }
1514                         }
1515
1516                         /* Advance (X) */
1517                         x += sx;
1518                 }
1519         }
1520
1521         /* Diagonal */
1522         else
1523         {
1524                 /* Start */
1525                 y = y1 + sy;
1526                 x = x1 + sx;
1527
1528                 /* Create the projection path */
1529                 while (TRUE)
1530                 {
1531                         /* Save grid */
1532                         gp[n++] = GRID(y, x);
1533
1534                         /* Hack -- Check maximum range */
1535                         if ((n + (n >> 1)) >= range) break;
1536
1537                         /* Sometimes stop at destination grid */
1538                         if (!(flg & (PROJECT_THRU)))
1539                         {
1540                                 if ((x == x2) && (y == y2)) break;
1541                         }
1542
1543                         if (flg & (PROJECT_DISI))
1544                         {
1545                                 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1546                         }
1547                         else if (flg & (PROJECT_LOS))
1548                         {
1549                                 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1550                         }
1551                         else if (!(flg & (PROJECT_PATH)))
1552                         {
1553                                 /* Always stop at non-initial wall grids */
1554                                 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1555                         }
1556
1557                         /* Sometimes stop at non-initial monsters/players */
1558                         if (flg & (PROJECT_STOP))
1559                         {
1560                                 if ((n > 0) &&
1561                                         (player_bold(p_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1562                                         break;
1563                         }
1564
1565                         if (!in_bounds(floor_ptr, y, x)) break;
1566
1567                         /* Advance (Y) */
1568                         y += sy;
1569
1570                         /* Advance (X) */
1571                         x += sx;
1572                 }
1573         }
1574
1575         /* Length */
1576         return (n);
1577 }
1578
1579
1580 /*!
1581  * @brief 指定のマスを床地形に変える / Set a square to be floor.  (Includes range checking.)
1582  * @param x 地形を変えたいマスのX座標
1583  * @param y 地形を変えたいマスのY座標
1584  * @return なし
1585  */
1586 void set_floor(floor_type *floor_ptr, POSITION x, POSITION y)
1587 {
1588         if (!in_bounds(floor_ptr, y, x))
1589         {
1590                 /* Out of bounds */
1591                 return;
1592         }
1593
1594         if (floor_ptr->grid_array[y][x].info & CAVE_ROOM)
1595         {
1596                 /* A room border don't touch. */
1597                 return;
1598         }
1599
1600         /* Set to be floor if is a wall (don't touch lakes). */
1601         if (is_extra_bold(floor_ptr, y, x))
1602                 place_floor_bold(floor_ptr, y, x);
1603 }
1604
1605
1606 /*!
1607  * @brief フロアの指定位置に生成階に応じたベースアイテムの生成を行う。
1608  * Attempt to place an object (normal or good/great) at the given location.
1609  * @param owner_ptr プレーヤーへの参照ポインタ
1610  * @param y 配置したいフロアのY座標
1611  * @param x 配置したいフロアのX座標
1612  * @param mode オプションフラグ
1613  * @return 生成に成功したらTRUEを返す。
1614  * @details
1615  * This routine plays nasty games to generate the "special artifacts".\n
1616  * This routine uses "object_level" for the "generation level".\n
1617  * This routine requires a clean floor grid destination.\n
1618  */
1619 void place_object(player_type *owner_ptr, POSITION y, POSITION x, BIT_FLAGS mode)
1620 {
1621         floor_type *floor_ptr = owner_ptr->current_floor_ptr;
1622
1623         /* Acquire grid */
1624         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1625
1626         object_type forge;
1627         object_type *q_ptr;
1628
1629         /* Paranoia -- check bounds */
1630         if (!in_bounds(floor_ptr, y, x)) return;
1631
1632         /* Require floor space */
1633         if (!cave_drop_bold(floor_ptr, y, x)) return;
1634
1635         /* Avoid stacking on other objects */
1636         if (g_ptr->o_idx) return;
1637
1638         q_ptr = &forge;
1639         object_wipe(q_ptr);
1640
1641         /* Make an object (if possible) */
1642         if (!make_object(owner_ptr, q_ptr, mode)) return;
1643
1644         OBJECT_IDX o_idx = o_pop(floor_ptr);
1645
1646         /* Success */
1647         if (o_idx)
1648         {
1649                 object_type *o_ptr;
1650                 o_ptr = &floor_ptr->o_list[o_idx];
1651
1652                 /* Structure Copy */
1653                 object_copy(o_ptr, q_ptr);
1654
1655                 o_ptr->iy = y;
1656                 o_ptr->ix = x;
1657
1658                 /* Build a stack */
1659                 o_ptr->next_o_idx = g_ptr->o_idx;
1660
1661                 g_ptr->o_idx = o_idx;
1662                 note_spot(y, x);
1663                 lite_spot(y, x);
1664         }
1665         else
1666         {
1667                 /* Hack -- Preserve artifacts */
1668                 if (object_is_fixed_artifact(q_ptr))
1669                 {
1670                         a_info[q_ptr->name1].cur_num = 0;
1671                 }
1672         }
1673 }
1674
1675
1676
1677 /*!
1678  * @brief フロアの指定位置に生成階に応じた財宝オブジェクトの生成を行う。
1679  * Places a treasure (Gold or Gems) at given location
1680  * @param floor_ptr 現在フロアへの参照ポインタ
1681  * @param y 配置したいフロアのY座標
1682  * @param x 配置したいフロアのX座標
1683  * @return 生成に成功したらTRUEを返す。
1684  * @details
1685  * The location must be a legal, clean, floor grid.
1686  */
1687 void place_gold(floor_type *floor_ptr, POSITION y, POSITION x)
1688 {
1689         OBJECT_IDX o_idx;
1690
1691         /* Acquire grid */
1692         grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1693
1694         object_type forge;
1695         object_type *q_ptr;
1696
1697
1698         /* Paranoia -- check bounds */
1699         if (!in_bounds(floor_ptr, y, x)) return;
1700
1701         /* Require floor space */
1702         if (!cave_drop_bold(floor_ptr, y, x)) return;
1703
1704         /* Avoid stacking on other objects */
1705         if (g_ptr->o_idx) return;
1706
1707         q_ptr = &forge;
1708         object_wipe(q_ptr);
1709
1710         /* Make some gold */
1711         if (!make_gold(floor_ptr, q_ptr)) return;
1712
1713         o_idx = o_pop(floor_ptr);
1714
1715         /* Success */
1716         if (o_idx)
1717         {
1718                 object_type *o_ptr;
1719                 o_ptr = &floor_ptr->o_list[o_idx];
1720                 object_copy(o_ptr, q_ptr);
1721
1722                 /* Save location */
1723                 o_ptr->iy = y;
1724                 o_ptr->ix = x;
1725
1726                 /* Build a stack */
1727                 o_ptr->next_o_idx = g_ptr->o_idx;
1728
1729                 g_ptr->o_idx = o_idx;
1730                 note_spot(y, x);
1731                 lite_spot(y, x);
1732         }
1733 }
1734
1735
1736 /*!
1737  * @brief 指定位置に存在するモンスターを削除する / Delete the monster, if any, at a given location
1738  * @param x 削除位置x座標
1739  * @param y 削除位置y座標
1740  * @return なし
1741  */
1742 void delete_monster(floor_type *floor_ptr, POSITION y, POSITION x)
1743 {
1744         grid_type *g_ptr;
1745         if (!in_bounds(floor_ptr, y, x)) return;
1746
1747         /* Check the grid */
1748         g_ptr = &floor_ptr->grid_array[y][x];
1749
1750         /* Delete the monster (if any) */
1751         if (g_ptr->m_idx) delete_monster_idx(g_ptr->m_idx);
1752 }
1753
1754
1755
1756 /*!
1757  * @brief グローバルオブジェクト配列に対し指定範囲のオブジェクトを整理してIDの若い順に寄せる /
1758  * Move an object from index i1 to index i2 in the object list
1759  * @param i1 整理したい配列の始点
1760  * @param i2 整理したい配列の終点
1761  * @return なし
1762  */
1763 static void compact_objects_aux(floor_type *floor_ptr, OBJECT_IDX i1, OBJECT_IDX i2)
1764 {
1765         OBJECT_IDX i;
1766         grid_type *g_ptr;
1767         object_type *o_ptr;
1768
1769         /* Do nothing */
1770         if (i1 == i2) return;
1771
1772         /* Repair objects */
1773         for (i = 1; i < floor_ptr->o_max; i++)
1774         {
1775                 o_ptr = &floor_ptr->o_list[i];
1776
1777                 /* Skip "dead" objects */
1778                 if (!o_ptr->k_idx) continue;
1779
1780                 /* Repair "next" pointers */
1781                 if (o_ptr->next_o_idx == i1)
1782                 {
1783                         /* Repair */
1784                         o_ptr->next_o_idx = i2;
1785                 }
1786         }
1787         o_ptr = &floor_ptr->o_list[i1];
1788
1789         if (OBJECT_IS_HELD_MONSTER(o_ptr))
1790         {
1791                 monster_type *m_ptr;
1792                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
1793
1794                 /* Repair monster */
1795                 if (m_ptr->hold_o_idx == i1)
1796                 {
1797                         /* Repair */
1798                         m_ptr->hold_o_idx = i2;
1799                 }
1800         }
1801
1802         /* Dungeon */
1803         else
1804         {
1805                 POSITION y, x;
1806
1807                 /* Acquire location */
1808                 y = o_ptr->iy;
1809                 x = o_ptr->ix;
1810
1811                 /* Acquire grid */
1812                 g_ptr = &floor_ptr->grid_array[y][x];
1813
1814                 /* Repair grid */
1815                 if (g_ptr->o_idx == i1)
1816                 {
1817                         /* Repair */
1818                         g_ptr->o_idx = i2;
1819                 }
1820         }
1821
1822         /* Structure copy */
1823         floor_ptr->o_list[i2] = floor_ptr->o_list[i1];
1824
1825         /* Wipe the hole */
1826         object_wipe(o_ptr);
1827 }
1828
1829 /*!
1830  * @brief グローバルオブジェクト配列から優先度の低いものを削除し、データを圧縮する。 /
1831  * Compact and Reorder the object list.
1832  * @param player_ptr プレーヤーへの参照ポインタ
1833  * @param size 最低でも減らしたいオブジェクト数の水準
1834  * @return なし
1835  * @details
1836  * (危険なので使用には注意すること)
1837  * This function can be very dangerous, use with caution!\n
1838  *\n
1839  * When actually "compacting" objects, we base the saving throw on a\n
1840  * combination of object level, distance from player, and current\n
1841  * "desperation".\n
1842  *\n
1843  * After "compacting" (if needed), we "reorder" the objects into a more\n
1844  * compact order, and we reset the allocation info, and the "live" array.\n
1845  */
1846 void compact_objects(floor_type *floor_ptr, int size)
1847 {
1848         OBJECT_IDX i;
1849         POSITION y, x;
1850         int num, cnt;
1851         int cur_lev, cur_dis, chance;
1852         object_type *o_ptr;
1853
1854         /* Compact */
1855         if (size)
1856         {
1857                 msg_print(_("アイテム情報を圧縮しています...", "Compacting objects..."));
1858                 p_ptr->redraw |= (PR_MAP);
1859                 p_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1860         }
1861
1862
1863         /* Compact at least 'size' objects */
1864         for (num = 0, cnt = 1; num < size; cnt++)
1865         {
1866                 /* Get more vicious each iteration */
1867                 cur_lev = 5 * cnt;
1868
1869                 /* Get closer each iteration */
1870                 cur_dis = 5 * (20 - cnt);
1871
1872                 /* Examine the objects */
1873                 for (i = 1; i < floor_ptr->o_max; i++)
1874                 {
1875                         o_ptr = &floor_ptr->o_list[i];
1876
1877                         if (!OBJECT_IS_VALID(o_ptr)) continue;
1878
1879                         /* Hack -- High level objects start out "immune" */
1880                         if (k_info[o_ptr->k_idx].level > cur_lev) continue;
1881
1882                         if (OBJECT_IS_HELD_MONSTER(o_ptr))
1883                         {
1884                                 monster_type *m_ptr;
1885                                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
1886
1887                                 y = m_ptr->fy;
1888                                 x = m_ptr->fx;
1889
1890                                 /* Monsters protect their objects */
1891                                 if (randint0(100) < 90) continue;
1892                         }
1893
1894                         /* Dungeon */
1895                         else
1896                         {
1897                                 y = o_ptr->iy;
1898                                 x = o_ptr->ix;
1899                         }
1900
1901                         /* Nearby objects start out "immune" */
1902                         if ((cur_dis > 0) && (distance(p_ptr->y, p_ptr->x, y, x) < cur_dis)) continue;
1903
1904                         /* Saving throw */
1905                         chance = 90;
1906
1907                         /* Hack -- only compact artifacts in emergencies */
1908                         if ((object_is_fixed_artifact(o_ptr) || o_ptr->art_name) &&
1909                                 (cnt < 1000)) chance = 100;
1910
1911                         /* Apply the saving throw */
1912                         if (randint0(100) < chance) continue;
1913
1914                         delete_object_idx(floor_ptr, i);
1915
1916                         /* Count it */
1917                         num++;
1918                 }
1919         }
1920
1921
1922         /* Excise dead objects (backwards!) */
1923         for (i = floor_ptr->o_max - 1; i >= 1; i--)
1924         {
1925                 o_ptr = &floor_ptr->o_list[i];
1926
1927                 /* Skip real objects */
1928                 if (o_ptr->k_idx) continue;
1929
1930                 /* Move last object into open hole */
1931                 compact_objects_aux(floor_ptr, floor_ptr->o_max - 1, i);
1932
1933                 /* Compress "floor_ptr->o_max" */
1934                 floor_ptr->o_max--;
1935         }
1936 }
1937
1938 /*!
1939  * @brief 特殊な部屋向けに各種アイテムを配置する(メインルーチン) / Place some traps with a given displacement of given location
1940  * @param player_ptr プレーヤーへの参照ポインタ
1941  * @param y トラップを配置したいマスの中心Y座標
1942  * @param x トラップを配置したいマスの中心X座標
1943  * @param yd Y方向の配置分散マス数
1944  * @param xd X方向の配置分散マス数
1945  * @param num 配置したいトラップの数
1946  * @return なし
1947  * @details
1948  * Only really called by some of the "vault" routines.
1949  */
1950 void vault_traps(player_type *player_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd, int num)
1951 {
1952         int i;
1953
1954         for (i = 0; i < num; i++)
1955         {
1956                 vault_trap_aux(player_ptr, y, x, yd, xd);
1957         }
1958 }
1959
1960
1961 /*
1962  * Standard "find me a location" function
1963  *
1964  * Obtains a legal location within the given distance of the initial
1965  * location, and with "los()" from the source to destination location.
1966  *
1967  * This function is often called from inside a loop which searches for
1968  * locations while increasing the "d" distance.
1969  *
1970  * Currently the "m" parameter is unused.
1971  */
1972 void scatter(floor_type *floor_ptr, POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION d, BIT_FLAGS mode)
1973 {
1974         POSITION nx, ny;
1975
1976         /* Pick a location */
1977         while (TRUE)
1978         {
1979                 /* Pick a new location */
1980                 ny = rand_spread(y, d);
1981                 nx = rand_spread(x, d);
1982
1983                 /* Ignore annoying locations */
1984                 if (!in_bounds(floor_ptr, ny, nx)) continue;
1985
1986                 /* Ignore "excessively distant" locations */
1987                 if ((d > 1) && (distance(y, x, ny, nx) > d)) continue;
1988
1989                 if (mode & PROJECT_LOS)
1990                 {
1991                         if (los(floor_ptr, y, x, ny, nx)) break;
1992                 }
1993                 else
1994                 {
1995                         if (projectable(floor_ptr, y, x, ny, nx)) break;
1996                 }
1997
1998         }
1999
2000         /* Save the location */
2001         (*yp) = ny;
2002         (*xp) = nx;
2003 }