OSDN Git Service

[Refactor] #37353 後で同名の構造体を作り、feat_*と命名を一致させるため floor_type を feat_ground_type に改名...
[hengband/hengband.git] / src / grid.c
1 /*!
2  * @file grid.c
3  * @brief ダンジョンの生成処理の基幹部分 / low-level dungeon creation primitives
4  * @date 2014/01/04
5  * @author
6  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
7  *\n
8  * This software may be copied and distributed for educational, research,\n
9  * and not for profit purposes provided that this copyright and statement\n
10  * are included in all such copies.  Other copyrights may also apply.\n
11  * \n
12  * 2014 Deskull Doxygen向けのコメント整理\n
13  */
14
15 #include "angband.h"
16 #include "generate.h"
17 #include "grid.h"
18 #include "trap.h"
19 #include "rooms.h"
20 #include "monster.h"
21 #include "quest.h"
22
23
24 /*!
25  * @brief 新規フロアに入りたてのプレイヤーをランダムな場所に配置する / Returns random co-ordinates for player/monster/object
26  * @return 配置に成功したらTRUEを返す
27  */
28 bool new_player_spot(void)
29 {
30         POSITION y = 0, x = 0;
31         int max_attempts = 10000;
32
33         cave_type *c_ptr;
34         feature_type *f_ptr;
35
36         /* Place the player */
37         while (max_attempts--)
38         {
39                 /* Pick a legal spot */
40                 y = (POSITION)rand_range(1, cur_hgt - 2);
41                 x = (POSITION)rand_range(1, cur_wid - 2);
42
43                 c_ptr = &cave[y][x];
44
45                 /* Must be a "naked" floor grid */
46                 if (c_ptr->m_idx) continue;
47                 if (dun_level)
48                 {
49                         f_ptr = &f_info[c_ptr->feat];
50
51                         if (max_attempts > 5000) /* Rule 1 */
52                         {
53                                 if (!have_flag(f_ptr->flags, FF_FLOOR)) continue;
54                         }
55                         else /* Rule 2 */
56                         {
57                                 if (!have_flag(f_ptr->flags, FF_MOVE)) continue;
58                                 if (have_flag(f_ptr->flags, FF_HIT_TRAP)) continue;
59                         }
60
61                         /* Refuse to start on anti-teleport grids in dungeon */
62                         if (!have_flag(f_ptr->flags, FF_TELEPORTABLE)) continue;
63                 }
64                 if (!player_can_enter(c_ptr->feat, 0)) continue;
65                 if (!in_bounds(y, x)) continue;
66
67                 /* Refuse to start on anti-teleport grids */
68                 if (c_ptr->info & (CAVE_ICKY)) continue;
69
70                 break;
71         }
72
73         if (max_attempts < 1) /* Should be -1, actually if we failed... */
74                 return FALSE;
75
76         /* Save the new player grid */
77         p_ptr->y = y;
78         p_ptr->x = x;
79
80         return TRUE;
81 }
82
83
84
85 /*!
86  * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
87  * @param y 配置を試みたいマスのY座標
88  * @param x 配置を試みたいマスのX座標
89  * @return なし
90  */
91 void place_random_stairs(POSITION y, POSITION x)
92 {
93         bool up_stairs = TRUE;
94         bool down_stairs = TRUE;
95         cave_type *c_ptr;
96
97         /* Paranoia */
98         c_ptr = &cave[y][x];
99         if (!is_floor_grid(c_ptr) || c_ptr->o_idx) return;
100
101         /* Town */
102         if (!dun_level) up_stairs = FALSE;
103
104         /* Ironman */
105         if (ironman_downward) up_stairs = FALSE;
106
107         /* Bottom */
108         if (dun_level >= d_info[dungeon_type].maxdepth) down_stairs = FALSE;
109
110         /* Quest-level */
111         if (quest_number(dun_level) && (dun_level > 1)) down_stairs = FALSE;
112
113         /* We can't place both */
114         if (down_stairs && up_stairs)
115         {
116                 /* Choose a staircase randomly */
117                 if (randint0(100) < 50) up_stairs = FALSE;
118                 else down_stairs = FALSE;
119         }
120
121         /* Place the stairs */
122         if (up_stairs) place_up_stairs(y, x);
123         else if (down_stairs) place_down_stairs(y, x);
124 }
125
126 /*!
127  * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
128  * @param y ドアの配置を試みたいマスのY座標
129  * @param x ドアの配置を試みたいマスのX座標
130  * @param room 部屋に接している場合向けのドア生成か否か
131  * @return なし
132  */
133 void place_random_door(POSITION y, POSITION x, bool room)
134 {
135         int tmp, type;
136         FEAT_IDX feat = feat_none;
137         cave_type *c_ptr = &cave[y][x];
138
139         /* Initialize mimic info */
140         c_ptr->mimic = 0;
141
142         if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
143         {
144                 place_floor_bold(y, x);
145                 return;
146         }
147
148         type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
149                 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
150                 ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
151
152         /* Choose an object */
153         tmp = randint0(1000);
154
155         /* Open doors (300/1000) */
156         if (tmp < 300)
157         {
158                 /* Create open door */
159                 feat = feat_door[type].open;
160         }
161
162         /* Broken doors (100/1000) */
163         else if (tmp < 400)
164         {
165                 /* Create broken door */
166                 feat = feat_door[type].broken;
167         }
168
169         /* Secret doors (200/1000) */
170         else if (tmp < 600)
171         {
172                 /* Create secret door */
173                 place_closed_door(y, x, type);
174
175                 if (type != DOOR_CURTAIN)
176                 {
177                         /* Hide. If on the edge of room, use outer wall. */
178                         c_ptr->mimic = room ? feat_wall_outer : fill_type[randint0(100)];
179
180                         /* Floor type terrain cannot hide a door */
181                         if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
182                         {
183                                 if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
184                                 {
185                                         c_ptr->feat = one_in_(2) ? c_ptr->mimic : feat_ground_type[randint0(100)];
186                                 }
187                                 c_ptr->mimic = 0;
188                         }
189                 }
190         }
191
192         /* Closed, locked, or stuck doors (400/1000) */
193         else place_closed_door(y, x, type);
194
195         if (tmp < 400)
196         {
197                 if (feat != feat_none)
198                 {
199                         set_cave_feat(y, x, feat);
200                 }
201                 else
202                 {
203                         place_floor_bold(y, x);
204                 }
205         }
206
207         delete_monster(y, x);
208 }
209
210 /*!
211  * @brief 所定の位置に各種の閉じたドアを配置する / Place a random type of normal door at the given location.
212  * @param y ドアの配置を試みたいマスのY座標
213  * @param x ドアの配置を試みたいマスのX座標
214  * @param type ドアの地形ID
215  * @return なし
216  */
217 void place_closed_door(POSITION y, POSITION x, int type)
218 {
219         int tmp;
220         FEAT_IDX feat = feat_none;
221
222         if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
223         {
224                 place_floor_bold(y, x);
225                 return;
226         }
227
228         /* Choose an object */
229         tmp = randint0(400);
230
231         /* Closed doors (300/400) */
232         if (tmp < 300)
233         {
234                 /* Create closed door */
235                 feat = feat_door[type].closed;
236         }
237
238         /* Locked doors (99/400) */
239         else if (tmp < 399)
240         {
241                 /* Create locked door */
242                 feat = feat_locked_door_random(type);
243         }
244
245         /* Stuck doors (1/400) */
246         else
247         {
248                 /* Create jammed door */
249                 feat = feat_jammed_door_random(type);
250         }
251
252         if (feat != feat_none)
253         {
254                 cave_set_feat(y, x, feat);
255
256                 /* Now it is not floor */
257                 cave[y][x].info &= ~(CAVE_MASK);
258         }
259         else
260         {
261                 place_floor_bold(y, x);
262         }
263 }
264
265 /*!
266 * @brief 鍵のかかったドアを配置する
267 * @param y 配置したいフロアのY座標
268 * @param x 配置したいフロアのX座標
269 * @return なし
270 */
271 void place_locked_door(POSITION y, POSITION x)
272 {
273         if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
274         {
275                 place_floor_bold(y, x);
276         }
277         else
278         {
279                 set_cave_feat(y, x, feat_locked_door_random((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
280                 cave[y][x].info &= ~(CAVE_FLOOR);
281                 delete_monster(y, x);
282         }
283 }
284
285
286 /*!
287 * @brief 隠しドアを配置する
288 * @param y 配置したいフロアのY座標
289 * @param x 配置したいフロアのX座標
290 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
291 * @return なし
292 */
293 void place_secret_door(POSITION y, POSITION x, int type)
294 {
295         if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
296         {
297                 place_floor_bold(y, x);
298         }
299         else
300         {
301                 cave_type *c_ptr = &cave[y][x];
302
303                 if (type == DOOR_DEFAULT)
304                 {
305                         type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
306                                 one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
307                                 ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
308                 }
309
310                 /* Create secret door */
311                 place_closed_door(y, x, type);
312
313                 if (type != DOOR_CURTAIN)
314                 {
315                         /* Hide by inner wall because this is used in rooms only */
316                         c_ptr->mimic = feat_wall_inner;
317
318                         /* Floor type terrain cannot hide a door */
319                         if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
320                         {
321                                 if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
322                                 {
323                                         c_ptr->feat = one_in_(2) ? c_ptr->mimic : feat_ground_type[randint0(100)];
324                                 }
325                                 c_ptr->mimic = 0;
326                         }
327                 }
328
329                 c_ptr->info &= ~(CAVE_FLOOR);
330                 delete_monster(y, x);
331         }
332 }
333
334 /*
335  * Routine used by the random vault creators to add a door to a location
336  * Note that range checking has to be done in the calling routine.
337  *
338  * The doors must be INSIDE the allocated region.
339  */
340 void add_door(POSITION x, POSITION y)
341 {
342         /* Need to have a wall in the center square */
343         if (!is_outer_bold(y, x)) return;
344
345         /* look at:
346         *  x#x
347         *  .#.
348         *  x#x
349         *
350         *  where x=don't care
351         *  .=floor, #=wall
352         */
353
354         if (is_floor_bold(y - 1, x) && is_floor_bold(y + 1, x) &&
355                 (is_outer_bold(y, x - 1) && is_outer_bold(y, x + 1)))
356         {
357                 /* secret door */
358                 place_secret_door(y, x, DOOR_DEFAULT);
359
360                 /* set boundarys so don't get wide doors */
361                 place_solid_bold(y, x - 1);
362                 place_solid_bold(y, x + 1);
363         }
364
365
366         /* look at:
367         *  x#x
368         *  .#.
369         *  x#x
370         *
371         *  where x = don't care
372         *  .=floor, #=wall
373         */
374         if (is_outer_bold(y - 1, x) && is_outer_bold(y + 1, x) &&
375                 is_floor_bold(y, x - 1) && is_floor_bold(y, x + 1))
376         {
377                 /* secret door */
378                 place_secret_door(y, x, DOOR_DEFAULT);
379
380                 /* set boundarys so don't get wide doors */
381                 place_solid_bold(y - 1, x);
382                 place_solid_bold(y + 1, x);
383         }
384 }
385
386 /*!
387 * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
388 * @param y1 基準となるマスのY座標
389 * @param x1 基準となるマスのX座標
390 * @return 通路の数
391 * @note Assumes "in_bounds(y1, x1)"
392 * @details
393 * XXX XXX This routine currently only counts actual "empty floor"\n
394 * grids which are not in rooms.  We might want to also count stairs,\n
395 * open doors, closed doors, etc.
396 */
397 static int next_to_corr(POSITION y1, POSITION x1)
398 {
399         int i, k = 0;
400         POSITION y, x;
401
402         cave_type *c_ptr;
403
404         /* Scan adjacent grids */
405         for (i = 0; i < 4; i++)
406         {
407                 /* Extract the location */
408                 y = y1 + ddy_ddd[i];
409                 x = x1 + ddx_ddd[i];
410                 c_ptr = &cave[y][x];
411
412                 /* Skip non floors */
413                 if (cave_have_flag_grid(c_ptr, FF_WALL)) continue;
414
415                 /* Skip non "empty floor" grids */
416                 if (!is_floor_grid(c_ptr))
417                         continue;
418
419                 /* Skip grids inside rooms */
420                 if (c_ptr->info & (CAVE_ROOM)) continue;
421
422                 /* Count these grids */
423                 k++;
424         }
425
426         /* Return the number of corridors */
427         return (k);
428 }
429
430 /*!
431 * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
432 * @param y 判定を行いたいマスのY座標
433 * @param x 判定を行いたいマスのX座標
434 * @return ドアを設置可能ならばTRUEを返す
435 * @note Assumes "in_bounds(y1, x1)"
436 * @details
437 * \n
438 * Assumes "in_bounds(y, x)"\n
439 */
440 static bool possible_doorway(POSITION y, POSITION x)
441 {
442         /* Count the adjacent corridors */
443         if (next_to_corr(y, x) >= 2)
444         {
445                 /* Check Vertical */
446                 if (cave_have_flag_bold(y - 1, x, FF_WALL) &&
447                         cave_have_flag_bold(y + 1, x, FF_WALL))
448                 {
449                         return (TRUE);
450                 }
451
452                 /* Check Horizontal */
453                 if (cave_have_flag_bold(y, x - 1, FF_WALL) &&
454                         cave_have_flag_bold(y, x + 1, FF_WALL))
455                 {
456                         return (TRUE);
457                 }
458         }
459
460         /* No doorway */
461         return (FALSE);
462 }
463
464 /*!
465 * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
466 * @param y 設置を行いたいマスのY座標
467 * @param x 設置を行いたいマスのX座標
468 * @return なし
469 */
470 void try_door(POSITION y, POSITION x)
471 {
472         /* Paranoia */
473         if (!in_bounds(y, x)) return;
474
475         /* Ignore walls */
476         if (cave_have_flag_bold(y, x, FF_WALL)) return;
477
478         /* Ignore room grids */
479         if (cave[y][x].info & (CAVE_ROOM)) return;
480
481         /* Occasional door (if allowed) */
482         if ((randint0(100) < dun_tun_jct) && possible_doorway(y, x) && !(d_info[dungeon_type].flags1 & DF1_NO_DOORS))
483         {
484                 /* Place a door */
485                 place_random_door(y, x, FALSE);
486         }
487 }
488
489
490 /*!
491  * @brief 長方形の空洞を生成する / Make an empty square floor, for the middle of rooms
492  * @param x1 長方形の左端X座標(-1)
493  * @param x2 長方形の右端X座標(+1)
494  * @param y1 長方形の上端Y座標(-1)
495  * @param y2 長方形の下端Y座標(+1)
496  * @param light 照明の有無
497  * @return なし
498  */
499 void place_floor(POSITION x1, POSITION x2, POSITION y1, POSITION y2, bool light)
500 {
501         POSITION x, y;
502
503         /* Place a full floor under the room */
504         for (y = y1 - 1; y <= y2 + 1; y++)
505         {
506                 for (x = x1 - 1; x <= x2 + 1; x++)
507                 {
508                         place_floor_bold(y, x);
509                         add_cave_info(y, x, CAVE_ROOM);
510                         if (light) add_cave_info(y, x, CAVE_GLOW);
511                 }
512         }
513 }
514
515
516 /*!
517  * @brief 長方形の部屋を生成する / Make an empty square room, only floor and wall grids
518  * @param x1 長方形の左端X座標(-1)
519  * @param x2 長方形の右端X座標(+1)
520  * @param y1 長方形の上端Y座標(-1)
521  * @param y2 長方形の下端Y座標(+1)
522  * @param light 照明の有無
523  * @return なし
524  */
525 void place_room(POSITION x1, POSITION x2, POSITION y1, POSITION y2, bool light)
526 {
527         POSITION y, x;
528
529         place_floor(x1, x2, y1, y2, light);
530
531         /* Walls around the room */
532         for (y = y1 - 1; y <= y2 + 1; y++)
533         {
534                 place_outer_bold(y, x1 - 1);
535                 place_outer_bold(y, x2 + 1);
536         }
537         for (x = x1 - 1; x <= x2 + 1; x++)
538         {
539                 place_outer_bold(y1 - 1, x);
540                 place_outer_bold(y2 + 1, x);
541         }
542 }
543
544
545 /*!
546  * @brief 特殊な部屋向けに各種アイテムを配置する / Create up to "num" objects near the given coordinates
547  * @param y 配置したい中心マスのY座標
548  * @param x 配置したい中心マスのX座標
549  * @param num 配置したい数
550  * @return なし
551  * @details
552  * Only really called by some of the "vault" routines.
553  */
554 void vault_objects(POSITION y, POSITION x, int num)
555 {
556         int dummy = 0;
557         int i = 0, j = y, k = x;
558
559         cave_type *c_ptr;
560
561
562         /* Attempt to place 'num' objects */
563         for (; num > 0; --num)
564         {
565                 /* Try up to 11 spots looking for empty space */
566                 for (i = 0; i < 11; ++i)
567                 {
568                         /* Pick a random location */
569                         while (dummy < SAFE_MAX_ATTEMPTS)
570                         {
571                                 j = rand_spread(y, 2);
572                                 k = rand_spread(x, 3);
573                                 dummy++;
574                                 if (!in_bounds(j, k)) continue;
575                                 break;
576                         }
577
578                         if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
579                         {
580                                 msg_print(_("警告!地下室のアイテムを配置できません!", "Warning! Could not place vault object!"));
581                         }
582
583                         /* Require "clean" floor space */
584                         c_ptr = &cave[j][k];
585                         if (!is_floor_grid(c_ptr) || c_ptr->o_idx) continue;
586
587                         if (randint0(100) < 75)
588                         {
589                                 place_object(j, k, 0L);
590                         }
591                         else
592                         {
593                                 place_gold(j, k);
594                         }
595
596                         /* Placement accomplished */
597                         break;
598                 }
599         }
600 }
601
602 /*!
603  * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
604  * @param y トラップを配置したいマスの中心Y座標
605  * @param x トラップを配置したいマスの中心X座標
606  * @param yd Y方向の配置分散マス数
607  * @param xd X方向の配置分散マス数
608  * @return なし
609  * @details
610  * Only really called by some of the "vault" routines.
611  */
612 void vault_trap_aux(POSITION y, POSITION x, POSITION yd, POSITION xd)
613 {
614         int count = 0, y1 = y, x1 = x;
615         int dummy = 0;
616
617         cave_type *c_ptr;
618
619         /* Place traps */
620         for (count = 0; count <= 5; count++)
621         {
622                 /* Get a location */
623                 while (dummy < SAFE_MAX_ATTEMPTS)
624                 {
625                         y1 = rand_spread(y, yd);
626                         x1 = rand_spread(x, xd);
627                         dummy++;
628                         if (!in_bounds(y1, x1)) continue;
629                         break;
630                 }
631
632                 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
633                 {
634                         msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
635                 }
636
637                 /* Require "naked" floor grids */
638                 c_ptr = &cave[y1][x1];
639                 if (!is_floor_grid(c_ptr) || c_ptr->o_idx || c_ptr->m_idx) continue;
640
641                 /* Place the trap */
642                 place_trap(y1, x1);
643
644                 break;
645         }
646 }
647
648 /*!
649  * @brief 特殊な部屋向けに各種アイテムを配置する(メインルーチン) / Place some traps with a given displacement of given location
650  * @param y トラップを配置したいマスの中心Y座標
651  * @param x トラップを配置したいマスの中心X座標
652  * @param yd Y方向の配置分散マス数
653  * @param xd X方向の配置分散マス数
654  * @param num 配置したいトラップの数
655  * @return なし
656  * @details
657  * Only really called by some of the "vault" routines.
658  */
659 void vault_traps(POSITION y, POSITION x, POSITION yd, POSITION xd, int num)
660 {
661         int i;
662
663         for (i = 0; i < num; i++)
664         {
665                 vault_trap_aux(y, x, yd, xd);
666         }
667 }
668
669 /*!
670  * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
671  * @param y1 モンスターを配置したいマスの中心Y座標
672  * @param x1 モンスターを配置したいマスの中心X座標
673  * @param num 配置したいモンスターの数
674  * @return なし
675  * @details
676  * Only really called by some of the "vault" routines.
677  */
678 void vault_monsters(POSITION y1, POSITION x1, int num)
679 {
680         int k, i;
681         POSITION y, x;
682         cave_type *c_ptr;
683
684         /* Try to summon "num" monsters "near" the given location */
685         for (k = 0; k < num; k++)
686         {
687                 /* Try nine locations */
688                 for (i = 0; i < 9; i++)
689                 {
690                         int d = 1;
691
692                         /* Pick a nearby location */
693                         scatter(&y, &x, y1, x1, d, 0);
694
695                         /* Require "empty" floor grids */
696                         c_ptr = &cave[y][x];
697                         if (!cave_empty_grid(c_ptr)) continue;
698
699                         /* Place the monster (allow groups) */
700                         monster_level = base_level + 2;
701                         (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
702                         monster_level = base_level;
703                 }
704         }
705 }
706
707
708 /*!
709  * @brief build_tunnel用に通路を掘るための方向を位置関係通りに決める / Always picks a correct direction
710  * @param rdir Y方向に取るべきベクトル値を返す参照ポインタ
711  * @param cdir X方向に取るべきベクトル値を返す参照ポインタ
712  * @param y1 始点Y座標
713  * @param x1 始点X座標
714  * @param y2 終点Y座標
715  * @param x2 終点X座標
716  * @return なし
717  */
718 void correct_dir(POSITION *rdir, POSITION *cdir, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
719 {
720         /* Extract vertical and horizontal directions */
721         *rdir = (y1 == y2) ? 0 : (y1 < y2) ? 1 : -1;
722         *cdir = (x1 == x2) ? 0 : (x1 < x2) ? 1 : -1;
723
724         /* Never move diagonally */
725         if (*rdir && *cdir)
726         {
727                 if (randint0(100) < 50)
728                         *rdir = 0;
729                 else
730                         *cdir = 0;
731         }
732 }
733
734 /*!
735  * @brief build_tunnel用に通路を掘るための方向をランダムに決める / Pick a random direction
736  * @param rdir Y方向に取るべきベクトル値を返す参照ポインタ
737  * @param cdir X方向に取るべきベクトル値を返す参照ポインタ
738  * @return なし
739  */
740 void rand_dir(POSITION *rdir, POSITION *cdir)
741 {
742         /* Pick a random direction */
743         int i = randint0(4);
744
745         /* Extract the dy/dx components */
746         *rdir = ddy_ddd[i];
747         *cdir = ddx_ddd[i];
748 }
749
750 /*!
751  * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor.  (Includes range checking.)
752  * @param x チェックするマスのX座標
753  * @param y チェックするマスのY座標
754  * @return 床系地形ならばTRUE
755  */
756 bool get_is_floor(POSITION x, POSITION y)
757 {
758         if (!in_bounds(y, x))
759         {
760                 /* Out of bounds */
761                 return (FALSE);
762         }
763
764         /* Do the real check */
765         if (is_floor_bold(y, x)) return (TRUE);
766
767         return (FALSE);
768 }
769
770 /*!
771  * @brief 指定のマスを床地形に変える / Set a square to be floor.  (Includes range checking.)
772  * @param x 地形を変えたいマスのX座標
773  * @param y 地形を変えたいマスのY座標
774  * @return なし
775  */
776 void set_floor(POSITION x, POSITION y)
777 {
778         if (!in_bounds(y, x))
779         {
780                 /* Out of bounds */
781                 return;
782         }
783
784         if (cave[y][x].info & CAVE_ROOM)
785         {
786                 /* A room border don't touch. */
787                 return;
788         }
789
790         /* Set to be floor if is a wall (don't touch lakes). */
791         if (is_extra_bold(y, x))
792                 place_floor_bold(y, x);
793 }
794
795