OSDN Git Service

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