Freeciv21
Develop your civilization from humble roots to a global empire
mapgen_utils.cpp
Go to the documentation of this file.
1 /*
2 _ ._ Copyright (c) 1996-2021 Freeciv21 and Freeciv contributors.
3  \ | This file is part of Freeciv21. Freeciv21 is free software: you
4  \_| can redistribute it and/or modify it under the terms of the
5  .' '. GNU General Public License as published by the Free
6  :O O: Software Foundation, either version 3 of the License,
7  '/ \' or (at your option) any later version. You should have
8  :X: received a copy of the GNU General Public License along with
9  :X: Freeciv21. If not, see https://www.gnu.org/licenses/.
10  */
11 // utility
12 #include "fcintl.h"
13 #include "log.h"
14 #include "rand.h"
15 #include "support.h" // bool type
16 
17 // common
18 #include "map.h"
19 #include "terrain.h"
20 #include "tile.h"
21 
22 #include "mapgen_utils.h"
23 
28 static bool *placed_map;
29 
33 bool placed_map_is_initialized() { return placed_map != nullptr; }
34 
39 {
41  placed_map = new bool[MAP_INDEX_SIZE];
43 }
44 
49 {
51  delete[] placed_map;
52  placed_map = nullptr;
53 }
54 
55 #define pmap(_tile) (placed_map[tile_index(_tile)])
56 
60 bool not_placed(const struct tile *ptile) { return !pmap(ptile); }
61 
65 void map_set_placed(struct tile *ptile) { pmap(ptile) = true; }
66 
70 void map_unset_placed(struct tile *ptile) { pmap(ptile) = false; }
71 
76 {
77  whole_map_iterate(&(wld.map), ptile)
78  {
79  if (is_ocean_tile(ptile)) {
80  map_set_placed(ptile);
81  }
82  }
84 }
85 
89 void set_placed_near_pos(struct tile *ptile, int dist)
90 {
91  square_iterate(&(wld.map), ptile, dist, tile1) { map_set_placed(tile1); }
93 }
94 
103 void adjust_int_map_filtered(int *int_map, int int_map_max, void *data,
104  bool (*filter)(const struct tile *ptile,
105  const void *data))
106 {
107  int minval = 0, maxval = 0, total = 0;
108  bool first = true;
109 
110  // Determine minimum and maximum value.
111  whole_map_iterate_filtered(ptile, data, filter)
112  {
113  if (first) {
114  minval = int_map[tile_index(ptile)];
115  maxval = int_map[tile_index(ptile)];
116  } else {
117  maxval = MAX(maxval, int_map[tile_index(ptile)]);
118  minval = MIN(minval, int_map[tile_index(ptile)]);
119  }
120  first = false;
121  total++;
122  }
124 
125  if (total == 0) {
126  return;
127  }
128 
129  {
130  int const size = 1 + maxval - minval;
131  int i, count = 0, frequencies[size];
132 
133  INITIALIZE_ARRAY(frequencies, size, 0);
134 
135  /* Translate value so the minimum value is 0
136  and count the number of occurencies of all values to initialize the
137  frequencies[] */
138  whole_map_iterate_filtered(ptile, data, filter)
139  {
140  int_map[tile_index(ptile)] -= minval;
141  frequencies[int_map[tile_index(ptile)]]++;
142  }
144 
145  // create the linearize function as "incremental" frequencies
146  for (i = 0; i < size; i++) {
147  count += frequencies[i];
148  frequencies[i] = (count * int_map_max) / total;
149  }
150 
151  // apply the linearize function
152  whole_map_iterate_filtered(ptile, data, filter)
153  {
154  int_map[tile_index(ptile)] = frequencies[int_map[tile_index(ptile)]];
155  }
157  }
158 }
159 
166 void smooth_int_map(int *int_map, bool zeroes_at_edges)
167 {
168  fc_assert_ret(nullptr != int_map);
169 
170  static const float weight_standard[5] = {0.13, 0.19, 0.37, 0.19, 0.13};
171  static const float weight_isometric[5] = {0.15, 0.21, 0.29, 0.21, 0.15};
172  const float *weight;
173  bool axe = true;
174  int *target_map, *source_map;
175  int *alt_int_map = new int[MAP_INDEX_SIZE]();
176 
177  weight = weight_standard;
178  target_map = alt_int_map;
179  source_map = int_map;
180 
181  do {
182  whole_map_iterate(&(wld.map), ptile)
183  {
184  float N = 0, D = 0;
185 
186  axis_iterate(&(wld.map), ptile, pnear, i, 2, axe)
187  {
188  D += weight[i + 2];
189  N += weight[i + 2] * source_map[tile_index(pnear)];
190  }
192  if (zeroes_at_edges) {
193  D = 1;
194  }
195  target_map[tile_index(ptile)] = N / D;
196  }
198 
199  if (MAP_IS_ISOMETRIC) {
200  weight = weight_isometric;
201  }
202 
203  axe = !axe;
204 
205  source_map = alt_int_map;
206  target_map = int_map;
207  } while (!axe);
208 
209  delete[] alt_int_map;
210  alt_int_map = nullptr;
211 }
212 
213 /* These arrays are indexed by continent number (or negative of the
214  * ocean number) so the 0th element is unused and the array is 1 element
215  * larger than you'd expect.
216  *
217  * The lake surrounders array tells how many land continents surround each
218  * ocean (or -1 if the ocean touches more than one continent).
219  *
220  * The _sizes arrays give the sizes (in tiles) of each continent and
221  * ocean.
222  */
223 std::vector<Continent_id> lake_surrounders;
224 std::vector<int> continent_sizes;
225 std::vector<int> ocean_sizes;
226 
231 {
232  lake_surrounders = std::vector<Continent_id>(wld.map.num_oceans + 1, 0);
233 
234  whole_map_iterate(&(wld.map), ptile)
235  {
236  const struct terrain *pterrain = tile_terrain(ptile);
237  Continent_id cont = tile_continent(ptile);
238 
239  if (T_UNKNOWN == pterrain) {
240  continue;
241  }
242 
243  if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
244  adjc_iterate(&(wld.map), ptile, tile2)
245  {
246  Continent_id cont2 = tile_continent(tile2);
247 
248  if (is_ocean_tile(tile2)) {
249  if (lake_surrounders[-cont2] == 0) {
250  lake_surrounders[-cont2] = cont;
251  } else if (lake_surrounders[-cont2] != cont) {
252  lake_surrounders[-cont2] = -1;
253  }
254  }
255  }
257  }
258  }
260 }
261 
270 static void assign_continent_flood(struct tile *ptile, bool is_land, int nr)
271 {
272  struct tile_list *tlist = nullptr;
273  const struct terrain *pterrain = nullptr;
274 
275  fc_assert_ret(ptile != nullptr);
276 
277  pterrain = tile_terrain(ptile);
278  /* Check if the initial tile is a valid tile for continent / ocean. */
280  tile_continent(ptile) == 0 && T_UNKNOWN != pterrain
281  && XOR(is_land, terrain_type_terrain_class(pterrain) == TC_OCEAN));
282 
283  // Create tile list and insert the initial tile.
284  tlist = tile_list_new();
285  tile_list_append(tlist, ptile);
286 
287  while (tile_list_size(tlist) > 0) {
288  // Iterate over all unchecked tiles.
289  tile_list_iterate(tlist, ptile2)
290  {
291  // Iterate over the adjacent tiles.
292  adjc_iterate(&(wld.map), ptile2, ptile3)
293  {
294  pterrain = tile_terrain(ptile3);
295 
296  // Check if it is a valid tile for continent / ocean.
297  if (tile_continent(ptile3) != 0 || T_UNKNOWN == pterrain
298  || !XOR(is_land,
299  terrain_type_terrain_class(pterrain) == TC_OCEAN)) {
300  continue;
301  }
302 
303  // Add the tile to the list of tiles to check.
304  if (!tile_list_search(tlist, ptile3)) {
305  tile_list_append(tlist, ptile3);
306  }
307  }
309 
310  // Set the continent data and remove the tile from the list.
311  tile_set_continent(ptile2, nr);
312  tile_list_remove(tlist, ptile2);
313  // count the tile
314  if (nr < 0) {
315  ocean_sizes[-nr]++;
316  } else {
317  continent_sizes[nr]++;
318  }
319  }
321  }
322 
323  tile_list_destroy(tlist);
324 }
325 
333 {
334  struct terrain *lake_for_ocean[2][wld.map.num_oceans];
335 
336  {
337  struct terrain *lakes[2][5];
338  int num_laketypes[2] = {0, 0};
339  int i;
340 
341  terrain_type_iterate(pterr)
342  {
343  if (terrain_has_flag(pterr, TER_FRESHWATER)
344  && !terrain_has_flag(pterr, TER_NOT_GENERATED)) {
345  int frozen = terrain_has_flag(pterr, TER_FROZEN);
346 
347  if (num_laketypes[frozen] < ARRAY_SIZE(lakes[frozen])) {
348  lakes[frozen][num_laketypes[frozen]++] = pterr;
349  } else {
350  qDebug("Ruleset has more than %d %s lake types, ignoring %s",
351  static_cast<int> ARRAY_SIZE(lakes[frozen]),
352  frozen ? "frozen" : "unfrozen", terrain_rule_name(pterr));
353  }
354  }
355  }
357 
358  /* We don't want to generate any boundaries between fresh and
359  * non-fresh water.
360  * If there are no unfrozen lake types, just give up.
361  * Else if there are no frozen lake types, use unfrozen lake instead.
362  * If both are available, preserve frozenness of previous terrain. */
363  if (num_laketypes[0] == 0) {
364  return;
365  } else if (num_laketypes[1] == 0) {
366  for (i = 0; i < wld.map.num_oceans; i++) {
367  lake_for_ocean[0][i] = lake_for_ocean[1][i] =
368  lakes[0][fc_rand(num_laketypes[0])];
369  }
370  } else {
371  for (i = 0; i < wld.map.num_oceans; i++) {
372  int frozen;
373  for (frozen = 0; frozen < 2; frozen++) {
374  lake_for_ocean[frozen][i] =
375  lakes[frozen][fc_rand(num_laketypes[frozen])];
376  }
377  }
378  }
379  }
380 
381  whole_map_iterate(&(wld.map), ptile)
382  {
383  struct terrain *pterrain = tile_terrain(ptile);
384  Continent_id here = tile_continent(ptile);
385 
386  if (T_UNKNOWN == pterrain) {
387  continue;
388  }
389  if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
390  continue;
391  }
392  if (0 < lake_surrounders[-here]) {
393  if (terrain_control.lake_max_size >= ocean_sizes[-here]) {
394  int frozen = terrain_has_flag(pterrain, TER_FROZEN);
395  tile_change_terrain(ptile, lake_for_ocean[frozen][-here - 1]);
396  }
397  }
398  }
400 }
401 
406 {
407  return lake_surrounders[-cont];
408 }
409 
414 {
415  fc_assert_ret_val(id > 0, -1);
416  return continent_sizes[id];
417 }
418 
424 {
425  fc_assert_ret_val(id > 0, -1);
426  return ocean_sizes[id];
427 }
428 
438 {
439  // Initialize
440  wld.map.num_continents = 0;
441  wld.map.num_oceans = 0;
442  continent_sizes = std::vector<int>(1);
443  ocean_sizes = std::vector<int>(1);
444 
445  whole_map_iterate(&(wld.map), ptile) { tile_set_continent(ptile, 0); }
447 
448  // Assign new numbers
449  whole_map_iterate(&(wld.map), ptile)
450  {
451  const struct terrain *pterrain = tile_terrain(ptile);
452 
453  if (tile_continent(ptile) != 0) {
454  // Already assigned.
455  continue;
456  }
457 
458  if (T_UNKNOWN == pterrain) {
459  continue; // Can't assign this.
460  }
461 
462  if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
464  continent_sizes.push_back(0);
466  } else {
467  wld.map.num_oceans++;
468  ocean_sizes.push_back(0);
469  assign_continent_flood(ptile, false, -wld.map.num_oceans);
470  }
471  }
473 
475 
476  qDebug("Map has %d continents and %d oceans", wld.map.num_continents,
477  wld.map.num_oceans);
478 }
479 
484 struct terrain *most_shallow_ocean(bool frozen)
485 {
486  bool oceans = false, frozenmatch = false;
487  struct terrain *shallow = nullptr;
488 
489  terrain_type_iterate(pterr)
490  {
491  if (is_ocean(pterr) && !terrain_has_flag(pterr, TER_NOT_GENERATED)) {
492  bool nonfresh = !terrain_has_flag(pterr, TER_FRESHWATER);
493  bool frozen_ok = terrain_has_flag(pterr, TER_FROZEN) == frozen;
494 
495  if (!oceans && nonfresh) {
496  // First ocean type seen, reset even if frozenness doesn't match
497  oceans = true;
498  shallow = pterr;
499  frozenmatch = frozen_ok;
500  continue;
501  } else if (oceans && !nonfresh) {
502  // Dismiss any step backward on freshness
503  continue;
504  }
505  if (!frozenmatch && frozen_ok) {
506  /* Prefer terrain that matches frozenness (as long as we don't go
507  * backwards on freshness) */
508  frozenmatch = true;
509  shallow = pterr;
510  continue;
511  } else if (frozenmatch && !frozen_ok) {
512  // Dismiss any step backward on frozenness
513  continue;
514  }
515  if (!shallow
516  || pterr->property[MG_OCEAN_DEPTH]
517  < shallow->property[MG_OCEAN_DEPTH]) {
518  shallow = pterr;
519  }
520  }
521  }
523 
524  return shallow;
525 }
526 
532 struct terrain *pick_ocean(int depth, bool frozen)
533 {
534  struct terrain *best_terrain = nullptr;
535  int best_match = TERRAIN_OCEAN_DEPTH_MAXIMUM;
536 
537  terrain_type_iterate(pterrain)
538  {
539  if (terrain_type_terrain_class(pterrain) == TC_OCEAN
540  && TERRAIN_OCEAN_DEPTH_MINIMUM <= pterrain->property[MG_OCEAN_DEPTH]
541  && frozen == terrain_has_flag(pterrain, TER_FROZEN)
542  && !terrain_has_flag(pterrain, TER_NOT_GENERATED)) {
543  int match = abs(depth - pterrain->property[MG_OCEAN_DEPTH]);
544 
545  if (best_match > match) {
546  best_match = match;
547  best_terrain = pterrain;
548  }
549  }
550  }
552 
553  return best_terrain;
554 }
555 
559 static int real_distance_to_land(const struct tile *ptile, int max)
560 {
561  square_dxy_iterate(&(wld.map), ptile, max, atile, dx, dy)
562  {
563  if (terrain_type_terrain_class(tile_terrain(atile)) != TC_OCEAN) {
564  return map_vector_to_real_distance(dx, dy);
565  }
566  }
568 
569  return max + 1;
570 }
571 
576 static struct terrain *most_adjacent_ocean_type(const struct tile *ptile)
577 {
578  const int need = 2 * wld.map.num_valid_dirs / 3;
579  int count;
580 
581  terrain_type_iterate(pterrain)
582  {
583  if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
584  continue;
585  }
586 
587  count = 0;
588  adjc_iterate(&(wld.map), ptile, atile)
589  {
590  if (pterrain == tile_terrain(atile) && need <= ++count) {
591  return pterrain;
592  }
593  }
595  }
597 
598  return nullptr;
599 }
600 
607 {
608  const int OCEAN_DEPTH_STEP = 25;
609  const int OCEAN_DEPTH_RAND = 15;
610  const int OCEAN_DIST_MAX = TERRAIN_OCEAN_DEPTH_MAXIMUM / OCEAN_DEPTH_STEP;
611  struct terrain *ocean;
612  int dist;
613 
614  // First, improve the coasts.
615  whole_map_iterate(&(wld.map), ptile)
616  {
617  if (terrain_type_terrain_class(tile_terrain(ptile)) != TC_OCEAN) {
618  continue;
619  }
620 
621  dist = real_distance_to_land(ptile, OCEAN_DIST_MAX);
622  if (dist <= OCEAN_DIST_MAX) {
623  // Overwrite the terrain (but preserve frozenness).
624  ocean = pick_ocean(dist * OCEAN_DEPTH_STEP + fc_rand(OCEAN_DEPTH_RAND),
625  terrain_has_flag(tile_terrain(ptile), TER_FROZEN));
626  if (nullptr != ocean && ocean != tile_terrain(ptile)) {
627  log_debug("Replacing %s by %s at (%d, %d) "
628  "to have shallow ocean on coast.",
630  terrain_rule_name(ocean), TILE_XY(ptile));
631  tile_set_terrain(ptile, ocean);
632  }
633  }
634  }
636 
637  // Now, try to have something more continuous.
638  whole_map_iterate(&(wld.map), ptile)
639  {
640  if (terrain_type_terrain_class(tile_terrain(ptile)) != TC_OCEAN) {
641  continue;
642  }
643 
644  ocean = most_adjacent_ocean_type(ptile);
645  if (nullptr != ocean && ocean != tile_terrain(ptile)) {
646  log_debug("Replacing %s by %s at (%d, %d) "
647  "to smooth the ocean types.",
649  terrain_rule_name(ocean), TILE_XY(ptile));
650  tile_set_terrain(ptile, ocean);
651  }
652  }
654 }
655 
660 {
661  lake_surrounders.clear();
662  continent_sizes.clear();
663  ocean_sizes.clear();
664 }
665 
670 struct terrain *pick_terrain_by_flag(enum terrain_flag_id flag)
671 {
672  bool has_flag[terrain_count()];
673  int count = 0;
674 
675  terrain_type_iterate(pterrain)
676  {
677  if ((has_flag[terrain_index(pterrain)] =
678  (terrain_has_flag(pterrain, flag)
679  && !terrain_has_flag(pterrain, TER_NOT_GENERATED)))) {
680  count++;
681  }
682  }
684 
685  count = fc_rand(count);
686  terrain_type_iterate(pterrain)
687  {
688  if (has_flag[terrain_index(pterrain)]) {
689  if (count == 0) {
690  return pterrain;
691  }
692  count--;
693  }
694  }
696 
697  return T_UNKNOWN;
698 }
699 
716 struct terrain *pick_terrain(enum mapgen_terrain_property target,
717  enum mapgen_terrain_property prefer,
718  enum mapgen_terrain_property avoid)
719 {
720  int sum = 0;
721 
722  // Find the total weight.
723  terrain_type_iterate(pterrain)
724  {
725  if (!terrain_has_flag(pterrain, TER_NOT_GENERATED)) {
726  if (avoid != MG_UNUSED && pterrain->property[avoid] > 0) {
727  continue;
728  }
729  if (prefer != MG_UNUSED && pterrain->property[prefer] == 0) {
730  continue;
731  }
732 
733  if (target != MG_UNUSED) {
734  sum += pterrain->property[target];
735  } else {
736  sum++;
737  }
738  }
739  }
741 
742  // Now pick.
743  sum = fc_rand(sum);
744 
745  // Finally figure out which one we picked.
746  terrain_type_iterate(pterrain)
747  {
748  if (!terrain_has_flag(pterrain, TER_NOT_GENERATED)) {
749  int property;
750 
751  if (avoid != MG_UNUSED && pterrain->property[avoid] > 0) {
752  continue;
753  }
754  if (prefer != MG_UNUSED && pterrain->property[prefer] == 0) {
755  continue;
756  }
757 
758  if (target != MG_UNUSED) {
759  property = pterrain->property[target];
760  } else {
761  property = 1;
762  }
763  if (sum < property) {
764  return pterrain;
765  }
766  sum -= property;
767  }
768  }
770 
771  /* This can happen with sufficient quantities of preferred and avoided
772  * characteristics. Drop a requirement and try again. */
773  if (prefer != MG_UNUSED) {
774  log_debug("pick_terrain(target: %s, [dropping prefer: %s], avoid: %s)",
775  mapgen_terrain_property_name(target),
776  mapgen_terrain_property_name(prefer),
777  mapgen_terrain_property_name(avoid));
778  return pick_terrain(target, MG_UNUSED, avoid);
779  } else if (avoid != MG_UNUSED) {
780  log_debug(
781  "pick_terrain(target: %s, prefer: MG_UNUSED, [dropping avoid: %s])",
782  mapgen_terrain_property_name(target),
783  mapgen_terrain_property_name(avoid));
784  return pick_terrain(target, prefer, MG_UNUSED);
785  } else {
786  log_debug("pick_terrain([dropping target: %s], prefer: MG_UNUSED, "
787  "avoid: MG_UNUSED)",
788  mapgen_terrain_property_name(target));
789  return pick_terrain(MG_UNUSED, prefer, avoid);
790  }
791 }
signed short Continent_id
Definition: fc_types.h:289
#define MG_UNUSED
Definition: fracture_map.h:29
struct world wld
Definition: game.cpp:48
#define fc_assert_ret(condition)
Definition: log.h:112
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define log_debug(message,...)
Definition: log.h:65
struct terrain_misc terrain_control
Definition: map.cpp:40
int map_vector_to_real_distance(int dx, int dy)
Return the "real" distance for a given vector.
Definition: map.cpp:549
#define adjc_iterate_end
Definition: map.h:358
#define MAP_INDEX_SIZE
Definition: map.h:91
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition: map.h:312
#define MAP_IS_ISOMETRIC
Definition: map.h:32
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition: map.h:351
#define square_iterate_end
Definition: map.h:315
#define whole_map_iterate(_map, _tile)
Definition: map.h:473
#define square_dxy_iterate(nmap, center_tile, radius, tile_itr, dx_itr, dy_itr)
Definition: map.h:301
#define whole_map_iterate_end
Definition: map.h:480
#define square_dxy_iterate_end
Definition: map.h:305
int get_continent_size(Continent_id id)
Return size in tiles of the given continent (not ocean)
std::vector< Continent_id > lake_surrounders
void smooth_int_map(int *int_map, bool zeroes_at_edges)
Apply a Gaussian diffusion filter on the map.
static int real_distance_to_land(const struct tile *ptile, int max)
Determines the minimal distance to the land.
#define pmap(_tile)
std::vector< int > continent_sizes
static bool * placed_map
Map that contains, according to circumstances, information on whether we have already placed terrain ...
static struct terrain * most_adjacent_ocean_type(const struct tile *ptile)
Determines what is the most popular ocean type arround (need 2/3 of the adjcacent tiles).
void map_set_placed(struct tile *ptile)
Mark tile terrain as placed.
bool not_placed(const struct tile *ptile)
Checks if land has not yet been placed on pmap at (x, y)
struct terrain * pick_ocean(int depth, bool frozen)
Picks an ocean terrain to match the given depth.
void create_placed_map()
Create a clean pmap.
std::vector< int > ocean_sizes
void adjust_int_map_filtered(int *int_map, int int_map_max, void *data, bool(*filter)(const struct tile *ptile, const void *data))
Change the values of the integer map, so that they contain ranking of each tile scaled to [0 .
void destroy_placed_map()
Free the pmap.
void set_all_ocean_tiles_placed()
Set all oceanics tiles in placed_map.
void set_placed_near_pos(struct tile *ptile, int dist)
Set all nearby tiles as placed on pmap.
bool placed_map_is_initialized()
Return TRUE if initialized.
struct terrain * most_shallow_ocean(bool frozen)
Return most shallow ocean terrain type.
int get_ocean_size(Continent_id id)
Return size in tiles of the given ocean.
void regenerate_lakes()
Regenerate all oceanic tiles for small water bodies as lakes.
static void recalculate_lake_surrounders()
Calculate lake_surrounders[] array.
void generator_free()
Free resources allocated by the generator.
struct terrain * pick_terrain_by_flag(enum terrain_flag_id flag)
Return a random terrain that has the specified flag.
void smooth_water_depth()
Makes a simple depth map for all ocean tiles based on their proximity to any land tiles and reassigne...
struct terrain * pick_terrain(enum mapgen_terrain_property target, enum mapgen_terrain_property prefer, enum mapgen_terrain_property avoid)
Pick a terrain based on the target property and a property to avoid.
static void assign_continent_flood(struct tile *ptile, bool is_land, int nr)
Number this tile and nearby tiles with the specified continent number 'nr'.
void assign_continent_numbers()
Assigns continent and ocean numbers to all tiles, and set map.num_continents and map....
void map_unset_placed(struct tile *ptile)
Mark tile terrain as not placed.
int get_lake_surrounders(Continent_id cont)
Get continent surrounding lake, or -1 if there is multiple continents.
#define whole_map_iterate_filtered(_tile, pdata, pfilter)
Definition: mapgen_utils.h:80
#define axis_iterate(nmap, center_tile, _tile, _index, dist, is_X_axis)
Definition: mapgen_utils.h:54
#define whole_map_iterate_filtered_end
Definition: mapgen_utils.h:91
#define axis_iterate_end
Definition: mapgen_utils.h:72
#define fc_rand(_size)
Definition: rand.h:16
#define INITIALIZE_ARRAY(array, size, value)
Definition: shared.h:99
#define ARRAY_SIZE(x)
Definition: shared.h:79
#define MIN(x, y)
Definition: shared.h:49
#define MAX(x, y)
Definition: shared.h:48
#define XOR(p, q)
Definition: shared.h:64
size_t size
Definition: specvec.h:64
int num_continents
Definition: map_types.h:74
int num_valid_dirs
Definition: map_types.h:70
int num_oceans
Definition: map_types.h:75
int property[MG_COUNT]
Definition: terrain.h:232
Definition: tile.h:42
struct civ_map map
Definition: world_object.h:21
Terrain_type_id terrain_count()
Return the number of terrains.
Definition: terrain.cpp:93
const char * terrain_rule_name(const struct terrain *pterrain)
Return the (untranslated) rule name of the terrain.
Definition: terrain.cpp:184
Terrain_type_id terrain_index(const struct terrain *pterrain)
Return the terrain index.
Definition: terrain.cpp:110
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
What terrain class terrain type belongs to.
Definition: terrain.cpp:464
#define terrain_type_iterate(_p)
Definition: terrain.h:331
#define T_UNKNOWN
Definition: terrain.h:51
#define is_ocean(pterrain)
Definition: terrain.h:276
#define is_ocean_tile(ptile)
Definition: terrain.h:279
#define terrain_type_iterate_end
Definition: terrain.h:337
#define TERRAIN_OCEAN_DEPTH_MAXIMUM
Definition: terrain.h:234
#define terrain_has_flag(terr, flag)
Definition: terrain.h:260
void tile_set_terrain(struct tile *ptile, struct terrain *pterrain)
Set the given terrain at the specified tile.
Definition: tile.cpp:114
void tile_change_terrain(struct tile *ptile, struct terrain *pterrain)
Change the terrain to the given type.
Definition: tile.cpp:491
void tile_set_continent(struct tile *ptile, Continent_id val)
Set the continent ID of the tile.
Definition: tile.cpp:388
#define tile_index(_pt_)
Definition: tile.h:70
#define tile_list_iterate(tile_list, ptile)
Definition: tile.h:65
#define tile_terrain(_tile)
Definition: tile.h:93
#define TILE_XY(ptile)
Definition: tile.h:36
#define tile_list_iterate_end
Definition: tile.h:67
#define tile_continent(_tile)
Definition: tile.h:74