1 #include "room/rooms-city.h"
2 #include "floor/floor-generator.h"
3 #include "floor/wild.h"
4 #include "game-option/cheat-types.h"
5 #include "grid/feature.h"
7 #include "room/space-finder.h"
8 #include "store/store-util.h"
9 #include "store/store.h"
10 #include "system/floor-type-definition.h"
11 #include "system/player-type-definition.h"
12 #include "util/bit-flags-calculator.h"
13 #include "wizard/wizard-messages.h"
15 static ugbldg_type *ugbldg;
18 * Precalculate buildings' location of underground arcade
20 static bool precalc_ugarcade(int town_hgt, int town_wid, int n)
22 POSITION i, y, x, center_y, center_x;
23 int tmp, attempt = 10000;
24 POSITION max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT;
25 POSITION max_bldg_wid = 5 * town_wid / MAX_TOWN_WID;
26 ugbldg_type *cur_ugbldg;
27 bool **ugarcade_used, abort;
28 C_MAKE(ugarcade_used, town_hgt, bool *);
29 C_MAKE(*ugarcade_used, town_hgt * town_wid, bool);
30 for (y = 1; y < town_hgt; y++)
31 ugarcade_used[y] = *ugarcade_used + y * town_wid;
33 for (i = 0; i < n; i++) {
34 cur_ugbldg = &ugbldg[i];
35 (void)WIPE(cur_ugbldg, ugbldg_type);
37 center_y = rand_range(2, town_hgt - 3);
38 center_x = rand_range(2, town_wid - 3);
39 tmp = center_y - randint1(max_bldg_hgt);
40 cur_ugbldg->y0 = MAX(tmp, 1);
41 tmp = center_x - randint1(max_bldg_wid);
42 cur_ugbldg->x0 = MAX(tmp, 1);
43 tmp = center_y + randint1(max_bldg_hgt);
44 cur_ugbldg->y1 = MIN(tmp, town_hgt - 2);
45 tmp = center_x + randint1(max_bldg_wid);
46 cur_ugbldg->x1 = MIN(tmp, town_wid - 2);
47 for (abort = false, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++) {
48 for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++) {
49 if (ugarcade_used[y][x]) {
57 } while (abort && attempt);
62 for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++) {
63 for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++) {
64 ugarcade_used[y][x] = true;
69 C_KILL(*ugarcade_used, town_hgt * town_wid, bool);
70 C_KILL(ugarcade_used, town_hgt, bool *);
74 /* Create a new floor room with optional light */
75 static void generate_room_floor(player_type *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2, int light)
78 for (POSITION y = y1; y <= y2; y++) {
79 for (POSITION x = x1; x <= x2; x++) {
80 g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
81 place_grid(player_ptr, g_ptr, GB_FLOOR);
82 g_ptr->info |= (CAVE_ROOM);
84 g_ptr->info |= (CAVE_GLOW);
89 static void generate_fill_perm_bold(player_type *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
91 for (POSITION y = y1; y <= y2; y++)
92 for (POSITION x = x1; x <= x2; x++)
93 place_bold(player_ptr, y, x, GB_INNER_PERM);
97 * @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings
98 * @param player_ptr プレーヤーへの参照ポインタ
100 * @param ltcx 生成基準X座標
101 * @param stotes[] 生成する店舗のリスト
104 * Note: ltcy and ltcx indicate "left top corner".
106 static void build_stores(player_type *player_ptr, POSITION ltcy, POSITION ltcx, int stores[], int n)
111 ugbldg_type *cur_ugbldg;
113 for (i = 0; i < n; i++) {
114 cur_ugbldg = &ugbldg[i];
115 generate_room_floor(player_ptr, ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2, ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2, false);
118 for (i = 0; i < n; i++) {
119 cur_ugbldg = &ugbldg[i];
120 generate_fill_perm_bold(player_ptr, ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0, ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1);
122 /* Pick a door direction (S,N,E,W) */
123 switch (randint0(4)) {
127 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
133 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
138 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
144 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
149 for (j = 0; j < max_f_idx; j++) {
150 if (has_flag(f_info[j].flags, FF_STORE)) {
151 if (f_info[j].subtype == stores[i])
157 cave_set_feat(player_ptr, ltcy + y, ltcx + x, j);
158 store_init(NO_TOWN, stores[i]);
164 * @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade
166 * Town logic flow for generation of new town\n
167 * Originally from Vanilla 3.0.3\n
169 * We start with a fully wiped grids of normal floors.\n
171 * Note that town_gen_hack() plays games with the R.N.G.\n
173 * This function does NOT do anything about the owners of the stores,\n
174 * nor the contents thereof. It only handles the physical layout.\n
176 bool build_type16(player_type *player_ptr, dun_data_type *dd_ptr)
188 int n = sizeof stores / sizeof(int);
189 POSITION i, y, x, y1, x1, yval, xval;
190 int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT);
191 int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID);
192 bool prevent_bm = false;
193 floor_type *floor_ptr = player_ptr->current_floor_ptr;
194 for (y = 0; (y < floor_ptr->height) && !prevent_bm; y++) {
195 for (x = 0; x < floor_ptr->width; x++) {
196 if (floor_ptr->grid_array[y][x].feat == FF_STORE) {
197 prevent_bm = (f_info[floor_ptr->grid_array[y][x].feat].subtype == STORE_BLACK);
203 for (i = 0; i < n; i++)
204 if ((stores[i] == STORE_BLACK) && prevent_bm)
205 stores[i] = stores[--n];
210 C_MAKE(ugbldg, n, ugbldg_type);
211 if (!precalc_ugarcade(town_hgt, town_wid, n)) {
212 C_KILL(ugbldg, n, ugbldg_type);
216 if (!find_space(player_ptr, dd_ptr, &yval, &xval, town_hgt + 4, town_wid + 4)) {
217 C_KILL(ugbldg, n, ugbldg_type);
221 y1 = yval - (town_hgt / 2);
222 x1 = xval - (town_wid / 2);
223 generate_room_floor(player_ptr, y1 + town_hgt / 3, x1 + town_wid / 3, y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, false);
224 build_stores(player_ptr, y1, x1, stores, n);
225 msg_print_wizard(player_ptr, CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated."));
226 C_KILL(ugbldg, n, ugbldg_type);