summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dgn-height.cc
diff options
context:
space:
mode:
authorDarshan Shaligram <dshaligram@users.sourceforge.net>2010-01-13 21:39:16 +0530
committerDarshan Shaligram <dshaligram@users.sourceforge.net>2010-01-13 23:18:45 +0530
commit9a308a7dd9f9abb274e2024d41239c587dd7eb77 (patch)
treeec2df2835be41a08547a2e0fd3956f3efaba34c1 /crawl-ref/source/dgn-height.cc
parentcf4b73981be2f79f2bddf38109b8e2662f3a36a0 (diff)
downloadcrawl-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.cc171
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;
+}