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;
35int num_landmass = 50;
36
37typedef struct {
38 int x;
39 int y;
40} map_point;
41
42typedef struct {
43 int minX, minY;
44 int maxX, maxY;
47
48/* Landmass: a chunk of rock with common properties */
51
52/**********************************************************************/
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. */
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();
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++) {
81 fracture_points[nn].y = 3;
82 }
83 for (x = 3; x < MAP_NATIVE_WIDTH; x += 5, nn++) {
86 }
87 for (y = 3; y < MAP_NATIVE_HEIGHT; y += 5, nn++) {
88 fracture_points[nn].x = 3;
90 }
91 for (y = 3; y < MAP_NATIVE_HEIGHT; y += 5, nn++) {
94 }
95
96 /* Pick remaining points randomly */
97 mm = nn;
98 for (; nn < mm + num_landmass; nn++) {
101 }
102 for (nn = 0; nn < mm + num_landmass; nn++) {
105 landmass[nn].maxX = 0;
106 landmass[nn].maxY = 0;
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++) {
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 }
139
141 free(landmass);
143}
144
145/**********************************************************************/
150static 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/**********************************************************************/
181static 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) {
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) {
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) {
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;
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/**********************************************************************/
268static 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++;
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/**********************************************************************/
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 }
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) {
326 }
327 if (choose_mountain) {
328 total_mtns++;
330 map_set_placed(ptile);
331 } else if (choose_hill) {
332 /* hills */
333 total_mtns++;
335 map_set_placed(ptile);
336 }
337 }
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++;
354 map_set_placed(ptile);
355 } else if (choose_hill) {
356 /* hills */
357 total_mtns++;
359 map_set_placed(ptile);
360 }
361 }
362 if (total_mtns >= landarea * wld.map.server.steepness / 100) {
363 break;
364 }
366 }
367}
#define n
Definition astring.c:77
char * incite_cost
Definition comments.c:76
void make_fracture_map(void)
static int local_ave_elevation(struct tile *ptile)
int num_landmass
void make_fracture_relief(void)
static void fmfill(int x, int y, int c, int r)
static map_landmass * landmass
static void circle_bresenham(int xc, int yc, int r, int nn)
static map_point * fracture_points
int * height_map
Definition height_map.c:29
int hmap_mountain_level
#define MG_UNUSED
int hmap_shore_level
Definition height_map.c:30
struct world wld
Definition game.c:62
bool area_is_too_flat(struct tile *ptile, int thill, int my_height)
Definition height_map.c:271
#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
#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 whole_map_iterate_end
Definition map.h:582
int get_sqsize(void)
void map_set_placed(struct tile *ptile)
bool not_placed(const struct tile *ptile)
struct terrain * pick_terrain(enum mapgen_terrain_property target, enum mapgen_terrain_property prefer, enum mapgen_terrain_property avoid)
#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
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
int steepness
Definition map_types.h:118
struct civ_map::@44::@46 server
Definition tile.h:50
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
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
void tile_set_terrain(struct tile *ptile, struct terrain *pterrain)
Definition tile.c:124
#define MAP_NATIVE_WIDTH
#define MAP_INDEX_SIZE
#define MAP_NATIVE_HEIGHT