Freeciv-3.2
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
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 return factor;
56}
57
58/**********************************************************************/
65{
66 whole_map_iterate(&(wld.map), ptile) {
67 if (map_colatitude(ptile) <= 2.5 * ICE_BASE_LEVEL) {
68 hmap(ptile) *= hmap_pole_factor(ptile);
69 } else if (near_singularity(ptile)) {
70 /* Near map edge but not near pole. */
71 hmap(ptile) = 0;
72 }
74}
75
76/**********************************************************************/
81{
82 whole_map_iterate(&(wld.map), ptile) {
83 if (hmap(ptile) == 0) {
84 /* Nothing left to restore. */
85 } else if (map_colatitude(ptile) <= 2.5 * ICE_BASE_LEVEL) {
86 float factor = hmap_pole_factor(ptile);
87
88 if (factor > 0) {
89 /* Invert the previously applied function */
90 hmap(ptile) /= factor;
91 }
92 }
94}
95
96/**********************************************************************/
101{
102 int i = 0;
104
106
107 for (; i < smooth; i++) {
109 }
110
112}
113
114/**********************************************************************/
119static void gen5rec(int step, int xl, int yt, int xr, int yb)
120{
121 int val[2][2];
122 int x1wrap = xr; /* to wrap correctly */
123 int y1wrap = yb;
124
125 /* All x and y values are native. */
126
127 if (((yb - yt <= 0) || (xr - xl <= 0))
128 || ((yb - yt == 1) && (xr - xl == 1))) {
129 return;
130 }
131
132 if (xr == wld.map.xsize) {
133 x1wrap = 0;
134 }
135 if (yb == wld.map.ysize) {
136 y1wrap = 0;
137 }
138
139 val[0][0] = hmap(native_pos_to_tile(&(wld.map), xl, yt));
140 val[0][1] = hmap(native_pos_to_tile(&(wld.map), xl, y1wrap));
141 val[1][0] = hmap(native_pos_to_tile(&(wld.map), x1wrap, yt));
142 val[1][1] = hmap(native_pos_to_tile(&(wld.map), x1wrap, y1wrap));
143
144 /* set midpoints of sides to avg of side's vertices plus a random factor */
145 /* unset points are zero, don't reset if set */
146#define set_midpoints(X, Y, V) \
147 { \
148 struct tile *ptile = native_pos_to_tile(&(wld.map), (X), (Y)); \
149 if (map_colatitude(ptile) <= ICE_BASE_LEVEL / 2) { \
150 /* possibly flatten poles, or possibly not (even at map edge) */ \
151 hmap(ptile) = (V) * (100 - wld.map.server.flatpoles) / 100; \
152 } else if (near_singularity(ptile) \
153 || hmap(ptile) != 0) { \
154 /* do nothing */ \
155 } else { \
156 hmap(ptile) = (V); \
157 } \
158 }
159
160 set_midpoints((xl + xr) / 2, yt,
161 (val[0][0] + val[1][0]) / 2 + (int)fc_rand(step) - step / 2);
162 set_midpoints((xl + xr) / 2, y1wrap,
163 (val[0][1] + val[1][1]) / 2 + (int)fc_rand(step) - step / 2);
164 set_midpoints(xl, (yt + yb)/2,
165 (val[0][0] + val[0][1]) / 2 + (int)fc_rand(step) - step / 2);
166 set_midpoints(x1wrap, (yt + yb) / 2,
167 (val[1][0] + val[1][1]) / 2 + (int)fc_rand(step) - step / 2);
168
169 /* set middle to average of midpoints plus a random factor, if not set */
170 set_midpoints((xl + xr) / 2, (yt + yb) / 2,
171 ((val[0][0] + val[0][1] + val[1][0] + val[1][1]) / 4
172 + (int)fc_rand(step) - step / 2));
173
174#undef set_midpoints
175
176 /* now call recursively on the four subrectangles */
177 gen5rec(2 * step / 3, xl, yt, (xr + xl) / 2, (yb + yt) / 2);
178 gen5rec(2 * step / 3, xl, (yb + yt) / 2, (xr + xl) / 2, yb);
179 gen5rec(2 * step / 3, (xr + xl) / 2, yt, xr, (yb + yt) / 2);
180 gen5rec(2 * step / 3, (xr + xl) / 2, (yb + yt) / 2, xr, yb);
181}
182
183/**********************************************************************/
198{
199 const bool xnowrap = !current_wrap_has_flag(WRAP_X);
200 const bool ynowrap = !current_wrap_has_flag(WRAP_Y);
201
202 /*
203 * How many blocks should the x and y directions be divided into
204 * initially.
205 */
206 const int xdiv = 5 + extra_div;
207 const int ydiv = 5 + extra_div;
208
209 int xdiv2 = xdiv + (xnowrap ? 1 : 0);
210 int ydiv2 = ydiv + (ynowrap ? 1 : 0);
211
212 int xmax = wld.map.xsize - (xnowrap ? 1 : 0);
213 int ymax = wld.map.ysize - (ynowrap ? 1 : 0);
214 int x_current, y_current;
215 /* just need something > log(max(xsize, ysize)) for the recursion */
216 int step = wld.map.xsize + wld.map.ysize;
217 /* edges are avoided more strongly as this increases */
218 int avoidedge = (100 - wld.map.server.landpercent) * step / 100 + step / 3;
219
221
222 /* initialize map */
224
225 /* set initial points */
226 for (x_current = 0; x_current < xdiv2; x_current++) {
227 for (y_current = 0; y_current < ydiv2; y_current++) {
228 do_in_map_pos(&(wld.map), ptile,
229 (x_current * xmax / xdiv), (y_current * ymax / ydiv)) {
230 /* set initial points */
231 hmap(ptile) = fc_rand(2 * step) - (2 * step) / 2;
232
233 if (near_singularity(ptile)) {
234 /* avoid edges (topological singularities) */
235 hmap(ptile) -= avoidedge;
236 }
237
238 if (map_colatitude(ptile) <= ICE_BASE_LEVEL / 2 ) {
239 /* separate poles and avoid too much land at poles */
240 hmap(ptile) -= fc_rand(avoidedge * wld.map.server.flatpoles / 100);
241 }
243 }
244 }
245
246 /* calculate recursively on each block */
247 for (x_current = 0; x_current < xdiv; x_current++) {
248 for (y_current = 0; y_current < ydiv; y_current++) {
250 (x_current + 1) * xmax / xdiv, (y_current + 1) * ymax / ydiv);
251 }
252 }
253
254 /* put in some random fuzz */
255 whole_map_iterate(&(wld.map), ptile) {
256 hmap(ptile) = 8 * hmap(ptile) + fc_rand(4) - 2;
258
260}
261
262/**********************************************************************/
269bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
270{
271 int higher_than_me = 0;
272
273 square_iterate(&(wld.map), ptile, 2, tile1) {
274 if (hmap(tile1) > thill) {
275 return FALSE;
276 }
277 if (hmap(tile1) > my_height) {
278 if (map_distance(ptile, tile1) == 1) {
279 return FALSE;
280 }
281 if (++higher_than_me > 2) {
282 return FALSE;
283 }
284 }
286
288 > (my_height - hmap_shore_level) * 4) {
289 return FALSE;
290 }
291
292 return TRUE;
293}
char * incite_cost
Definition comments.c:75
struct world wld
Definition game.c:63
static void gen5rec(int step, int xl, int yt, int xr, int yb)
Definition height_map.c:119
void renormalize_hmap_poles(void)
Definition height_map.c:80
int hmap_mountain_level
Definition height_map.c:30
static float hmap_pole_factor(struct tile *ptile)
Definition height_map.c:35
void normalize_hmap_poles(void)
Definition height_map.c:64
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:269
void make_pseudofractal1_hmap(int extra_div)
Definition height_map.c:197
void make_random_hmap(int smooth)
Definition height_map.c:100
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:443
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:654
#define MAP_INDEX_SIZE
Definition map.h:137
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:391
#define square_iterate_end
Definition map.h:394
#define whole_map_iterate(_map, _tile)
Definition map.h:545
#define current_wrap_has_flag(flag)
Definition map.h:51
#define whole_map_iterate_end
Definition map.h:554
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
int xsize
Definition map_types.h:78
int ysize
Definition map_types.h:78
struct civ_map::@42::@44 server
int landpercent
Definition map_types.h:97
int flatpoles
Definition map_types.h:102
bool separatepoles
Definition map_types.h:101
Definition tile.h:50
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47