Freeciv-3.3
Loading...
Searching...
No Matches
height_map.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2007 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17/* utility */
18#include "rand.h"
19
20/* common */
21#include "map.h"
22
23/* server/generator */
24#include "mapgen_topology.h"
25#include "mapgen_utils.h"
26
27#include "height_map.h"
28
29int *height_map = nullptr;
31
32/**********************************************************************/
35static float hmap_pole_factor(struct tile *ptile)
36{
37 float factor = 1.0;
38
39 if (near_singularity(ptile)) {
40 /* Map edge near pole: clamp to what linear ramp would give us at pole
41 * (maybe greater than 0) */
42 factor = (100 - wld.map.server.flatpoles) / 100.0;
43 } else if (wld.map.server.flatpoles > 0) {
44 /* Linear ramp down from 100% at 2.5*ICE_BASE_LEVEL to (100-flatpoles) %
45 * at the poles */
46 factor = 1 - ((1 - (map_colatitude(ptile) / (2.5 * ICE_BASE_LEVEL)))
47 * wld.map.server.flatpoles / 100);
48 }
50 && map_colatitude(ptile) >= 2 * ICE_BASE_LEVEL) {
51 /* A band of low height to try to separate the pole (this function is
52 * only assumed to be called <= 2.5*ICE_BASE_LEVEL) */
53 factor = MIN(factor, 0.1);
54 }
55
56 return factor;
57}
58
59/**********************************************************************/
66{
67 whole_map_iterate(&(wld.map), ptile) {
68 if (map_colatitude(ptile) <= 2.5 * ICE_BASE_LEVEL) {
69 hmap(ptile) *= hmap_pole_factor(ptile);
70 } else if (near_singularity(ptile)) {
71 /* Near map edge but not near pole. */
72 hmap(ptile) = 0;
73 }
75}
76
77/**********************************************************************/
82{
83 whole_map_iterate(&(wld.map), ptile) {
84 if (hmap(ptile) == 0) {
85 /* Nothing left to restore. */
86 } else if (map_colatitude(ptile) <= 2.5 * ICE_BASE_LEVEL) {
87 float factor = hmap_pole_factor(ptile);
88
89 if (factor > 0) {
90 /* Invert the previously applied function */
91 hmap(ptile) /= factor;
92 }
93 }
95}
96
97/**********************************************************************/
102{
103 int i = 0;
105
107
108 for (; i < smooth; i++) {
110 }
111
113}
114
115/**********************************************************************/
120static void gen5rec(int step, int xl, int yt, int xr, int yb)
121{
122 int val[2][2];
123 int x1wrap = xr; /* To wrap correctly */
124 int y1wrap = yb;
125
126 /* All x and y values are native. */
127
128 if (((yb - yt <= 0) || (xr - xl <= 0))
129 || ((yb - yt == 1) && (xr - xl == 1))) {
130 return;
131 }
132
133 if (xr == MAP_NATIVE_WIDTH) {
134 x1wrap = 0;
135 }
136 if (yb == MAP_NATIVE_HEIGHT) {
137 y1wrap = 0;
138 }
139
140 val[0][0] = hmap(native_pos_to_tile(&(wld.map), xl, yt));
141 val[0][1] = hmap(native_pos_to_tile(&(wld.map), xl, y1wrap));
142 val[1][0] = hmap(native_pos_to_tile(&(wld.map), x1wrap, yt));
143 val[1][1] = hmap(native_pos_to_tile(&(wld.map), x1wrap, y1wrap));
144
145 /* Set midpoints of sides to avg of side's vertices plus a random factor.
146 * Unset points are zero, don't reset if set */
147#define set_midpoints(X, Y, V) \
148 { \
149 struct tile *ptile = native_pos_to_tile(&(wld.map), (X), (Y)); \
150 if (map_colatitude(ptile) <= ICE_BASE_LEVEL / 2) { \
151 /* Possibly flatten poles, or possibly not (even at map edge) */ \
152 hmap(ptile) = (V) * (100 - wld.map.server.flatpoles) / 100; \
153 } else if (near_singularity(ptile) \
154 || hmap(ptile) != 0) { \
155 /* Do nothing */ \
156 } else { \
157 hmap(ptile) = (V); \
158 } \
159 }
160
161 set_midpoints((xl + xr) / 2, yt,
162 (val[0][0] + val[1][0]) / 2 + (int)fc_rand(step) - step / 2);
163 set_midpoints((xl + xr) / 2, y1wrap,
164 (val[0][1] + val[1][1]) / 2 + (int)fc_rand(step) - step / 2);
165 set_midpoints(xl, (yt + yb)/2,
166 (val[0][0] + val[0][1]) / 2 + (int)fc_rand(step) - step / 2);
167 set_midpoints(x1wrap, (yt + yb) / 2,
168 (val[1][0] + val[1][1]) / 2 + (int)fc_rand(step) - step / 2);
169
170 /* Set middle to average of midpoints plus a random factor, if not set */
171 set_midpoints((xl + xr) / 2, (yt + yb) / 2,
172 ((val[0][0] + val[0][1] + val[1][0] + val[1][1]) / 4
173 + (int)fc_rand(step) - step / 2));
174
175#undef set_midpoints
176
177 /* Now call recursively on the four subrectangles */
178 gen5rec(2 * step / 3, xl, yt, (xr + xl) / 2, (yb + yt) / 2);
179 gen5rec(2 * step / 3, xl, (yb + yt) / 2, (xr + xl) / 2, yb);
180 gen5rec(2 * step / 3, (xr + xl) / 2, yt, xr, (yb + yt) / 2);
181 gen5rec(2 * step / 3, (xr + xl) / 2, (yb + yt) / 2, xr, yb);
182}
183
184/**********************************************************************/
199{
200 const bool xnowrap = !current_wrap_has_flag(WRAP_X);
201 const bool ynowrap = !current_wrap_has_flag(WRAP_Y);
202
203 /*
204 * How many blocks should the x and y directions be divided into
205 * initially.
206 */
207 const int xdiv = 5 + extra_div;
208 const int ydiv = 5 + extra_div;
209
210 int xdiv2 = xdiv + (xnowrap ? 1 : 0);
211 int ydiv2 = ydiv + (ynowrap ? 1 : 0);
212
213 int xmax = MAP_NATIVE_WIDTH - (xnowrap ? 1 : 0);
214 int ymax = MAP_NATIVE_HEIGHT - (ynowrap ? 1 : 0);
215 int x_current, y_current;
216 /* Just need something > log(max(xsize, ysize)) for the recursion */
218 /* Edges are avoided more strongly as this increases */
219 int avoidedge = (100 - wld.map.server.landpercent) * step / 100 + step / 3;
220
222
223 /* Initialize map */
225
226 /* Set initial points */
227 for (x_current = 0; x_current < xdiv2; x_current++) {
228 for (y_current = 0; y_current < ydiv2; y_current++) {
229 do_in_map_pos(&(wld.map), ptile,
230 (x_current * xmax / xdiv), (y_current * ymax / ydiv)) {
231 /* Set initial points */
232 hmap(ptile) = fc_rand(2 * step) - (2 * step) / 2;
233
234 if (near_singularity(ptile)) {
235 /* Avoid edges (topological singularities) */
236 hmap(ptile) -= avoidedge;
237 }
238
239 if (map_colatitude(ptile) <= ICE_BASE_LEVEL / 2 ) {
240 /* Separate poles and avoid too much land at poles */
241 hmap(ptile) -= fc_rand(avoidedge * wld.map.server.flatpoles / 100);
242 }
244 }
245 }
246
247 /* Calculate recursively on each block */
248 for (x_current = 0; x_current < xdiv; x_current++) {
249 for (y_current = 0; y_current < ydiv; y_current++) {
251 (x_current + 1) * xmax / xdiv, (y_current + 1) * ymax / ydiv);
252 }
253 }
254
255 /* Put in some random fuzz */
256 whole_map_iterate(&(wld.map), ptile) {
257 hmap(ptile) = 8 * hmap(ptile) + fc_rand(4) - 2;
259
261}
262
263/**********************************************************************/
271bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
272{
273 int higher_than_me = 0;
274
275 square_iterate(&(wld.map), ptile, 2, tile1) {
276 if (hmap(tile1) > thill) {
277 return FALSE;
278 }
279 if (hmap(tile1) > my_height) {
280 if (map_distance(ptile, tile1) == 1) {
281 return FALSE;
282 }
283 if (++higher_than_me > 2) {
284 return FALSE;
285 }
286 }
288
290 > (my_height - hmap_shore_level) * 4) {
291 return FALSE;
292 }
293
294 return TRUE;
295}
296
297/**********************************************************************/
301{
302 whole_map_iterate(&(wld.map), ptile) {
303 ptile->altitude = hmap(ptile);
305
307}
char * incite_cost
Definition comments.c:76
struct world wld
Definition game.c:62
static void gen5rec(int step, int xl, int yt, int xr, int yb)
Definition height_map.c:120
void renormalize_hmap_poles(void)
Definition height_map.c:81
int hmap_mountain_level
Definition height_map.c:30
void height_map_to_map(void)
Definition height_map.c:300
static float hmap_pole_factor(struct tile *ptile)
Definition height_map.c:35
void normalize_hmap_poles(void)
Definition height_map.c:65
int hmap_shore_level
Definition height_map.c:30
#define set_midpoints(X, Y, V)
bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
Definition height_map.c:271
void make_pseudofractal1_hmap(int extra_div)
Definition height_map.c:198
void make_random_hmap(int smooth)
Definition height_map.c:101
int * height_map
Definition height_map.c:29
#define hmap_max_level
Definition height_map.h:33
#define hmap(_tile)
Definition height_map.h:17
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:458
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:699
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:388
#define square_iterate_end
Definition map.h:391
#define whole_map_iterate(_map, _tile)
Definition map.h:573
#define current_wrap_has_flag(flag)
Definition map.h:46
#define whole_map_iterate_end
Definition map.h:582
int map_colatitude(const struct tile *ptile)
bool near_singularity(const struct tile *ptile)
#define ICE_BASE_LEVEL
void smooth_int_map(int *int_map, bool zeroes_at_edges)
#define do_in_map_pos_end
#define do_in_map_pos(nmap, ptile, nat_x, nat_y)
#define adjust_int_map(int_map, int_map_min, int_map_max)
#define fc_malloc(sz)
Definition mem.h:34
#define fc_rand(_size)
Definition rand.h:56
#define INITIALIZE_ARRAY(array, size, value)
Definition shared.h:101
#define MIN(x, y)
Definition shared.h:55
int step
Definition specpq.h:92
bool altitude_info
Definition map_types.h:74
int landpercent
Definition map_types.h:110
struct civ_map::@44::@46 server
int flatpoles
Definition map_types.h:115
bool separatepoles
Definition map_types.h:114
Definition tile.h:50
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define MAP_NATIVE_WIDTH
#define MAP_INDEX_SIZE
#define MAP_NATIVE_HEIGHT