Apply the new ground_level method.
[crawl.git] / crawl-ref / source / dgn-height.cc
blob74d8cba4d9a81848fa0bcc8ae0e432e79cb6b1ae
1 /*
2 * File: dgn-height.cc
3 * Summary: Dungeon heightmap routines.
4 */
6 #include "AppHdr.h"
8 #include "coord.h"
9 #include "coordit.h"
10 #include "dgn-height.h"
11 #include "dungeon.h"
12 #include "random.h"
14 void dgn_initialise_heightmap(int height)
16 env.heightmap.reset(new grid_heightmap);
17 for (rectangle_iterator ri(0); ri; ++ri)
18 dgn_height_at(*ri) = height;
21 int resolve_range(int_range range, int nrolls)
23 return random_range(range.first, range.second, nrolls);
26 void dgn_island_centred_at(const coord_def &c,
27 int n_points,
28 int radius,
29 int_range height_delta_range,
30 int border_margin,
31 bool make_atoll)
33 if (make_atoll)
35 dgn_island_centred_at(c, n_points, radius,
36 int_range(-height_delta_range.second,
37 -height_delta_range.first),
38 border_margin,
39 false);
40 radius += 3;
42 for (int i = 0; i < n_points; ++i)
44 const int thisrad = random2(1 + radius);
45 const coord_def p = dgn_random_point_from(c, thisrad, border_margin);
46 if (!p.origin())
47 dgn_height_at(p) += resolve_range(height_delta_range);
51 void dgn_smooth_height_at(coord_def c, int radius, int max_height)
53 const int height = dgn_height_at(c);
54 if (max_height != DGN_UNDEFINED_HEIGHT && height > max_height)
55 return;
57 const int max_delta = radius * radius * 2 + 2;
58 int divisor = 0;
59 int total = 0;
60 for (int y = c.y - radius; y <= c.y + radius; ++y)
62 for (int x = c.x - radius; x <= c.x + radius; ++x)
64 const coord_def p(x, y);
65 if (!in_bounds(p))
66 continue;
67 const int nheight = dgn_height_at(p);
68 if (max_height != DGN_UNDEFINED_HEIGHT && nheight > max_height)
69 continue;
70 const coord_def off = c - p;
71 const int weight = max_delta - off.abs();
72 divisor += weight;
73 total += nheight * weight;
76 dgn_height_at(c) = total / divisor;
79 void dgn_smooth_heights(int radius, int npasses)
81 for (int i = 0; i < npasses; ++i)
83 const int xspan = GXM / 2, yspan = GYM / 2;
84 for (int y = yspan - 1; y >= 0; --y)
85 for (int x = xspan - 1; x >= 0; --x)
87 dgn_smooth_height_at(coord_def(x, y), radius);
88 dgn_smooth_height_at(coord_def(2 * xspan - x - 1, y), radius);
89 dgn_smooth_height_at(coord_def(x, 2 * yspan - y - 1), radius);
90 dgn_smooth_height_at(coord_def(2 * xspan - x - 1,
91 2 * yspan - y - 1),
92 radius);
97 //////////////////////////////////////////////////////////////////////
98 // dgn_island_plan
100 void dgn_island_plan::build(int nislands)
102 for (int i = 0; i < nislands; ++i)
103 build_island();
106 coord_def dgn_island_plan::pick_island_spot()
108 coord_def c;
109 // Try to find a spot that's not too close to other islands; this
110 // is not a guarantee, though.
111 for (int i = 0; i < 15; ++i)
113 // Primary island centres should have a little clearance
114 // around them, so use 2x the actual margin.
115 c = dgn_random_point_in_margin(level_border_depth * 2);
117 bool collides = false;
118 for (int j = 0, size = islands.size(); j < size; ++j)
120 const coord_def island = islands[j];
121 const coord_def dist = island - c;
122 if (dist.abs() < island_separation_dist2)
124 collides = true;
125 break;
128 if (!collides)
129 break;
131 islands.push_back(c);
132 return c;
135 void dgn_island_plan::build_island()
137 const coord_def c = pick_island_spot();
138 dgn_island_centred_at(c, resolve_range(n_island_centre_delta_points),
139 resolve_range(island_centre_radius_range),
140 island_centre_point_height_increment,
141 level_border_depth,
142 x_chance_in_y(atoll_roll, 100));
144 const int additional_heights = resolve_range(n_aux_centres);
145 for (int i = 0; i < additional_heights; ++i)
147 const int addition_offset = resolve_range(aux_centre_offset_range);
149 const coord_def offsetC =
150 dgn_random_point_from(c, addition_offset, level_border_depth);
151 if (!offsetC.origin())
152 dgn_island_centred_at(
153 offsetC, resolve_range(n_island_aux_delta_points),
154 resolve_range(island_aux_radius_range),
155 island_aux_point_height_increment,
156 level_border_depth,
157 x_chance_in_y(atoll_roll, 100));
161 coord_def dgn_island_plan::pick_and_remove_random_island()
163 if (islands.empty())
164 return coord_def(0, 0);
166 const int lucky_island = random2(islands.size());
167 const coord_def c = islands[lucky_island];
168 islands.erase(islands.begin() + lucky_island);
169 return c;