OSDN Git Service

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