OSDN Git Service

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