OSDN Git Service

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