Freeciv-3.3: /fast/freeciv/nightly/main/server/generator/fracture_map.c Source File

Freeciv-3.3

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
71 = (map_landmass *)fc_malloc((MAP_NATIVE_WIDTH / 2 + MAP_NATIVE_HEIGHT / 2 + num_landmass) * sizeof(map_landmass));
72 fracture_points
73 = (map_point *)fc_malloc((MAP_NATIVE_WIDTH / 2 + MAP_NATIVE_HEIGHT / 2 + num_landmass) * sizeof(map_point));
74 height_map = fc_malloc(sizeof(*height_map) * MAP_INDEX_SIZE);
75
76 /* Setup a whole bunch of landmasses along the view bordere. These will be sunken
77 to create ocean terrain.*/
78 nn = 0;
79 for (x = 3; x < MAP_NATIVE_WIDTH; x += 5, nn++) {
80 fracture_points[nn].x = x;
81 fracture_points[nn].y = 3;
82 }
83 for (x = 3; x < MAP_NATIVE_WIDTH; x += 5, nn++) {
84 fracture_points[nn].x = x;
85 fracture_points[nn].y = MAP_NATIVE_HEIGHT - 3;
86 }
87 for (y = 3; y < MAP_NATIVE_HEIGHT; y += 5, nn++) {
88 fracture_points[nn].x = 3;
89 fracture_points[nn].y = y;
90 }
91 for (y = 3; y < MAP_NATIVE_HEIGHT; y += 5, nn++) {
92 fracture_points[nn].x = MAP_NATIVE_WIDTH - 3;
93 fracture_points[nn].y = y;
94 }
95
96 /* Pick remaining points randomly */
97 mm = nn;
98 for (; nn < mm + num_landmass; nn++) {
99 fracture_points[nn].x = fc_rand(MAP_NATIVE_WIDTH - 6) + 3;
100 fracture_points[nn].y = fc_rand(MAP_NATIVE_HEIGHT - 6) + 3;
101 }
102 for (nn = 0; nn < mm + num_landmass; nn++) {
103 landmass[nn].minX = MAP_NATIVE_WIDTH - 1;
104 landmass[nn].minY = MAP_NATIVE_HEIGHT - 1;
105 landmass[nn].maxX = 0;
106 landmass[nn].maxY = 0;
107 x = fracture_points[nn].x;
108 y = fracture_points[nn].y;
109 ptile1 = native_pos_to_tile(&(wld.map), x, y);
110 ptile1->continent = nn + 1;
111 }
112
113 /* Assign a base elevation to the landmass */
114 for (nn = 0; nn < mm + num_landmass; nn++) {
115 if (nn < mm) { /* sink the border masses */
116 landmass[nn].elevation = 0;
117 } else {
118 landmass[nn].elevation = fc_rand(1000);
119 }
120 }
121
122 /* Assign cells to landmass. Gradually expand the radius of the
123 fracture point. */
124 for (rad = 1; rad < (MAP_NATIVE_WIDTH >> 1); rad++) {
125 for (nn = 0; nn < mm + num_landmass; nn++) {
126 circle_bresenham(fracture_points[nn].x, fracture_points[nn].y, rad, nn+1);
127 }
128 }
129
130 /* Put in some random fuzz */
131 whole_map_iterate(&(wld.map), ptile) {
132 if (hmap(ptile) > hmap_shore_level) {
133 hmap(ptile) = hmap(ptile) + fc_rand(4) - 2;
134 }
135 if (hmap(ptile) <= hmap_shore_level) {
136 hmap(ptile) = hmap_shore_level + 1;
137 }
138 } whole_map_iterate_end;
139
140 adjust_int_map(height_map, 0, hmap_max_level);
141 free(landmass);
142 free(fracture_points);
143}
144
145/**********************************************************************/
150 static void circle_bresenham(int xc, int yc, int r, int nn)
151{
152 int x = 0;
153 int y = r;
154 int p = 3 - 2 * r;
155
156 if (!r) {
157 return;
158 }
159
160 while (y >= x) { /* only formulate 1/8 of circle */
161 fmfill(xc-x, yc-y, nn, r); /* upper left left */
162 fmfill(xc-y, yc-x, nn, r); /* upper upper left */
163 fmfill(xc+y, yc-x, nn, r); /* upper upper right */
164 fmfill(xc+x, yc-y, nn, r); /* upper right right */
165 fmfill(xc-x, yc+y, nn, r); /* lower left left */
166 fmfill(xc-y, yc+x, nn, r); /* lower lower left */
167 fmfill(xc+y, yc+x, nn, r); /* lower lower right */
168 fmfill(xc+x, yc+y, nn, r); /* lower right right */
169 if (p < 0) {
170 p += 4 * x++ + 6;
171 } else {
172 p += 4 * (x++ - y--) + 10;
173 }
174 }
175}
176
177/**********************************************************************/
181 static void fmfill(int x, int y, int c, int r)
182{
183 int x_less, x_more, y_less, y_more;
184 struct tile *ptileXY;
185 struct tile *ptileX2Y;
186 struct tile *ptileX1Y;
187 struct tile *ptileXY2;
188 struct tile *ptileXY1;
189 struct tile *ptileX2Y1;
190 struct tile *ptileX2Y2;
191 struct tile *ptileX1Y2;
192 struct tile *ptileX1Y1;
193
194 if (x < 0) {
195 x = MAP_NATIVE_WIDTH + x;
196 } else if (x > MAP_NATIVE_WIDTH) {
197 x = x - MAP_NATIVE_WIDTH;
198 }
199 x_less = x - 1;
200 if (x_less < 0) {
201 x_less = MAP_NATIVE_WIDTH - 1;
202 }
203 x_more = x + 1;
204 if (x_more >= MAP_NATIVE_WIDTH) {
205 x_more = 0;
206 }
207 y_less = y - 1;
208 if (y_less < 0) {
209 y_less = MAP_NATIVE_HEIGHT - 1;
210 }
211 y_more = y + 1;
212 if (y_more >= MAP_NATIVE_HEIGHT) {
213 y_more = 0;
214 }
215
216 if (y >= 0 && y < MAP_NATIVE_HEIGHT) {
217 ptileXY = native_pos_to_tile(&(wld.map), x, y);
218 ptileX2Y = native_pos_to_tile(&(wld.map), x_more, y);
219 ptileX1Y = native_pos_to_tile(&(wld.map), x_less, y);
220 ptileXY2 = native_pos_to_tile(&(wld.map), x, y_more);
221 ptileXY1 = native_pos_to_tile(&(wld.map), x, y_less);
222 ptileX2Y1 = native_pos_to_tile(&(wld.map), x_more, y_less);
223 ptileX2Y2 = native_pos_to_tile(&(wld.map), x_more, y_more);
224 ptileX1Y2 = native_pos_to_tile(&(wld.map), x_less, y_more);
225 ptileX1Y1 = native_pos_to_tile(&(wld.map), x_less, y_less);
226
227 if (ptileXY->continent == 0 ) {
228 ptileXY->continent = c;
229 ptileX2Y->continent = c;
230 ptileX1Y->continent = c;
231 ptileXY2->continent = c;
232 ptileXY1->continent = c;
233 ptileX2Y2->continent = c;
234 ptileX2Y1->continent = c;
235 ptileX1Y2->continent = c;
236 ptileX1Y1->continent = c;
237 hmap(ptileXY) = landmass[c-1].elevation;
238 hmap(ptileX2Y) = landmass[c-1].elevation;
239 hmap(ptileX1Y) = landmass[c-1].elevation;
240 hmap(ptileXY2) = landmass[c-1].elevation;
241 hmap(ptileXY1) = landmass[c-1].elevation;
242 hmap(ptileX2Y1) = landmass[c-1].elevation;
243 hmap(ptileX2Y2) = landmass[c-1].elevation;
244 hmap(ptileX1Y2) = landmass[c-1].elevation;
245 hmap(ptileX1Y1) = landmass[c-1].elevation;
246 /* This bit of code could track the maximum and minimum extent
247 * of the landmass. */
248 if (x < landmass[c-1].minX) {
249 landmass[c-1].minX = x;
250 }
251 if (x > landmass[c-1].maxX) {
252 landmass[c-1].maxX = x;
253 }
254 if (y < landmass[c-1].minY) {
255 landmass[c-1].minY = y;
256 }
257 if (y > landmass[c-1].maxY) {
258 landmass[c-1].maxY = y;
259 }
260 }
261 }
262}
263
264/**********************************************************************/
268 static int local_ave_elevation(struct tile *ptile)
269{
270 int ele;
271 int n;
272
273 n = ele = 0;
274 square_iterate(&(wld.map), ptile, 3, tile2) {
275 ele = ele + hmap(tile2);
276 n++;
277 } square_iterate_end;
278
279 if (ele > 0) { /* Avoids div by zero, as means also that n > 0 */
280 ele /= n;
281 }
282
283 return ele;
284}
285
286/**********************************************************************/
294 void make_fracture_relief(void)
295{
296 bool choose_mountain;
297 bool choose_hill;
298 int landarea;
299 int total_mtns;
300 int iter;
301
302 /* Compute the land area */
303 landarea = 0;
304 whole_map_iterate(&(wld.map), ptile) {
305 if (hmap(ptile) > hmap_shore_level) {
306 landarea++;
307 }
308 } whole_map_iterate_end;
309
310 /* Iteration 1
311 Choose hills and mountains based on local elevation.
312 */
313 total_mtns = 0;
314 whole_map_iterate(&(wld.map), ptile) {
315 if (not_placed(ptile) && hmap(ptile) > hmap_shore_level) { /* Place on land only */
316 /* Mountains */
317 choose_mountain = (hmap(ptile) > local_ave_elevation(ptile) * 1.20)
318 || (area_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)) && (fc_rand(10) < 4));
319
320 choose_hill = (hmap(ptile) > local_ave_elevation(ptile) * 1.10)
321 || (area_is_too_flat(ptile, hmap_mountain_level, hmap(ptile)) && (fc_rand(10) < 4));
322 /* The following avoids hills and mountains directly along the coast. */
323 if (count_terrain_class_near_tile(&(wld.map), ptile, TRUE, TRUE, TC_OCEAN) > 0) {
324 choose_mountain = FALSE;
325 choose_hill = FALSE;
326 }
327 if (choose_mountain) {
328 total_mtns++;
329 tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_UNUSED, MG_GREEN));
330 map_set_placed(ptile);
331 } else if (choose_hill) {
332 /* hills */
333 total_mtns++;
334 tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_GREEN, MG_UNUSED));
335 map_set_placed(ptile);
336 }
337 }
338 } whole_map_iterate_end;
339
340 /* Iteration 2
341 Make sure the map has at least the minimum number of mountains according to the
342 map steepness setting.
343 The iteration limit is a failsafe to prevent the iteration from taking forever.
344 */
345 for (iter = 0; total_mtns < (landarea * wld.map.server.steepness) / 100 && iter < 50;
346 iter++) {
347 whole_map_iterate(&(wld.map), ptile) {
348 if (not_placed(ptile) && hmap(ptile) > hmap_shore_level) { /* place on land only */
349 choose_mountain = fc_rand(10000) < 10;
350 choose_hill = fc_rand(10000) < 10;
351 if (choose_mountain) {
352 total_mtns++;
353 tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_UNUSED, MG_GREEN));
354 map_set_placed(ptile);
355 } else if (choose_hill) {
356 /* hills */
357 total_mtns++;
358 tile_set_terrain(ptile,pick_terrain(MG_MOUNTAINOUS, MG_GREEN, MG_UNUSED));
359 map_set_placed(ptile);
360 }
361 }
362 if (total_mtns >= landarea * wld.map.server.steepness / 100) {
363 break;
364 }
365 } whole_map_iterate_end;
366 }
367}
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:268
num_landmass
int num_landmass
Definition fracture_map.c:35
make_fracture_relief
void make_fracture_relief(void)
Definition fracture_map.c:294
fmfill
static void fmfill(int x, int y, int c, int r)
Definition fracture_map.c:181
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:150
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:271
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:449
map.h
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:377
square_iterate_end
#define square_iterate_end
Definition map.h:380
whole_map_iterate
#define whole_map_iterate(_map, _tile)
Definition map.h:531
whole_map_iterate_end
#define whole_map_iterate_end
Definition map.h:540
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::server
struct civ_map::@42::@44 server
civ_map::steepness
int steepness
Definition map_types.h:106
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
MAP_NATIVE_WIDTH
#define MAP_NATIVE_WIDTH
Definition world_object.h:55
MAP_INDEX_SIZE
#define MAP_INDEX_SIZE
Definition world_object.h:52
MAP_NATIVE_HEIGHT
#define MAP_NATIVE_HEIGHT
Definition world_object.h:56