diff options
Diffstat (limited to 'src/wild.c')
-rw-r--r-- | src/wild.c | 1275 |
1 files changed, 0 insertions, 1275 deletions
diff --git a/src/wild.c b/src/wild.c deleted file mode 100644 index 7a9d1c51..00000000 --- a/src/wild.c +++ /dev/null @@ -1,1275 +0,0 @@ -/* File: generate.c */ - -/* Purpose: Wilderness & Town related things */ - -/* - * Copyright (c) 2001 James E. Wilson, Robert A. Koeneke, DarkGod - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - - - -/* - * Various defines for the wilderness - */ -#define DUN_WILD_VAULT 50 /* Chance of finding a wilderness vault. */ - -/* - * Various defines for the towns - */ -#define TOWN_NORMAL_FLOOR 70 -#define TOWN_BORDER 90 - - -/* - * Helper for plasma generation. - */ -static void perturb_point_mid(int x1, int x2, int x3, int x4, - int xmid, int ymid, int rough, int depth_max) -{ - /* - * Average the four corners & perturb it a bit. - * tmp is a random int +/- rough - */ - int tmp2 = rough * 2 + 1; - int tmp = randint(tmp2) - (rough + 1); - - int avg = ((x1 + x2 + x3 + x4) / 4) + tmp; - - /* Division always rounds down, so we round up again */ - if (((x1 + x2 + x3 + x4) % 4) > 1) avg++; - - /* Normalize */ - if (avg < 0) avg = 0; - if (avg > depth_max) avg = depth_max; - - /* Set the new value. */ - cave[ymid][xmid].feat = (byte)avg; -} - - -static void perturb_point_end(int x1, int x2, int x3, - int xmid, int ymid, int rough, int depth_max) -{ - /* - * Average the three corners & perturb it a bit. - * tmp is a random int +/- rough - */ - int tmp2 = rough * 2 + 1; - int tmp = randint(tmp2) - (rough + 1); - - int avg = ((x1 + x2 + x3) / 3) + tmp; - - /* Division always rounds down, so we round up again */ - if ((x1 + x2 + x3) % 3) avg++; - - /* Normalize */ - if (avg < 0) avg = 0; - if (avg > depth_max) avg = depth_max; - - /* Set the new value. */ - cave[ymid][xmid].feat = (byte)avg; -} - - -/* - * A generic function to generate the plasma fractal. - * Note that it uses ``cave_feat'' as temporary storage. - * The values in ``cave_feat'' after this function - * are NOT actual features; They are raw heights which - * need to be converted to features. - * - * So we shouldn't call cave_set_feat in the helper functions - * above. - */ -static void plasma_recursive(int x1, int y1, int x2, int y2, - int depth_max, int rough) -{ - /* Find middle */ - int xmid = (x2 - x1) / 2 + x1; - int ymid = (y2 - y1) / 2 + y1; - - /* Are we done? */ - if (x1 + 1 == x2) return; - - perturb_point_mid(cave[y1][x1].feat, cave[y2][x1].feat, cave[y1][x2].feat, - cave[y2][x2].feat, xmid, ymid, rough, depth_max); - - perturb_point_end(cave[y1][x1].feat, cave[y1][x2].feat, cave[ymid][xmid].feat, - xmid, y1, rough, depth_max); - - perturb_point_end(cave[y1][x2].feat, cave[y2][x2].feat, cave[ymid][xmid].feat, - x2, ymid, rough, depth_max); - - perturb_point_end(cave[y2][x2].feat, cave[y2][x1].feat, cave[ymid][xmid].feat, - xmid, y2, rough, depth_max); - - perturb_point_end(cave[y2][x1].feat, cave[y1][x1].feat, cave[ymid][xmid].feat, - x1, ymid, rough, depth_max); - - - /* Recurse the four quadrants */ - plasma_recursive(x1, y1, xmid, ymid, depth_max, rough); - plasma_recursive(xmid, y1, x2, ymid, depth_max, rough); - plasma_recursive(x1, ymid, xmid, y2, depth_max, rough); - plasma_recursive(xmid, ymid, x2, y2, depth_max, rough); -} - - -/* - * Load a town or generate a terrain level using "plasma" fractals. - * - * x and y are the coordinates of the area in the wilderness. - * Border and corner are optimization flags to speed up the - * generation of the fractal terrain. - * If border is set then only the border of the terrain should - * be generated (for initializing the border structure). - * If corner is set then only the corners of the area are needed. - * - * Return the number of floor grids - */ -int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh) -{ - int road, entrance; - int x1, y1; - int hack_floor = 0; - - /* Number of the town (if any) */ - p_ptr->town_num = wf_info[wild_map[y][x].feat].entrance; - if (!p_ptr->town_num) p_ptr->town_num = wild_map[y][x].entrance; - - { - int roughness = 1; /* The roughness of the level. */ - int terrain[3][3]; /* The terrain around the current area */ - int ym, xm, yp, xp; - - /* Place the player at the center */ - if (!p_ptr->oldpx) p_ptr->oldpx = MAX_WID / 2; - if (!p_ptr->oldpy) p_ptr->oldpy = MAX_HGT / 2; - - /* Initialize the terrain array */ - ym = ((y - 1) < 0) ? 0 : (y - 1); - xm = ((x - 1) < 0) ? 0 : (x - 1); - yp = ((y + 1) >= max_wild_y) ? (max_wild_y - 1) : (y + 1); - xp = ((x + 1) >= max_wild_x) ? (max_wild_x - 1) : (x + 1); - terrain[0][0] = wild_map[ym][xm].feat; - terrain[0][1] = wild_map[ym][x].feat; - terrain[0][2] = wild_map[ym][xp].feat; - terrain[1][0] = wild_map[y][xm].feat; - terrain[1][1] = wild_map[y][x].feat; - terrain[1][2] = wild_map[y][xp].feat; - terrain[2][0] = wild_map[yp][xm].feat; - terrain[2][1] = wild_map[yp][x].feat; - terrain[2][2] = wild_map[yp][xp].feat; - - /* Hack -- Use the "simple" RNG */ - Rand_quick = TRUE; - - /* Hack -- Induce consistant town layout */ - Rand_value = wild_map[y][x].seed; - - if (!corner) - { - /* Create level background */ - for (y1 = 0; y1 < MAX_HGT; y1++) - { - for (x1 = 0; x1 < MAX_WID; x1++) - { - cave_set_feat(y1, x1, MAX_WILD_TERRAIN / 2); - } - } - } - - /* - * Initialize the four corners - * ToDo: calculate the medium height of the adjacent - * terrains for every corner. - */ - cave_set_feat(1, 1, (byte)rand_int(MAX_WILD_TERRAIN)); - cave_set_feat(MAX_HGT - 2, 1, (byte)rand_int(MAX_WILD_TERRAIN)); - cave_set_feat(1, MAX_WID - 2, (byte)rand_int(MAX_WILD_TERRAIN)); - cave_set_feat(MAX_HGT - 2, MAX_WID - 2, (byte)rand_int(MAX_WILD_TERRAIN)); - - if (!corner) - { - /* x1, y1, x2, y2, num_depths, roughness */ - plasma_recursive(1, 1, MAX_WID - 2, MAX_HGT - 2, MAX_WILD_TERRAIN - 1, roughness); - } - - /* Use the complex RNG */ - Rand_quick = FALSE; - - for (y1 = 1; y1 < MAX_HGT - 1; y1++) - { - for (x1 = 1; x1 < MAX_WID - 1; x1++) - { - cave_set_feat(y1, x1, - wf_info[terrain[1][1]].terrain[cave[y1][x1].feat]); - } - } - - } - - /* Should we create a town ? */ - if ((p_ptr->town_num > 0) && (p_ptr->town_num < 1000)) - { - /* Create the town */ - int xstart = 0; - int ystart = 0; - - /* Initialize the town */ - init_flags = INIT_CREATE_DUNGEON; - process_dungeon_file("t_info.txt", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE); - } - else - { - /* Reset the town flag */ - p_ptr->town_num = 0; - } - - if (!corner) - { - /* - * Place roads in the wilderness - * ToDo: make the road a bit more interresting - */ - road = wf_info[wild_map[y][x].feat].road; - - if (road & ROAD_NORTH) - { - /* North road */ - for (y1 = 1; y1 < MAX_HGT / 2; y1++) - { - x1 = MAX_WID / 2; - cave_set_feat(y1, x1, FEAT_FLOOR); - } - } - - if (road & ROAD_SOUTH) - { - /* North road */ - for (y1 = MAX_HGT / 2; y1 < MAX_HGT - 1; y1++) - { - x1 = MAX_WID / 2; - cave_set_feat(y1, x1, FEAT_FLOOR); - } - } - - if (road & ROAD_EAST) - { - /* East road */ - for (x1 = MAX_WID / 2; x1 < MAX_WID - 1; x1++) - { - y1 = MAX_HGT / 2; - cave_set_feat(y1, x1, FEAT_FLOOR); - } - } - - if (road & ROAD_WEST) - { - /* West road */ - for (x1 = 1; x1 < MAX_WID / 2; x1++) - { - y1 = MAX_HGT / 2; - cave_set_feat(y1, x1, FEAT_FLOOR); - } - } - } - - /* Hack -- Use the "simple" RNG */ - Rand_quick = TRUE; - - /* Hack -- Induce consistant town layout */ - Rand_value = wild_map[y][x].seed; - - entrance = wf_info[wild_map[y][x].feat].entrance; - if (!entrance) entrance = wild_map[y][x].entrance; - - /* Create the dungeon if requested on the map */ - if (entrance >= 1000) - { - int dy, dx; - - dy = rand_range(6, cur_hgt - 6); - dx = rand_range(6, cur_wid - 6); - - cave_set_feat(dy, dx, FEAT_MORE); - cave[dy][dx].special = entrance - 1000; - cave[dy][dx].info |= (CAVE_GLOW | CAVE_MARK); - } - - /* Use the complex RNG */ - Rand_quick = FALSE; - - /* MEGA HACK -- set at least one floor grid */ - for (y1 = 1; y1 < cur_hgt - 1; y1++) - { - for (x1 = 1; x1 < cur_wid - 1; x1++) - { - if (cave_floor_bold(y1, x1)) hack_floor++; - } - } - - /* NO floor ? put one */ - if (!hack_floor) - { - cave_set_feat(cur_hgt / 2, cur_wid / 2, FEAT_GRASS); - cave[cur_hgt / 2][cur_wid / 2].special = 0; - hack_floor = 1; - } - - /* Set the monster generation level to the wilderness level */ - monster_level = wf_info[wild_map[y][x].feat].level; - - /* Set the object generation level to the wilderness level */ - object_level = wf_info[wild_map[y][x].feat].level; - - return hack_floor; -} - -/* - * Border of the wilderness area - */ -static border_type border; - -/* - * Build the wilderness area outside of the town. - * -KMW- - */ -void wilderness_gen(int refresh) -{ - int i, y, x, hack_floor; - bool_ daytime; - int xstart = 0; - int ystart = 0; - cave_type *c_ptr; - - /* Init the wilderness */ - process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE); - - x = p_ptr->wilderness_x; - y = p_ptr->wilderness_y; - - /* Set the correct monster hook */ - set_mon_num_hook(); - - /* Prepare allocation table */ - get_mon_num_prep(); - - /* North border */ - generate_area(y - 1, x, TRUE, FALSE, refresh); - - for (i = 1; i < MAX_WID - 1; i++) - { - border.north[i] = cave[MAX_HGT - 2][i].feat; - } - - /* South border */ - generate_area(y + 1, x, TRUE, FALSE, refresh); - - for (i = 1; i < MAX_WID - 1; i++) - { - border.south[i] = cave[1][i].feat; - } - - /* West border */ - generate_area(y, x - 1, TRUE, FALSE, refresh); - - for (i = 1; i < MAX_HGT - 1; i++) - { - border.west[i] = cave[i][MAX_WID - 2].feat; - } - - /* East border */ - generate_area(y, x + 1, TRUE, FALSE, refresh); - - for (i = 1; i < MAX_HGT - 1; i++) - { - border.east[i] = cave[i][1].feat; - } - - /* North west corner */ - generate_area(y - 1, x - 1, FALSE, TRUE, refresh); - border.north_west = cave[MAX_HGT - 2][MAX_WID - 2].feat; - - /* North east corner */ - generate_area(y - 1, x + 1, FALSE, TRUE, refresh); - border.north_east = cave[MAX_HGT - 2][1].feat; - - /* South west corner */ - generate_area(y + 1, x - 1, FALSE, TRUE, refresh); - border.south_west = cave[1][MAX_WID - 2].feat; - - /* South east corner */ - generate_area(y + 1, x + 1, FALSE, TRUE, refresh); - border.south_east = cave[1][1].feat; - - - /* Create terrain of the current area */ - hack_floor = generate_area(y, x, FALSE, FALSE, refresh); - - - /* Special boundary walls -- North */ - for (i = 0; i < MAX_WID; i++) - { - cave[0][i].mimic = border.north[i]; - cave_set_feat(0, i, FEAT_PERM_SOLID); - } - - /* Special boundary walls -- South */ - for (i = 0; i < MAX_WID; i++) - { - cave[MAX_HGT - 1][i].mimic = border.south[i]; - cave_set_feat(MAX_HGT - 1, i, FEAT_PERM_SOLID); - } - - /* Special boundary walls -- West */ - for (i = 0; i < MAX_HGT; i++) - { - cave[i][0].mimic = border.west[i]; - cave_set_feat(i, 0, FEAT_PERM_SOLID); - } - - /* Special boundary walls -- East */ - for (i = 0; i < MAX_HGT; i++) - { - cave[i][MAX_WID - 1].mimic = border.east[i]; - cave_set_feat(i, MAX_WID - 1, FEAT_PERM_SOLID); - } - - /* North west corner */ - cave[0][0].mimic = border.north_west; - - /* Make sure it has correct CAVE_WALL flag set */ - cave_set_feat(0, 0, cave[0][0].feat); - - /* North east corner */ - cave[0][MAX_WID - 1].mimic = border.north_east; - - /* Make sure it has correct CAVE_WALL flag set */ - cave_set_feat(0, MAX_WID - 1, cave[0][MAX_WID - 1].feat); - - /* South west corner */ - cave[MAX_HGT - 1][0].mimic = border.south_west; - - /* Make sure it has correct CAVE_WALL flag set */ - cave_set_feat(MAX_HGT - 1, 0, cave[MAX_HGT - 1][0].feat); - - /* South east corner */ - cave[MAX_HGT - 1][MAX_WID - 1].mimic = border.south_east; - - /* Make sure it has correct CAVE_WALL flag set */ - cave_set_feat(MAX_HGT - 1, MAX_WID - 1, cave[MAX_HGT - 1][MAX_WID - 1].feat); - - - /* Day time */ - if ((turn % (10L * DAY)) < ((10L * DAY) / 2)) - daytime = TRUE; - else - daytime = FALSE; - - /* Light up or darken the area */ - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - /* Get the cave grid */ - c_ptr = &cave[y][x]; - - if (daytime) - { - /* Assume lit */ - c_ptr->info |= (CAVE_GLOW); - - /* Hack -- Memorize lit grids if allowed */ - if (view_perma_grids) c_ptr->info |= (CAVE_MARK); - } - else - { - /* Darken "boring" features */ - if (!(f_info[c_ptr->feat].flags1 & FF1_REMEMBER)) - { - /* Forget the grid */ - c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK); - } - } - } - } - - player_place(p_ptr->oldpy, p_ptr->oldpx); - - if (!refresh) - { - int lim = (generate_encounter == TRUE) ? 60 : MIN_M_ALLOC_TN; - - /* - * Can't have more monsters than floor grids -1(for the player, - * not needed but safer - */ - if (lim > hack_floor - 1) lim = hack_floor - 1; - - /* Make some residents */ - for (i = 0; i < lim; i++) - { - /* Make a resident */ - (void)alloc_monster((generate_encounter == TRUE) ? 0 : 3, (generate_encounter == TRUE) ? FALSE : TRUE); - } - - if (generate_encounter) ambush_flag = TRUE; - generate_encounter = FALSE; - } - - /* Set rewarded quests to finished */ - for (i = 0; i < max_q_idx; i++) - { - if (quest[i].status == QUEST_STATUS_REWARDED) - quest[i].status = QUEST_STATUS_FINISHED; - } - - process_hooks(HOOK_WILD_GEN, "(d)", FALSE); -} - -/* - * Build the wilderness area. - * -DG- - */ -void wilderness_gen_small() -{ - int i, j, entrance; - int xstart = 0; - int ystart = 0; - - /* To prevent stupid things */ - for (i = 0; i < MAX_WID; i++) - { - for (j = 0; j < MAX_HGT; j++) - { - cave_set_feat(j, i, FEAT_EKKAIA); - } - } - - /* Init the wilderness */ - process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE); - - /* Fill the map */ - for (i = 0; i < max_wild_x; i++) - { - for (j = 0; j < max_wild_y; j++) - { - entrance = wf_info[wild_map[j][i].feat].entrance; - if (!entrance) entrance = wild_map[j][i].entrance; - - if (wild_map[j][i].entrance) - { - cave_set_feat(j, i, FEAT_MORE); - } - else - { - cave_set_feat(j, i, wf_info[wild_map[j][i].feat].feat); - } - - if ((cave[j][i].feat == FEAT_MORE) && (entrance >= 1000)) - { - cave[j][i].special = entrance - 1000; - } - - /* Show it if we know it */ - if (wild_map[j][i].known) - { - cave[j][i].info |= (CAVE_GLOW | CAVE_MARK); - } - } - } - - /* Place the player */ - p_ptr->px = p_ptr->wilderness_x; - p_ptr->py = p_ptr->wilderness_y; - - /* Set rewarded quests to finished */ - for (i = 0; i < max_q_idx; i++) - { - if (quest[i].status == QUEST_STATUS_REWARDED) - quest[i].status = QUEST_STATUS_FINISHED; - } - - process_hooks(HOOK_WILD_GEN, "(d)", TRUE); -} - -/* Show a small radius of wilderness around the player */ -void reveal_wilderness_around_player(int y, int x, int h, int w) -{ - int i, j; - - /* Circle or square ? */ - if (h == 0) - { - for (i = x - w; i < x + w; i++) - { - for (j = y - w; j < y + w; j++) - { - /* Bound checking */ - if (!in_bounds(j, i)) continue; - - /* Severe bound checking */ - if ((i < 0) || (i >= max_wild_x) || (j < 0) || (j >= max_wild_y)) continue; - - /* We want a radius, not a "squarus" :) */ - if (distance(y, x, j, i) >= w) continue; - - /* New we know here */ - wild_map[j][i].known = TRUE; - - /* Only if we are in overview */ - if (p_ptr->wild_mode) - { - cave[j][i].info |= (CAVE_GLOW | CAVE_MARK); - - /* Show it */ - lite_spot(j, i); - } - } - } - } - else - { - for (i = x; i < x + w; i++) - { - for (j = y; j < y + h; j++) - { - /* Bound checking */ - if (!in_bounds(j, i)) continue; - - /* New we know here */ - wild_map[j][i].known = TRUE; - - /* Only if we are in overview */ - if (p_ptr->wild_mode) - { - cave[j][i].info |= (CAVE_GLOW | CAVE_MARK); - - /* Show it */ - lite_spot(j, i); - } - } - } - } -} - -/* - * Builds a store at a given pseudo-location - * - * As of 2.8.1 (?) the town is actually centered in the middle of a - * complete level, and thus the top left corner of the town itself - * is no longer at (0,0), but rather, at (qy,qx), so the constants - * in the comments below should be mentally modified accordingly. - * - * As of 2.7.4 (?) the stores are placed in a more "user friendly" - * configuration, such that the four "center" buildings always - * have at least four grids between them, to allow easy running, - * and the store doors tend to face the middle of town. - * - * The stores now lie inside boxes from 3-9 and 12-18 vertically, - * and from 7-17, 21-31, 35-45, 49-59. Note that there are thus - * always at least 2 open grids between any disconnected walls. - * - * Note the use of "town_illuminate()" to handle all "illumination" - * and "memorization" issues. - */ -static void build_store(int qy, int qx, int n, int yy, int xx) -{ - int y, x, y0, x0, y1, x1, y2, x2, tmp; - - /* Find the "center" of the store */ - y0 = qy + yy * 9 + 6; - x0 = qx + xx * 14 + 12; - - /* Determine the store boundaries */ - y1 = y0 - randint((yy == 0) ? 3 : 2); - y2 = y0 + randint((yy == 1) ? 3 : 2); - x1 = x0 - randint(5); - x2 = x0 + randint(5); - - /* Build an invulnerable rectangular building */ - for (y = y1; y <= y2; y++) - { - for (x = x1; x <= x2; x++) - { - /* Create the building */ - cave_set_feat(y, x, FEAT_PERM_EXTRA); - } - } - - /* Pick a door direction (S,N,E,W) */ - tmp = rand_int(4); - - /* Re-roll "annoying" doors */ - if (((tmp == 0) && (yy == 1)) || - ((tmp == 1) && (yy == 0)) || - ((tmp == 2) && (xx == 3)) || - ((tmp == 3) && (xx == 0))) - { - /* Pick a new direction */ - tmp = rand_int(4); - } - - /* Extract a "door location" */ - switch (tmp) - { - /* Bottom side */ - case 0: - { - y = y2; - x = rand_range(x1, x2); - break; - } - - /* Top side */ - case 1: - { - y = y1; - x = rand_range(x1, x2); - break; - } - - /* Right side */ - case 2: - { - y = rand_range(y1, y2); - x = x2; - break; - } - - /* Left side */ - default: - { - y = rand_range(y1, y2); - x = x1; - break; - } - } - - /* Clear previous contents, add a store door */ - cave_set_feat(y, x, FEAT_SHOP); - cave[y][x].special = n; - cave[y][x].info |= CAVE_FREE; -} - -static void build_store_circle(int qy, int qx, int n, int yy, int xx) -{ - int tmp, y, x, y0, x0, rad = 2 + rand_int(2); - - /* Find the "center" of the store */ - y0 = qy + yy * 9 + 6; - x0 = qx + xx * 14 + 12; - - /* Determine the store boundaries */ - - /* Build an invulnerable circular building */ - for (y = y0 - rad; y <= y0 + rad; y++) - { - for (x = x0 - rad; x <= x0 + rad; x++) - { - if (distance(y0, x0, y, x) > rad) continue; - - /* Create the building */ - cave_set_feat(y, x, FEAT_PERM_EXTRA); - } - } - - /* Pick a door direction (S,N,E,W) */ - tmp = rand_int(4); - - /* Re-roll "annoying" doors */ - if (((tmp == 0) && (yy == 1)) || - ((tmp == 1) && (yy == 0)) || - ((tmp == 2) && (xx == 3)) || - ((tmp == 3) && (xx == 0))) - { - /* Pick a new direction */ - tmp = rand_int(4); - } - - /* Extract a "door location" */ - switch (tmp) - { - /* Bottom side */ - case 0: - { - for (y = y0; y <= y0 + rad; y++) cave_set_feat(y, x0, FEAT_FLOOR); - break; - } - - /* Top side */ - case 1: - { - for (y = y0 - rad; y <= y0; y++) cave_set_feat(y, x0, FEAT_FLOOR); - break; - } - - /* Right side */ - case 2: - { - for (x = x0; x <= x0 + rad; x++) cave_set_feat(y0, x, FEAT_FLOOR); - break; - } - - /* Left side */ - default: - { - for (x = x0 - rad; x <= x0; x++) cave_set_feat(y0, x, FEAT_FLOOR); - break; - } - } - - /* Clear previous contents, add a store door */ - cave_set_feat(y0, x0, FEAT_SHOP); - cave[y0][x0].special = n; - cave[y0][x0].info |= CAVE_FREE; -} - -static void build_store_hidden(int n, int yy, int xx) -{ - /* Clear previous contents, add a store door */ - cave_set_feat(yy, xx, FEAT_SHOP); - cave[yy][xx].special = n; - cave[yy][xx].info |= CAVE_FREE; -} - -/* Return a list of stores */ -static int get_shops(int *rooms) -{ - int i, n, num = 0; - - for (n = 0; n < max_st_idx; n++) - { - rooms[n] = 0; - } - - for (n = 0; n < max_st_idx; n++) - { - int chance = 50; - - if (st_info[n].flags1 & SF1_COMMON) chance += 30; - if (st_info[n].flags1 & SF1_RARE) chance -= 20; - if (st_info[n].flags1 & SF1_VERY_RARE) chance -= 30; - - if (!magik(chance)) continue; - - for (i = 0; i < num; ++i) - if (rooms[i] == n) - continue; - - if (st_info[n].flags1 & SF1_RANDOM) rooms[num++] = n; - } - - return num; -} - -/* Generate town borders */ -static void set_border(int y, int x) -{ - cave_type *c_ptr; - - /* Paranoia */ - if (!in_bounds(y, x)) return; - - /* Was a floor */ - if (cave_floor_bold(y, x) || - (f_info[cave[y][x].feat].flags1 & FF1_DOOR)) - { - cave_set_feat(y, x, FEAT_DOOR_HEAD); - } - - /* Was a wall */ - else - { - cave_set_feat(y, x, FEAT_PERM_SOLID); - - } - - /* Access grid */ - c_ptr = &cave[y][x]; - - /* Clear special attrs */ - c_ptr->mimic = 0; - c_ptr->special = 0; - c_ptr->info |= (CAVE_ROOM); -} - - -static void town_borders(int t_idx, int qy, int qx) -{ - int y, x; - - x = qx; - for (y = qy; y < qy + SCREEN_HGT - 1; y++) - { - set_border(y, x); - } - - x = qx + SCREEN_WID - 1; - for (y = qy; y < qy + SCREEN_HGT - 1; y++) - { - set_border(y, x); - } - - y = qy; - for (x = qx; x < qx + SCREEN_WID - 1; x++) - { - set_border(y, x); - } - - y = qy + SCREEN_HGT - 1; - for (x = qx; x < qx + SCREEN_WID; x++) - { - set_border(y, x); - } -} - -static bool_ create_townpeople_hook(int r_idx) -{ - monster_race *r_ptr = &r_info[r_idx]; - - if (r_ptr->d_char == 't') return TRUE; - else return FALSE; -} - - -/* - * Generate the "consistent" town features, and place the player - * - * Hack -- play with the R.N.G. to always yield the same town - * layout, including the size and shape of the buildings, the - * locations of the doorways, and the location of the stairs. - */ -static void town_gen_hack(int t_idx, int qy, int qx) -{ - int y, x, floor, num = 0; - bool_ (*old_get_mon_num_hook)(int r_idx); - - int *rooms; - - /* Do we use dungeon floor or normal one */ - if (magik(TOWN_NORMAL_FLOOR)) floor = FEAT_FLOOR; - else floor = 0; - - /* Place some floors */ - for (y = qy + 1; y < qy + SCREEN_HGT - 1; y++) - { - for (x = qx + 1; x < qx + SCREEN_WID - 1; x++) - { - /* Create empty floor */ - cave_set_feat(y, x, (floor) ? floor : floor_type[rand_int(100)]); - cave[y][x].info |= (CAVE_ROOM | CAVE_FREE); - } - } - - /* Prepare an Array of "remaining stores", and count them */ - C_MAKE(rooms, max_st_idx, int); - num = get_shops(rooms); - - /* Place two rows of stores */ - for (y = 0; y < 2; y++) - { - /* Place four stores per row */ - for (x = 0; x < 4; x++) - { - if(--num > -1) - { - /* Build that store at the proper location */ - build_store(qy, qx, rooms[num], y, x); - } - } - } - C_FREE(rooms, max_st_idx, int); - - /* Generates the town's borders */ - if (magik(TOWN_NORMAL_FLOOR)) town_borders(t_idx, qy, qx); - - - /* Some inhabitants(leveled .. hehe :) */ - - /* Backup the old hook */ - old_get_mon_num_hook = get_mon_num_hook; - - /* Require "okay" monsters */ - get_mon_num_hook = create_townpeople_hook; - - /* Prepare allocation table */ - get_mon_num_prep(); - - for (x = qx; x < qx + SCREEN_WID; x++) - for (y = qy; y < qy + SCREEN_HGT; y++) - { - int m_idx, r_idx; - - /* Only in town */ - if (!in_bounds(y, x)) continue; - if (!(cave[y][x].info & CAVE_FREE)) continue; - if (!cave_empty_bold(y, x)) continue; - - if (rand_int(100)) continue; - - r_idx = get_mon_num(0); - m_allow_special[r_idx] = TRUE; - m_idx = place_monster_one(y, x, r_idx, 0, TRUE, MSTATUS_ENEMY); - m_allow_special[r_idx] = FALSE; - - if (m_idx) - { - monster_type *m_ptr = &m_list[m_idx]; - if (m_ptr->level < (dun_level / 2)) - { - m_ptr->exp = MONSTER_EXP(m_ptr->level + (dun_level / 2) + randint(dun_level / 2)); - monster_check_experience(m_idx, TRUE); - } - } - } - - /* Reset restriction */ - get_mon_num_hook = old_get_mon_num_hook; - - /* Prepare allocation table */ - get_mon_num_prep(); -} - -static void town_gen_circle(int t_idx, int qy, int qx) -{ - int y, x, cy, cx, rad, floor, num = 0; - bool_ (*old_get_mon_num_hook)(int r_idx); - - int *rooms; - - /* Do we use dungeon floor or normal one */ - if (magik(TOWN_NORMAL_FLOOR)) floor = FEAT_FLOOR; - else floor = 0; - - rad = (SCREEN_HGT / 2); - - y = qy; - for (x = qx + rad; x < qx + SCREEN_WID - rad; x++) - { - set_border(y, x); - } - - y = qy + SCREEN_HGT - 1; - for (x = qx + rad; x < qx + SCREEN_WID - rad; x++) - { - set_border(y, x); - } - /* Place some floors */ - for (y = qy + 1; y < qy + SCREEN_HGT - 1; y++) - { - for (x = qx + rad; x < qx + SCREEN_WID - rad; x++) - { - /* Create empty floor */ - cave_set_feat(y, x, (floor) ? floor : floor_type[rand_int(100)]); - cave[y][x].info |= CAVE_ROOM | CAVE_FREE; - } - } - - cy = qy + (SCREEN_HGT / 2); - - cx = qx + rad; - for (y = cy - rad; y < cy + rad; y++) - for (x = cx - rad; x < cx + 1; x++) - { - int d = distance(cy, cx, y, x); - - if ((d == rad) || (d == rad - 1)) set_border(y, x); - - if (d < rad - 1) - { - cave_set_feat(y, x, (floor) ? floor : floor_type[rand_int(100)]); - cave[y][x].info |= CAVE_ROOM | CAVE_FREE; - } - } - - cx = qx + SCREEN_WID - rad - 1; - for (y = cy - rad; y < cy + rad; y++) - for (x = cx; x < cx + rad + 1; x++) - { - int d = distance(cy, cx, y, x); - - if ((d == rad) || (d == rad - 1)) set_border(y, x); - - if (d < rad - 1) - { - cave_set_feat(y, x, (floor) ? floor : floor_type[rand_int(100)]); - cave[y][x].info |= CAVE_ROOM | CAVE_FREE; - } - } - - /* Prepare an Array of "remaining stores", and count them */ - C_MAKE(rooms, max_st_idx, int); - num = get_shops(rooms); - - /* Place two rows of stores */ - for (y = 0; y < 2; y++) - { - /* Place four stores per row */ - for (x = 0; x < 4; x++) - { - if(--num > -1) - { - /* Build that store at the proper location */ - build_store_circle(qy, qx, rooms[num], y, x); - } - } - } - C_FREE(rooms, max_st_idx, int); - - /* Some inhabitants(leveled .. hehe :) */ - - /* Backup the old hook */ - old_get_mon_num_hook = get_mon_num_hook; - - /* Require "okay" monsters */ - get_mon_num_hook = create_townpeople_hook; - - /* Prepare allocation table */ - get_mon_num_prep(); - - for (x = qx; x < qx + SCREEN_WID; x++) - for (y = qy; y < qy + SCREEN_HGT; y++) - { - int m_idx, r_idx; - - /* Only in town */ - if (!in_bounds(y, x)) continue; - if (!(cave[y][x].info & CAVE_FREE)) continue; - if (!cave_empty_bold(y, x)) continue; - - if (rand_int(100)) continue; - - r_idx = get_mon_num(0); - m_allow_special[r_idx] = TRUE; - m_idx = place_monster_one(y, x, r_idx, 0, TRUE, MSTATUS_ENEMY); - m_allow_special[r_idx] = FALSE; - if (m_idx) - { - monster_type *m_ptr = &m_list[m_idx]; - if (m_ptr->level < (dun_level / 2)) - { - m_ptr->exp = MONSTER_EXP(m_ptr->level + (dun_level / 2) + randint(dun_level / 2)); - monster_check_experience(m_idx, TRUE); - } - } - } - - /* Reset restriction */ - get_mon_num_hook = old_get_mon_num_hook; - - /* Prepare allocation table */ - get_mon_num_prep(); -} - - -static void town_gen_hidden(int t_idx, int qy, int qx) -{ - int y, x, n, num = 0, i; - - int *rooms; - - /* Prepare an Array of "remaining stores", and count them */ - C_MAKE(rooms, max_st_idx, int); - num = get_shops(rooms); - - /* Get a number of stores to place */ - n = rand_int(num / 2) + (num / 2); - - /* Place k stores */ - for (i = 0; i < n; i++) - { - /* Find a good spot */ - while (TRUE) - { - y = rand_range(1, cur_hgt - 2); - x = rand_range(1, cur_wid - 2); - - if (cave_empty_bold(y, x)) break; - } - - if(--num > -1) - { - /* Build that store at the proper location */ - build_store_hidden(rooms[num], y, x); - } - } - C_FREE(rooms, max_st_idx, int); -} - - - -/* - * Town logic flow for generation of new town - * - * We start with a fully wiped cave of normal floors. - * - * Note that town_gen_hack() plays games with the R.N.G. - * - * This function does NOT do anything about the owners of the stores, - * nor the contents thereof. It only handles the physical layout. - * - * We place the player on the stairs at the same time we make them. - * - * Hack -- since the player always leaves the dungeon by the stairs, - * he is always placed on the stairs, even if he left the dungeon via - * word of recall or teleport level. - */ -void town_gen(int t_idx) -{ - int qy, qx; - - /* Level too small to contain a town */ - if (cur_hgt < SCREEN_HGT) return; - if (cur_wid < SCREEN_WID) return; - - /* Center fo the level */ - qy = (cur_hgt - SCREEN_HGT) / 2; - qx = (cur_wid - SCREEN_WID) / 2; - - /* Build stuff */ - switch (rand_int(3)) - { - case 0: - { - town_gen_hack(t_idx, qy, qx); - if (wizard) - { - msg_format("Town level(normal) (%d, seed %d)", - t_idx, town_info[t_idx].seed); - } - break; - } - - case 1: - { - town_gen_circle(t_idx, qy, qx); - if (wizard) - { - msg_format("Town level(circle)(%d, seed %d)", - t_idx, town_info[t_idx].seed); - } - break; - } - - case 2: - { - town_gen_hidden(t_idx, qy, qx); - if (wizard) - { - msg_format("Town level(hidden)(%d, seed %d)", - t_idx, town_info[t_idx].seed); - } - break; - } - } - - p_ptr->town_num = t_idx; -} |