1 #include "floor/object-allocator.h"
2 #include "dungeon/dungeon.h"
3 #include "dungeon/quest.h"
4 #include "floor/cave.h"
5 #include "floor/floor-allocation-types.h"
6 #include "floor/floor-generator-util.h"
7 #include "floor/dungeon-tunnel-util.h"
8 #include "game-option/birth-options.h"
9 #include "game-option/cheat-types.h"
10 #include "grid/feature.h"
11 #include "grid/grid.h"
12 #include "grid/object-placer.h"
13 #include "grid/trap.h"
14 #include "monster-race/monster-race.h"
15 #include "monster-race/race-flags1.h"
16 #include "system/floor-type-definition.h"
17 #include "util/bit-flags-calculator.h"
18 #include "wizard/wizard-messages.h"
21 * @brief 上下左右の外壁数をカウントする / Count the number of walls adjacent to the given grid.
25 * @note Assumes "in_bounds()"
26 * @details We count only granite walls and permanent walls.
28 static int next_to_walls(floor_type *floor_ptr, POSITION y, POSITION x)
31 if (in_bounds(floor_ptr, y + 1, x) && is_extra_bold(floor_ptr, y + 1, x))
34 if (in_bounds(floor_ptr, y - 1, x) && is_extra_bold(floor_ptr, y - 1, x))
37 if (in_bounds(floor_ptr, y, x + 1) && is_extra_bold(floor_ptr, y, x + 1))
40 if (in_bounds(floor_ptr, y, x - 1) && is_extra_bold(floor_ptr, y, x - 1))
47 * @brief alloc_stairs()の補助として指定の位置に階段を生成できるかの判定を行う / Helper function for alloc_stairs(). Is this a good location for stairs?
48 * @param player_ptr プレーヤーへの参照ポインタ
51 * @param walls 最低減隣接させたい外壁の数
52 * @return 階段を生成して問題がないならばTRUEを返す。
54 static bool alloc_stairs_aux(player_type *player_ptr, POSITION y, POSITION x, int walls)
56 floor_type *floor_ptr = player_ptr->current_floor_ptr;
57 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
58 if (!is_floor_grid(g_ptr) || pattern_tile(floor_ptr, y, x) || (g_ptr->o_idx != 0) || (g_ptr->m_idx != 0) || next_to_walls(floor_ptr, y, x) < walls)
65 * @brief 外壁に隣接させて階段を生成する / Places some staircases near walls
66 * @param owner_ptr プレーヤーへの参照ポインタ
67 * @param feat 配置したい地形ID
68 * @param num 配置したい階段の数
69 * @param walls 最低減隣接させたい外壁の数
70 * @return 規定数通りに生成に成功したらTRUEを返す。
72 bool alloc_stairs(player_type *owner_ptr, FEAT_IDX feat, int num, int walls)
75 feature_type *f_ptr = &f_info[feat];
76 floor_type *floor_ptr = owner_ptr->current_floor_ptr;
77 if (has_flag(f_ptr->flags, FF_LESS)) {
78 if (ironman_downward || !floor_ptr->dun_level)
81 if (floor_ptr->dun_level > d_info[floor_ptr->dungeon_idx].mindepth)
82 shaft_num = (randint1(num + 1)) / 2;
83 } else if (has_flag(f_ptr->flags, FF_MORE)) {
84 QUEST_IDX q_idx = quest_number(owner_ptr, floor_ptr->dun_level);
85 if (floor_ptr->dun_level > 1 && q_idx) {
86 monster_race *r_ptr = &r_info[quest[q_idx].r_idx];
87 if (!(r_ptr->flags1 & RF1_UNIQUE) || 0 < r_ptr->max_num)
91 if (floor_ptr->dun_level >= d_info[floor_ptr->dungeon_idx].maxdepth)
94 if ((floor_ptr->dun_level < d_info[floor_ptr->dungeon_idx].maxdepth - 1) && !quest_number(owner_ptr, floor_ptr->dun_level + 1))
95 shaft_num = (randint1(num) + 1) / 2;
99 for (int i = 0; i < num; i++) {
103 const POSITION max_x = floor_ptr->width - 1;
104 for (POSITION y = 1; y < floor_ptr->height - 1; y++)
105 for (POSITION x = 1; x < max_x; x++)
106 if (alloc_stairs_aux(owner_ptr, y, x, walls))
117 int pick = randint1(candidates);
120 for (y = 1; y < floor_ptr->height - 1; y++) {
121 for (x = 1; x < floor_ptr->width - 1; x++) {
122 if (alloc_stairs_aux(owner_ptr, y, x, walls)) {
133 g_ptr = &floor_ptr->grid_array[y][x];
135 g_ptr->feat = (i < shaft_num) ? feat_state(owner_ptr, feat, FF_SHAFT) : feat;
136 g_ptr->info &= ~(CAVE_FLOOR);
145 * @brief フロア上のランダム位置に各種オブジェクトを配置する / Allocates some objects (using "place" and "type")
146 * @param set 配置したい地形の種類
147 * @param typ 配置したいオブジェクトの種類
149 * @return 規定数通りに生成に成功したらTRUEを返す。
151 void alloc_object(player_type *owner_ptr, dap_type set, EFFECT_ID typ, int num)
157 floor_type *floor_ptr = owner_ptr->current_floor_ptr;
158 num = num * floor_ptr->height * floor_ptr->width / (MAX_HGT * MAX_WID) + 1;
159 for (int k = 0; k < num; k++) {
160 while (dummy < SAFE_MAX_ATTEMPTS) {
162 y = randint0(floor_ptr->height);
163 x = randint0(floor_ptr->width);
164 g_ptr = &floor_ptr->grid_array[y][x];
165 if (!is_floor_grid(g_ptr) || g_ptr->o_idx || g_ptr->m_idx)
168 if (player_bold(owner_ptr, y, x))
171 bool room = (floor_ptr->grid_array[y][x].info & CAVE_ROOM) ? TRUE : FALSE;
172 if (((set == ALLOC_SET_CORR) && room) || ((set == ALLOC_SET_ROOM) && !room))
178 if (dummy >= SAFE_MAX_ATTEMPTS) {
179 msg_print_wizard(owner_ptr, CHEAT_DUNGEON, _("アイテムの配置に失敗しました。", "Failed to place object."));
184 case ALLOC_TYP_RUBBLE:
185 place_rubble(floor_ptr, y, x);
186 floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
189 place_trap(owner_ptr, y, x);
190 floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
193 place_gold(owner_ptr, y, x);
195 case ALLOC_TYP_OBJECT:
196 place_object(owner_ptr, y, x, 0L);