OSDN Git Service

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