OSDN Git Service

[Refactor] #37353 floor.c を作成して floor_type 型整理。
[hengband/hengband.git] / src / rooms-city.c
1 #include "angband.h"
2 #include "util.h"
3
4 #include "grid.h"
5 #include "floor.h"
6 #include "floor-generate.h"
7 #include "rooms.h"
8 #include "rooms-city.h"
9 #include "store.h"
10
11
12
13 /*
14 * Precalculate buildings' location of underground arcade
15 */
16 static bool precalc_ugarcade(int town_hgt, int town_wid, int n)
17 {
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;
24
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;
29
30         /* Calculate building locations */
31         for (i = 0; i < n; i++)
32         {
33                 cur_ugbldg = &ugbldg[i];
34                 (void)WIPE(cur_ugbldg, ugbldg_type);
35
36                 do
37                 {
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);
41
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);
51
52                         /* Scan this building's area */
53                         for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++)
54                         {
55                                 for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++)
56                                 {
57                                         if (ugarcade_used[y][x])
58                                         {
59                                                 abort = TRUE;
60                                                 break;
61                                         }
62                                 }
63                         }
64
65                         attempt--;
66                 } while (abort && attempt); /* Accept this building if no overlapping */
67
68                                                                         /* Failed to generate underground arcade */
69                 if (!attempt) break;
70
71                 /*
72                 * Mark to ugarcade_used[][] as "used"
73                 * Note: Building-adjacent grids are included for preventing
74                 * connected bulidings.
75                 */
76                 for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++)
77                 {
78                         for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++)
79                         {
80                                 ugarcade_used[y][x] = TRUE;
81                         }
82                 }
83         }
84
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 *);
88
89         /* If i < n, generation is not allowed */
90         return i == n;
91 }
92
93
94 /*!
95 * @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings
96 * @return なし
97 * @param ltcy 生成基準Y座標
98 * @param ltcx 生成基準X座標
99 * @param stotes[] 生成する店舗のリスト
100 * @param n 生成する店舗の数
101 * @note
102 * Note: ltcy and ltcx indicate "left top corner".
103 */
104 static void build_stores(POSITION ltcy, POSITION ltcx, int stores[], int n)
105 {
106         int i;
107         POSITION y, x;
108         FEAT_IDX j;
109         ugbldg_type *cur_ugbldg;
110
111         for (i = 0; i < n; i++)
112         {
113                 cur_ugbldg = &ugbldg[i];
114
115                 /* Generate new room */
116                 generate_room_floor(
117                         ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2,
118                         ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2,
119                         FALSE);
120         }
121
122         for (i = 0; i < n; i++)
123         {
124                 cur_ugbldg = &ugbldg[i];
125
126                 /* Build an invulnerable rectangular building */
127                 generate_fill_perm_bold(
128                         ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0,
129                         ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1);
130
131                 /* Pick a door direction (S,N,E,W) */
132                 switch (randint0(4))
133                 {
134                         /* Bottom side */
135                 case 0:
136                         y = cur_ugbldg->y1;
137                         x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
138                         break;
139
140                         /* Top side */
141                 case 1:
142                         y = cur_ugbldg->y0;
143                         x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1);
144                         break;
145
146                         /* Right side */
147                 case 2:
148                         y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
149                         x = cur_ugbldg->x1;
150                         break;
151
152                         /* Left side */
153                 default:
154                         y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1);
155                         x = cur_ugbldg->x0;
156                         break;
157                 }
158
159                 for (j = 0; j < max_f_idx; j++)
160                 {
161                         if (have_flag(f_info[j].flags, FF_STORE))
162                         {
163                                 if (f_info[j].subtype == stores[i]) break;
164                         }
165                 }
166
167                 /* Clear previous contents, add a store door */
168                 if (j < max_f_idx)
169                 {
170                         cave_set_feat(ltcy + y, ltcx + x, j);
171
172                         /* Init store */
173                         store_init(NO_TOWN, stores[i]);
174                 }
175         }
176 }
177
178
179 /*!
180 * @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade
181 * @return なし
182 * @details
183 * Town logic flow for generation of new town\n
184 * Originally from Vanilla 3.0.3\n
185 *\n
186 * We start with a fully wiped current_floor_ptr->grid_array of normal floors.\n
187 *\n
188 * Note that town_gen_hack() plays games with the R.N.G.\n
189 *\n
190 * This function does NOT do anything about the owners of the stores,\n
191 * nor the contents thereof.  It only handles the physical layout.\n
192 */
193 bool build_type16(void)
194 {
195         int stores[] =
196         {
197                 STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE,
198                 STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK,
199         };
200         int n = sizeof stores / sizeof(int);
201         POSITION i, y, x, y1, x1, yval, xval;
202         int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT);
203         int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID);
204         bool prevent_bm = FALSE;
205
206         /* Hack -- If already exist black market, prevent building */
207         for (y = 0; (y < current_floor_ptr->height) && !prevent_bm; y++)
208         {
209                 for (x = 0; x < current_floor_ptr->width; x++)
210                 {
211                         if (current_floor_ptr->grid_array[y][x].feat == FF_STORE)
212                         {
213                                 prevent_bm = (f_info[current_floor_ptr->grid_array[y][x].feat].subtype == STORE_BLACK);
214                                 break;
215                         }
216                 }
217         }
218         for (i = 0; i < n; i++)
219         {
220                 if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n];
221         }
222         if (!n) return FALSE;
223
224         /* Allocate buildings array */
225         C_MAKE(ugbldg, n, ugbldg_type);
226
227         /* If cannot build stores, abort */
228         if (!precalc_ugarcade(town_hgt, town_wid, n))
229         {
230                 /* Free buildings array */
231                 C_KILL(ugbldg, n, ugbldg_type);
232                 return FALSE;
233         }
234
235         /* Find and reserve some space in the dungeon.  Get center of room. */
236         if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4))
237         {
238                 /* Free buildings array */
239                 C_KILL(ugbldg, n, ugbldg_type);
240                 return FALSE;
241         }
242
243         /* Get top left corner */
244         y1 = yval - (town_hgt / 2);
245         x1 = xval - (town_wid / 2);
246
247         /* Generate new room */
248         generate_room_floor(
249                 y1 + town_hgt / 3, x1 + town_wid / 3,
250                 y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE);
251
252         /* Build stores */
253         build_stores(y1, x1, stores, n);
254
255         msg_print_wizard(CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated."));
256
257         /* Free buildings array */
258         C_KILL(ugbldg, n, ugbldg_type);
259
260         return TRUE;
261 }
262