From: Deskull Date: Sat, 15 Sep 2018 07:51:41 +0000 (+0900) Subject: [Refactor] #37353 地下都市生成処理を rooms.c から rooms-city.c/h へ分離。 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=2770610bbe2eecfe382561cd89d2d024095eb87a;p=hengband%2Fhengband.git [Refactor] #37353 地下都市生成処理を rooms.c から rooms-city.c/h へ分離。 Separate generation of underground city from rooms.c to rooms-city.c/h. --- diff --git a/Hengband_vcs2015/Hengband/Hengband.vcxproj b/Hengband_vcs2015/Hengband/Hengband.vcxproj index 30668d9c4..84720dfb6 100644 --- a/Hengband_vcs2015/Hengband/Hengband.vcxproj +++ b/Hengband_vcs2015/Hengband/Hengband.vcxproj @@ -209,6 +209,7 @@ + @@ -273,6 +274,7 @@ + diff --git a/Hengband_vcs2015/Hengband/Hengband.vcxproj.filters b/Hengband_vcs2015/Hengband/Hengband.vcxproj.filters index a7c5ef072..0bc7d49b3 100644 --- a/Hengband_vcs2015/Hengband/Hengband.vcxproj.filters +++ b/Hengband_vcs2015/Hengband/Hengband.vcxproj.filters @@ -292,6 +292,9 @@ Source + + Source + @@ -460,6 +463,9 @@ Header + + Header + diff --git a/src/rooms-city.c b/src/rooms-city.c new file mode 100644 index 000000000..415566b9a --- /dev/null +++ b/src/rooms-city.c @@ -0,0 +1,256 @@ +#include "angband.h" +#include "grid.h" +#include "generate.h" +#include "rooms.h" +#include "rooms-city.h" + + + +/* +* Precalculate buildings' location of underground arcade +*/ +static bool precalc_ugarcade(int town_hgt, int town_wid, int n) +{ + int i, y, x, center_y, center_x, tmp, attempt = 10000; + int max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT; + int max_bldg_wid = 5 * town_wid / MAX_TOWN_WID; + ugbldg_type *cur_ugbldg; + bool **ugarcade_used, abort; + + /* Allocate "ugarcade_used" array (2-dimension) */ + C_MAKE(ugarcade_used, town_hgt, bool *); + C_MAKE(*ugarcade_used, town_hgt * town_wid, bool); + for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid; + + /* Calculate building locations */ + for (i = 0; i < n; i++) + { + cur_ugbldg = &ugbldg[i]; + (void)WIPE(cur_ugbldg, ugbldg_type); + + do + { + /* Find the "center" of the store */ + center_y = rand_range(2, town_hgt - 3); + center_x = rand_range(2, town_wid - 3); + + /* Determine the store boundaries */ + tmp = center_y - randint1(max_bldg_hgt); + cur_ugbldg->y0 = MAX(tmp, 1); + tmp = center_x - randint1(max_bldg_wid); + cur_ugbldg->x0 = MAX(tmp, 1); + tmp = center_y + randint1(max_bldg_hgt); + cur_ugbldg->y1 = MIN(tmp, town_hgt - 2); + tmp = center_x + randint1(max_bldg_wid); + cur_ugbldg->x1 = MIN(tmp, town_wid - 2); + + /* Scan this building's area */ + for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++) + { + for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++) + { + if (ugarcade_used[y][x]) + { + abort = TRUE; + break; + } + } + } + + attempt--; + } while (abort && attempt); /* Accept this building if no overlapping */ + + /* Failed to generate underground arcade */ + if (!attempt) break; + + /* + * Mark to ugarcade_used[][] as "used" + * Note: Building-adjacent grids are included for preventing + * connected bulidings. + */ + for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++) + { + for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++) + { + ugarcade_used[y][x] = TRUE; + } + } + } + + /* Free "ugarcade_used" array (2-dimension) */ + C_KILL(*ugarcade_used, town_hgt * town_wid, bool); + C_KILL(ugarcade_used, town_hgt, bool *); + + /* If i < n, generation is not allowed */ + return i == n; +} + + +/*! +* @brief ƒ^ƒCƒv16‚Ì•”‰®c’n‰º“sŽs¶¬‚̃Tƒuƒ‹[ƒ`ƒ“ / Actually create buildings +* @return ‚È‚µ +* @param ltcy ¶¬Šî€YÀ•W +* @param ltcx ¶¬Šî€XÀ•W +* @param stotes[] ¶¬‚·‚é“X•Ü‚̃ŠƒXƒg +* @param n ¶¬‚·‚é“X•Ü‚̐” +* @note +* Note: ltcy and ltcx indicate "left top corner". +*/ +static void build_stores(int ltcy, int ltcx, int stores[], int n) +{ + int i, y, x; + IDX j; + ugbldg_type *cur_ugbldg; + + for (i = 0; i < n; i++) + { + cur_ugbldg = &ugbldg[i]; + + /* Generate new room */ + generate_room_floor( + ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2, + ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2, + FALSE); + } + + for (i = 0; i < n; i++) + { + cur_ugbldg = &ugbldg[i]; + + /* Build an invulnerable rectangular building */ + generate_fill_perm_bold( + ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0, + ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1); + + /* Pick a door direction (S,N,E,W) */ + switch (randint0(4)) + { + /* Bottom side */ + case 0: + y = cur_ugbldg->y1; + x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1); + break; + + /* Top side */ + case 1: + y = cur_ugbldg->y0; + x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1); + break; + + /* Right side */ + case 2: + y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1); + x = cur_ugbldg->x1; + break; + + /* Left side */ + default: + y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1); + x = cur_ugbldg->x0; + break; + } + + for (j = 0; j < max_f_idx; j++) + { + if (have_flag(f_info[j].flags, FF_STORE)) + { + if (f_info[j].subtype == stores[i]) break; + } + } + + /* Clear previous contents, add a store door */ + if (j < max_f_idx) + { + cave_set_feat(ltcy + y, ltcx + x, j); + + /* Init store */ + store_init(NO_TOWN, stores[i]); + } + } +} + + +/*! +* @brief ƒ^ƒCƒv16‚Ì•”‰®c’n‰º“sŽs‚̐¶¬ / Type 16 -- Underground Arcade +* @return ‚È‚µ +* @details +* Town logic flow for generation of new town\n +* Originally from Vanilla 3.0.3\n +*\n +* We start with a fully wiped cave of normal floors.\n +*\n +* Note that town_gen_hack() plays games with the R.N.G.\n +*\n +* This function does NOT do anything about the owners of the stores,\n +* nor the contents thereof. It only handles the physical layout.\n +*/ +bool build_type16(void) +{ + int stores[] = + { + STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE, + STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK, + }; + int n = sizeof stores / sizeof(int); + POSITION i, y, x, y1, x1, yval, xval; + int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT); + int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID); + bool prevent_bm = FALSE; + + /* Hack -- If already exist black market, prevent building */ + for (y = 0; (y < cur_hgt) && !prevent_bm; y++) + { + for (x = 0; x < cur_wid; x++) + { + if (cave[y][x].feat == FF_STORE) + { + prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK); + break; + } + } + } + for (i = 0; i < n; i++) + { + if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n]; + } + if (!n) return FALSE; + + /* Allocate buildings array */ + C_MAKE(ugbldg, n, ugbldg_type); + + /* If cannot build stores, abort */ + if (!precalc_ugarcade(town_hgt, town_wid, n)) + { + /* Free buildings array */ + C_KILL(ugbldg, n, ugbldg_type); + return FALSE; + } + + /* Find and reserve some space in the dungeon. Get center of room. */ + if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4)) + { + /* Free buildings array */ + C_KILL(ugbldg, n, ugbldg_type); + return FALSE; + } + + /* Get top left corner */ + y1 = yval - (town_hgt / 2); + x1 = xval - (town_wid / 2); + + /* Generate new room */ + generate_room_floor( + y1 + town_hgt / 3, x1 + town_wid / 3, + y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE); + + /* Build stores */ + build_stores(y1, x1, stores, n); + + msg_print_wizard(CHEAT_DUNGEON, _("’n‰ºŠX‚𐶐¬‚µ‚Ü‚µ‚½", "Underground arcade was generated.")); + + /* Free buildings array */ + C_KILL(ugbldg, n, ugbldg_type); + + return TRUE; +} + diff --git a/src/rooms-city.h b/src/rooms-city.h new file mode 100644 index 000000000..8a67b94b2 --- /dev/null +++ b/src/rooms-city.h @@ -0,0 +1,17 @@ +extern bool build_type16(void); + +/* Minimum & maximum town size */ +#define MIN_TOWN_WID ((MAX_WID / 3) / 2) +#define MIN_TOWN_HGT ((MAX_HGT / 3) / 2) +#define MAX_TOWN_WID ((MAX_WID / 3) * 2 / 3) +#define MAX_TOWN_HGT ((MAX_HGT / 3) * 2 / 3) + +/* Struct for build underground buildings */ +typedef struct +{ + int y0, x0; /* North-west corner (relative) */ + int y1, x1; /* South-east corner (relative) */ +} +ugbldg_type; + +ugbldg_type *ugbldg; diff --git a/src/rooms.c b/src/rooms.c index 04f4839e0..8d49cf691 100644 --- a/src/rooms.c +++ b/src/rooms.c @@ -44,6 +44,7 @@ #include "rooms-normal.h" #include "rooms-pitnest.h" #include "rooms-vault.h" +#include "rooms-city.h" /*! @@ -3269,270 +3270,6 @@ void generate_fill_perm_bold(int y1, int x1, int y2, int x2) } } -/* Minimum & maximum town size */ -#define MIN_TOWN_WID ((MAX_WID / 3) / 2) -#define MIN_TOWN_HGT ((MAX_HGT / 3) / 2) -#define MAX_TOWN_WID ((MAX_WID / 3) * 2 / 3) -#define MAX_TOWN_HGT ((MAX_HGT / 3) * 2 / 3) - -/* Struct for build underground buildings */ -typedef struct -{ - int y0, x0; /* North-west corner (relative) */ - int y1, x1; /* South-east corner (relative) */ -} -ugbldg_type; - -ugbldg_type *ugbldg; - -/* - * Precalculate buildings' location of underground arcade - */ -static bool precalc_ugarcade(int town_hgt, int town_wid, int n) -{ - int i, y, x, center_y, center_x, tmp, attempt = 10000; - int max_bldg_hgt = 3 * town_hgt / MAX_TOWN_HGT; - int max_bldg_wid = 5 * town_wid / MAX_TOWN_WID; - ugbldg_type *cur_ugbldg; - bool **ugarcade_used, abort; - - /* Allocate "ugarcade_used" array (2-dimension) */ - C_MAKE(ugarcade_used, town_hgt, bool *); - C_MAKE(*ugarcade_used, town_hgt * town_wid, bool); - for (y = 1; y < town_hgt; y++) ugarcade_used[y] = *ugarcade_used + y * town_wid; - - /* Calculate building locations */ - for (i = 0; i < n; i++) - { - cur_ugbldg = &ugbldg[i]; - (void)WIPE(cur_ugbldg, ugbldg_type); - - do - { - /* Find the "center" of the store */ - center_y = rand_range(2, town_hgt - 3); - center_x = rand_range(2, town_wid - 3); - - /* Determine the store boundaries */ - tmp = center_y - randint1(max_bldg_hgt); - cur_ugbldg->y0 = MAX(tmp, 1); - tmp = center_x - randint1(max_bldg_wid); - cur_ugbldg->x0 = MAX(tmp, 1); - tmp = center_y + randint1(max_bldg_hgt); - cur_ugbldg->y1 = MIN(tmp, town_hgt - 2); - tmp = center_x + randint1(max_bldg_wid); - cur_ugbldg->x1 = MIN(tmp, town_wid - 2); - - /* Scan this building's area */ - for (abort = FALSE, y = cur_ugbldg->y0; (y <= cur_ugbldg->y1) && !abort; y++) - { - for (x = cur_ugbldg->x0; x <= cur_ugbldg->x1; x++) - { - if (ugarcade_used[y][x]) - { - abort = TRUE; - break; - } - } - } - - attempt--; - } - while (abort && attempt); /* Accept this building if no overlapping */ - - /* Failed to generate underground arcade */ - if (!attempt) break; - - /* - * Mark to ugarcade_used[][] as "used" - * Note: Building-adjacent grids are included for preventing - * connected bulidings. - */ - for (y = cur_ugbldg->y0 - 1; y <= cur_ugbldg->y1 + 1; y++) - { - for (x = cur_ugbldg->x0 - 1; x <= cur_ugbldg->x1 + 1; x++) - { - ugarcade_used[y][x] = TRUE; - } - } - } - - /* Free "ugarcade_used" array (2-dimension) */ - C_KILL(*ugarcade_used, town_hgt * town_wid, bool); - C_KILL(ugarcade_used, town_hgt, bool *); - - /* If i < n, generation is not allowed */ - return i == n; -} - -/*! - * @brief タイプ16の部屋…地下都市生成のサブルーチン / Actually create buildings - * @return なし - * @param ltcy 生成基準Y座標 - * @param ltcx 生成基準X座標 - * @param stotes[] 生成する店舗のリスト - * @param n 生成する店舗の数 - * @note - * Note: ltcy and ltcx indicate "left top corner". - */ -static void build_stores(int ltcy, int ltcx, int stores[], int n) -{ - int i, y, x; - IDX j; - ugbldg_type *cur_ugbldg; - - for (i = 0; i < n; i++) - { - cur_ugbldg = &ugbldg[i]; - - /* Generate new room */ - generate_room_floor( - ltcy + cur_ugbldg->y0 - 2, ltcx + cur_ugbldg->x0 - 2, - ltcy + cur_ugbldg->y1 + 2, ltcx + cur_ugbldg->x1 + 2, - FALSE); - } - - for (i = 0; i < n; i++) - { - cur_ugbldg = &ugbldg[i]; - - /* Build an invulnerable rectangular building */ - generate_fill_perm_bold( - ltcy + cur_ugbldg->y0, ltcx + cur_ugbldg->x0, - ltcy + cur_ugbldg->y1, ltcx + cur_ugbldg->x1); - - /* Pick a door direction (S,N,E,W) */ - switch (randint0(4)) - { - /* Bottom side */ - case 0: - y = cur_ugbldg->y1; - x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1); - break; - - /* Top side */ - case 1: - y = cur_ugbldg->y0; - x = rand_range(cur_ugbldg->x0, cur_ugbldg->x1); - break; - - /* Right side */ - case 2: - y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1); - x = cur_ugbldg->x1; - break; - - /* Left side */ - default: - y = rand_range(cur_ugbldg->y0, cur_ugbldg->y1); - x = cur_ugbldg->x0; - break; - } - - for (j = 0; j < max_f_idx; j++) - { - if (have_flag(f_info[j].flags, FF_STORE)) - { - if (f_info[j].subtype == stores[i]) break; - } - } - - /* Clear previous contents, add a store door */ - if (j < max_f_idx) - { - cave_set_feat(ltcy + y, ltcx + x, j); - - /* Init store */ - store_init(NO_TOWN, stores[i]); - } - } -} - - -/*! - * @brief タイプ16の部屋…地下都市の生成 / Type 16 -- Underground Arcade - * @return なし - * @details - * Town logic flow for generation of new town\n - * Originally from Vanilla 3.0.3\n - *\n - * We start with a fully wiped cave of normal floors.\n - *\n - * Note that town_gen_hack() plays games with the R.N.G.\n - *\n - * This function does NOT do anything about the owners of the stores,\n - * nor the contents thereof. It only handles the physical layout.\n - */ -static bool build_type16(void) -{ - int stores[] = - { - STORE_GENERAL, STORE_ARMOURY, STORE_WEAPON, STORE_TEMPLE, - STORE_ALCHEMIST, STORE_MAGIC, STORE_BLACK, STORE_BOOK, - }; - int n = sizeof stores / sizeof (int); - POSITION i, y, x, y1, x1, yval, xval; - int town_hgt = rand_range(MIN_TOWN_HGT, MAX_TOWN_HGT); - int town_wid = rand_range(MIN_TOWN_WID, MAX_TOWN_WID); - bool prevent_bm = FALSE; - - /* Hack -- If already exist black market, prevent building */ - for (y = 0; (y < cur_hgt) && !prevent_bm; y++) - { - for (x = 0; x < cur_wid; x++) - { - if (cave[y][x].feat == FF_STORE) - { - prevent_bm = (f_info[cave[y][x].feat].subtype == STORE_BLACK); - break; - } - } - } - for (i = 0; i < n; i++) - { - if ((stores[i] == STORE_BLACK) && prevent_bm) stores[i] = stores[--n]; - } - if (!n) return FALSE; - - /* Allocate buildings array */ - C_MAKE(ugbldg, n, ugbldg_type); - - /* If cannot build stores, abort */ - if (!precalc_ugarcade(town_hgt, town_wid, n)) - { - /* Free buildings array */ - C_KILL(ugbldg, n, ugbldg_type); - return FALSE; - } - - /* Find and reserve some space in the dungeon. Get center of room. */ - if (!find_space(&yval, &xval, town_hgt + 4, town_wid + 4)) - { - /* Free buildings array */ - C_KILL(ugbldg, n, ugbldg_type); - return FALSE; - } - - /* Get top left corner */ - y1 = yval - (town_hgt / 2); - x1 = xval - (town_wid / 2); - - /* Generate new room */ - generate_room_floor( - y1 + town_hgt / 3, x1 + town_wid / 3, - y1 + town_hgt * 2 / 3, x1 + town_wid * 2 / 3, FALSE); - - /* Build stores */ - build_stores(y1, x1, stores, n); - - msg_print_wizard(CHEAT_DUNGEON, _("地下街を生成しました", "Underground arcade was generated.")); - - /* Free buildings array */ - C_KILL(ugbldg, n, ugbldg_type); - - return TRUE; -} - /*! * @brief 与えられた部屋型IDに応じて部屋の生成処理分岐を行い結果を返す / Attempt to build a room of the given type at the given block diff --git a/src/rooms.h b/src/rooms.h index 8866db1e7..3f962d355 100644 --- a/src/rooms.h +++ b/src/rooms.h @@ -72,4 +72,6 @@ extern bool find_space(POSITION *y, POSITION *x, POSITION height, POSITION width extern void build_small_room(int x0, int y0); extern void add_outer_wall(int x, int y, int light, int x1, int y1, int x2, int y2); extern int dist2(int x1, int y1, int x2, int y2, int h1, int h2, int h3, int h4); +extern void generate_room_floor(int y1, int x1, int y2, int x2, int light); +extern void generate_fill_perm_bold(int y1, int x1, int y2, int x2);