Freeciv-3.2: /fast/freeciv/nightly/S3_2/server/generator/fracture_map.c Source File

Freeciv-3.2

Loading...
Searching...
No Matches
fracture_map.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2016 - 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 "height_map.h"
25#include "mapgen_topology.h"
26#include "mapgen_utils.h"
27
28#include "fracture_map.h"
29
30static void circle_bresenham(int xc, int yc, int r, int nn);
31static void fmfill(int x, int y, int c, int r);
32static int local_ave_elevation(struct tile *ptile);
33
34extern int *height_map;
35 int num_landmass = 50;
36
37 typedef struct {
38 int x;
39 int y;
40} map_point;
41
42 typedef struct {
43 int minX, minY;
44 int maxX, maxY;
45 int elevation;
46} map_landmass;
47
48/* Landmass: a chunk of rock with common properties */
49 static map_landmass *landmass;
50 static map_point *fracture_points;
51
52/**********************************************************************/
55 void make_fracture_map(void)
56{
57 int nn, mm;
58 int rad;
59 int x,y;
60 struct tile *ptile1;
61
62 /* Calculate the mountain level. map.server.mountains specifies the
63 * percentage of land that is turned into hills and mountains. */
64 hmap_mountain_level = (((hmap_max_level - hmap_shore_level)
65 * (100 - wld.map.server.steepness))
66 / 100 + hmap_shore_level);
67
68 /* For larger maps, increase the number of landmasses - makes the map more interesting */
69 num_landmass = 20 + 15 * get_sqsize();
70 landmass = (map_landmass *)fc_malloc((wld.map.xsize / 2 + wld.map.ysize / 2 + num_landmass) * sizeof(map_landmass));
71 fracture_points = (map_point *)fc_malloc((wld.map.xsize / 2 + wld.map.ysize / 2 + num_landmass) * sizeof(map_point));
72 height_map = fc_malloc(sizeof(*height_map) * MAP_INDEX_SIZE);
73
74 /* Setup a whole bunch of landmasses along the view bordere. These will be sunken
75 to create ocean terrain.*/
76 nn = 0;
77 for (x = 3; x < wld.map.xsize; x += 5, nn++) {
78 fracture_points[nn].x = x;
79 fracture_points[nn].y = 3;
80 }
81 for (x = 3; x < wld.map.xsize; x += 5, nn++) {
82 fracture_points[nn].x = x;
83 fracture_points[nn].y = wld.map.ysize - 3;
84 }
85 for (y = 3; y < wld.map.ysize; y += 5, nn++) {
86 fracture_points[nn].x = 3;
87 fracture_points[nn].y = y;
88 }
89 for (y = 3; y < wld.map.ysize; y += 5, nn++) {
90 fracture_points[nn].x = wld.map.xsize - 3;
91 fracture_points[nn].y = y;
92 }
93
94 /* pick remaining points randomly */
95 mm = nn;
96 for (; nn < mm + num_landmass; nn++) {
97 fracture_points[nn].x = fc_rand(wld.map.xsize - 6) + 3;
98 fracture_points[nn].y = fc_rand(wld.map.ysize - 6) + 3;
99 }
100 for (nn = 0; nn < mm + num_landmass; nn++) {
101 landmass[nn].minX = wld.map.xsize - 1;
102 landmass[nn].minY = wld.map.ysize - 1;
103 landmass[nn].maxX = 0;
104 landmass[nn].maxY = 0;
105 x = fracture_points[nn].x;
106 y = fracture_points[nn].y;
107 ptile1 = native_pos_to_tile(&(wld.map), x, y);
108 ptile1->continent = nn + 1;
109 }
110
111 /* Assign a base elevation to the landmass */
112 for (nn = 0; nn < mm + num_landmass; nn++) {
113 if (nn < mm) { /* sink the border masses */
114 landmass[nn].elevation = 0;
115 } else {
116 landmass[nn].elevation = fc_rand(1000);
117 }
118 }
119
120 /* Assign cells to landmass. Gradually expand the radius of the
121 fracture point. */
122 for (rad = 1; rad < (wld.map.xsize >> 1); rad++) {
123 for (nn = 0; nn < mm + num_landmass; nn++) {
124 circle_bresenham(fracture_points[nn].x, fracture_points[nn].y, rad, nn+1);
125 }
126 }
127
128 /* put in some random fuzz */
129 whole_map_iterate(&(wld.map), ptile) {
130 if (hmap(ptile) > hmap_shore_level) {
131 hmap(ptile) = hmap(ptile) + fc_rand(4) - 2;
132 }
133 if (hmap(ptile) <= hmap_shore_level) {
134 hmap(ptile) = hmap_shore_level + 1;
135 }
136 } whole_map_iterate_end;
137
138 adjust_int_map(height_map, 0, hmap_max_level);
139 free(landmass);
140 free(fracture_points);
141}
142
143/**********************************************************************/
148 static void circle_bresenham(int xc, int yc, int r, int nn)
149{
150 int x = 0;
151 int y = r;
152 int p = 3 - 2 * r;
153
154 if (!r) {
155 return;
156 }
157
158 while (y >= x) { /* only formulate 1/8 of circle */
159 fmfill(xc-x, yc-y, nn, r); /* upper left left */
160 fmfill(xc-y, yc-x, nn, r); /* upper upper left */
161 fmfill(xc+y, yc-x, nn, r); /* upper upper right */
162 fmfill(xc+x, yc-y, nn, r); /* upper right right */
163 fmfill(xc-x, yc+y, nn, r); /* lower left left */
164 fmfill(xc-y, yc+x, nn, r); /* lower lower left */
165 fmfill(xc+y, yc+x, nn, r); /* lower lower right */
166 fmfill(xc+x, yc+y, nn, r); /* lower right right */
167 if (p < 0) {
168 p += 4 * x++ + 6;
169 } else {
170 p += 4 * (x++ - y--) + 10;
171 }
172 }
173}
174
175/**********************************************************************/
179 static void fmfill(int x, int y, int c, int r)
180{
181 int x_less, x_more, y_less, y_more;
182 struct tile *ptileXY;
183 struct tile *ptileX2Y;
184 struct tile *ptileX1Y;
185 struct tile *ptileXY2;
186 struct tile *ptileXY1;
187 struct tile *ptileX2Y1;
188 struct tile *ptileX2Y2;
189 struct tile *ptileX1Y2;
190 struct tile *ptileX1Y1;
191
192 if (x < 0) {
193 x = wld.map.xsize + x;
194 } else if (x > wld.map.xsize) {
195 x = x - wld.map.xsize;
196 }
197 x_less = x - 1;
198 if (x_less < 0) {
199 x_less = wld.map.xsize - 1;
200 }
201 x_more = x + 1;
202 if (x_more >= wld.map.xsize) {
203 x_more = 0;
204 }
205 y_less = y - 1;
206 if (y_less < 0) {
207 y_less = wld.map.ysize - 1;
208 }
209 y_more = y + 1;
210 if (y_more >= wld.map.ysize) {
211 y_more = 0;
212 }
213
214 if (y >= 0 && y < wld.map.ysize) {
215 ptileXY = native_pos_to_tile(&(wld.map), x, y);
216 ptileX2Y = native_pos_to_tile(&(wld.map), x_more, y);
217 ptileX1Y = native_pos_to_tile(&(wld.map), x_less, y);
218 ptileXY2 = native_pos_to_tile(&(wld.map), x, y_more);
219 ptileXY1 = native_pos_to_tile(&(wld.map), x, y_less);
220 ptileX2Y1 = native_pos_to_tile(&(wld.map), x_more, y_less);
221 ptileX2Y2 = native_pos_to_tile(&(wld.map), x_more, y_more);
222 ptileX1Y2 = native_pos_to_tile(&(wld.map), x_less, y_more);
223 ptileX1Y1 = native_pos_to_tile(&(wld.map), x_less, y_less);
224
225 if (ptileXY->continent == 0 ) {
226 ptileXY->continent = c;
227 ptileX2Y->continent = c;
228 ptileX1Y->continent = c;
229 ptileXY2->continent = c;
230 ptileXY1->continent = c;
231 ptileX2Y2->continent = c;
232 ptileX2Y1->continent = c;
233 ptileX1Y2->continent = c;
234 ptileX1Y1->continent = c;
235 hmap(ptileXY) = landmass[c-1].elevation;
236 hmap(ptileX2Y) = landmass[c-1].elevation;
237 hmap(ptileX1Y) = landmass[c-1].elevation;
238 hmap(ptileXY2) = landmass[c-1].elevation;
239 hmap(ptileXY1) = landmass[c-1].elevation;
240 hmap(ptileX2Y1) = landmass[c-1].elevation;
241 hmap(ptileX2Y2) = landmass[c-1].elevation;
242 hmap(ptileX1Y2) = landmass[c-1].elevation;
243 hmap(ptileX1Y1) = landmass[c-1].elevation;
244 /* This bit of code could track the maximum and minimum extent
245 * of the landmass. */
246 if (x < landmass[c-1].minX) {
247 landmass[c-1].minX = x;
248 }
249 if (x > landmass[c-1].maxX) {
250 landmass[c-1].maxX = x;
251 }
252 if (y < landmass[c-1].minY) {
253 landmass[c-1].minY = y;
254 }
255 if (y > landmass[c-1].maxY) {
256 landmass[c-1].maxY = y;
257 }
258 }
259 }
260}
261
262/**********************************************************************/
266 static int local_ave_elevation(struct tile *ptile)
267{
268 int ele;
269 int n;
270
271 n = ele = 0;
272 square_iterate(&(wld.map), ptile, 3, tile2) {
273 ele = ele + hmap(tile2);
274 n++;
275 } square_iterate_end;
276
277 if (ele > 0) { /* Avoids div by zero, as means also that n > 0 */
278 ele /= n;
279 }
280
281 return ele;
282}
283
284/**********************************************************************/
292 void make_fracture_relief(void)
293{
294 bool choose_mountain;
295 bool choose_hill;
296 int landarea;
297 int total_mtns;
298 int iter;
299
300 /* Compute the land area */
301 landarea = 0;
302 whole_map_iterate(&(wld.map), ptile) {
303 if (hmap(ptile) > hmap_shore_level) {
304 landarea++;
305 }
306 } whole_map_iterate_end;
307
308 /* Iteration 1
309 Choose hills and mountains based on local elevation.
310 */
311 total_mtns = 0;
312 whole_map_iterate(&(wld.map), ptile) {
313 if (not_placed(ptile) && hmap(ptile) > hmap_shore_level) { /* Place on land only */
314 /* Mountains */
315 choose_mountain = (hmap(ptile) > local_ave_elevation(ptile) * 1.20)
316 || (area_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)) && (fc_rand(10) < 4));
317
318 choose_hill = (hmap(ptile) > local_ave_elevation(ptile) * 1.10)
319 || (area_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)) && (fc_rand(10) < 4));
320 /* The following avoids hills and mountains directly along the coast. */
321 if (count_terrain_class_near_tile(&(wld.map), ptile, TRUE, TRUE, TC_OCEAN) > 0) {
322 choose_mountain = FALSE;
323 choose_hill = FALSE;
324 }
325 if (choose_mountain) {
326 total_mtns++;
327 tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_UNUSED, MG_GREEN));
328 map_set_placed(ptile);
329 } else if (choose_hill) {
330 /* hills */
331 total_mtns++;
332 tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_GREEN, MG_UNUSED));
333 map_set_placed(ptile);
334 }
335 }
336 } whole_map_iterate_end;
337
338 /* Iteration 2
339 Make sure the map has at least the minimum number of mountains according to the
340 map steepness setting.
341 The iteration limit is a failsafe to prevent the iteration from taking forever.
342 */
343 for (iter = 0; total_mtns < (landarea * wld.map.server.steepness) / 100 && iter < 50;
344 iter++) {
345 whole_map_iterate(&(wld.map), ptile) {
346 if (not_placed(ptile) && hmap(ptile) > hmap_shore_level) { /* place on land only */
347 choose_mountain = fc_rand(10000) < 10;
348 choose_hill = fc_rand(10000) < 10;
349 if (choose_mountain) {
350 total_mtns++;
351 tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_UNUSED, MG_GREEN));
352 map_set_placed(ptile);
353 } else if (choose_hill) {
354 /* hills */
355 total_mtns++;
356 tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_GREEN, MG_UNUSED));
357 map_set_placed(ptile);
358 }
359 }
360 if (total_mtns >= landarea * wld.map.server.steepness / 100) {
361 break;
362 }
363 } whole_map_iterate_end;
364 }
365}
n
#define n
Definition astring.c:77
incite_cost
char * incite_cost
Definition comments.c:74
make_fracture_map
void make_fracture_map(void)
Definition fracture_map.c:55
local_ave_elevation
static int local_ave_elevation(struct tile *ptile)
Definition fracture_map.c:266
num_landmass
int num_landmass
Definition fracture_map.c:35
make_fracture_relief
void make_fracture_relief(void)
Definition fracture_map.c:292
fmfill
static void fmfill(int x, int y, int c, int r)
Definition fracture_map.c:179
landmass
static map_landmass * landmass
Definition fracture_map.c:49
circle_bresenham
static void circle_bresenham(int xc, int yc, int r, int nn)
Definition fracture_map.c:148
fracture_points
static map_point * fracture_points
Definition fracture_map.c:50
height_map
int * height_map
Definition height_map.c:29
fracture_map.h
hmap_mountain_level
int hmap_mountain_level
Definition fracture_map.h:28
MG_UNUSED
#define MG_UNUSED
Definition fracture_map.h:32
hmap_shore_level
int hmap_shore_level
Definition height_map.c:30
wld
struct world wld
Definition game.c:63
area_is_too_flat
bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
Definition height_map.c:269
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:443
map.h
MAP_INDEX_SIZE
#define MAP_INDEX_SIZE
Definition map.h:137
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:391
square_iterate_end
#define square_iterate_end
Definition map.h:394
whole_map_iterate
#define whole_map_iterate(_map, _tile)
Definition map.h:545
whole_map_iterate_end
#define whole_map_iterate_end
Definition map.h:554
get_sqsize
int get_sqsize(void)
Definition mapgen_topology.c:271
mapgen_topology.h
map_set_placed
void map_set_placed(struct tile *ptile)
Definition mapgen_utils.c:79
not_placed
bool not_placed(const struct tile *ptile)
Definition mapgen_utils.c:71
pick_terrain
struct terrain * pick_terrain(enum mapgen_terrain_property target, enum mapgen_terrain_property prefer, enum mapgen_terrain_property avoid)
Definition mapgen_utils.c:725
mapgen_utils.h
adjust_int_map
#define adjust_int_map(int_map, int_map_min, int_map_max)
Definition mapgen_utils.h:105
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:56
y
struct sprite int int y
Definition sprite_g.h:31
x
struct sprite int x
Definition sprite_g.h:31
civ_map::xsize
int xsize
Definition map_types.h:78
civ_map::ysize
int ysize
Definition map_types.h:78
civ_map::server
struct civ_map::@42::@44 server
civ_map::steepness
int steepness
Definition map_types.h:105
map_landmass
Definition fracture_map.c:42
map_landmass::minY
int minY
Definition fracture_map.c:43
map_landmass::maxY
int maxY
Definition fracture_map.c:44
map_landmass::maxX
int maxX
Definition fracture_map.c:44
map_landmass::minX
int minX
Definition fracture_map.c:43
map_landmass::elevation
int elevation
Definition fracture_map.c:45
map_point
Definition fracture_map.c:37
map_point::y
int y
Definition fracture_map.c:39
map_point::x
int x
Definition fracture_map.c:38
tile
Definition tile.h:50
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
count_terrain_class_near_tile
int count_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, bool cardinal_only, bool percentage, enum terrain_class tclass)
Definition terrain.c:633
tile_set_terrain
void tile_set_terrain(struct tile *ptile, struct terrain *pterrain)
Definition tile.c:124