diff options
author | Darshan Shaligram <dshaligram@users.sourceforge.net> | 2010-01-13 21:39:16 +0530 |
---|---|---|
committer | Darshan Shaligram <dshaligram@users.sourceforge.net> | 2010-01-13 23:18:45 +0530 |
commit | 9a308a7dd9f9abb274e2024d41239c587dd7eb77 (patch) | |
tree | ec2df2835be41a08547a2e0fd3956f3efaba34c1 /crawl-ref/source/dgn-height.cc | |
parent | cf4b73981be2f79f2bddf38109b8e2662f3a36a0 (diff) | |
download | crawl-ref-9a308a7dd9f9abb274e2024d41239c587dd7eb77.tar.gz crawl-ref-9a308a7dd9f9abb274e2024d41239c587dd7eb77.zip |
Move island-building code from dgn-shoals.cc->dgn-height.cc.
Diffstat (limited to 'crawl-ref/source/dgn-height.cc')
-rw-r--r-- | crawl-ref/source/dgn-height.cc | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/crawl-ref/source/dgn-height.cc b/crawl-ref/source/dgn-height.cc new file mode 100644 index 0000000000..8a52736fb5 --- /dev/null +++ b/crawl-ref/source/dgn-height.cc @@ -0,0 +1,171 @@ +/* + * File: dgn-height.cc + * Summary: Dungeon heightmap routines. + */ + +#include "AppHdr.h" + +#include "coord.h" +#include "coordit.h" +#include "dgn-height.h" +#include "dungeon.h" +#include "random.h" + +const int SHOALS_ISLAND_COLLIDE_DIST2 = 5 * 5; + +void dgn_initialise_heightmap(int height) +{ + env.heightmap.reset(new grid_heightmap); + for (rectangle_iterator ri(0); ri; ++ri) + dgn_height_at(*ri) = height; +} + +int resolve_range(int_range range, int nrolls) +{ + return random_range(range.first, range.second, nrolls); +} + +void dgn_island_centred_at(const coord_def &c, + int n_points, + int radius, + int_range height_delta_range, + int border_margin, + bool make_atoll) +{ + for (int i = 0; i < n_points; ++i) { + const int thisrad = make_atoll? radius : random2(1 + radius); + const coord_def p = dgn_random_point_from(c, thisrad, border_margin); + if (!p.origin()) + dgn_height_at(p) += resolve_range(height_delta_range); + } +} + +void dgn_smooth_height_at(coord_def c, int radius, int max_height) +{ + const int height = dgn_height_at(c); + if (max_height != DGN_UNDEFINED_HEIGHT && height > max_height) + return; + + const int max_delta = radius * radius * 2 + 2; + int divisor = 0; + int total = 0; + for (int y = c.y - radius; y <= c.y + radius; ++y) { + for (int x = c.x - radius; x <= c.x + radius; ++x) { + const coord_def p(x, y); + if (!in_bounds(p)) + continue; + const int nheight = dgn_height_at(p); + if (max_height != DGN_UNDEFINED_HEIGHT && nheight > max_height) + continue; + const coord_def off = c - p; + const int weight = max_delta - off.abs(); + divisor += weight; + total += nheight * weight; + } + } + dgn_height_at(c) = total / divisor; +} + +void dgn_smooth_heights(int radius, int npasses) +{ + for (int i = 0; i < npasses; ++i) + { + for (rectangle_iterator ri(0); ri; ++ri) + dgn_smooth_height_at(*ri, radius); + } +} + +////////////////////////////////////////////////////////////////////// +// dgn_island_plan + +dgn_island_plan dgn_island_plan::shoals_islands(int margin) +{ + dgn_island_plan plan; + plan.level_border_depth = margin; + plan.n_aux_centres = int_range(0, 3); + plan.aux_centre_offset_range = int_range(2, 10); + + plan.atoll_roll = 10; + plan.island_separation_dist2 = SHOALS_ISLAND_COLLIDE_DIST2; + + plan.n_island_centre_delta_points = int_range(50, 60); + plan.island_centre_radius_range = int_range(3, 10); + plan.island_centre_point_height_increment = int_range(40, 60); + + plan.n_island_aux_delta_points = int_range(25, 45); + plan.island_aux_radius_range = int_range(2, 7); + plan.island_aux_point_height_increment = int_range(25, 35); + + return (plan); +} + +void dgn_island_plan::build(int nislands) +{ + for (int i = 0; i < nislands; ++i) + build_island(); +} + +coord_def dgn_island_plan::pick_island_spot() +{ + coord_def c; + // Try to find a spot that's not too close to other islands; this + // is not a guarantee, though. + for (int i = 0; i < 15; ++i) + { + // Primary island centres should have a little clearance + // around them, so use 2x the actual margin. + c = dgn_random_point_in_margin(level_border_depth * 2); + + bool collides = false; + for (int j = 0, size = islands.size(); j < size; ++j) + { + const coord_def island = islands[j]; + const coord_def dist = island - c; + if (dist.abs() < island_separation_dist2) + { + collides = true; + break; + } + } + if (!collides) + break; + } + islands.push_back(c); + return c; +} + +void dgn_island_plan::build_island() +{ + const coord_def c = pick_island_spot(); + dgn_island_centred_at(c, resolve_range(n_island_centre_delta_points), + resolve_range(island_centre_radius_range), + island_centre_point_height_increment, + level_border_depth, + x_chance_in_y(atoll_roll, 100)); + + const int additional_heights = resolve_range(n_aux_centres); + for (int i = 0; i < additional_heights; ++i) { + const int addition_offset = resolve_range(aux_centre_offset_range); + + const coord_def offsetC = + dgn_random_point_from(c, addition_offset, level_border_depth); + if (!offsetC.origin()) + dgn_island_centred_at( + offsetC, resolve_range(n_island_aux_delta_points), + resolve_range(island_aux_radius_range), + island_aux_point_height_increment, + level_border_depth, + x_chance_in_y(atoll_roll, 100)); + } +} + +coord_def dgn_island_plan::pick_and_remove_random_island() +{ + if (islands.empty()) + return coord_def(0, 0); + + const int lucky_island = random2(islands.size()); + const coord_def c = islands[lucky_island]; + islands.erase(islands.begin() + lucky_island); + return c; +} |