Freeciv-3.1
Loading...
Searching...
No Matches
mapgen_utils.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2004 - Marcelo J. Burda
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 "fcintl.h"
19#include "log.h"
20#include "rand.h"
21#include "support.h" /* bool type */
22
23/* common */
24#include "map.h"
25#include "packets.h"
26#include "terrain.h"
27#include "tile.h"
28
29#include "mapgen_utils.h"
30
31/**************************************************************************
32 Map that contains, according to circumstances, information on whether
33 we have already placed terrain (special, hut) here.
34**************************************************************************/
35static bool *placed_map;
36
37/**********************************************************************/
41{
42 return placed_map != NULL;
43}
44
45/**********************************************************************/
54
55/**********************************************************************/
64
65
66#define pmap(_tile) (placed_map[tile_index(_tile)])
67
68/**********************************************************************/
71bool not_placed(const struct tile *ptile)
72{
73 return !pmap(ptile);
74}
75
76/**********************************************************************/
79void map_set_placed(struct tile *ptile)
80{
81 pmap(ptile) = TRUE;
82}
83
84/**********************************************************************/
87void map_unset_placed(struct tile *ptile)
88{
89 pmap(ptile) = FALSE;
90}
91
92/**********************************************************************/
96{
97 whole_map_iterate(&(wld.map), ptile) {
98 if (is_ocean_tile(ptile)) {
99 map_set_placed(ptile);
100 }
102}
103
104/**********************************************************************/
107void set_placed_near_pos(struct tile *ptile, int dist)
108{
109 square_iterate(&(wld.map), ptile, dist, tile1) {
110 map_set_placed(tile1);
112}
113
114/**********************************************************************/
122void adjust_int_map_filtered(int *int_map, int int_map_max, void *data,
123 bool (*filter)(const struct tile *ptile,
124 const void *data))
125{
126 int minval = 0, maxval = 0, total = 0;
127 bool first = TRUE;
128
129 /* Determine minimum and maximum value. */
130 whole_map_iterate_filtered(ptile, data, filter) {
131 if (first) {
132 minval = int_map[tile_index(ptile)];
133 maxval = int_map[tile_index(ptile)];
134 } else {
135 maxval = MAX(maxval, int_map[tile_index(ptile)]);
136 minval = MIN(minval, int_map[tile_index(ptile)]);
137 }
138 first = FALSE;
139 total++;
141
142 if (total == 0) {
143 return;
144 }
145
146 {
147 int const size = 1 + maxval - minval;
148 int i, count = 0, frequencies[size];
149
150 INITIALIZE_ARRAY(frequencies, size, 0);
151
152 /* Translate value so the minimum value is 0
153 and count the number of occurrences of all values to initialize the
154 frequencies[] */
155 whole_map_iterate_filtered(ptile, data, filter) {
156 int_map[tile_index(ptile)] -= minval;
157 frequencies[int_map[tile_index(ptile)]]++;
159
160 /* create the linearize function as "incremental" frequencies */
161 for (i = 0; i < size; i++) {
162 count += frequencies[i];
163 frequencies[i] = (count * int_map_max) / total;
164 }
165
166 /* apply the linearize function */
167 whole_map_iterate_filtered(ptile, data, filter) {
168 int_map[tile_index(ptile)] = frequencies[int_map[tile_index(ptile)]];
170 }
171}
172
173/**********************************************************************/
176bool is_normal_nat_pos(int x, int y)
177{
178 NATIVE_TO_MAP_POS(&x, &y, x, y);
179 return is_normal_map_pos(x, y);
180}
181
182/**********************************************************************/
188void smooth_int_map(int *int_map, bool zeroes_at_edges)
189{
190 static const float weight_standard[5] = { 0.13, 0.19, 0.37, 0.19, 0.13 };
191 static const float weight_isometric[5] = { 0.15, 0.21, 0.29, 0.21, 0.15 };
192 const float *weight;
193 bool axe = TRUE;
194 int *target_map, *source_map;
195 int *alt_int_map = fc_calloc(MAP_INDEX_SIZE, sizeof(*alt_int_map));
196
197 fc_assert_ret(NULL != int_map);
198
199 weight = weight_standard;
200 target_map = alt_int_map;
201 source_map = int_map;
202
203 do {
204 whole_map_iterate(&(wld.map), ptile) {
205 float N = 0, D = 0;
206
207 axis_iterate(&(wld.map), ptile, pnear, i, 2, axe) {
208 D += weight[i + 2];
209 N += weight[i + 2] * source_map[tile_index(pnear)];
211 if (zeroes_at_edges) {
212 D = 1;
213 }
214 target_map[tile_index(ptile)] = (float)N / D;
216
217 if (MAP_IS_ISOMETRIC) {
218 weight = weight_isometric;
219 }
220
221 axe = !axe;
222
223 source_map = alt_int_map;
224 target_map = int_map;
225
226 } while (!axe);
227
228 FC_FREE(alt_int_map);
229}
230
231/* These arrays are indexed by continent number (or negative of the
232 * ocean number) so the 0th element is unused and the array is 1 element
233 * larger than you'd expect.
234 *
235 * The lake surrounders array tells how many land continents surround each
236 * ocean (or -1 if the ocean touches more than one continent).
237 *
238 * The _sizes arrays give the sizes (in tiles) of each continent and
239 * ocean.
240 */
242static int *continent_sizes = NULL;
243static int *ocean_sizes = NULL;
244
245/**********************************************************************/
249{
250 const size_t size = (wld.map.num_oceans + 1) * sizeof(*lake_surrounders);
251
253 memset(lake_surrounders, 0, size);
254
255 whole_map_iterate(&(wld.map), ptile) {
256 const struct terrain *pterrain = tile_terrain(ptile);
257 Continent_id cont = tile_continent(ptile);
258
259 if (T_UNKNOWN == pterrain) {
260 continue;
261 }
262
263 if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
264 adjc_iterate(&(wld.map), ptile, tile2) {
265 Continent_id cont2 = tile_continent(tile2);
266
267 if (is_ocean_tile(tile2)) {
268 if (lake_surrounders[-cont2] == 0) {
269 lake_surrounders[-cont2] = cont;
270 } else if (lake_surrounders[-cont2] != cont) {
271 lake_surrounders[-cont2] = -1;
272 }
273 }
275 }
277}
278
279/**********************************************************************/
287static void assign_continent_flood(struct tile *ptile, bool is_land, int nr)
288{
289 struct tile_list *tlist = NULL;
290 const struct terrain *pterrain;
291
292 fc_assert_ret(ptile != NULL);
293
294#ifndef FREECIV_NDEBUG
295 pterrain = tile_terrain(ptile);
296#endif
297 /* Check if the initial tile is a valid tile for continent / ocean. */
298 fc_assert_ret(tile_continent(ptile) == 0
299 && T_UNKNOWN != pterrain
300 && XOR(is_land, terrain_type_terrain_class(pterrain) == TC_OCEAN));
301
302 /* Create tile list and insert the initial tile. */
303 tlist = tile_list_new();
304 tile_list_append(tlist, ptile);
305
306 while (tile_list_size(tlist) > 0) {
307 struct tile *ptile2 = tile_list_get(tlist, 0);
308
309 /* Iterate over the adjacent tiles. */
310 adjc_iterate(&(wld.map), ptile2, ptile3) {
311 pterrain = tile_terrain(ptile3);
312
313 /* Check if it is a valid tile for continent / ocean. */
314 if (tile_continent(ptile3) != 0
315 || T_UNKNOWN == pterrain
316 || !XOR(is_land, terrain_type_terrain_class(pterrain) == TC_OCEAN)) {
317 continue;
318 }
319
320 /* Add the tile to the list of tiles to check. */
321 if (!tile_list_search(tlist, ptile3)) {
322 tile_list_append(tlist, ptile3);
323 }
325
326 /* Set the continent data and remove the tile from the list. */
327 tile_set_continent(ptile2, nr);
328 tile_list_remove(tlist, ptile2);
329
330 /* Count the tile */
331 if (nr < 0) {
332 ocean_sizes[-nr]++;
333 } else {
334 continent_sizes[nr]++;
335 }
336 }
337
338 tile_list_destroy(tlist);
339}
340
341/**********************************************************************/
348{
349 struct terrain *lake_for_ocean[2][wld.map.num_oceans];
350
351 {
352 struct terrain *lakes[2][5];
353 int num_laketypes[2] = { 0, 0 };
354 int i;
355
356 terrain_type_iterate(pterr) {
357 if (terrain_has_flag(pterr, TER_FRESHWATER)
358 && !terrain_has_flag(pterr, TER_NOT_GENERATED)) {
359 int frozen = terrain_has_flag(pterr, TER_FROZEN);
360
361 if (num_laketypes[frozen] < ARRAY_SIZE(lakes[frozen])) {
362 lakes[frozen][num_laketypes[frozen]++] = pterr;
363 } else {
364 log_verbose("Ruleset has more than %d %s lake types, ignoring %s",
365 (int) ARRAY_SIZE(lakes[frozen]),
366 frozen ? "frozen" : "unfrozen",
367 terrain_rule_name(pterr));
368 }
369 }
371
372 /* We don't want to generate any boundaries between fresh and
373 * non-fresh water.
374 * If there are no unfrozen lake types, just give up.
375 * Else if there are no frozen lake types, use unfrozen lake instead.
376 * If both are available, preserve frozenness of previous terrain. */
377 if (num_laketypes[0] == 0) {
378 return;
379 } else if (num_laketypes[1] == 0) {
380 for (i = 0; i < wld.map.num_oceans; i++) {
381 lake_for_ocean[0][i] = lake_for_ocean[1][i]
382 = lakes[0][fc_rand(num_laketypes[0])];
383 }
384 } else {
385 for (i = 0; i < wld.map.num_oceans; i++) {
386 int frozen;
387 for (frozen = 0; frozen < 2; frozen++) {
388 lake_for_ocean[frozen][i]
389 = lakes[frozen][fc_rand(num_laketypes[frozen])];
390 }
391 }
392 }
393 }
394
395 whole_map_iterate(&(wld.map), ptile) {
396 struct terrain *pterrain = tile_terrain(ptile);
397 Continent_id here = tile_continent(ptile);
398
399 if (T_UNKNOWN == pterrain) {
400 continue;
401 }
402 if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
403 continue;
404 }
405 if (0 < lake_surrounders[-here]) {
406 if (terrain_control.lake_max_size >= ocean_sizes[-here]) {
407 int frozen = terrain_has_flag(pterrain, TER_FROZEN);
408 tile_change_terrain(ptile, lake_for_ocean[frozen][-here-1]);
409 }
410 }
412}
413
414/**********************************************************************/
418{
419 return lake_surrounders[-cont];
420}
421
422/**********************************************************************/
426{
427 fc_assert_ret_val(id > 0, -1);
428 return continent_sizes[id];
429}
430
431/**********************************************************************/
436{
437 fc_assert_ret_val(id > 0, -1);
438 return ocean_sizes[id];
439}
440
441/**********************************************************************/
450{
451 /* Initialize */
453 wld.map.num_oceans = 0;
454
455 whole_map_iterate(&(wld.map), ptile) {
456 tile_set_continent(ptile, 0);
458
459 /* Assign new numbers */
460 whole_map_iterate(&(wld.map), ptile) {
461 const struct terrain *pterrain = tile_terrain(ptile);
462
463 if (tile_continent(ptile) != 0) {
464 /* Already assigned. */
465 continue;
466 }
467
468 if (T_UNKNOWN == pterrain) {
469 continue; /* Can't assign this. */
470 }
471
472 if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
475 (wld.map.num_continents + 1) * sizeof(*continent_sizes));
478 } else {
481 (wld.map.num_oceans + 1) * sizeof(*ocean_sizes));
484 }
486
488
489 log_verbose("Map has %d continents and %d oceans",
491}
492
493/**********************************************************************/
497struct terrain *most_shallow_ocean(bool frozen)
498{
499 bool oceans = FALSE, frozenmatch = FALSE;
500 struct terrain *shallow = NULL;
501
502 terrain_type_iterate(pterr) {
503 if (is_ocean(pterr) && !terrain_has_flag(pterr, TER_NOT_GENERATED)) {
504 bool nonfresh = !terrain_has_flag(pterr, TER_FRESHWATER);
505 bool frozen_ok = terrain_has_flag(pterr, TER_FROZEN) == frozen;
506
507 if (!oceans && nonfresh) {
508 /* First ocean type seen, reset even if frozenness doesn't match */
509 oceans = TRUE;
510 shallow = pterr;
511 frozenmatch = frozen_ok;
512 continue;
513 } else if (oceans && !nonfresh) {
514 /* Dismiss any step backward on freshness */
515 continue;
516 }
517 if (!frozenmatch && frozen_ok) {
518 /* Prefer terrain that matches frozenness (as long as we don't go
519 * backwards on freshness) */
520 frozenmatch = TRUE;
521 shallow = pterr;
522 continue;
523 } else if (frozenmatch && !frozen_ok) {
524 /* Dismiss any step backward on frozenness */
525 continue;
526 }
527 if (!shallow
528 || pterr->property[MG_OCEAN_DEPTH] <
529 shallow->property[MG_OCEAN_DEPTH]) {
530 shallow = pterr;
531 }
532 }
534
535 return shallow;
536}
537
538/**********************************************************************/
543struct terrain *pick_ocean(int depth, bool frozen)
544{
545 struct terrain *best_terrain = NULL;
546 int best_match = TERRAIN_OCEAN_DEPTH_MAXIMUM;
547
548 terrain_type_iterate(pterrain) {
549 if (terrain_type_terrain_class(pterrain) == TC_OCEAN
550 && TERRAIN_OCEAN_DEPTH_MINIMUM <= pterrain->property[MG_OCEAN_DEPTH]
551 && !!frozen == terrain_has_flag(pterrain, TER_FROZEN)
552 && !terrain_has_flag(pterrain, TER_NOT_GENERATED)) {
553 int match = abs(depth - pterrain->property[MG_OCEAN_DEPTH]);
554
555 if (best_match > match) {
556 best_match = match;
557 best_terrain = pterrain;
558 }
559 }
561
562 return best_terrain;
563}
564
565/**********************************************************************/
568static int real_distance_to_land(const struct tile *ptile, int max)
569{
570 square_dxy_iterate(&(wld.map), ptile, max, atile, dx, dy) {
571 if (terrain_type_terrain_class(tile_terrain(atile)) != TC_OCEAN) {
572 return map_vector_to_real_distance(dx, dy);
573 }
575
576 return max + 1;
577}
578
579/**********************************************************************/
583static struct terrain *most_adjacent_ocean_type(const struct tile *ptile)
584{
585 const int need = 2 * wld.map.num_valid_dirs / 3;
586 int count;
587
588 terrain_type_iterate(pterrain) {
589 if (terrain_type_terrain_class(pterrain) != TC_OCEAN) {
590 continue;
591 }
592
593 count = 0;
594 adjc_iterate(&(wld.map), ptile, atile) {
595 if (pterrain == tile_terrain(atile) && need <= ++count) {
596 return pterrain;
597 }
600
601 return NULL;
602}
603
604/**********************************************************************/
610{
611 const int OCEAN_DEPTH_STEP = 25;
612 const int OCEAN_DEPTH_RAND = 15;
613 const int OCEAN_DIST_MAX = TERRAIN_OCEAN_DEPTH_MAXIMUM / OCEAN_DEPTH_STEP;
614 struct terrain *ocean;
615 int dist;
616
617 /* First, improve the coasts. */
618 whole_map_iterate(&(wld.map), ptile) {
619 if (terrain_type_terrain_class(tile_terrain(ptile)) != TC_OCEAN) {
620 continue;
621 }
622
623 dist = real_distance_to_land(ptile, OCEAN_DIST_MAX);
624 if (dist <= OCEAN_DIST_MAX) {
625 /* Overwrite the terrain (but preserve frozenness). */
626 ocean = pick_ocean(dist * OCEAN_DEPTH_STEP
627 + fc_rand(OCEAN_DEPTH_RAND),
628 terrain_has_flag(tile_terrain(ptile), TER_FROZEN));
629 if (NULL != ocean && ocean != tile_terrain(ptile)) {
630 log_debug("Replacing %s by %s at (%d, %d) "
631 "to have shallow ocean on coast.",
633 terrain_rule_name(ocean), TILE_XY(ptile));
634 tile_set_terrain(ptile, ocean);
635 }
636 }
638
639 /* Now, try to have something more continuous. */
640 whole_map_iterate(&(wld.map), ptile) {
641 if (terrain_type_terrain_class(tile_terrain(ptile)) != TC_OCEAN) {
642 continue;
643 }
644
645 ocean = most_adjacent_ocean_type(ptile);
646 if (NULL != ocean && ocean != tile_terrain(ptile)) {
647 log_debug("Replacing %s by %s at (%d, %d) "
648 "to smooth the ocean types.",
650 terrain_rule_name(ocean), TILE_XY(ptile));
651 tile_set_terrain(ptile, ocean);
652 }
654}
655
656/**********************************************************************/
660{
661 if (lake_surrounders != NULL) {
662 free(lake_surrounders);
663 lake_surrounders = NULL;
664 }
665 if (continent_sizes != NULL) {
666 free(continent_sizes);
667 continent_sizes = NULL;
668 }
669 if (ocean_sizes != NULL) {
670 free(ocean_sizes);
671 ocean_sizes = NULL;
672 }
673}
674
675/**********************************************************************/
679struct terrain *pick_terrain_by_flag(enum terrain_flag_id flag)
680{
681 bool has_flag[terrain_count()];
682 int count = 0;
683
684 terrain_type_iterate(pterrain) {
685 if ((has_flag[terrain_index(pterrain)]
686 = (terrain_has_flag(pterrain, flag)
687 && !terrain_has_flag(pterrain, TER_NOT_GENERATED)))) {
688 count++;
689 }
691
692 count = fc_rand(count);
693 terrain_type_iterate(pterrain) {
694 if (has_flag[terrain_index(pterrain)]) {
695 if (count == 0) {
696 return pterrain;
697 }
698 count--;
699 }
701
702 return T_UNKNOWN;
703}
704
705
706/**********************************************************************/
722struct terrain *pick_terrain(enum mapgen_terrain_property target,
723 enum mapgen_terrain_property prefer,
724 enum mapgen_terrain_property avoid)
725{
726 int sum = 0;
727
728 /* Find the total weight. */
729 terrain_type_iterate(pterrain) {
730 if (!terrain_has_flag(pterrain, TER_NOT_GENERATED)) {
731 if (avoid != MG_UNUSED && pterrain->property[avoid] > 0) {
732 continue;
733 }
734 if (prefer != MG_UNUSED && pterrain->property[prefer] == 0) {
735 continue;
736 }
737
738 if (target != MG_UNUSED) {
739 sum += pterrain->property[target];
740 } else {
741 sum++;
742 }
743 }
745
746 /* Now pick. */
747 sum = fc_rand(sum);
748
749 /* Finally figure out which one we picked. */
750 terrain_type_iterate(pterrain) {
751 if (!terrain_has_flag(pterrain, TER_NOT_GENERATED)) {
752 int property;
753
754 if (avoid != MG_UNUSED && pterrain->property[avoid] > 0) {
755 continue;
756 }
757 if (prefer != MG_UNUSED && pterrain->property[prefer] == 0) {
758 continue;
759 }
760
761 if (target != MG_UNUSED) {
762 property = pterrain->property[target];
763 } else {
764 property = 1;
765 }
766 if (sum < property) {
767 return pterrain;
768 }
769 sum -= property;
770 }
772
773 /* This can happen with sufficient quantities of preferred and avoided
774 * characteristics. Drop a requirement and try again. */
775 if (prefer != MG_UNUSED) {
776 log_debug("pick_terrain(target: %s, [dropping prefer: %s], avoid: %s)",
777 mapgen_terrain_property_name(target),
778 mapgen_terrain_property_name(prefer),
779 mapgen_terrain_property_name(avoid));
780 return pick_terrain(target, MG_UNUSED, avoid);
781 } else if (avoid != MG_UNUSED) {
782 log_debug("pick_terrain(target: %s, prefer: MG_UNUSED, [dropping avoid: %s])",
783 mapgen_terrain_property_name(target),
784 mapgen_terrain_property_name(avoid));
785 return pick_terrain(target, prefer, MG_UNUSED);
786 } else {
787 log_debug("pick_terrain([dropping target: %s], prefer: MG_UNUSED, avoid: MG_UNUSED)",
788 mapgen_terrain_property_name(target));
789 return pick_terrain(MG_UNUSED, prefer, avoid);
790 }
791}
int int id
Definition editgui_g.h:28
signed short Continent_id
Definition fc_types.h:342
#define MG_UNUSED
struct world wld
Definition game.c:58
#define fc_assert_ret(condition)
Definition log.h:191
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_debug(message,...)
Definition log.h:115
bool is_normal_map_pos(int x, int y)
Definition map.c:961
struct terrain_misc terrain_control
Definition map.c:69
int map_vector_to_real_distance(int dx, int dy)
Definition map.c:576
#define adjc_iterate_end
Definition map.h:427
#define MAP_INDEX_SIZE
Definition map.h:131
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:385
#define MAP_IS_ISOMETRIC
Definition map.h:40
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:422
#define NATIVE_TO_MAP_POS(pmap_x, pmap_y, nat_x, nat_y)
Definition map.h:160
#define square_iterate_end
Definition map.h:388
#define whole_map_iterate(_map, _tile)
Definition map.h:539
#define square_dxy_iterate(nmap, center_tile, radius, tile_itr, dx_itr, dy_itr)
Definition map.h:375
#define whole_map_iterate_end
Definition map.h:548
#define square_dxy_iterate_end
Definition map.h:378
int get_continent_size(Continent_id id)
static struct terrain * most_adjacent_ocean_type(const struct tile *ptile)
static int * continent_sizes
static int * ocean_sizes
void smooth_int_map(int *int_map, bool zeroes_at_edges)
void set_all_ocean_tiles_placed(void)
void create_placed_map(void)
static int real_distance_to_land(const struct tile *ptile, int max)
#define pmap(_tile)
static bool * placed_map
void map_set_placed(struct tile *ptile)
void destroy_placed_map(void)
bool not_placed(const struct tile *ptile)
struct terrain * pick_terrain_by_flag(enum terrain_flag_id flag)
void assign_continent_numbers(void)
static Continent_id * lake_surrounders
void adjust_int_map_filtered(int *int_map, int int_map_max, void *data, bool(*filter)(const struct tile *ptile, const void *data))
void regenerate_lakes(void)
static void recalculate_lake_surrounders(void)
void set_placed_near_pos(struct tile *ptile, int dist)
int get_ocean_size(Continent_id id)
void generator_free(void)
void smooth_water_depth(void)
bool placed_map_is_initialized(void)
bool is_normal_nat_pos(int x, int y)
struct terrain * pick_terrain(enum mapgen_terrain_property target, enum mapgen_terrain_property prefer, enum mapgen_terrain_property avoid)
struct terrain * most_shallow_ocean(bool frozen)
struct terrain * pick_ocean(int depth, bool frozen)
static void assign_continent_flood(struct tile *ptile, bool is_land, int nr)
void map_unset_placed(struct tile *ptile)
int get_lake_surrounders(Continent_id cont)
#define whole_map_iterate_filtered(_tile, pdata, pfilter)
#define axis_iterate(nmap, center_tile, _tile, _index, dist, is_X_axis)
#define whole_map_iterate_filtered_end
#define axis_iterate_end
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
#define fc_rand(_size)
Definition rand.h:34
#define INITIALIZE_ARRAY(array, size, value)
Definition shared.h:101
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX(x, y)
Definition shared.h:54
#define XOR(p, q)
Definition shared.h:71
size_t size
Definition specvec.h:72
int num_continents
Definition map_types.h:78
int num_valid_dirs
Definition map_types.h:74
int num_oceans
Definition map_types.h:79
int property[MG_COUNT]
Definition terrain.h:239
Definition tile.h:49
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
Terrain_type_id terrain_count(void)
Definition terrain.c:106
Terrain_type_id terrain_index(const struct terrain *pterrain)
Definition terrain.c:126
const char * terrain_rule_name(const struct terrain *pterrain)
Definition terrain.c:235
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
Definition terrain.c:570
#define terrain_type_iterate(_p)
Definition terrain.h:358
#define T_UNKNOWN
Definition terrain.h:57
#define is_ocean(pterrain)
Definition terrain.h:287
#define is_ocean_tile(ptile)
Definition terrain.h:289
#define terrain_type_iterate_end
Definition terrain.h:364
#define TERRAIN_OCEAN_DEPTH_MAXIMUM
Definition terrain.h:241
#define terrain_has_flag(terr, flag)
Definition terrain.h:269
void tile_set_terrain(struct tile *ptile, struct terrain *pterrain)
Definition tile.c:124
void tile_change_terrain(struct tile *ptile, struct terrain *pterrain)
Definition tile.c:473
void tile_set_continent(struct tile *ptile, Continent_id val)
Definition tile.c:376
#define tile_index(_pt_)
Definition tile.h:87
#define tile_terrain(_tile)
Definition tile.h:109
#define TILE_XY(ptile)
Definition tile.h:42
#define tile_continent(_tile)
Definition tile.h:91