Freeciv-3.1: /fast/freeciv/nightly/S3_1/server/generator/height_map.c Source File

Freeciv-3.1

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
29 int *height_map = NULL;
30 int hmap_shore_level = 0, hmap_mountain_level = 0;
31
32/**********************************************************************/
35 static 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 }
49 if (wld.map.server.separatepoles
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/**********************************************************************/
64 void normalize_hmap_poles(void)
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 }
73 } whole_map_iterate_end;
74}
75
76/**********************************************************************/
80 void renormalize_hmap_poles(void)
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 }
93 } whole_map_iterate_end;
94}
95
96/**********************************************************************/
100 void make_random_hmap(int smooth)
101{
102 int i = 0;
103 height_map = fc_malloc(sizeof(*height_map) * MAP_INDEX_SIZE);
104
105 INITIALIZE_ARRAY(height_map, MAP_INDEX_SIZE, fc_rand(1000 * smooth));
106
107 for (; i < smooth; i++) {
108 smooth_int_map(height_map, TRUE);
109 }
110
111 adjust_int_map(height_map, hmap_max_level);
112}
113
114/**********************************************************************/
119 static 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/**********************************************************************/
197 void make_pseudofractal1_hmap(int extra_div)
198{
199 const bool xnowrap = !current_topo_has_flag(TF_WRAPX);
200 const bool ynowrap = !current_topo_has_flag(TF_WRAPY);
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
220 height_map = fc_malloc(sizeof(*height_map) * MAP_INDEX_SIZE);
221
222 /* initialize map */
223 INITIALIZE_ARRAY(height_map, MAP_INDEX_SIZE, 0);
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 }
242 } do_in_map_pos_end;
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++) {
249 gen5rec(step, x_current * xmax / xdiv, y_current * ymax / ydiv,
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;
257 } whole_map_iterate_end;
258
259 adjust_int_map(height_map, hmap_max_level);
260}
261
262/**********************************************************************/
269 bool 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 }
285 } square_iterate_end;
286
287 if ((thill - hmap_shore_level) * higher_than_me
288 > (my_height - hmap_shore_level) * 4) {
289 return FALSE;
290 }
291
292 return TRUE;
293}
wld
struct world wld
Definition game.c:58
gen5rec
static void gen5rec(int step, int xl, int yt, int xr, int yb)
Definition height_map.c:119
renormalize_hmap_poles
void renormalize_hmap_poles(void)
Definition height_map.c:80
hmap_mountain_level
int hmap_mountain_level
Definition height_map.c:30
hmap_pole_factor
static float hmap_pole_factor(struct tile *ptile)
Definition height_map.c:35
normalize_hmap_poles
void normalize_hmap_poles(void)
Definition height_map.c:64
hmap_shore_level
int hmap_shore_level
Definition height_map.c:30
set_midpoints
#define set_midpoints(X, Y, V)
area_is_too_flat
bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
Definition height_map.c:269
make_pseudofractal1_hmap
void make_pseudofractal1_hmap(int extra_div)
Definition height_map.c:197
make_random_hmap
void make_random_hmap(int smooth)
Definition height_map.c:100
height_map
int * height_map
Definition height_map.c:29
height_map.h
hmap_max_level
#define hmap_max_level
Definition height_map.h:33
hmap
#define hmap(_tile)
Definition height_map.h:17
native_pos_to_tile
struct tile * native_pos_to_tile(const struct civ_map *nmap, int nat_x, int nat_y)
Definition map.c:441
map_distance
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:652
map.h
current_topo_has_flag
#define current_topo_has_flag(flag)
Definition map.h:45
MAP_INDEX_SIZE
#define MAP_INDEX_SIZE
Definition map.h:131
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:385
square_iterate_end
#define square_iterate_end
Definition map.h:388
whole_map_iterate
#define whole_map_iterate(_map, _tile)
Definition map.h:539
whole_map_iterate_end
#define whole_map_iterate_end
Definition map.h:548
map_colatitude
int map_colatitude(const struct tile *ptile)
Definition mapgen_topology.c:38
near_singularity
bool near_singularity(const struct tile *ptile)
Definition mapgen_topology.c:205
mapgen_topology.h
ICE_BASE_LEVEL
#define ICE_BASE_LEVEL
Definition mapgen_topology.h:49
smooth_int_map
void smooth_int_map(int *int_map, bool zeroes_at_edges)
Definition mapgen_utils.c:188
mapgen_utils.h
do_in_map_pos_end
#define do_in_map_pos_end
Definition mapgen_utils.h:49
do_in_map_pos
#define do_in_map_pos(nmap, ptile, nat_x, nat_y)
Definition mapgen_utils.h:44
adjust_int_map
#define adjust_int_map(int_map, int_map_max)
Definition mapgen_utils.h:103
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:34
INITIALIZE_ARRAY
#define INITIALIZE_ARRAY(array, size, value)
Definition shared.h:101
MIN
#define MIN(x, y)
Definition shared.h:55
step
int step
Definition specpq.h:92
civ_map::xsize
int xsize
Definition map_types.h:77
civ_map::ysize
int ysize
Definition map_types.h:77
civ_map::landpercent
int landpercent
Definition map_types.h:94
civ_map::server
struct civ_map::@41::@43 server
civ_map::flatpoles
int flatpoles
Definition map_types.h:99
civ_map::separatepoles
bool separatepoles
Definition map_types.h:98
tile
Definition tile.h:49
world::map
struct civ_map map
Definition world_object.h:38
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47