OSDN Git Service

[Refactor] #38997 get_is_floor() に player_type * 引数を追加. / Add player_type * argument...
[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(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(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(y, x - 1);
230                 place_solid_bold(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(y - 1, x);
250                 place_solid_bold(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(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(&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[p_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(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[p_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(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(p_ptr->current_floor_ptr, y, x))
1027         {
1028                 /* Out of bounds */
1029                 return (FALSE);
1030         }
1031
1032         /* Do the real check */
1033         if (is_floor_bold(p_ptr->current_floor_ptr, y, x)) return (TRUE);
1034
1035         return (FALSE);
1036 }