1 #include "system/angband.h"
5 #include "floor/floor.h"
6 #include "floor/floor-generate.h"
7 #include "room/rooms.h"
8 #include "room/rooms-city.h"
9 #include "market/store.h"
11 #include "market/store-util.h"
14 * Precalculate buildings' location of underground arcade
16 static bool precalc_ugarcade(int town_hgt, int town_wid, int n)
18 POSITION i, y, x, center_y, center_x;
19 int tmp, attempt = 10000;
20 POSITION max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT;
21 POSITION max_bldg_wid = 5 * town_wid / MAX_TOWN_WID;
22 ugbldg_type *cur_ugbldg;
23 bool **ugarcade_used, abort;
25 /* Allocate "ugarcade_used" array (2-dimension) */
26 C_MAKE(ugarcade_used, town_hgt, bool *);
27 C_MAKE(*ugarcade_used, town_hgt * town_wid, bool);
28 for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid;
30 /* Calculate building locations */
31 for (i = 0; i < n; i++)
33 cur_ugbldg = &ugbldg[i];
34 (void)WIPE(cur_ugbldg, ugbldg_type);
38 /* Find the "center" of the store */
39 center_y = rand_range(2, town_hgt - 3);
40 center_x = rand_range(2, town_wid - 3);
42 /* Determine the store boundaries */
43 tmp = center_y - randint1(max_bldg_hgt);
44 cur_ugbldg->y0 = MAX(tmp, 1);
45 tmp = center_x - randint1(max_bldg_wid);
46 cur_ugbldg->x0 = MAX(tmp, 1);
47 tmp = center_y + randint1(max_bldg_hgt);
48 cur_ugbldg->y1 = MIN(tmp, town_hgt - 2);
49 tmp = center_x + randint1(max_bldg_wid);
50 cur_ugbldg->x1 = MIN(tmp, town_wid - 2);
52 /* Scan this building's area */
53 for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++)
55 for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++)
57 if (ugarcade_used[y][x])
66 } while (abort && attempt); /* Accept this building if no overlapping */
68 /* Failed to generate underground arcade */
72 * Mark to ugarcade_used[][] as "used"
73 * Note: Building-adjacent grids are included for preventing
74 * connected bulidings.
76 for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++)
78 for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++)
80 ugarcade_used[y][x] = TRUE;
85 /* Free "ugarcade_used" array (2-dimension) */
86 C_KILL(*ugarcade_used, town_hgt * town_wid, bool);
87 C_KILL(ugarcade_used, town_hgt, bool *);
89 /* If i < n, generation is not allowed */
95 * @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings
96 * @param player_ptr プレーヤーへの参照ポインタ
100 * @param stotes[] 生成する店舗のリスト
103 * Note: ltcy and ltcx indicate "left top corner".
105 static void build_stores(player_type *player_ptr, POSITION ltcy, POSITION ltcx, int stores[], int n)
110 ugbldg_type *cur_ugbldg;
112 for (i = 0; i < n; i++)
114 cur_ugbldg = &ugbldg[i];
116 /* Generate new room */
117 generate_room_floor(player_ptr,
118 ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2,
119 ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2,
123 for (i = 0; i < n; i++)
125 cur_ugbldg = &ugbldg[i];
127 /* Build an invulnerable rectangular building */
128 generate_fill_perm_bold(player_ptr,
129 ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0,
130 ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1);
132 /* Pick a door direction (S,N,E,W) */
138 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
144 x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
149 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
155 y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
160 for (j = 0; j < max_f_idx; j++)
162 if (have_flag(f_info[j].flags, FF_STORE))
164 if (f_info[j].subtype == stores[i]) break;
168 /* Clear previous contents, add a store door */
171 cave_set_feat(player_ptr, ltcy + y, ltcx + x, j);
174 store_init(NO_TOWN, stores[i]);
181 * @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade
184 * Town logic flow for generation of new town\n
185 * Originally from Vanilla 3.0.3\n
187 * We start with a fully wiped grids of normal floors.\n
189 * Note that town_gen_hack() plays games with the R.N.G.\n
191 * This function does NOT do anything about the owners of the stores,\n
192 * nor the contents thereof. It only handles the physical layout.\n
194 bool build_type16(player_type *player_ptr)
198 STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE,
199 STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK,
201 int n = sizeof stores / sizeof(int);
202 POSITION i, y, x, y1, x1, yval, xval;
203 int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT);
204 int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID);
205 bool prevent_bm = FALSE;
207 /* Hack -- If already exist black market, prevent building */
208 floor_type *floor_ptr = player_ptr->current_floor_ptr;
209 for (y = 0; (y < floor_ptr->height) && !prevent_bm; y++)
211 for (x = 0; x < floor_ptr->width; x++)
213 if (floor_ptr->grid_array[y][x].feat == FF_STORE)
215 prevent_bm = (f_info[floor_ptr->grid_array[y][x].feat].subtype == STORE_BLACK);
220 for (i = 0; i < n; i++)
222 if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n];
224 if (!n) return FALSE;
226 /* Allocate buildings array */
227 C_MAKE(ugbldg, n, ugbldg_type);
229 /* If cannot build stores, abort */
230 if (!precalc_ugarcade(town_hgt, town_wid, n))
232 /* Free buildings array */
233 C_KILL(ugbldg, n, ugbldg_type);
237 /* Find and reserve some space in the dungeon. Get center of room. */
238 if (!find_space(player_ptr, &yval, &xval, town_hgt + 4, town_wid + 4))
240 /* Free buildings array */
241 C_KILL(ugbldg, n, ugbldg_type);
245 /* Get top left corner */
246 y1 = yval - (town_hgt / 2);
247 x1 = xval - (town_wid / 2);
249 /* Generate new room */
250 generate_room_floor(player_ptr,
251 y1 + town_hgt / 3, x1 + town_wid / 3,
252 y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE);
255 build_stores(player_ptr, y1, x1, stores, n);
257 msg_print_wizard(CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated."));
259 /* Free buildings array */
260 C_KILL(ugbldg, n, ugbldg_type);